<commit_before>#include "gtest/gtest.h"
#include <string.h>
#include "tests/fff.h"
DEFINE_FFF_GLOBALS;

extern "C" {
#undef LOG_TAG
#include "../../utl/utl_thread.c"
#undef LOG_TAG
#include "../../utl/utl_log.c"
#include "../../utl/utl_dbg.c"
#include "../../utl/utl_buf.c"
#include "../../utl/utl_push.c"
#include "../../utl/utl_time.c"
#include "../../utl/utl_int.c"
#include "../../utl/utl_str.c"
#include "../../utl/utl_mem.c"
#undef LOG_TAG
#include "../../btc/btc.c"
#include "../../btc/btc_buf.c"
#include "../../btc/btc_extkey.c"
#include "../../btc/btc_keys.c"
#include "../../btc/btc_sw.c"
#include "../../btc/btc_sig.c"
#include "../../btc/btc_script.c"
#include "../../btc/btc_tx.c"
#include "../../btc/btc_tx_buf.c"
#include "../../btc/btc_crypto.c"
#include "../../btc/segwit_addr.c"
#include "../../btc/btc_segwit_addr.c"
#include "../../btc/btc_test_util.c"

#undef LOG_TAG
#include "ln_derkey.c"
#include "ln_derkey_ex.c"
#include "ln_msg_anno.c"
#include "ln_msg_close.c"
//#include "ln_msg_establish.c"
#include "ln_msg_normalope.c"
#include "ln_msg_setupctl.c"
#include "ln_node.c"
#include "ln_onion.c"
#include "ln_script.c"
#include "ln_noise.c"
#include "ln_signer.c"
#include "ln_invoice.c"
#include "ln_print.c"
#include "ln_update.c"
#include "ln_update_info.c"

#include "ln.c"
}

////////////////////////////////////////////////////////////////////////
//FAKE関数

// FAKE_VOID_FUNC(ln_db_preimage_cur_close, void *);
// FAKE_VALUE_FUNC(bool, ln_db_cnlupd_load, utl_buf_t *, uint32_t *, uint64_t, uint8_t);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_del, const uint8_t *);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_cur_open, void **);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_cur_get, void *, bool *, ln_db_preimage_t *, const char**);
// FAKE_VALUE_FUNC(bool, ln_db_channel_search, ln_db_func_cmp_t, void *);
// FAKE_VALUE_FUNC(bool, ln_db_channel_search_readonly, ln_db_func_cmp_t, void *);
// FAKE_VALUE_FUNC(bool, ln_db_payment_hash_save, const uint8_t*, const uint8_t*, ln_commit_tx_output_type_t, uint32_t);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_search, ln_db_func_preimage_t, void*);

// FAKE_VALUE_FUNC(bool, ln_msg_open_channel_write, utl_buf_t *, const ln_open_channel_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_open_channel_read, ln_open_channel_t*, const uint8_t*, uint16_t);
// FAKE_VALUE_FUNC(bool, ln_msg_accept_channel_write, utl_buf_t *, const ln_msg_accept_channel_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_accept_channel_read, ln_msg_accept_channel_t *, const uint8_t *, uint16_t );
// FAKE_VALUE_FUNC(bool, ln_msg_funding_created_write, utl_buf_t *, const ln_funding_writed_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_funding_created_read, ln_msg_funding_created_t *, const uint8_t *, uint16_t );
// FAKE_VALUE_FUNC(bool, ln_msg_funding_signed_write, utl_buf_t *, const ln_msg_funding_signed_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_funding_signed_read, ln_msg_funding_signed_t *, const uint8_t *, uint16_t );
typedef uint8_t (fake_sig_t)[LN_SZ_SIGNATURE];
FAKE_VALUE_FUNC(bool, ln_commit_tx_create_remote, ln_commit_info_t *, const ln_update_info_t *, const ln_derkey_local_keys_t *, const ln_derkey_remote_keys_t *, fake_sig_t **);
FAKE_VALUE_FUNC(bool, ln_commit_tx_create_remote_close, const ln_commit_info_t *, const ln_update_info_t *, const ln_derkey_local_keys_t *, const ln_derkey_remote_keys_t *, const utl_buf_t *, ln_close_force_t *);

////////////////////////////////////////////////////////////////////////

class ln: public testing::Test {
protected:
    virtual void SetUp() {
        //utl_log_init_stderr();
        // RESET_FAKE(ln_db_preimage_cur_close)
        // RESET_FAKE(ln_db_cnlupd_load)
        // RESET_FAKE(ln_db_preimage_del)
        // RESET_FAKE(ln_db_preimage_cur_open)
        // RESET_FAKE(ln_db_preimage_cur_get)
        // RESET_FAKE(ln_db_channel_search)
        // RESET_FAKE(ln_db_channel_search_readonly)
        // RESET_FAKE(ln_db_payment_hash_save)
        // RESET_FAKE(ln_db_preimage_search)
        // RESET_FAKE(ln_msg_open_channel_read)
        // RESET_FAKE(ln_msg_accept_channel_write)
        // RESET_FAKE(ln_msg_accept_channel_read)
        // RESET_FAKE(ln_msg_funding_created_write)
        // RESET_FAKE(ln_msg_funding_created_read)
        // RESET_FAKE(ln_msg_funding_signed_write)
        // RESET_FAKE(ln_msg_funding_signed_read)
        RESET_FAKE(ln_commit_tx_create_remote)

        ln_commit_tx_create_remote_fake.return_val = true;
        ln_commit_tx_create_remote_close_fake.return_val = true;
        utl_dbg_malloc_cnt_reset();
        btc_init(BTC_BLOCK_CHAIN_BTCTEST, true);
    }

    virtual void TearDown() {
        ln_node_term();
        btc_term();
        ASSERT_EQ(0, utl_dbg_malloc_cnt());
    }

public:
    static void DumpBin(const uint8_t *pData, uint16_t Len)
    {
        for (uint16_t lp = 0; lp < Len; lp++) {
            printf("%02x", pData[lp]);
        }
        printf("\n");
    }
    static bool DumpCheck(const void *pData, uint32_t Len, uint8_t Fill)
    {
        bool ret = true;
        const uint8_t *p = (const uint8_t *)pData;
        for (uint32_t lp = 0; lp < Len; lp++) {
            if (p[lp] != Fill) {
                ret = false;
                break;
            }
        }
        return ret;
    }
    static void LnCallbackType(ln_cb_type_t Type, void *pCommonParam, void *pTypeSpecificParam) {
        (void)pCommonParam; (void)pTypeSpecificParam;
        const char *p_str;
        switch (Type) {
        case LN_CB_TYPE_NOTIFY_ERROR: p_str = "LN_CB_TYPE_NOTIFY_ERROR"; break;
        case LN_CB_TYPE_NOTIFY_INIT_RECV: p_str = "LN_CB_TYPE_NOTIFY_INIT_RECV"; break;
        case LN_CB_TYPE_NOTIFY_REESTABLISH_RECV: p_str = "LN_CB_TYPE_NOTIFY_REESTABLISH_RECV"; break;
        case LN_CB_TYPE_SIGN_FUNDING_TX: p_str = "LN_CB_TYPE_SIGN_FUNDING_TX"; break;
        case LN_CB_TYPE_WAIT_FUNDING_TX: p_str = "LN_CB_TYPE_WAIT_FUNDING_TX"; break;
        case LN_CB_TYPE_NOTIFY_FUNDING_LOCKED_RECV: p_str = "LN_CB_TYPE_NOTIFY_FUNDING_LOCKED_RECV"; break;
        case LN_CB_TYPE_NOTIFY_ANNODB_UPDATE: p_str = "LN_CB_TYPE_NOTIFY_ANNODB_UPDATE"; break;
        case LN_CB_TYPE_NOTIFY_ADDFINAL_HTLC_RECV: p_str = "LN_CB_TYPE_NOTIFY_ADDFINAL_HTLC_RECV"; break;
        case LN_CB_TYPE_NOTIFY_FULFILL_HTLC_RECV: p_str = "LN_CB_TYPE_NOTIFY_FULFILL_HTLC_RECV"; break;
        case LN_CB_TYPE_NOTIFY_REV_AND_ACK_EXCHANGE: p_str = "LN_CB_TYPE_NOTIFY_REV_AND_ACK_EXCHANGE"; break;
        case LN_CB_TYPE_NOTIFY_UPDATE_FEE_RECV: p_str = "LN_CB_TYPE_NOTIFY_UPDATE_FEE_RECV"; break;
        case LN_CB_TYPE_NOTIFY_SHUTDOWN_RECV: p_str = "LN_CB_TYPE_NOTIFY_SHUTDOWN_RECV"; break;
        case LN_CB_TYPE_UPDATE_CLOSING_FEE: p_str = "LN_CB_TYPE_UPDATE_CLOSING_FEE"; break;
        case LN_CB_TYPE_NOTIFY_CLOSING_END: p_str = "LN_CB_TYPE_NOTIFY_CLOSING_END"; break;
        case LN_CB_TYPE_SEND_MESSAGE: p_str = "LN_CB_TYPE_SEND_MESSAGE"; break;
        case LN_CB_TYPE_GET_LATEST_FEERATE: p_str = "LN_CB_TYPE_GET_LATEST_FEERATE"; break;
        case LN_CB_TYPE_GET_BLOCK_COUNT: p_str = "LN_CB_TYPE_GET_BLOCK_COUNT"; break;
        default:
            p_str = "unknown";
        }
        printf("*** callback: %s(%d)\n", p_str, Type);
    }
    static void LnInit(ln_channel_t *pChannel)
    {
        ln_anno_param_t anno_param;

        memset(pChannel, 0xcc, sizeof(ln_channel_t));
        anno_param.cltv_expiry_delta = 10;
        anno_param.htlc_minimum_msat = 1000;
        anno_param.fee_base_msat = 20;
        anno_param.fee_prop_millionths = 200;
        ln_init(pChannel, &anno_param, NULL, (ln_callback_t)0x123456, NULL);
        pChannel->commit_info_local.dust_limit_sat = BTC_DUST_LIMIT;
        pChannel->commit_info_local.htlc_minimum_msat = 0;
        pChannel->commit_info_local.max_accepted_htlcs = 10;
        pChannel->commit_info_local.local_msat = 1000000;
        pChannel->commit_info_local.remote_msat = 1000000;
        pChannel->commit_info_remote.dust_limit_sat = BTC_DUST_LIMIT;
        pChannel->commit_info_remote.htlc_minimum_msat = 0;
        pChannel->commit_info_remote.max_accepted_htlcs = 10;
        pChannel->commit_info_remote.local_msat = 1000000;
        pChannel->commit_info_remote.remote_msat = 1000000;
        btc_tx_init(&pChannel->funding_info.tx_data);
        utl_buf_init(&pChannel->funding_info.wit_script);
        pChannel->p_callback = LnCallbackType;
    }
};

////////////////////////////////////////////////////////////////////////

TEST_F(ln, init)
{
    ln_channel_t channel;
    ln_anno_param_t anno_param;

    memset(&channel, 0xcc, sizeof(channel));
    anno_param.cltv_expiry_delta = 10;
    anno_param.htlc_minimum_msat = 1000;
    anno_param.fee_base_msat = 20;
    anno_param.fee_prop_millionths = 200;
    ln_init(&channel, &anno_param, NULL, (ln_callback_t)0x123456, (void *)0x654321);

    ASSERT_EQ(LN_STATUS_NONE, channel.status);
    for (uint16_t idx = 0; idx < LN_UPDATE_MAX; idx++) {
        ASSERT_TRUE(utl_mem_is_all_zero(
            &channel.update_info.updates[idx].state, sizeof(channel.update_info.updates[idx].state)));
    }
    ASSERT_EQ(0x654321, channel.p_param);
    ASSERT_EQ(0x123456, channel.p_callback);

    ln_term(&channel);
}

////////////////////////////////////////////////////////////////////////

TEST_F(ln, calc_short1)
{
    uint64_t sid = ln_short_channel_id_calc(0x12345678, 0x9abcdef0, 0x6543210f);
    ASSERT_EQ(0x345678bcdef0210f, sid);
}

TEST_F(ln, calc_short2)
{
    uint64_t sid = ln_short_channel_id_calc(1116104, 33, 0);
    ASSERT_EQ(0x1107c80000210000, sid);
}
<commit_msg>tests<commit_after>#include "gtest/gtest.h"
#include <string.h>
#include "tests/fff.h"
DEFINE_FFF_GLOBALS;

extern "C" {
#undef LOG_TAG
#include "../../utl/utl_thread.c"
#undef LOG_TAG
#include "../../utl/utl_log.c"
#include "../../utl/utl_dbg.c"
#include "../../utl/utl_buf.c"
#include "../../utl/utl_push.c"
#include "../../utl/utl_time.c"
#include "../../utl/utl_int.c"
#include "../../utl/utl_str.c"
#include "../../utl/utl_mem.c"
#undef LOG_TAG
#include "../../btc/btc.c"
#include "../../btc/btc_buf.c"
#include "../../btc/btc_extkey.c"
#include "../../btc/btc_keys.c"
#include "../../btc/btc_sw.c"
#include "../../btc/btc_sig.c"
#include "../../btc/btc_script.c"
#include "../../btc/btc_tx.c"
#include "../../btc/btc_tx_buf.c"
#include "../../btc/btc_crypto.c"
#include "../../btc/segwit_addr.c"
#include "../../btc/btc_segwit_addr.c"
#include "../../btc/btc_test_util.c"

#undef LOG_TAG
#include "ln_derkey.c"
#include "ln_derkey_ex.c"
#include "ln_msg_anno.c"
#include "ln_msg_close.c"
//#include "ln_msg_establish.c"
#include "ln_msg_normalope.c"
#include "ln_msg_setupctl.c"
#include "ln_node.c"
#include "ln_onion.c"
#include "ln_script.c"
#include "ln_noise.c"
#include "ln_signer.c"
#include "ln_invoice.c"
#include "ln_print.c"
#include "ln_update.c"
#include "ln_update_info.c"

#include "ln.c"
}

////////////////////////////////////////////////////////////////////////
//FAKE関数

// FAKE_VOID_FUNC(ln_db_preimage_cur_close, void *);
// FAKE_VALUE_FUNC(bool, ln_db_cnlupd_load, utl_buf_t *, uint32_t *, uint64_t, uint8_t);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_del, const uint8_t *);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_cur_open, void **);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_cur_get, void *, bool *, ln_db_preimage_t *, const char**);
// FAKE_VALUE_FUNC(bool, ln_db_channel_search, ln_db_func_cmp_t, void *);
// FAKE_VALUE_FUNC(bool, ln_db_channel_search_readonly, ln_db_func_cmp_t, void *);
// FAKE_VALUE_FUNC(bool, ln_db_payment_hash_save, const uint8_t*, const uint8_t*, ln_commit_tx_output_type_t, uint32_t);
// FAKE_VALUE_FUNC(bool, ln_db_preimage_search, ln_db_func_preimage_t, void*);

// FAKE_VALUE_FUNC(bool, ln_msg_open_channel_write, utl_buf_t *, const ln_open_channel_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_open_channel_read, ln_open_channel_t*, const uint8_t*, uint16_t);
// FAKE_VALUE_FUNC(bool, ln_msg_accept_channel_write, utl_buf_t *, const ln_msg_accept_channel_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_accept_channel_read, ln_msg_accept_channel_t *, const uint8_t *, uint16_t );
// FAKE_VALUE_FUNC(bool, ln_msg_funding_created_write, utl_buf_t *, const ln_funding_writed_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_funding_created_read, ln_msg_funding_created_t *, const uint8_t *, uint16_t );
// FAKE_VALUE_FUNC(bool, ln_msg_funding_signed_write, utl_buf_t *, const ln_msg_funding_signed_t *);
// FAKE_VALUE_FUNC(bool, ln_msg_funding_signed_read, ln_msg_funding_signed_t *, const uint8_t *, uint16_t );
typedef uint8_t (fake_sig_t)[LN_SZ_SIGNATURE];
FAKE_VALUE_FUNC(bool, ln_commit_tx_create_remote, ln_commit_info_t *, const ln_update_info_t *, const ln_derkey_local_keys_t *, const ln_derkey_remote_keys_t *, fake_sig_t **);
FAKE_VALUE_FUNC(bool, ln_commit_tx_create_remote_close, const ln_commit_info_t *, const ln_update_info_t *, const ln_derkey_local_keys_t *, const ln_derkey_remote_keys_t *, const utl_buf_t *, ln_close_force_t *);

////////////////////////////////////////////////////////////////////////

class ln: public testing::Test {
protected:
    virtual void SetUp() {
        //utl_log_init_stderr();
        // RESET_FAKE(ln_db_preimage_cur_close)
        // RESET_FAKE(ln_db_cnlupd_load)
        // RESET_FAKE(ln_db_preimage_del)
        // RESET_FAKE(ln_db_preimage_cur_open)
        // RESET_FAKE(ln_db_preimage_cur_get)
        // RESET_FAKE(ln_db_channel_search)
        // RESET_FAKE(ln_db_channel_search_readonly)
        // RESET_FAKE(ln_db_payment_hash_save)
        // RESET_FAKE(ln_db_preimage_search)
        // RESET_FAKE(ln_msg_open_channel_read)
        // RESET_FAKE(ln_msg_accept_channel_write)
        // RESET_FAKE(ln_msg_accept_channel_read)
        // RESET_FAKE(ln_msg_funding_created_write)
        // RESET_FAKE(ln_msg_funding_created_read)
        // RESET_FAKE(ln_msg_funding_signed_write)
        // RESET_FAKE(ln_msg_funding_signed_read)
        RESET_FAKE(ln_commit_tx_create_remote)

        ln_commit_tx_create_remote_fake.return_val = true;
        ln_commit_tx_create_remote_close_fake.return_val = true;
        utl_dbg_malloc_cnt_reset();
        btc_init(BTC_BLOCK_CHAIN_BTCTEST, true);
    }

    virtual void TearDown() {
        ln_node_term();
        btc_term();
        ASSERT_EQ(0, utl_dbg_malloc_cnt());
    }

public:
    static void DumpBin(const uint8_t *pData, uint16_t Len)
    {
        for (uint16_t lp = 0; lp < Len; lp++) {
            printf("%02x", pData[lp]);
        }
        printf("\n");
    }
    static bool DumpCheck(const void *pData, uint32_t Len, uint8_t Fill)
    {
        bool ret = true;
        const uint8_t *p = (const uint8_t *)pData;
        for (uint32_t lp = 0; lp < Len; lp++) {
            if (p[lp] != Fill) {
                ret = false;
                break;
            }
        }
        return ret;
    }
    static void LnCallbackType(ln_cb_type_t Type, void *pCommonParam, void *pTypeSpecificParam) {
        (void)pCommonParam; (void)pTypeSpecificParam;
        const char *p_str;
        switch (Type) {
        case LN_CB_TYPE_NOTIFY_ERROR: p_str = "LN_CB_TYPE_NOTIFY_ERROR"; break;
        case LN_CB_TYPE_NOTIFY_INIT_RECV: p_str = "LN_CB_TYPE_NOTIFY_INIT_RECV"; break;
        case LN_CB_TYPE_NOTIFY_REESTABLISH_RECV: p_str = "LN_CB_TYPE_NOTIFY_REESTABLISH_RECV"; break;
        case LN_CB_TYPE_SIGN_FUNDING_TX: p_str = "LN_CB_TYPE_SIGN_FUNDING_TX"; break;
        case LN_CB_TYPE_WAIT_FUNDING_TX: p_str = "LN_CB_TYPE_WAIT_FUNDING_TX"; break;
        case LN_CB_TYPE_NOTIFY_FUNDING_LOCKED_RECV: p_str = "LN_CB_TYPE_NOTIFY_FUNDING_LOCKED_RECV"; break;
        case LN_CB_TYPE_NOTIFY_ANNODB_UPDATE: p_str = "LN_CB_TYPE_NOTIFY_ANNODB_UPDATE"; break;
        case LN_CB_TYPE_NOTIFY_ADDFINAL_HTLC_RECV: p_str = "LN_CB_TYPE_NOTIFY_ADDFINAL_HTLC_RECV"; break;
        case LN_CB_TYPE_NOTIFY_FULFILL_HTLC_RECV: p_str = "LN_CB_TYPE_NOTIFY_FULFILL_HTLC_RECV"; break;
        case LN_CB_TYPE_NOTIFY_REV_AND_ACK_EXCHANGE: p_str = "LN_CB_TYPE_NOTIFY_REV_AND_ACK_EXCHANGE"; break;
        case LN_CB_TYPE_NOTIFY_UPDATE_FEE_RECV: p_str = "LN_CB_TYPE_NOTIFY_UPDATE_FEE_RECV"; break;
        case LN_CB_TYPE_NOTIFY_SHUTDOWN_RECV: p_str = "LN_CB_TYPE_NOTIFY_SHUTDOWN_RECV"; break;
        case LN_CB_TYPE_UPDATE_CLOSING_FEE: p_str = "LN_CB_TYPE_UPDATE_CLOSING_FEE"; break;
        case LN_CB_TYPE_NOTIFY_CLOSING_END: p_str = "LN_CB_TYPE_NOTIFY_CLOSING_END"; break;
        case LN_CB_TYPE_SEND_MESSAGE: p_str = "LN_CB_TYPE_SEND_MESSAGE"; break;
        case LN_CB_TYPE_GET_LATEST_FEERATE: p_str = "LN_CB_TYPE_GET_LATEST_FEERATE"; break;
        case LN_CB_TYPE_GET_BLOCK_COUNT: p_str = "LN_CB_TYPE_GET_BLOCK_COUNT"; break;
        default:
            p_str = "unknown";
        }
        printf("*** callback: %s(%d)\n", p_str, Type);
    }
    static void LnInit(ln_channel_t *pChannel)
    {
        ln_anno_param_t anno_param;

        memset(pChannel, 0xcc, sizeof(ln_channel_t));
        anno_param.cltv_expiry_delta = 10;
        anno_param.htlc_minimum_msat = 1000;
        anno_param.fee_base_msat = 20;
        anno_param.fee_prop_millionths = 200;
        ln_init(pChannel, &anno_param, NULL, (ln_callback_t)0x123456, NULL);
        pChannel->commit_info_local.dust_limit_sat = BTC_DUST_LIMIT;
        pChannel->commit_info_local.htlc_minimum_msat = 0;
        pChannel->commit_info_local.max_accepted_htlcs = 10;
        pChannel->commit_info_local.local_msat = 1000000;
        pChannel->commit_info_local.remote_msat = 1000000;
        pChannel->commit_info_remote.dust_limit_sat = BTC_DUST_LIMIT;
        pChannel->commit_info_remote.htlc_minimum_msat = 0;
        pChannel->commit_info_remote.max_accepted_htlcs = 10;
        pChannel->commit_info_remote.local_msat = 1000000;
        pChannel->commit_info_remote.remote_msat = 1000000;
        btc_tx_init(&pChannel->funding_info.tx_data);
        utl_buf_init(&pChannel->funding_info.wit_script);
        pChannel->p_callback = LnCallbackType;
    }
};

////////////////////////////////////////////////////////////////////////

TEST_F(ln, init)
{
    ln_channel_t channel;
    ln_anno_param_t anno_param;

    memset(&channel, 0xcc, sizeof(channel));
    anno_param.cltv_expiry_delta = 10;
    anno_param.htlc_minimum_msat = 1000;
    anno_param.fee_base_msat = 20;
    anno_param.fee_prop_millionths = 200;
    ln_init(&channel, &anno_param, NULL, (ln_callback_t)0x123456, (void *)0x654321);

    ASSERT_EQ(LN_STATUS_NONE, channel.status);
    for (uint16_t idx = 0; idx < LN_UPDATE_MAX; idx++) {
        ASSERT_TRUE(utl_mem_is_all_zero(
            &channel.update_info.updates[idx].state, sizeof(channel.update_info.updates[idx].state)));
    }
    ASSERT_EQ(0x654321, channel.p_param);
    ASSERT_EQ(0x123456, channel.p_callback);

    ln_term(&channel);
}

////////////////////////////////////////////////////////////////////////

TEST_F(ln, calc_short1)
{
    uint64_t sid = ln_short_channel_id_calc(0x12345678, 0x9abcdef0, 0x6543210f);
    ASSERT_EQ(0x345678bcdef0210f, sid);
}

TEST_F(ln, calc_short2)
{
    uint64_t sid = ln_short_channel_id_calc(1116104, 33, 0);
    ASSERT_EQ(0x1107c80000210000, sid);
}

////////////////////////////////////////////////////////////////////////

TEST_F(ln, ln_feerate_limit_set)
{
    ln_feerate_limit_set(65535, 0);
    ASSERT_EQ(65535, mFeerateMin);
    ASSERT_EQ(0, mFeerateMax);

    ln_feerate_limit_set(0, 65535);
    ASSERT_EQ(0, mFeerateMin);
    ASSERT_EQ(65535, mFeerateMax);
}

TEST_F(ln, ln_feerate_limit_get)
{
    uint32_t min, max;

    mFeerateMin = 0;
    mFeerateMax = 0;
    ln_feerate_limit_get(&min, &max, 253);
    ASSERT_EQ(0, min);
    ASSERT_EQ(0, max);

    mFeerateMin = 100;
    mFeerateMax = 200;
    ln_feerate_limit_get(&min, &max, 253);
    ASSERT_EQ(253, min);
    ASSERT_EQ(506, max);

    mFeerateMin = 5;
    mFeerateMax = 2000;
    ln_feerate_limit_get(&min, &max, 253);
    ASSERT_EQ(12, min);
    ASSERT_EQ(5060, max);

    mFeerateMin = 5;
    mFeerateMax = 2000;
    ln_feerate_limit_get(&min, &max, 50000);
    ASSERT_EQ(2500, min);
    ASSERT_EQ(1000000, max);

    mFeerateMin = 0;
    mFeerateMax = 0;
    ln_feerate_limit_get(&min, &max, 50000);
    ASSERT_EQ(0, min);
    ASSERT_EQ(0, max);
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 Nervana Systems Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

#pragma once

#include <vector>
#include <cstdio>
#include <stdexcept>
#include <cstring>
#include <sstream>

using std::vector;

class RawMedia {
public:
    RawMedia() : _bufSize(0), _dataSize(0), _bytesPerSample(0) {
    }

    RawMedia(const RawMedia& media)
    : _bufSize(media._bufSize),
      _dataSize(media._dataSize),
      _bytesPerSample(media._bytesPerSample) {
        for (uint i = 0; i < media._bufs.size(); i++) {
            _bufs.push_back(new char[_bufSize]);
            memcpy(_bufs[i], media._bufs[i], _bufSize);
        }
    }

    virtual ~RawMedia() {
        for (uint i = 0; i < _bufs.size(); i++) {
            delete[] _bufs[i];
        }
    }

    void reset() {
        _dataSize = 0;
    }

    void addBufs(int count, int size) {
        for (int i = 0; i < count; i++) {
            _bufs.push_back(new char[size]);
       }
        _bufSize = size;
    }

    void fillBufs(char** frames, int frameSize) {
        // `frames` should contain one frame per channel of audio
        for (uint i = 0; i < _bufs.size(); i++) {
            memcpy(_bufs[i] + _dataSize, frames[i], frameSize);
        }
        _dataSize += frameSize;
    }

    void growBufs(int grow) {
        for (uint i = 0; i < _bufs.size(); i++) {
            char* buf = new char[_bufSize + grow];
            memcpy(buf, _bufs[i], _dataSize);
            delete[] _bufs[i];
            _bufs[i] = buf;
        }
        _bufSize += grow;
    }

    void setBytesPerSample(int bytesPerSample) {
        _bytesPerSample = bytesPerSample;
    }

    int size() {
        return _bufs.size();
    }

    char* getBuf(int idx) {
        return _bufs[idx];
    }

    int bufSize() {
        return _bufSize;
    }

    int dataSize() {
        return _dataSize;
    }

    int bytesPerSample() {
        return _bytesPerSample;
    }

    int numSamples() {
        return dataSize() / bytesPerSample();
    }

private:
    vector<char*>               _bufs;
    int                         _bufSize;
    int                         _dataSize;
    int                         _bytesPerSample;
};
<commit_msg>remove unused RawMedia copy constructor<commit_after>/*
 Copyright 2016 Nervana Systems Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

#pragma once

#include <vector>
#include <cstdio>
#include <stdexcept>
#include <cstring>
#include <sstream>

using std::vector;

class RawMedia {
public:
    RawMedia() : _bufSize(0), _dataSize(0), _bytesPerSample(0) {
    }

    virtual ~RawMedia() {
        for (uint i = 0; i < _bufs.size(); i++) {
            delete[] _bufs[i];
        }
    }

    void reset() {
        _dataSize = 0;
    }

    void addBufs(int count, int size) {
        for (int i = 0; i < count; i++) {
            _bufs.push_back(new char[size]);
       }
        _bufSize = size;
    }

    void fillBufs(char** frames, int frameSize) {
        // `frames` should contain one frame per channel of audio
        for (uint i = 0; i < _bufs.size(); i++) {
            memcpy(_bufs[i] + _dataSize, frames[i], frameSize);
        }
        _dataSize += frameSize;
    }

    void growBufs(int grow) {
        for (uint i = 0; i < _bufs.size(); i++) {
            char* buf = new char[_bufSize + grow];
            memcpy(buf, _bufs[i], _dataSize);
            delete[] _bufs[i];
            _bufs[i] = buf;
        }
        _bufSize += grow;
    }

    void setBytesPerSample(int bytesPerSample) {
        _bytesPerSample = bytesPerSample;
    }

    int size() {
        return _bufs.size();
    }

    char* getBuf(int idx) {
        return _bufs[idx];
    }

    int bufSize() {
        return _bufSize;
    }

    int dataSize() {
        return _dataSize;
    }

    int bytesPerSample() {
        return _bytesPerSample;
    }

    int numSamples() {
        return dataSize() / bytesPerSample();
    }

private:
    vector<char*>               _bufs;
    int                         _bufSize;
    int                         _dataSize;
    int                         _bytesPerSample;
};
<|endoftext|>


<commit_before>/* -*- Mode: C++ -*-
   $Id: KDGanttSemiSizingControl.cpp,v 1.6 2005/10/11 13:59:02 lutz Exp $
*/

/****************************************************************************
 ** Copyright (C)  2002-2004 Klarälvdalens Datakonsult AB.  All rights reserved.
 **
 ** This file is part of the KDGantt library.
 **
 ** This file may be used under the terms of the GNU General Public
 ** License versions 2.0 or 3.0 as published by the Free Software
 ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
 ** included in the packaging of this file.  Alternatively you may (at
 ** your option) use any later version of the GNU General Public
 ** License if such license has been publicly approved by
 ** Klarälvdalens Datakonsult AB (or its successors, if any).
 **
 ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
 ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
 ** not expressly granted herein.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** As a special exception, permission is given to link this program
 ** with any edition of Qt, and distribute the resulting executable,
 ** without including the source code for Qt in the source distribution.
 **
 **********************************************************************/

#include "KDGanttSemiSizingControl.h"
#include <QPushButton>
#include <QPainter>
#include <QBitmap>

#include <QWhatsThis>
/*!
  \class KDGanttSemiSizingControl KDGanttSemiSizingControl.h
  This class provides exactly one child widget with a button for
  minimizing and restoring. You can also specify a so-called minimize
  widget that will be shown in place of the child widget while the
  latter one is minimized. While the child widget is not minimized,
  the minimize widget will not be visible.

  If you add more than one child widget (besides the minimize widget),
  only the last one added will be visible.
*/

/*!
  Constructs an empty semi sizing control with horizontal
  orientation and the control arrow button on top of the controlled
  widget.

  \param parent the parent widget. This parameter is passed to the
  base class.
  \param name the internal widget name. This parameter is passed to
  the base class.
*/

KDGanttSemiSizingControl::KDGanttSemiSizingControl( QWidget* parent ) :
    KDGanttSizingControl( parent ), _orient( Qt::Horizontal ),
    _arrowPos( Before ), _minimizedWidget(0), _maximizedWidget(0)
{
    init();
}

/*!
  Constructs an empty semi sizing control with the specified
  orientation and the control arrow button either on top or left of
  the controlled widget (depending on the orientation).

  \param orientation the orientation of the splitter
  \param parent the parent widget. This parameter is passed to the
  base class.
  \param name the internal widget name. This parameter is passed to
  the base class.
*/

KDGanttSemiSizingControl::KDGanttSemiSizingControl( Qt::Orientation orientation,
                                                    QWidget* parent ):
    KDGanttSizingControl( parent ), _orient( orientation ),
    _arrowPos( Before ), _minimizedWidget(0), _maximizedWidget(0)
{
    init();
}

/*!
  Constructs an empty semi sizing control with the specified
  orientation and position of the control arrow button.

  \param arrowPosition specifies whether the control arrow button
  should appear before or after the controlled widget
  \param orientation the orientation of the splitter
  \param parent the parent widget. This parameter is passed to the
  base class.
  \param name the internal widget name. This parameter is passed to
  the base class.
*/

KDGanttSemiSizingControl::KDGanttSemiSizingControl( ArrowPosition arrowPosition,
                                                    Qt::Orientation orientation,
                                                    QWidget* parent ):
    KDGanttSizingControl( parent ), _orient( orientation ),
    _arrowPos( arrowPosition ), _minimizedWidget(0), _maximizedWidget(0)
{
    init();
}

/*!
  Specifies the widget that should be shown while the child widget is
  minimized. This so-called minimize widget should be a child widget
  of the KDGanttSemiSizingControl.

  \param widget the minimize widget
  \sa minimizedWidget()
*/

void KDGanttSemiSizingControl::setMinimizedWidget( QWidget* widget )
{
    _minimizedWidget = widget;
    if( _minimizedWidget ) _minimizedWidget->hide();
    setup();
}

/*!
  Returns the widget that is shown while the child widget is
  minimized.

  \return the minimize widget
  \sa setMinimizedWidget()
*/

QWidget* KDGanttSemiSizingControl::minimizedWidget() const
{
    return _minimizedWidget;
}

/*!
  Specifies the widget that should be shown while the child widget is
  maximized. This so-called maximize widget should be a child widget
  of the KDGanttSemiSizingControl.

  \param widget the minimize widget
  \sa maximizedWidget()
*/

void KDGanttSemiSizingControl::setMaximizedWidget( QWidget* widget )
{
    _maximizedWidget = widget;
    //if( _maximizedWidget ) _maximizedWidget->show();
    setup();
}

/*!
  Returns the widget that is shown while the child widget is
  maximized.

  \return the maximize widget
  \sa setMaximizedWidget()
*/

QWidget* KDGanttSemiSizingControl::maximizedWidget() const
{
    return _maximizedWidget;
}

/*!
  Sets the orientation of the simple sizing control.

  \param orientation the new orientation
  \sa orientation()
*/

void KDGanttSemiSizingControl::setOrientation( Qt::Orientation orientation )
{
    if ( _orient != orientation ) {
        _orient = orientation;
        setup();
    }
}

/*!
  Returns the orientation of the simple sizing control.
  \return the orientation
  \sa setOrientation()
*/

Qt::Orientation KDGanttSemiSizingControl::orientation() const
{
    return _orient;
}

/*!
  Returns the position of the control arrow button.

  \param arrowPosition the position of the control arrow button
  \sa arrowPosition()
*/

void KDGanttSemiSizingControl::setArrowPosition( ArrowPosition arrowPosition )
{
    if ( _arrowPos != arrowPosition ) {
        _arrowPos = arrowPosition;
        setup();
    }
}

/*!
  Returns the position of the control arrow button.

  \return the position of the control arrow button
  \sa setArrowPosition()
*/

KDGanttSemiSizingControl::ArrowPosition KDGanttSemiSizingControl::arrowPosition() const
{
    return _arrowPos;
}

/*!
  \enum KDGanttSemiSizingControl::ArrowPosition

  This enum is used for specifying whether the control arrow button
  should appear before (on top of, left of) or after (below, right of)
  the controlled widget.
*/

void KDGanttSemiSizingControl::init()
{
    _but = new QPushButton( this );
    _but->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
    connect( _but, SIGNAL( clicked() ), this, SLOT(changeState()) );
    _layout = 0;
    _but->setWhatsThis( "Click on this button to show the \nlegend at the bottom of the widget");
    _but->setToolTip( "Show / hide legend");

}

void KDGanttSemiSizingControl::setup()
{
    //-------------------------------------------------- Setup layout
    delete _layout;
    QBoxLayout* butLayout; // _layout will delete me

    if ( _orient == Qt::Horizontal || isMinimized() )
        _layout = new QHBoxLayout( this );
    else
        _layout = new QVBoxLayout( this );

    if ( _orient == Qt::Vertical && !isMinimized() ) {
        butLayout = new QHBoxLayout();
        _layout->addItem( butLayout );
    } else {
        butLayout = new QVBoxLayout();
        _layout->addItem( butLayout );
    }

    //---------------------------------------- Set the arrow on the button
    if ( !isMinimized() ) {
        _but->setIcon( QIcon(pixmap( Down )) );
    }
    else {
        if ( _arrowPos == Before ) {
            _but->setIcon( QIcon(pixmap( Right )) );
        }
        else {
            _but->setIcon( QIcon(pixmap( Left )) );
        }
    }

    //------------------------------ Setup the button at the correct possition
    if ( _arrowPos == After && _orient == Qt::Vertical && !isMinimized() ) {
        butLayout->addStretch( 1 );
        butLayout->addWidget( _but, 0, Qt::AlignLeft );
    }
    else {
        butLayout->addWidget( _but, 0, Qt::AlignRight  );
        butLayout->addStretch( 1 );
    }

    // Set widget in the correct possition
    QWidget* widget;
    /* ************************** old code ***************
       if ( isMinimized() )
       widget = _minimizedWidget;
       else
       widget = _maximizedWidget;
       if( widget ) {
       if ( _arrowPos == Before  || _orient == Vertical && !isMinimized() )
       _layout->addWidget( widget, 1 );
       else
       _layout->insertWidget( 0, widget, 1 );
	}
     ************************************************** */
    // hack for the usage in KDGantt as pop-up legend widget
    // for this purpose,
    // the _maximizedWidget must be a child of the parent of this widget

    if ( isMinimized() ) {
       widget = _minimizedWidget;
       if( widget ) {
	 if ( _arrowPos == Before  || _orient == Qt::Vertical && !isMinimized() )
	   _layout->addWidget( widget, 1 );
	 else
	   _layout->insertWidget( 0, widget, 1 );
       }
    }
    else {
      if ( _arrowPos == Before  || _orient == Qt::Vertical && !isMinimized() )
	_layout->addStretch( 1 );
      else
	_layout->insertStretch( 0, 1 );
      widget = _maximizedWidget;
      // the following is only the special case
      // arrowPos == Before  and  _orient == Vertical
      //widget->move( 0+x(), _but->height()+y());
    }
}

/*!
  Restores or minimizes the child widget. \a minimize() does exactly the
  opposite to this method.

  \param restore true to restore, false to minimize
  \sa minimize()
*/

void KDGanttSemiSizingControl::restore( bool restore )
{
    if ( ! restore ) {
        minimize( true );
    }
    else {
        if( _maximizedWidget ) _maximizedWidget->show();
        if( _minimizedWidget ) _minimizedWidget->hide();
        KDGanttSizingControl::restore( restore );
        setup();
    }
}

/*!
  Restores or minimizes the child widget. \a restore() does exactly the
  opposite to this method.

  \param minimize true to minimize, false to restore
  \sa restore()

*/

void KDGanttSemiSizingControl::minimize( bool minimize )
{
    if ( ! minimize ) {
        restore( true );
    }
    else {
        if( _minimizedWidget ) _minimizedWidget->show();
	if( _maximizedWidget ) _maximizedWidget->hide();
        KDGanttSizingControl::minimize( minimize );
        setup();
    }
}

QPixmap KDGanttSemiSizingControl::pixmap( Direction direction ) {
    int s = 10;
    QPixmap pix( s, s );
    pix.fill( Qt::blue );

    QPointArray arr;
    switch ( direction ) {
    case Up:    arr.setPoints( 3,   0, s-1,   s-1, s-1,   0, s/2   ); ;break;
    case Down:  arr.setPoints( 3,   0, 0,     s-1, 0,     s/2, s-1 ); break;
    case Left:  arr.setPoints( 3,   s-1, 0,   s-1, s-1,   0, s/2   ); break;
    case Right: arr.setPoints( 3,   0,0,      s-1, s/2,   0, s-1   ); break;
    }
#if QT_VERSION < 0x040000
    QPainter p( &pix );
    p.setPen( Qt::black );
    p.setBrush( colorGroup().button() );
    p.drawPolygon( arr );
    QBitmap bit( s, s );
    bit.fill( color0 );

    QPainter p2( &bit );
    p2.setPen( color1 );
    p2.setBrush( color1 );
    p2.drawPolygon( arr );
    pix.setMask( bit );
#else
    QPainter p( &pix );
    p.setPen( Qt::black );
    p.setBrush( palette().color( QPalette::Button) );
    p.drawPolygon( arr );
    QBitmap bit( s, s );
    bit.fill( Qt::blue );

    QPainter p2( &bit );
    p2.setPen( Qt::red );
    p2.setBrush( Qt::red );
    p2.drawPolygon( arr );
    pix.setMask( bit );
#endif
    return pix;
}

#include "KDGanttSemiSizingControl.moc"
<commit_msg>complete with some more parentheses<commit_after>/* -*- Mode: C++ -*-
   $Id: KDGanttSemiSizingControl.cpp,v 1.6 2005/10/11 13:59:02 lutz Exp $
*/

/****************************************************************************
 ** Copyright (C)  2002-2004 Klarälvdalens Datakonsult AB.  All rights reserved.
 **
 ** This file is part of the KDGantt library.
 **
 ** This file may be used under the terms of the GNU General Public
 ** License versions 2.0 or 3.0 as published by the Free Software
 ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
 ** included in the packaging of this file.  Alternatively you may (at
 ** your option) use any later version of the GNU General Public
 ** License if such license has been publicly approved by
 ** Klarälvdalens Datakonsult AB (or its successors, if any).
 **
 ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
 ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
 ** not expressly granted herein.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** As a special exception, permission is given to link this program
 ** with any edition of Qt, and distribute the resulting executable,
 ** without including the source code for Qt in the source distribution.
 **
 **********************************************************************/

#include "KDGanttSemiSizingControl.h"
#include <QPushButton>
#include <QPainter>
#include <QBitmap>

#include <QWhatsThis>
/*!
  \class KDGanttSemiSizingControl KDGanttSemiSizingControl.h
  This class provides exactly one child widget with a button for
  minimizing and restoring. You can also specify a so-called minimize
  widget that will be shown in place of the child widget while the
  latter one is minimized. While the child widget is not minimized,
  the minimize widget will not be visible.

  If you add more than one child widget (besides the minimize widget),
  only the last one added will be visible.
*/

/*!
  Constructs an empty semi sizing control with horizontal
  orientation and the control arrow button on top of the controlled
  widget.

  \param parent the parent widget. This parameter is passed to the
  base class.
  \param name the internal widget name. This parameter is passed to
  the base class.
*/

KDGanttSemiSizingControl::KDGanttSemiSizingControl( QWidget* parent ) :
    KDGanttSizingControl( parent ), _orient( Qt::Horizontal ),
    _arrowPos( Before ), _minimizedWidget(0), _maximizedWidget(0)
{
    init();
}

/*!
  Constructs an empty semi sizing control with the specified
  orientation and the control arrow button either on top or left of
  the controlled widget (depending on the orientation).

  \param orientation the orientation of the splitter
  \param parent the parent widget. This parameter is passed to the
  base class.
  \param name the internal widget name. This parameter is passed to
  the base class.
*/

KDGanttSemiSizingControl::KDGanttSemiSizingControl( Qt::Orientation orientation,
                                                    QWidget* parent ):
    KDGanttSizingControl( parent ), _orient( orientation ),
    _arrowPos( Before ), _minimizedWidget(0), _maximizedWidget(0)
{
    init();
}

/*!
  Constructs an empty semi sizing control with the specified
  orientation and position of the control arrow button.

  \param arrowPosition specifies whether the control arrow button
  should appear before or after the controlled widget
  \param orientation the orientation of the splitter
  \param parent the parent widget. This parameter is passed to the
  base class.
  \param name the internal widget name. This parameter is passed to
  the base class.
*/

KDGanttSemiSizingControl::KDGanttSemiSizingControl( ArrowPosition arrowPosition,
                                                    Qt::Orientation orientation,
                                                    QWidget* parent ):
    KDGanttSizingControl( parent ), _orient( orientation ),
    _arrowPos( arrowPosition ), _minimizedWidget(0), _maximizedWidget(0)
{
    init();
}

/*!
  Specifies the widget that should be shown while the child widget is
  minimized. This so-called minimize widget should be a child widget
  of the KDGanttSemiSizingControl.

  \param widget the minimize widget
  \sa minimizedWidget()
*/

void KDGanttSemiSizingControl::setMinimizedWidget( QWidget* widget )
{
    _minimizedWidget = widget;
    if( _minimizedWidget ) _minimizedWidget->hide();
    setup();
}

/*!
  Returns the widget that is shown while the child widget is
  minimized.

  \return the minimize widget
  \sa setMinimizedWidget()
*/

QWidget* KDGanttSemiSizingControl::minimizedWidget() const
{
    return _minimizedWidget;
}

/*!
  Specifies the widget that should be shown while the child widget is
  maximized. This so-called maximize widget should be a child widget
  of the KDGanttSemiSizingControl.

  \param widget the minimize widget
  \sa maximizedWidget()
*/

void KDGanttSemiSizingControl::setMaximizedWidget( QWidget* widget )
{
    _maximizedWidget = widget;
    //if( _maximizedWidget ) _maximizedWidget->show();
    setup();
}

/*!
  Returns the widget that is shown while the child widget is
  maximized.

  \return the maximize widget
  \sa setMaximizedWidget()
*/

QWidget* KDGanttSemiSizingControl::maximizedWidget() const
{
    return _maximizedWidget;
}

/*!
  Sets the orientation of the simple sizing control.

  \param orientation the new orientation
  \sa orientation()
*/

void KDGanttSemiSizingControl::setOrientation( Qt::Orientation orientation )
{
    if ( _orient != orientation ) {
        _orient = orientation;
        setup();
    }
}

/*!
  Returns the orientation of the simple sizing control.
  \return the orientation
  \sa setOrientation()
*/

Qt::Orientation KDGanttSemiSizingControl::orientation() const
{
    return _orient;
}

/*!
  Returns the position of the control arrow button.

  \param arrowPosition the position of the control arrow button
  \sa arrowPosition()
*/

void KDGanttSemiSizingControl::setArrowPosition( ArrowPosition arrowPosition )
{
    if ( _arrowPos != arrowPosition ) {
        _arrowPos = arrowPosition;
        setup();
    }
}

/*!
  Returns the position of the control arrow button.

  \return the position of the control arrow button
  \sa setArrowPosition()
*/

KDGanttSemiSizingControl::ArrowPosition KDGanttSemiSizingControl::arrowPosition() const
{
    return _arrowPos;
}

/*!
  \enum KDGanttSemiSizingControl::ArrowPosition

  This enum is used for specifying whether the control arrow button
  should appear before (on top of, left of) or after (below, right of)
  the controlled widget.
*/

void KDGanttSemiSizingControl::init()
{
    _but = new QPushButton( this );
    _but->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
    connect( _but, SIGNAL( clicked() ), this, SLOT(changeState()) );
    _layout = 0;
    _but->setWhatsThis( "Click on this button to show the \nlegend at the bottom of the widget");
    _but->setToolTip( "Show / hide legend");

}

void KDGanttSemiSizingControl::setup()
{
    //-------------------------------------------------- Setup layout
    delete _layout;
    QBoxLayout* butLayout; // _layout will delete me

    if ( _orient == Qt::Horizontal || isMinimized() )
        _layout = new QHBoxLayout( this );
    else
        _layout = new QVBoxLayout( this );

    if ( _orient == Qt::Vertical && !isMinimized() ) {
        butLayout = new QHBoxLayout();
        _layout->addItem( butLayout );
    } else {
        butLayout = new QVBoxLayout();
        _layout->addItem( butLayout );
    }

    //---------------------------------------- Set the arrow on the button
    if ( !isMinimized() ) {
        _but->setIcon( QIcon(pixmap( Down )) );
    }
    else {
        if ( _arrowPos == Before ) {
            _but->setIcon( QIcon(pixmap( Right )) );
        }
        else {
            _but->setIcon( QIcon(pixmap( Left )) );
        }
    }

    //------------------------------ Setup the button at the correct possition
    if ( _arrowPos == After && _orient == Qt::Vertical && !isMinimized() ) {
        butLayout->addStretch( 1 );
        butLayout->addWidget( _but, 0, Qt::AlignLeft );
    }
    else {
        butLayout->addWidget( _but, 0, Qt::AlignRight  );
        butLayout->addStretch( 1 );
    }

    // Set widget in the correct possition
    QWidget* widget;
    /* ************************** old code ***************
       if ( isMinimized() )
       widget = _minimizedWidget;
       else
       widget = _maximizedWidget;
       if( widget ) {
       if ( _arrowPos == Before  || _orient == Vertical && !isMinimized() )
       _layout->addWidget( widget, 1 );
       else
       _layout->insertWidget( 0, widget, 1 );
	}
     ************************************************** */
    // hack for the usage in KDGantt as pop-up legend widget
    // for this purpose,
    // the _maximizedWidget must be a child of the parent of this widget

    if ( isMinimized() ) {
       widget = _minimizedWidget;
       if( widget ) {
	 if ( _arrowPos == Before  || ( _orient == Qt::Vertical && !isMinimized() ) )
	   _layout->addWidget( widget, 1 );
	 else
	   _layout->insertWidget( 0, widget, 1 );
       }
    }
    else {
      if ( _arrowPos == Before  || ( _orient == Qt::Vertical && !isMinimized() ) )
	_layout->addStretch( 1 );
      else
	_layout->insertStretch( 0, 1 );
      widget = _maximizedWidget;
      // the following is only the special case
      // arrowPos == Before  and  _orient == Vertical
      //widget->move( 0+x(), _but->height()+y());
    }
}

/*!
  Restores or minimizes the child widget. \a minimize() does exactly the
  opposite to this method.

  \param restore true to restore, false to minimize
  \sa minimize()
*/

void KDGanttSemiSizingControl::restore( bool restore )
{
    if ( ! restore ) {
        minimize( true );
    }
    else {
        if( _maximizedWidget ) _maximizedWidget->show();
        if( _minimizedWidget ) _minimizedWidget->hide();
        KDGanttSizingControl::restore( restore );
        setup();
    }
}

/*!
  Restores or minimizes the child widget. \a restore() does exactly the
  opposite to this method.

  \param minimize true to minimize, false to restore
  \sa restore()

*/

void KDGanttSemiSizingControl::minimize( bool minimize )
{
    if ( ! minimize ) {
        restore( true );
    }
    else {
        if( _minimizedWidget ) _minimizedWidget->show();
	if( _maximizedWidget ) _maximizedWidget->hide();
        KDGanttSizingControl::minimize( minimize );
        setup();
    }
}

QPixmap KDGanttSemiSizingControl::pixmap( Direction direction ) {
    int s = 10;
    QPixmap pix( s, s );
    pix.fill( Qt::blue );

    QPointArray arr;
    switch ( direction ) {
    case Up:    arr.setPoints( 3,   0, s-1,   s-1, s-1,   0, s/2   ); ;break;
    case Down:  arr.setPoints( 3,   0, 0,     s-1, 0,     s/2, s-1 ); break;
    case Left:  arr.setPoints( 3,   s-1, 0,   s-1, s-1,   0, s/2   ); break;
    case Right: arr.setPoints( 3,   0,0,      s-1, s/2,   0, s-1   ); break;
    }
#if QT_VERSION < 0x040000
    QPainter p( &pix );
    p.setPen( Qt::black );
    p.setBrush( colorGroup().button() );
    p.drawPolygon( arr );
    QBitmap bit( s, s );
    bit.fill( color0 );

    QPainter p2( &bit );
    p2.setPen( color1 );
    p2.setBrush( color1 );
    p2.drawPolygon( arr );
    pix.setMask( bit );
#else
    QPainter p( &pix );
    p.setPen( Qt::black );
    p.setBrush( palette().color( QPalette::Button) );
    p.drawPolygon( arr );
    QBitmap bit( s, s );
    bit.fill( Qt::blue );

    QPainter p2( &bit );
    p2.setPen( Qt::red );
    p2.setBrush( Qt::red );
    p2.drawPolygon( arr );
    pix.setMask( bit );
#endif
    return pix;
}

#include "KDGanttSemiSizingControl.moc"
<|endoftext|>


<commit_before>//
// Bareflank Hypervisor
//
// Copyright (C) 2015 Assured Information Security, Inc.
// Author: Rian Quinn        <quinnr@ainfosec.com>
// Author: Brendan Kerrigan  <kerriganb@ainfosec.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#include <gsl/gsl>

#include <json.h>
#include <debug.h>
#include <exception.h>
#include <ioctl_driver.h>
#include <vmcall_interface.h>
#include <driver_entry_interface.h>

ioctl_driver::ioctl_driver(gsl::not_null<file *> f,
                           gsl::not_null<ioctl *> ctl,
                           gsl::not_null<command_line_parser *> clp) :
    m_file(f),
    m_ioctl(ctl),
    m_clp(clp)
{ }

void
ioctl_driver::process()
{
    switch (m_clp->cmd())
    {
        case command_line_parser::command_type::help:
            return;

        case command_line_parser::command_type::load:
            return this->load_vmm();

        case command_line_parser::command_type::unload:
            return this->unload_vmm();

        case command_line_parser::command_type::start:
            return this->start_vmm();

        case command_line_parser::command_type::stop:
            return this->stop_vmm();

        case command_line_parser::command_type::dump:
            return this->dump_vmm();

        case command_line_parser::command_type::status:
            return this->vmm_status();

        case command_line_parser::command_type::vmcall:
            return this->vmcall();
    }
}

void
ioctl_driver::load_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: stop_vmm();
        case VMM_LOADED: unload_vmm();
        case VMM_UNLOADED: break;
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    auto &&modules = json::parse(m_file->read_text(m_clp->modules()));

    auto ___ = gsl::on_failure([&]
    { unload_vmm(); });

    for (const auto &module : modules["modules"])
        m_ioctl->call_ioctl_add_module(m_file->read_binary(module));

    m_ioctl->call_ioctl_load_vmm();
}

void
ioctl_driver::unload_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: stop_vmm();
        case VMM_LOADED: break;
        case VMM_UNLOADED: break;
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_unload_vmm();
}

void
ioctl_driver::start_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: stop_vmm();
        case VMM_LOADED: break;
        case VMM_UNLOADED: throw invalid_vmm_state("vmm must be loaded first");
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_start_vmm();
}

void
ioctl_driver::stop_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: break;
        case VMM_LOADED: return;
        case VMM_UNLOADED: return;
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_stop_vmm();
}

void
ioctl_driver::dump_vmm()
{
    auto drr = ioctl::drr_type{};
    auto buffer = std::make_unique<char[]>(DEBUG_RING_SIZE);

    switch (get_status())
    {
        case VMM_RUNNING: break;
        case VMM_LOADED: break;
        case VMM_UNLOADED: throw invalid_vmm_state("vmm must be loaded first");
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_dump_vmm(&drr, m_clp->vcpuid());

    if (debug_ring_read(&drr, buffer.get(), DEBUG_RING_SIZE) > 0)
        std::cout << buffer.get();
}

void
ioctl_driver::vmm_status()
{
    switch (get_status())
    {
        case VMM_UNLOADED: std::cout << "VMM_UNLOADED\n"; return;
        case VMM_LOADED: std::cout << "VMM_LOADED\n"; return;
        case VMM_RUNNING: std::cout << "VMM_RUNNING\n"; return;
        case VMM_CORRUPT: std::cout << "VMM_CORRUPT\n"; return;
        default: throw unknown_status();
    }
}

void
ioctl_driver::vmcall()
{
    auto regs = m_clp->registers();

    switch (get_status())
    {
        case VMM_RUNNING: break;
        case VMM_LOADED: throw invalid_vmm_state("vmm must be running first");
        case VMM_UNLOADED: throw invalid_vmm_state("vmm must be running first");
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    switch (regs.r00)
    {
        case VMCALL_VERSIONS:
            this->vmcall_versions(regs);
            break;

        case VMCALL_REGISTERS:
            this->vmcall_registers(regs);
            break;

        case VMCALL_DATA:
            this->vmcall_data(regs);
            break;

        case VMCALL_EVENT:
            this->vmcall_event(regs);
            break;

        case VMCALL_UNITTEST:
            this->vmcall_unittest(regs);
            break;

        default:
            throw std::logic_error("unknown vmcall opcode");
    }
}

void
ioctl_driver::vmcall_send_regs(registers_type &regs)
{
    m_ioctl->call_ioctl_vmcall(&regs, m_clp->cpuid());

    if (regs.r01 != 0)
        throw ioctl_failed(IOCTL_VMCALL);
}

void
ioctl_driver::vmcall_versions(registers_type &regs)
{
    this->vmcall_send_regs(regs);

    switch (regs.r02)
    {
        case VMCALL_VERSION_PROTOCOL:
            std::cout << "VMCALL_VERSIONS: " << view_as_pointer(regs.r03) << std::endl;
            break;

        case VMCALL_VERSION_BAREFLANK:
            std::cout << "BAREFLANK_VERSION_MAJOR: " << view_as_pointer(regs.r03) << std::endl;
            std::cout << "BAREFLANK_VERSION_MINOR: " << view_as_pointer(regs.r04) << std::endl;
            std::cout << "BAREFLANK_VERSION_PATCH: " << view_as_pointer(regs.r05) << std::endl;
            break;

        case VMCALL_VERSION_USER:
            std::cout << "USER_VERSION_MAJOR: " << view_as_pointer(regs.r03) << std::endl;
            std::cout << "USER_VERSION_MINOR: " << view_as_pointer(regs.r04) << std::endl;
            std::cout << "USER_VERSION_PATCH: " << view_as_pointer(regs.r05) << std::endl;
            break;

        default:
            break;
    }
}

void
ioctl_driver::vmcall_registers(registers_type &regs)
{
    this->vmcall_send_regs(regs);

    std::cout << "r02: " << view_as_pointer(regs.r02) << std::endl;
    std::cout << "r03: " << view_as_pointer(regs.r03) << std::endl;
    std::cout << "r04: " << view_as_pointer(regs.r04) << std::endl;
    std::cout << "r05: " << view_as_pointer(regs.r05) << std::endl;
    std::cout << "r06: " << view_as_pointer(regs.r06) << std::endl;
    std::cout << "r07: " << view_as_pointer(regs.r07) << std::endl;
    std::cout << "r08: " << view_as_pointer(regs.r08) << std::endl;
    std::cout << "r09: " << view_as_pointer(regs.r09) << std::endl;
    std::cout << "r10: " << view_as_pointer(regs.r10) << std::endl;
    std::cout << "r11: " << view_as_pointer(regs.r11) << std::endl;
    std::cout << "r12: " << view_as_pointer(regs.r12) << std::endl;
    // std::cout << "r13: " << view_as_pointer(regs.r13) << std::endl;
    // std::cout << "r14: " << view_as_pointer(regs.r14) << std::endl;
    // std::cout << "r15: " << view_as_pointer(regs.r15) << std::endl;
}

void
ioctl_driver::vmcall_data(registers_type &regs)
{
    switch (regs.r04)
    {
        case VMCALL_DATA_STRING_UNFORMATTED:
        case VMCALL_DATA_STRING_JSON:
            this->vmcall_data_string(regs);
            break;

        case VMCALL_DATA_BINARY_UNFORMATTED:
            this->vmcall_data_binary(regs);
            break;

        default:
            throw std::logic_error("unknown vmcall data type");
            break;
    }
}

void
ioctl_driver::vmcall_data_string(registers_type &regs)
{
    auto &&obuffer = std::make_unique<char[]>(VMCALL_OUT_BUFFER_SIZE);
    regs.r08 = reinterpret_cast<decltype(regs.r08)>(obuffer.get());
    regs.r09 = VMCALL_OUT_BUFFER_SIZE;

    vmcall_send_regs(regs);

    switch (regs.r07)
    {
        case VMCALL_DATA_STRING_JSON:

            if (regs.r09 >= VMCALL_OUT_BUFFER_SIZE)
                throw std::out_of_range("return output buffer size out of range");

            std::cout << "received from vmm: " << json::parse(std::string(obuffer.get(), regs.r09)) << '\n';
            break;

        case VMCALL_DATA_STRING_UNFORMATTED:

            if (regs.r09 >= VMCALL_OUT_BUFFER_SIZE)
                throw std::out_of_range("return output buffer size out of range");

            std::cout << "received from vmm: " << std::string(obuffer.get(), regs.r09) << '\n';
            break;

        default:
            break;
    }
}

void
ioctl_driver::vmcall_data_binary(registers_type &regs)
{
    auto &&ifile_buffer = m_file->read_binary(m_clp->ifile());
    auto &&ofile_buffer = file::binary_data(VMCALL_OUT_BUFFER_SIZE);
    regs.r05 = reinterpret_cast<decltype(regs.r05)>(ifile_buffer.data());
    regs.r06 = ifile_buffer.size();
    regs.r08 = reinterpret_cast<decltype(regs.r08)>(ofile_buffer.data());
    regs.r09 = VMCALL_OUT_BUFFER_SIZE;

    vmcall_send_regs(regs);

    switch (regs.r07)
    {
        case VMCALL_DATA_BINARY_UNFORMATTED:

            if (regs.r09 >= VMCALL_OUT_BUFFER_SIZE)
                throw std::out_of_range("return output buffer size out of range");

            ofile_buffer.resize(regs.r09);
            m_file->write_binary(m_clp->ofile(), ofile_buffer);
            break;

        default:
            break;
    }
}

void
ioctl_driver::vmcall_event(registers_type &regs)
{
    vmcall_send_regs(regs);
    std::cout << "success" << std::endl;
}

void
ioctl_driver::vmcall_unittest(registers_type &regs)
{
    vmcall_send_regs(regs);
    std::cout << "\033[1;36m" << std::hex << "0x" << regs.r02 << std::dec << ":\033[1;32m passed\033[0m\n";
}

ioctl_driver::status_type
ioctl_driver::get_status() const
{
    status_type status = -1;
    m_ioctl->call_ioctl_vmm_status(&status);

    return status;
}
<commit_msg>Turn on Pretty Print<commit_after>//
// Bareflank Hypervisor
//
// Copyright (C) 2015 Assured Information Security, Inc.
// Author: Rian Quinn        <quinnr@ainfosec.com>
// Author: Brendan Kerrigan  <kerriganb@ainfosec.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#include <gsl/gsl>

#include <json.h>
#include <debug.h>
#include <exception.h>
#include <ioctl_driver.h>
#include <vmcall_interface.h>
#include <driver_entry_interface.h>

ioctl_driver::ioctl_driver(gsl::not_null<file *> f,
                           gsl::not_null<ioctl *> ctl,
                           gsl::not_null<command_line_parser *> clp) :
    m_file(f),
    m_ioctl(ctl),
    m_clp(clp)
{ }

void
ioctl_driver::process()
{
    switch (m_clp->cmd())
    {
        case command_line_parser::command_type::help:
            return;

        case command_line_parser::command_type::load:
            return this->load_vmm();

        case command_line_parser::command_type::unload:
            return this->unload_vmm();

        case command_line_parser::command_type::start:
            return this->start_vmm();

        case command_line_parser::command_type::stop:
            return this->stop_vmm();

        case command_line_parser::command_type::dump:
            return this->dump_vmm();

        case command_line_parser::command_type::status:
            return this->vmm_status();

        case command_line_parser::command_type::vmcall:
            return this->vmcall();
    }
}

void
ioctl_driver::load_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: stop_vmm();
        case VMM_LOADED: unload_vmm();
        case VMM_UNLOADED: break;
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    auto &&modules = json::parse(m_file->read_text(m_clp->modules()));

    auto ___ = gsl::on_failure([&]
    { unload_vmm(); });

    for (const auto &module : modules["modules"])
        m_ioctl->call_ioctl_add_module(m_file->read_binary(module));

    m_ioctl->call_ioctl_load_vmm();
}

void
ioctl_driver::unload_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: stop_vmm();
        case VMM_LOADED: break;
        case VMM_UNLOADED: break;
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_unload_vmm();
}

void
ioctl_driver::start_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: stop_vmm();
        case VMM_LOADED: break;
        case VMM_UNLOADED: throw invalid_vmm_state("vmm must be loaded first");
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_start_vmm();
}

void
ioctl_driver::stop_vmm()
{
    switch (get_status())
    {
        case VMM_RUNNING: break;
        case VMM_LOADED: return;
        case VMM_UNLOADED: return;
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_stop_vmm();
}

void
ioctl_driver::dump_vmm()
{
    auto drr = ioctl::drr_type{};
    auto buffer = std::make_unique<char[]>(DEBUG_RING_SIZE);

    switch (get_status())
    {
        case VMM_RUNNING: break;
        case VMM_LOADED: break;
        case VMM_UNLOADED: throw invalid_vmm_state("vmm must be loaded first");
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    m_ioctl->call_ioctl_dump_vmm(&drr, m_clp->vcpuid());

    if (debug_ring_read(&drr, buffer.get(), DEBUG_RING_SIZE) > 0)
        std::cout << buffer.get();
}

void
ioctl_driver::vmm_status()
{
    switch (get_status())
    {
        case VMM_UNLOADED: std::cout << "VMM_UNLOADED\n"; return;
        case VMM_LOADED: std::cout << "VMM_LOADED\n"; return;
        case VMM_RUNNING: std::cout << "VMM_RUNNING\n"; return;
        case VMM_CORRUPT: std::cout << "VMM_CORRUPT\n"; return;
        default: throw unknown_status();
    }
}

void
ioctl_driver::vmcall()
{
    auto regs = m_clp->registers();

    switch (get_status())
    {
        case VMM_RUNNING: break;
        case VMM_LOADED: throw invalid_vmm_state("vmm must be running first");
        case VMM_UNLOADED: throw invalid_vmm_state("vmm must be running first");
        case VMM_CORRUPT: throw corrupt_vmm();
        default: throw unknown_status();
    }

    switch (regs.r00)
    {
        case VMCALL_VERSIONS:
            this->vmcall_versions(regs);
            break;

        case VMCALL_REGISTERS:
            this->vmcall_registers(regs);
            break;

        case VMCALL_DATA:
            this->vmcall_data(regs);
            break;

        case VMCALL_EVENT:
            this->vmcall_event(regs);
            break;

        case VMCALL_UNITTEST:
            this->vmcall_unittest(regs);
            break;

        default:
            throw std::logic_error("unknown vmcall opcode");
    }
}

void
ioctl_driver::vmcall_send_regs(registers_type &regs)
{
    m_ioctl->call_ioctl_vmcall(&regs, m_clp->cpuid());

    if (regs.r01 != 0)
        throw ioctl_failed(IOCTL_VMCALL);
}

void
ioctl_driver::vmcall_versions(registers_type &regs)
{
    this->vmcall_send_regs(regs);

    switch (regs.r02)
    {
        case VMCALL_VERSION_PROTOCOL:
            std::cout << "VMCALL_VERSIONS: " << view_as_pointer(regs.r03) << std::endl;
            break;

        case VMCALL_VERSION_BAREFLANK:
            std::cout << "BAREFLANK_VERSION_MAJOR: " << view_as_pointer(regs.r03) << std::endl;
            std::cout << "BAREFLANK_VERSION_MINOR: " << view_as_pointer(regs.r04) << std::endl;
            std::cout << "BAREFLANK_VERSION_PATCH: " << view_as_pointer(regs.r05) << std::endl;
            break;

        case VMCALL_VERSION_USER:
            std::cout << "USER_VERSION_MAJOR: " << view_as_pointer(regs.r03) << std::endl;
            std::cout << "USER_VERSION_MINOR: " << view_as_pointer(regs.r04) << std::endl;
            std::cout << "USER_VERSION_PATCH: " << view_as_pointer(regs.r05) << std::endl;
            break;

        default:
            break;
    }
}

void
ioctl_driver::vmcall_registers(registers_type &regs)
{
    this->vmcall_send_regs(regs);

    std::cout << "r02: " << view_as_pointer(regs.r02) << std::endl;
    std::cout << "r03: " << view_as_pointer(regs.r03) << std::endl;
    std::cout << "r04: " << view_as_pointer(regs.r04) << std::endl;
    std::cout << "r05: " << view_as_pointer(regs.r05) << std::endl;
    std::cout << "r06: " << view_as_pointer(regs.r06) << std::endl;
    std::cout << "r07: " << view_as_pointer(regs.r07) << std::endl;
    std::cout << "r08: " << view_as_pointer(regs.r08) << std::endl;
    std::cout << "r09: " << view_as_pointer(regs.r09) << std::endl;
    std::cout << "r10: " << view_as_pointer(regs.r10) << std::endl;
    std::cout << "r11: " << view_as_pointer(regs.r11) << std::endl;
    std::cout << "r12: " << view_as_pointer(regs.r12) << std::endl;
    // std::cout << "r13: " << view_as_pointer(regs.r13) << std::endl;
    // std::cout << "r14: " << view_as_pointer(regs.r14) << std::endl;
    // std::cout << "r15: " << view_as_pointer(regs.r15) << std::endl;
}

void
ioctl_driver::vmcall_data(registers_type &regs)
{
    switch (regs.r04)
    {
        case VMCALL_DATA_STRING_UNFORMATTED:
        case VMCALL_DATA_STRING_JSON:
            this->vmcall_data_string(regs);
            break;

        case VMCALL_DATA_BINARY_UNFORMATTED:
            this->vmcall_data_binary(regs);
            break;

        default:
            throw std::logic_error("unknown vmcall data type");
            break;
    }
}

void
ioctl_driver::vmcall_data_string(registers_type &regs)
{
    auto &&obuffer = std::make_unique<char[]>(VMCALL_OUT_BUFFER_SIZE);
    regs.r08 = reinterpret_cast<decltype(regs.r08)>(obuffer.get());
    regs.r09 = VMCALL_OUT_BUFFER_SIZE;

    vmcall_send_regs(regs);

    switch (regs.r07)
    {
        case VMCALL_DATA_STRING_JSON:

            if (regs.r09 >= VMCALL_OUT_BUFFER_SIZE)
                throw std::out_of_range("return output buffer size out of range");

            std::cout << "received from vmm: \n" << json::parse(std::string(obuffer.get(), regs.r09)).dump(4) << '\n';
            break;

        case VMCALL_DATA_STRING_UNFORMATTED:

            if (regs.r09 >= VMCALL_OUT_BUFFER_SIZE)
                throw std::out_of_range("return output buffer size out of range");

            std::cout << "received from vmm: " << std::string(obuffer.get(), regs.r09) << '\n';
            break;

        default:
            break;
    }
}

void
ioctl_driver::vmcall_data_binary(registers_type &regs)
{
    auto &&ifile_buffer = m_file->read_binary(m_clp->ifile());
    auto &&ofile_buffer = file::binary_data(VMCALL_OUT_BUFFER_SIZE);
    regs.r05 = reinterpret_cast<decltype(regs.r05)>(ifile_buffer.data());
    regs.r06 = ifile_buffer.size();
    regs.r08 = reinterpret_cast<decltype(regs.r08)>(ofile_buffer.data());
    regs.r09 = VMCALL_OUT_BUFFER_SIZE;

    vmcall_send_regs(regs);

    switch (regs.r07)
    {
        case VMCALL_DATA_BINARY_UNFORMATTED:

            if (regs.r09 >= VMCALL_OUT_BUFFER_SIZE)
                throw std::out_of_range("return output buffer size out of range");

            ofile_buffer.resize(regs.r09);
            m_file->write_binary(m_clp->ofile(), ofile_buffer);
            break;

        default:
            break;
    }
}

void
ioctl_driver::vmcall_event(registers_type &regs)
{
    vmcall_send_regs(regs);
    std::cout << "success" << std::endl;
}

void
ioctl_driver::vmcall_unittest(registers_type &regs)
{
    vmcall_send_regs(regs);
    std::cout << "\033[1;36m" << std::hex << "0x" << regs.r02 << std::dec << ":\033[1;32m passed\033[0m\n";
}

ioctl_driver::status_type
ioctl_driver::get_status() const
{
    status_type status = -1;
    m_ioctl->call_ioctl_vmm_status(&status);

    return status;
}
<|endoftext|>


<commit_before>int main() {
  return 0;
}
<commit_msg>Add license header to no_op.cc.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// No-op main() to provide a dummy executable target.
int main() {
  return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <ctime>

#include "kapi.hpp"
#include "libjson/libjson.h"

using namespace std;
using namespace Kraken;

//------------------------------------------------------------------------------
// deals with Kraken trades:
struct Trade {
   double price, volume;
   time_t time;
   char order;

   Trade(JSONNode node) {
      price  = node[0].as_float();
      volume = node[1].as_float();
      time   = node[2].as_int();
      order  = node[3].as_string()[0];
   }
};

//------------------------------------------------------------------------------
// prints out a kraken trade:
ostream& operator<<(ostream& os, const Trade& t)
{
   return os << '"'
	     << t.time << "\",\""
	     << t.order << "\",\""
	     << fixed
	     << setprecision(5) << t.price << "\",\""
	     << setprecision(9) << t.volume << '"';
}

//------------------------------------------------------------------------------
// helper types to map time to a group of trades:
typedef vector<Trade> Period;
typedef map<time_t,Period> Period_map;

//------------------------------------------------------------------------------
// deal with candlesticks:
struct Candlestick {
   double open, close, low, high;
   double volume;
   time_t time;
};

//------------------------------------------------------------------------------
struct HA_Candlestick : public Candlestick {

   // create a candlestick from current period
   HA_Candlestick(const Candlestick& curr)
   {
      time = curr.time;
      volume = curr.volume;
      close =  (curr.open + curr.close + curr.low + curr.high) / 4;
      open = (curr.open + curr.close) / 2;
      low = min(curr.low, min(open, close));
      high = max(curr.high, max(open, close));
   }

   // create a HA candlestick from current period
   // and WITH a prior HA candlestick
   HA_Candlestick(const Candlestick& curr, const HA_Candlestick& prior)
   {
      time = curr.time;
      volume = curr.volume;
      close =  (curr.open + curr.close + curr.low + curr.high) / 4;
      open = (prior.open + prior.close) / 2;
      low = min(curr.low, min(open, close));
      high = max(curr.high, max(open, close));
   }
};

//------------------------------------------------------------------------------
// prints out a Candlestick
ostream& operator<<(ostream& os, const Candlestick& c)
{
   struct tm timeinfo;
   localtime_r(&c.time, &timeinfo);

   return os << c.time << ','
	     << fixed << setprecision(5)
	     << c.open << ','
	     << c.high << ','
	     << c.low << ','
	     << c.close << ','
	     << setprecision(9)
	     << c.volume;
}

//------------------------------------------------------------------------------
// downloads recent trades:
string recent_trades(const KAPI& k, const KAPI::Input& i, vector<Trade>& v)
{
   string json_data = k.public_method("Trades", i);
   JSONNode root = libjson::parse(json_data);
   //cout << json_data << endl;

   // throw an exception if there are errors in the JSON response
   if (!root.at("error").empty()) {
      std::ostringstream oss;
      oss << "Kraken response contains errors: ";

      // append errors to output string stream
      for (auto it = root["error"].begin(); it != root["error"].end(); ++it)
	 oss << endl << " * " << libjson::to_std_string(it->as_string());

      throw runtime_error(oss.str());
   }

   // throw an exception if result is empty
   if (root.at("result").empty()) {
      throw runtime_error("Kraken response doesn't contain result data");
   }

   const string& pair = i.at("pair");

   JSONNode& result = root["result"];
   JSONNode& result_pair = result.at(pair);

   vector<Trade> output;
   for (JSONNode::iterator it = result_pair.begin();
	it != result_pair.end(); ++it)
      output.push_back(Trade(*it));

   output.swap(v);
   return libjson::to_std_string( result.at("last").as_string() );
}

//------------------------------------------------------------------------------
// fills a candlestick vector grouping trades by time:
void group_by_time(const vector<Trade>& trades,
		   const time_t step,
		   vector<Candlestick>& candlesticks)
{
   vector<Trade>::const_iterator it = trades.begin();

   while (it != trades.end()) {
      Candlestick period;
      period.volume = 0;
      period.open = it->price;
      period.low = it->price;
      period.high = it->price;

      // the period time
      period.time = it->time - (it->time % step);

      while (it != trades.end() && it->time < (period.time+step)) {
	 // the lowest price
	 if (it->price < period.low)
	    period.low = it->price;

	 // the highest price
	 if (it->price > period.high)
	    period.high = it->price;

	 // sum volumes
	 period.volume += it->volume;

	 // last price is close time
	 period.close = it->price;

	 // next element
	 it++;
      }

      // store period
      candlesticks.push_back(period);

      // next group
   }
}

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

int main(int argc, char* argv[])
{
   try {
      time_t step = 600; // by default 10 minutes

      //
      // usage: prog <pair> [seconds]
      //

      KAPI::Input input;
      input["since"] = "0";

      switch (argc) {
      case 3:
	 istringstream(argv[2]) >> step;
      case 2:
	 input["pair"] = std::string(argv[1]);
	 break;
      default:
	 throw std::runtime_error("wrong number of arguments");
      };

      // initialize kraken lib's resources:
      Kraken::initialize();
      KAPI kapi;

      std::vector<Trade> trades;
      std::vector<Candlestick> candlesticks;

      string last = recent_trades(kapi, input, trades);

      // group trades by time
      group_by_time(trades, step, candlesticks);

      if (!candlesticks.empty()) {
	 auto it = candlesticks.cbegin();
	 HA_Candlestick ha(*it);
	 cout << ha << endl;

	 for (++it; it != candlesticks.cend(); ++it) {
	    ha = HA_Candlestick(*it, ha);
	    cout << ha << endl;
	 }
      }
   }
   catch(exception& e) {
      cerr << "Error: " << e.what() << endl;
   }
   catch(...) {
      cerr << "Unknow exception." << endl;
   }

   curl_global_cleanup();
   return 0;
}
<commit_msg>added new parameter to kph<commit_after>#include <iostream>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <ctime>

#include "kapi.hpp"
#include "libjson/libjson.h"

using namespace std;
using namespace Kraken;

//------------------------------------------------------------------------------
// deals with Kraken trades:
struct Trade {
   double price, volume;
   time_t time;
   char order;

   Trade(JSONNode node) {
      price  = node[0].as_float();
      volume = node[1].as_float();
      time   = node[2].as_int();
      order  = node[3].as_string()[0];
   }
};

//------------------------------------------------------------------------------
// prints out a kraken trade:
ostream& operator<<(ostream& os, const Trade& t)
{
   return os << '"'
	     << t.time << "\",\""
	     << t.order << "\",\""
	     << fixed
	     << setprecision(5) << t.price << "\",\""
	     << setprecision(9) << t.volume << '"';
}

//------------------------------------------------------------------------------
// helper types to map time to a group of trades:
typedef vector<Trade> Period;
typedef map<time_t,Period> Period_map;

//------------------------------------------------------------------------------
// deal with candlesticks:
struct Candlestick {
   double open, close, low, high;
   double volume;
   time_t time;
};

//------------------------------------------------------------------------------
struct HA_Candlestick : public Candlestick {

   // create a candlestick from current period
   HA_Candlestick(const Candlestick& curr)
   {
      time = curr.time;
      volume = curr.volume;
      close =  (curr.open + curr.close + curr.low + curr.high) / 4;
      open = (curr.open + curr.close) / 2;
      low = min(curr.low, min(open, close));
      high = max(curr.high, max(open, close));
   }

   // create a HA candlestick from current period
   // and WITH a prior HA candlestick
   HA_Candlestick(const Candlestick& curr, const HA_Candlestick& prior)
   {
      time = curr.time;
      volume = curr.volume;
      close =  (curr.open + curr.close + curr.low + curr.high) / 4;
      open = (prior.open + prior.close) / 2;
      low = min(curr.low, min(open, close));
      high = max(curr.high, max(open, close));
   }
};

//------------------------------------------------------------------------------
// prints out a Candlestick
ostream& operator<<(ostream& os, const Candlestick& c)
{
   struct tm timeinfo;
   localtime_r(&c.time, &timeinfo);

   return os << c.time << ','
	     << fixed << setprecision(5)
	     << c.open << ','
	     << c.high << ','
	     << c.low << ','
	     << c.close << ','
	     << setprecision(9)
	     << c.volume;
}

//------------------------------------------------------------------------------
// downloads recent trades:
string recent_trades(const KAPI& k, const KAPI::Input& i, vector<Trade>& v)
{
   string json_data = k.public_method("Trades", i);
   JSONNode root = libjson::parse(json_data);
   //cout << json_data << endl;

   // throw an exception if there are errors in the JSON response
   if (!root.at("error").empty()) {
      std::ostringstream oss;
      oss << "Kraken response contains errors: ";

      // append errors to output string stream
      for (auto it = root["error"].begin(); it != root["error"].end(); ++it)
	 oss << endl << " * " << libjson::to_std_string(it->as_string());

      throw runtime_error(oss.str());
   }

   // throw an exception if result is empty
   if (root.at("result").empty()) {
      throw runtime_error("Kraken response doesn't contain result data");
   }

   const string& pair = i.at("pair");

   JSONNode& result = root["result"];
   JSONNode& result_pair = result.at(pair);

   vector<Trade> output;
   for (JSONNode::iterator it = result_pair.begin();
	it != result_pair.end(); ++it)
      output.push_back(Trade(*it));

   output.swap(v);
   return libjson::to_std_string( result.at("last").as_string() );
}

//------------------------------------------------------------------------------
// fills a candlestick vector grouping trades by time:
void group_by_time(const vector<Trade>& trades,
		   const time_t step,
		   vector<Candlestick>& candlesticks)
{
   vector<Trade>::const_iterator it = trades.begin();

   while (it != trades.end()) {
      Candlestick period;
      period.volume = 0;
      period.open = it->price;
      period.low = it->price;
      period.high = it->price;

      // the period time
      period.time = it->time - (it->time % step);

      while (it != trades.end() && it->time < (period.time+step)) {
	 // the lowest price
	 if (it->price < period.low)
	    period.low = it->price;

	 // the highest price
	 if (it->price > period.high)
	    period.high = it->price;

	 // sum volumes
	 period.volume += it->volume;

	 // last price is close time
	 period.close = it->price;

	 // next element
	 it++;
      }

      // store period
      candlesticks.push_back(period);

      // next group
   }
}

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

int main(int argc, char* argv[])
{
   try {
      time_t step = 15*60; // by default 15 minutes
      time_t last = 24*60*60; // by default last 24 hours

      //
      // usage: prog <pair> [seconds] [last]
      //
      // kph prints out the price history of the <pair> in
      // the [last] number of seconds. The trade data is
      // showed as candlesticks grouped in periods of
      // [seconds] seconds.
      //

      KAPI::Input input;
      input["since"] = "0";

      switch (argc) {
      case 4:
	 istringstream(argv[3]) >> last;
      case 3:
	 istringstream(argv[2]) >> step;
      case 2:
	 input["pair"] = std::string(argv[1]);
	 break;
      default:
	 throw std::runtime_error("wrong number of arguments");
      };

      // initialize kraken lib's resources:
      Kraken::initialize();
      KAPI kapi;

      std::vector<Trade> trades;
      std::vector<Candlestick> candlesticks;

      recent_trades(kapi, input, trades);

      // group trades by time
      group_by_time(trades, step, candlesticks);

      if (!candlesticks.empty()) {
	 // print candlestick after this threshold
	 time_t thresh = candlesticks.back().time - last;

	 auto it = candlesticks.cbegin();
	 HA_Candlestick ha(*it);
	 if (ha.time > thresh)
	    cout << ha << endl;

	 for (++it; it != candlesticks.cend(); ++it) {
	    ha = HA_Candlestick(*it, ha);
	    if (ha.time >= thresh)
	       cout << ha << endl;
	 }
      }
   }
   catch(exception& e) {
      cerr << "Error: " << e.what() << endl;
   }
   catch(...) {
      cerr << "Unknow exception." << endl;
   }

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


<commit_before>/* Consider the following continuous optimal control problem:
 *
 * find       q, u, a, lm (fiber length), e (excitation), mult_t
 * minimize   reaction force in knee joint
 * subject to
 *                        adot = f_act(a,e)      activation dynamics
 *       f_equil(q,lm,lmdot,a) = 0               fiber dynamics
 *                        qdot = N u             kinematics
 *            M udot + ~G mult = T + ~J*(F-C)    multi-body dynamics
 *               p(t,q)        = 0               holonomic constraints
 *               v(t,q,u)      = 0               non-holonomic constraints
 *               a(t,q,u,udot) = 0               acceleration-only constraints
 *
 *
 * The discretized problem (no derivatives):
 *
 * find       q_t, u_t, a_t, lm_t (fiber length), e_t (excitation), mult_t
 *            for t in [1, T]
 * minimize   sum (reaction_t)
 * subject to
 *                                (a_t+1-a_t)/h = f_act(a_t,e_t)
 *        f_equil(q_t,lm_t,(lm_t+1-lm_t)/h,a_t) = 0
 *                                (q_t+1-q_t)/h = N u_t
 *                  M (u_t+1-u_t)/h + ~G mult_t = T + ~J*(F-C)
 *                   p(t,q_t)                   = 0
 *                   v(t,q_t,u_t)               = 0
 *                   a(t,q_t,u_t,(u_t+1-u_t)/h) = 0
 *            (for t in [1, T-1])
 */

/* Here is a sketch of how to solve the above problem using a
 * SimTK::OptimizerSystem, if YDotGuess and LambdaGuess (MultiplierGuess)
 * live in the State.
 */
struct Trajectory {
    struct Step {
        State state;
        Vector excitations;
        int i; // Starting index in global vector of unknowns.
        int N; // Number of unknowns in this step.
    };
    std::vector<Step> steps;
};

class DirectCollocationProblem : public SimTK::OptimizerSystem {
public:
    Trajectory createTrajectory(const Vector& x) const {
        Trajectory traj;
        for (int istep = 0; istep < nsteps; ++istep) {
            Step step; step.state = State();
            step.state.updY() = x[indices];
            step.excitations = x[indices];
            step.state.updYDotGuess() = (x[indices+1] - x[indicies])/h;
            step.state.updMultipliersGuess() = x[indices];
            traj.append(step);
        }
        return traj;
    }
    int objectiveFunc(const Vector& x, Real& f) const {
        // Add up reaction on knee over all time.
        Trajectory traj = createTrajectory(x);
        for (const auto& step : traj) {
            model.realizeAcceleration(step.state);
            f += model.getJoint("knee").calcReactionOnParentExpressedInGround(step.state).norm();
        }
    }
    int constraintFunc(const Vector& x, Vector& constraints) const {
        Trajectory traj = createTrajectory(x);
        // Compute implicit diff eqn error and constraint error for all time.
        for (const auto& step : traj) {
            Vector residual, pvaerrs;
            model.realizeAcceleration(step.state);
            constraints(step.i,step.i+step.N) = [step.state.getResidual();
                                                 step.state.getUDotErr()];
        }
    }
};
/* One issue in the above scheme is that "realize" somewhat indicates
 * that the system is consistent; that the constraints are satisfied. You could
 * imagine that "realize" with an implicit form means that one performs a
 * root-solve on the implicit form to solve for a consistent YDot and Lambda.
 * But if the meaning of "realize" is "compute cache entries based on state
 * variables," then that's fine.
 */

/* The alternative OptimizerSystem, if YDotGuess and LambdaGuess do not live
 * in the State.
 */
struct Trajectory {
    struct Step {
        State state;
        Vector excitations;
        Vector yDotGuess; // Need to hold onto guesses separately.
        Vector lambdaGuess;
        int i; // Starting index in global vector of unknowns.
        int N; // Number of unknowns in this step.
    };
    std::vector<Step> steps;
};
class DirectCollocationProblem : public SimTK::OptimizerSystem {
public:
    Trajectory createTrajectory(const Vector& x) const {
        Trajectory traj;
        for (int istep = 0; istep < nsteps; ++istep) {
            Step step; step.state = State();
            step.state.updY() = x[indices];
            step.excitations = x[indices];
            step.yDotGuess = (x[indices+1] - x[indices])/h;
            step.lambdaGuess = x[indices];
            traj.append(step);
        }
        return traj;
    }
    int objectiveFunc(const Vector& x, Real& f) const {
        // Add up reaction on knee over all time.
        Trajectory traj = createTrajectory(x);
        for (const auto& step : traj) {
            Vector_<SpatialVec> allReactionForces;
            // WRONG: model.realizeAcceleration(step.state);
            // WRONG: f += model.getJoint("knee").calcReactionOnParentExpressedInGround(step.state).norm();
            // Must use operator form.
            // TODO this method does not exist yet.
            model.getMatterSubsystem().calcMobilizerReactionForces(step.state,
                    step.yDotGuess, step.lambda?,
                    allReactionForces);
            f += allReactionForces[kneeIndex].norm();
        }
    }
    int constraintFunc(const Vector& x, Vector& constraints) const {
        Trajectory traj = createTrajectory(x);
        // Compute implicit diff eqn error and constraint error for all time.
        for (const auto& step : traj) {
            Vector residual, pvaerrs;
            // Operator.
            model.calcImplicitResidualsAndConstraintErrors(step.state,
                    step.yDotGuess, step.lambdaGuess,
                    residuals, pvaerrs);
            constraints(step.i,step.i+step.N) = [residuals; pvaerrs];
        }
    }
};
<commit_msg>Update pseudoImplicitDifferentialEquations<commit_after>/* Consider the following continuous optimal control problem:
 *
 * find       q, u, a, lm (fiber length), e (excitation), mult_t
 * minimize   reaction force in knee joint
 * subject to
 *                        adot = f_act(a,e)      activation dynamics
 *       f_equil(q,lm,lmdot,a) = 0               fiber dynamics
 *                        qdot = N u             kinematics
 *            M udot + ~G mult = T + ~J*(F-C)    multi-body dynamics
 *               p(t,q)        = 0               holonomic constraints
 *               v(t,q,u)      = 0               non-holonomic constraints
 *               a(t,q,u,udot) = 0               acceleration-only constraints
 *
 *
 * The discretized problem (no derivatives):
 *
 * find       q_t, u_t, a_t, lm_t (fiber length), e_t (excitation), mult_t
 *            for t in [1, T]
 * minimize   sum (reaction_t)
 * subject to
 *                                (a_t+1-a_t)/h = f_act(a_t,e_t)
 *        f_equil(q_t,lm_t,(lm_t+1-lm_t)/h,a_t) = 0
 *                                (q_t+1-q_t)/h = N u_t
 *                  M (u_t+1-u_t)/h + ~G mult_t = T + ~J*(F-C)
 *                   p(t,q_t)                   = 0
 *                   v(t,q_t,u_t)               = 0
 *                   a(t,q_t,u_t,(u_t+1-u_t)/h) = 0
 *            (for t in [1, T-1])
 */

/* Here is a sketch of how to solve the above problem using a
 * SimTK::OptimizerSystem, if YDotGuess and LambdaGuess (MultiplierGuess)
 * live in the State.
 */
struct Trajectory {
    struct Step {
        State state;
        Vector excitations;
        int i; // Starting index in global vector of unknowns.
        int N; // Number of unknowns in this step.
    };
    std::vector<Step> steps;
};

class DirectCollocationProblem : public SimTK::OptimizerSystem {
public:
    Trajectory createTrajectory(const Vector& x) const {
        Trajectory traj;
        for (int istep = 0; istep < nsteps; ++istep) {
            Step step; step.state = State();
            step.state.updY() = x[indices];
            step.excitations = x[indices];
            step.state.updYDotGuess() = (x[indices+1] - x[indicies])/h;
            step.state.updMultipliersGuess() = x[indices];
            traj.append(step);
        }
        return traj;
    }
    int objectiveFunc(const Vector& x, Real& f) const {
        // Add up reaction on knee over all time.
        Trajectory traj = createTrajectory(x);
        for (const auto& step : traj) {
            model.realizeAcceleration(step.state);
            f += model.getJoint("knee").calcReactionOnParentExpressedInGround(step.state).norm();
        }
    }
    int constraintFunc(const Vector& x, Vector& constraints) const {
        Trajectory traj = createTrajectory(x);
        // Compute implicit diff eqn error and constraint error for all time.
        for (const auto& step : traj) {
            Vector residual, pvaerrs;
            model.realizeAcceleration(step.state);
            constraints(step.i,step.i+step.N) = [step.state.getResidual();
                                                 step.state.getUDotErr()];
        }
    }
};
/* One issue in the above scheme is that "realize" somewhat indicates
 * that the system is consistent; that the constraints are satisfied. You could
 * imagine that "realize" with an implicit form means that one performs a
 * root-solve on the implicit form to solve for a consistent YDot and Lambda.
 * But if the meaning of "realize" is "compute cache entries based on state
 * variables," then that's fine.
 */

/* The alternative OptimizerSystem, if YDotGuess and LambdaGuess do not live
 * in the State.
 */
struct Trajectory {
    struct Step {
        State state;
        Vector excitations;
        Vector yDotGuess; // Need to hold onto guesses separately.
        Vector lambdaGuess;
        int i; // Starting index in global vector of unknowns.
        int N; // Number of unknowns in this step.
    };
    std::vector<Step> steps;
};
class DirectCollocationProblem : public SimTK::OptimizerSystem {
public:
    Trajectory createTrajectory(const Vector& x) const {
        Trajectory traj;
        for (int istep = 0; istep < nsteps; ++istep) {
            Step step;
            step.state = State();
            step.state.updY() = x[indices];
            step.excitations = x[indices];
            step.yDotGuess = (x[indices+1] - x[indices])/h;
            step.lambdaGuess = x[indices];
            traj.append(step);
        }
        return traj;
    }
    int objectiveFunc(const Vector& x, Real& f) const {
        // Add up reaction on knee over all time.
        Trajectory traj = createTrajectory(x);
        for (const auto& step : traj) {
            Vector_<SpatialVec> allReactionForces;
            // WRONG: model.realizeAcceleration(step.state);
            // WRONG: f += model.getJoint("knee").calcReactionOnParentExpressedInGround(step.state).norm();
            // Must use operator form.
            // TODO this method does not exist yet.
            model.getMatterSubsystem().calcMobilizerReactionForces(step.state,
                    step.yDotGuess, step.lambda,
                    allReactionForces);
            f += allReactionForces[kneeIndex].norm();
        }
    }
    int constraintFunc(const Vector& x, Vector& constraints) const {
        Trajectory traj = createTrajectory(x);
        // Compute implicit diff eqn error and constraint error for all time.
        for (const auto& step : traj) {
            Vector residual, pvaerrs;
            // Operator.
            model.calcImplicitResidualsAndConstraintErrors(step.state,
                    step.yDotGuess, step.lambdaGuess,
                    residuals, pvaerrs);
            constraints(step.i,step.i+step.N) = [residuals; pvaerrs];
        }
    }
};
<|endoftext|>