<commit_before>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <rpc/rawtransaction_util.h>

#include <coins.h>
#include <core_io.h>
#include <key_io.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <rpc/request.h>
#include <rpc/util.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <tinyformat.h>
#include <univalue.h>
#include <util/rbf.h>
#include <util/strencodings.h>

CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime)
{
    if (inputs_in.isNull() || outputs_in.isNull())
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");

    UniValue inputs = inputs_in.get_array();
    const bool outputs_is_obj = outputs_in.isObject();
    UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();

    CMutableTransaction rawTx;

    if (!locktime.isNull()) {
        int64_t nLockTime = locktime.get_int64();
        if (nLockTime < 0 || nLockTime > LOCKTIME_MAX)
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
        rawTx.nLockTime = nLockTime;
    }

    for (unsigned int idx = 0; idx < inputs.size(); idx++) {
        const UniValue& input = inputs[idx];
        const UniValue& o = input.get_obj();

        uint256 txid = ParseHashO(o, "txid");

        const UniValue& vout_v = find_value(o, "vout");
        if (!vout_v.isNum())
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
        int nOutput = vout_v.get_int();
        if (nOutput < 0)
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");

        uint32_t nSequence;
        if (rawTx.nLockTime) {
            nSequence = CTxIn::SEQUENCE_FINAL - 1;
        } else {
            nSequence = CTxIn::SEQUENCE_FINAL;
        }

        // set the sequence number if passed in the parameters object
        const UniValue& sequenceObj = find_value(o, "sequence");
        if (sequenceObj.isNum()) {
            int64_t seqNr64 = sequenceObj.get_int64();
            if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
            } else {
                nSequence = (uint32_t)seqNr64;
            }
        }

        CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);

        rawTx.vin.push_back(in);
    }

    if (!outputs_is_obj) {
        // Translate array of key-value pairs into dict
        UniValue outputs_dict = UniValue(UniValue::VOBJ);
        for (size_t i = 0; i < outputs.size(); ++i) {
            const UniValue& output = outputs[i];
            if (!output.isObject()) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair not an object as expected");
            }
            if (output.size() != 1) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair must contain exactly one key");
            }
            outputs_dict.pushKVs(output);
        }
        outputs = std::move(outputs_dict);
    }

    // Duplicate checking
    std::set<CTxDestination> destinations;
    bool has_data{false};

    for (const std::string& name_ : outputs.getKeys()) {
        if (name_ == "data") {
            if (has_data) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, duplicate key: data");
            }
            has_data = true;
            std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");

            CTxOut out(0, CScript() << OP_RETURN << data);
            rawTx.vout.push_back(out);
        } else {
            CTxDestination destination = DecodeDestination(name_);
            if (!IsValidDestination(destination)) {
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
            }

            if (!destinations.insert(destination).second) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
            }

            CScript scriptPubKey = GetScriptForDestination(destination);
            CAmount nAmount = AmountFromValue(outputs[name_]);

            CTxOut out(nAmount, scriptPubKey);
            rawTx.vout.push_back(out);
        }
    }

    return rawTx;
}

/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
{
    UniValue entry(UniValue::VOBJ);
    entry.pushKV("txid", txin.prevout.hash.ToString());
    entry.pushKV("vout", (uint64_t)txin.prevout.n);
    UniValue witness(UniValue::VARR);
    for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
        witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
    }
    entry.pushKV("witness", witness);
    entry.pushKV("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
    entry.pushKV("sequence", (uint64_t)txin.nSequence);
    entry.pushKV("error", strMessage);
    vErrorsRet.push_back(entry);
}

void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins)
{
    if (!prevTxsUnival.isNull()) {
        UniValue prevTxs = prevTxsUnival.get_array();
        for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
            const UniValue& p = prevTxs[idx];
            if (!p.isObject()) {
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
            }

            UniValue prevOut = p.get_obj();

            RPCTypeCheckObj(prevOut,
                {
                    {"txid", UniValueType(UniValue::VSTR)},
                    {"vout", UniValueType(UniValue::VNUM)},
                    {"scriptPubKey", UniValueType(UniValue::VSTR)},
                });

            uint256 txid = ParseHashO(prevOut, "txid");

            int nOut = find_value(prevOut, "vout").get_int();
            if (nOut < 0) {
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
            }

            COutPoint out(txid, nOut);
            std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
            CScript scriptPubKey(pkData.begin(), pkData.end());

            {
                auto coin = coins.find(out);
                if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
                    std::string err("Previous output scriptPubKey mismatch:\n");
                    err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
                        ScriptToAsmStr(scriptPubKey);
                    throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
                }
                Coin newcoin;
                newcoin.out.scriptPubKey = scriptPubKey;
                newcoin.out.nValue = MAX_MONEY;
                if (prevOut.exists("amount")) {
                    newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
                }
                newcoin.nHeight = 1;
                coins[out] = std::move(newcoin);
            }

            // if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed
            const bool is_p2sh = scriptPubKey.IsPayToScriptHash();
            const bool is_p2wsh = scriptPubKey.IsPayToWitnessScriptHash();
            if (keystore && (is_p2sh || is_p2wsh)) {
                RPCTypeCheckObj(prevOut,
                    {
                        {"redeemScript", UniValueType(UniValue::VSTR)},
                        {"witnessScript", UniValueType(UniValue::VSTR)},
                    }, true);
                UniValue rs = find_value(prevOut, "redeemScript");
                UniValue ws = find_value(prevOut, "witnessScript");
                if (rs.isNull() && ws.isNull()) {
                    throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing redeemScript/witnessScript");
                }

                // work from witnessScript when possible
                std::vector<unsigned char> scriptData(!ws.isNull() ? ParseHexV(ws, "witnessScript") : ParseHexV(rs, "redeemScript"));
                CScript script(scriptData.begin(), scriptData.end());
                keystore->AddCScript(script);
                // Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
                // This is done for redeemScript only for compatibility, it is encouraged to use the explicit witnessScript field instead.
                CScript witness_output_script{GetScriptForWitness(script)};
                keystore->AddCScript(witness_output_script);

                if (!ws.isNull() && !rs.isNull()) {
                    // if both witnessScript and redeemScript are provided,
                    // they should either be the same (for backwards compat),
                    // or the redeemScript should be the encoded form of
                    // the witnessScript (ie, for p2sh-p2wsh)
                    if (ws.get_str() != rs.get_str()) {
                        std::vector<unsigned char> redeemScriptData(ParseHexV(rs, "redeemScript"));
                        CScript redeemScript(redeemScriptData.begin(), redeemScriptData.end());
                        if (redeemScript != witness_output_script) {
                            throw JSONRPCError(RPC_INVALID_PARAMETER, "redeemScript does not correspond to witnessScript");
                        }
                    }
                }

                if (is_p2sh) {
                    const CTxDestination p2sh{ScriptHash(script)};
                    const CTxDestination p2sh_p2wsh{ScriptHash(witness_output_script)};
                    if (scriptPubKey == GetScriptForDestination(p2sh)) {
                        // traditional p2sh; arguably an error if
                        // we got here with rs.IsNull(), because
                        // that means the p2sh script was specified
                        // via witnessScript param, but for now
                        // we'll just quietly accept it
                    } else if (scriptPubKey == GetScriptForDestination(p2sh_p2wsh)) {
                        // p2wsh encoded as p2sh; ideally the witness
                        // script was specified in the witnessScript
                        // param, but also support specifying it via
                        // redeemScript param for backwards compat
                        // (in which case ws.IsNull() == true)
                    } else {
                        // otherwise, can't generate scriptPubKey from
                        // either script, so we got unusable parameters
                        throw JSONRPCError(RPC_INVALID_PARAMETER, "redeemScript/witnessScript does not match scriptPubKey");
                    }
                } else if (is_p2wsh) {
                    // plain p2wsh; could throw an error if script
                    // was specified by redeemScript rather than
                    // witnessScript (ie, ws.IsNull() == true), but
                    // accept it for backwards compat
                    const CTxDestination p2wsh{WitnessV0ScriptHash(script)};
                    if (scriptPubKey != GetScriptForDestination(p2wsh)) {
                        throw JSONRPCError(RPC_INVALID_PARAMETER, "redeemScript/witnessScript does not match scriptPubKey");
                    }
                }
            }
        }
    }
}

UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, std::map<COutPoint, Coin>& coins, const UniValue& hashType)
{
    int nHashType = ParseSighashString(hashType);

    bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);

    // Script verification errors
    UniValue vErrors(UniValue::VARR);

    // Use CTransaction for the constant parts of the
    // transaction to avoid rehashing.
    const CTransaction txConst(mtx);
    // Sign what we can:
    for (unsigned int i = 0; i < mtx.vin.size(); i++) {
        CTxIn& txin = mtx.vin[i];
        auto coin = coins.find(txin.prevout);
        if (coin == coins.end() || coin->second.IsSpent()) {
            TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
            continue;
        }
        const CScript& prevPubKey = coin->second.out.scriptPubKey;
        const CAmount& amount = coin->second.out.nValue;

        SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
        // Only sign SIGHASH_SINGLE if there's a corresponding output:
        if (!fHashSingle || (i < mtx.vout.size())) {
            ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
        }

        UpdateInput(txin, sigdata);

        // amount must be specified for valid segwit signature
        if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
            throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString()));
        }

        ScriptError serror = SCRIPT_ERR_OK;
        if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
            if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
                // Unable to sign input and verification failed (possible attempt to partially sign).
                TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
            } else {
                TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
            }
        }
    }
    bool fComplete = vErrors.empty();

    UniValue result(UniValue::VOBJ);
    result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
    result.pushKV("complete", fComplete);
    if (!vErrors.empty()) {
        result.pushKV("errors", vErrors);
    }

    return result;
}
<commit_msg>signrawtransaction*: improve error for partial signing<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <rpc/rawtransaction_util.h>

#include <coins.h>
#include <core_io.h>
#include <key_io.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <rpc/request.h>
#include <rpc/util.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <tinyformat.h>
#include <univalue.h>
#include <util/rbf.h>
#include <util/strencodings.h>

CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime)
{
    if (inputs_in.isNull() || outputs_in.isNull())
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");

    UniValue inputs = inputs_in.get_array();
    const bool outputs_is_obj = outputs_in.isObject();
    UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();

    CMutableTransaction rawTx;

    if (!locktime.isNull()) {
        int64_t nLockTime = locktime.get_int64();
        if (nLockTime < 0 || nLockTime > LOCKTIME_MAX)
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
        rawTx.nLockTime = nLockTime;
    }

    for (unsigned int idx = 0; idx < inputs.size(); idx++) {
        const UniValue& input = inputs[idx];
        const UniValue& o = input.get_obj();

        uint256 txid = ParseHashO(o, "txid");

        const UniValue& vout_v = find_value(o, "vout");
        if (!vout_v.isNum())
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
        int nOutput = vout_v.get_int();
        if (nOutput < 0)
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");

        uint32_t nSequence;
        if (rawTx.nLockTime) {
            nSequence = CTxIn::SEQUENCE_FINAL - 1;
        } else {
            nSequence = CTxIn::SEQUENCE_FINAL;
        }

        // set the sequence number if passed in the parameters object
        const UniValue& sequenceObj = find_value(o, "sequence");
        if (sequenceObj.isNum()) {
            int64_t seqNr64 = sequenceObj.get_int64();
            if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
            } else {
                nSequence = (uint32_t)seqNr64;
            }
        }

        CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);

        rawTx.vin.push_back(in);
    }

    if (!outputs_is_obj) {
        // Translate array of key-value pairs into dict
        UniValue outputs_dict = UniValue(UniValue::VOBJ);
        for (size_t i = 0; i < outputs.size(); ++i) {
            const UniValue& output = outputs[i];
            if (!output.isObject()) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair not an object as expected");
            }
            if (output.size() != 1) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair must contain exactly one key");
            }
            outputs_dict.pushKVs(output);
        }
        outputs = std::move(outputs_dict);
    }

    // Duplicate checking
    std::set<CTxDestination> destinations;
    bool has_data{false};

    for (const std::string& name_ : outputs.getKeys()) {
        if (name_ == "data") {
            if (has_data) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, duplicate key: data");
            }
            has_data = true;
            std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");

            CTxOut out(0, CScript() << OP_RETURN << data);
            rawTx.vout.push_back(out);
        } else {
            CTxDestination destination = DecodeDestination(name_);
            if (!IsValidDestination(destination)) {
                throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_);
            }

            if (!destinations.insert(destination).second) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
            }

            CScript scriptPubKey = GetScriptForDestination(destination);
            CAmount nAmount = AmountFromValue(outputs[name_]);

            CTxOut out(nAmount, scriptPubKey);
            rawTx.vout.push_back(out);
        }
    }

    return rawTx;
}

/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
{
    UniValue entry(UniValue::VOBJ);
    entry.pushKV("txid", txin.prevout.hash.ToString());
    entry.pushKV("vout", (uint64_t)txin.prevout.n);
    UniValue witness(UniValue::VARR);
    for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
        witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
    }
    entry.pushKV("witness", witness);
    entry.pushKV("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
    entry.pushKV("sequence", (uint64_t)txin.nSequence);
    entry.pushKV("error", strMessage);
    vErrorsRet.push_back(entry);
}

void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins)
{
    if (!prevTxsUnival.isNull()) {
        UniValue prevTxs = prevTxsUnival.get_array();
        for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
            const UniValue& p = prevTxs[idx];
            if (!p.isObject()) {
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
            }

            UniValue prevOut = p.get_obj();

            RPCTypeCheckObj(prevOut,
                {
                    {"txid", UniValueType(UniValue::VSTR)},
                    {"vout", UniValueType(UniValue::VNUM)},
                    {"scriptPubKey", UniValueType(UniValue::VSTR)},
                });

            uint256 txid = ParseHashO(prevOut, "txid");

            int nOut = find_value(prevOut, "vout").get_int();
            if (nOut < 0) {
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
            }

            COutPoint out(txid, nOut);
            std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
            CScript scriptPubKey(pkData.begin(), pkData.end());

            {
                auto coin = coins.find(out);
                if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
                    std::string err("Previous output scriptPubKey mismatch:\n");
                    err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
                        ScriptToAsmStr(scriptPubKey);
                    throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
                }
                Coin newcoin;
                newcoin.out.scriptPubKey = scriptPubKey;
                newcoin.out.nValue = MAX_MONEY;
                if (prevOut.exists("amount")) {
                    newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
                }
                newcoin.nHeight = 1;
                coins[out] = std::move(newcoin);
            }

            // if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed
            const bool is_p2sh = scriptPubKey.IsPayToScriptHash();
            const bool is_p2wsh = scriptPubKey.IsPayToWitnessScriptHash();
            if (keystore && (is_p2sh || is_p2wsh)) {
                RPCTypeCheckObj(prevOut,
                    {
                        {"redeemScript", UniValueType(UniValue::VSTR)},
                        {"witnessScript", UniValueType(UniValue::VSTR)},
                    }, true);
                UniValue rs = find_value(prevOut, "redeemScript");
                UniValue ws = find_value(prevOut, "witnessScript");
                if (rs.isNull() && ws.isNull()) {
                    throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing redeemScript/witnessScript");
                }

                // work from witnessScript when possible
                std::vector<unsigned char> scriptData(!ws.isNull() ? ParseHexV(ws, "witnessScript") : ParseHexV(rs, "redeemScript"));
                CScript script(scriptData.begin(), scriptData.end());
                keystore->AddCScript(script);
                // Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
                // This is done for redeemScript only for compatibility, it is encouraged to use the explicit witnessScript field instead.
                CScript witness_output_script{GetScriptForWitness(script)};
                keystore->AddCScript(witness_output_script);

                if (!ws.isNull() && !rs.isNull()) {
                    // if both witnessScript and redeemScript are provided,
                    // they should either be the same (for backwards compat),
                    // or the redeemScript should be the encoded form of
                    // the witnessScript (ie, for p2sh-p2wsh)
                    if (ws.get_str() != rs.get_str()) {
                        std::vector<unsigned char> redeemScriptData(ParseHexV(rs, "redeemScript"));
                        CScript redeemScript(redeemScriptData.begin(), redeemScriptData.end());
                        if (redeemScript != witness_output_script) {
                            throw JSONRPCError(RPC_INVALID_PARAMETER, "redeemScript does not correspond to witnessScript");
                        }
                    }
                }

                if (is_p2sh) {
                    const CTxDestination p2sh{ScriptHash(script)};
                    const CTxDestination p2sh_p2wsh{ScriptHash(witness_output_script)};
                    if (scriptPubKey == GetScriptForDestination(p2sh)) {
                        // traditional p2sh; arguably an error if
                        // we got here with rs.IsNull(), because
                        // that means the p2sh script was specified
                        // via witnessScript param, but for now
                        // we'll just quietly accept it
                    } else if (scriptPubKey == GetScriptForDestination(p2sh_p2wsh)) {
                        // p2wsh encoded as p2sh; ideally the witness
                        // script was specified in the witnessScript
                        // param, but also support specifying it via
                        // redeemScript param for backwards compat
                        // (in which case ws.IsNull() == true)
                    } else {
                        // otherwise, can't generate scriptPubKey from
                        // either script, so we got unusable parameters
                        throw JSONRPCError(RPC_INVALID_PARAMETER, "redeemScript/witnessScript does not match scriptPubKey");
                    }
                } else if (is_p2wsh) {
                    // plain p2wsh; could throw an error if script
                    // was specified by redeemScript rather than
                    // witnessScript (ie, ws.IsNull() == true), but
                    // accept it for backwards compat
                    const CTxDestination p2wsh{WitnessV0ScriptHash(script)};
                    if (scriptPubKey != GetScriptForDestination(p2wsh)) {
                        throw JSONRPCError(RPC_INVALID_PARAMETER, "redeemScript/witnessScript does not match scriptPubKey");
                    }
                }
            }
        }
    }
}

UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, std::map<COutPoint, Coin>& coins, const UniValue& hashType)
{
    int nHashType = ParseSighashString(hashType);

    bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);

    // Script verification errors
    UniValue vErrors(UniValue::VARR);

    // Use CTransaction for the constant parts of the
    // transaction to avoid rehashing.
    const CTransaction txConst(mtx);
    // Sign what we can:
    for (unsigned int i = 0; i < mtx.vin.size(); i++) {
        CTxIn& txin = mtx.vin[i];
        auto coin = coins.find(txin.prevout);
        if (coin == coins.end() || coin->second.IsSpent()) {
            TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
            continue;
        }
        const CScript& prevPubKey = coin->second.out.scriptPubKey;
        const CAmount& amount = coin->second.out.nValue;

        SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
        // Only sign SIGHASH_SINGLE if there's a corresponding output:
        if (!fHashSingle || (i < mtx.vout.size())) {
            ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
        }

        UpdateInput(txin, sigdata);

        // amount must be specified for valid segwit signature
        if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
            throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin->second.out.ToString()));
        }

        ScriptError serror = SCRIPT_ERR_OK;
        if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
            if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
                // Unable to sign input and verification failed (possible attempt to partially sign).
                TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
            } else if (serror == SCRIPT_ERR_SIG_NULLFAIL) {
                // Verification failed (possibly due to insufficient signatures).
                TxInErrorToJSON(txin, vErrors, "CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)");
            } else {
                TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
            }
        }
    }
    bool fComplete = vErrors.empty();

    UniValue result(UniValue::VOBJ);
    result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
    result.pushKV("complete", fComplete);
    if (!vErrors.empty()) {
        result.pushKV("errors", vErrors);
    }

    return result;
}
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

#include "tensorflow/compiler/xla/service/rng_bit_generator_expander.h"

#include "tensorflow/compiler/xla/client/lib/prng.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/service/hlo_casting_utils.h"
#include "tensorflow/compiler/xla/service/hlo_computation.h"
#include "tensorflow/compiler/xla/service/hlo_instruction.h"
#include "tensorflow/compiler/xla/service/hlo_instructions.h"
#include "tensorflow/compiler/xla/service/hlo_module.h"
#include "tensorflow/compiler/xla/shape.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/stream_executor/lib/statusor.h"

namespace xla {
namespace {

StatusOr<XlaOp> GetPhiloxStateOp(XlaOp input_state) {
  TF_ASSIGN_OR_RETURN(const Shape* shape,
                      input_state.builder()->GetShapePtr(input_state));
  if (shape->dimensions(0) >= 3) {
    return Slice(input_state, {1}, {3}, {1});
  }
  return Rev(input_state, {0});
}

}  // namespace

bool RngBitGeneratorExpander::InstructionMatchesPattern(
    HloInstruction* instruction) {
  return instruction->opcode() == HloOpcode::kRngBitGenerator;
}

StatusOr<HloComputation*> RngBitGeneratorExpander::GetGeneratorComputation(
    const Shape& data_shape, const Shape& state_shape,
    RandomAlgorithm algorithm, HloModule* module) {
  RngGeneratorKey cache_key{data_shape, state_shape, algorithm, module};
  auto it = computation_cache_.find(cache_key);
  if (it != computation_cache_.end()) {
    return it->second;
  }

  XlaBuilder builder("rng");
  XlaOp state_param = Parameter(&builder, 0, state_shape, "state");
  XlaOp key_op = Reshape(Slice(state_param, {0}, {1}, {1}), {});
  XlaOp state_op;

  BitGeneratorTy generator = nullptr;
  switch (algorithm) {
    case RandomAlgorithm::RNG_THREE_FRY:
      generator = ThreeFryBitGenerator;
      state_op = Slice(state_param, {1}, {2}, {1});
      break;
    case RandomAlgorithm::RNG_PHILOX: {
      generator = PhiloxBitGenerator;
      TF_ASSIGN_OR_RETURN(state_op, GetPhiloxStateOp(state_param));
      break;
    }
    default:
      return Unimplemented("Unsupported random algorthm: %s",
                           RandomAlgorithm_Name(algorithm));
  }

  RngOutput output = generator(key_op, state_op, data_shape);
  XlaOp final_state =
      ConcatInDim(&builder, {Reshape(key_op, {1}), output.state}, 0);
  Tuple(&builder, {final_state, output.value});
  TF_ASSIGN_OR_RETURN(XlaComputation xla_computation, builder.Build());

  TF_ASSIGN_OR_RETURN(ProgramShape program_shape,
                      xla_computation.GetProgramShape());
  HloModuleConfig config(program_shape);
  TF_ASSIGN_OR_RETURN(auto new_module, HloModule::CreateFromProto(
                                           xla_computation.proto(), config));
  HloCloneContext context(module);
  HloComputation* new_computation =
      module->DeepCloneComputation(new_module->entry_computation(), &context);
  computation_cache_.emplace(cache_key, new_computation);
  return new_computation;
}

StatusOr<HloInstruction*> RngBitGeneratorExpander::ExpandInstruction(
    HloInstruction* hlo) {
  HloRngBitGeneratorInstruction* rng = Cast<HloRngBitGeneratorInstruction>(hlo);
  RandomAlgorithm algorithm = rng->algorithm();
  if (algorithm == RandomAlgorithm::RNG_DEFAULT) {
    algorithm = default_algorithm_;
  }

  HloModule* module = hlo->parent()->parent();
  const Shape& data_shape = rng->shape().tuple_shapes(1);
  const Shape& state_shape = rng->operand(0)->shape();
  TF_ASSIGN_OR_RETURN(
      HloComputation * generator_computation,
      GetGeneratorComputation(data_shape, state_shape, algorithm, module));
  return hlo->parent()->AddInstruction(HloInstruction::CreateCall(
      ShapeUtil::MakeTupleShape({state_shape, data_shape}),
      {hlo->mutable_operand(0)}, generator_computation));
}

}  // namespace xla
<commit_msg>Rewrite output state to match the input.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

#include "tensorflow/compiler/xla/service/rng_bit_generator_expander.h"

#include "tensorflow/compiler/xla/client/lib/prng.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/service/hlo_casting_utils.h"
#include "tensorflow/compiler/xla/service/hlo_computation.h"
#include "tensorflow/compiler/xla/service/hlo_instruction.h"
#include "tensorflow/compiler/xla/service/hlo_instructions.h"
#include "tensorflow/compiler/xla/service/hlo_module.h"
#include "tensorflow/compiler/xla/shape.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/stream_executor/lib/statusor.h"

namespace xla {
namespace {

XlaOp GetPhiloxStateOp(XlaOp input_state, const Shape& state_shape) {
  if (state_shape.dimensions(0) >= 3) {
    return Slice(input_state, {1}, {3}, {1});
  }
  return Rev(input_state, {0});
}

XlaOp GetPhiloxOutputStateOp(XlaOp output_state, const Shape& state_shape) {
  if (state_shape.dimensions(0) < 3) {
    output_state = Slice(output_state, {0}, {1}, {1});
  }
  return output_state;
}

}  // namespace

bool RngBitGeneratorExpander::InstructionMatchesPattern(
    HloInstruction* instruction) {
  return instruction->opcode() == HloOpcode::kRngBitGenerator;
}

StatusOr<HloComputation*> RngBitGeneratorExpander::GetGeneratorComputation(
    const Shape& data_shape, const Shape& state_shape,
    RandomAlgorithm algorithm, HloModule* module) {
  RngGeneratorKey cache_key{data_shape, state_shape, algorithm, module};
  auto it = computation_cache_.find(cache_key);
  if (it != computation_cache_.end()) {
    return it->second;
  }

  XlaBuilder builder("rng");
  XlaOp state_param = Parameter(&builder, 0, state_shape, "state");
  XlaOp key_op = Reshape(Slice(state_param, {0}, {1}, {1}), {});
  RngOutput output;
  switch (algorithm) {
    case RandomAlgorithm::RNG_THREE_FRY:
      output = ThreeFryBitGenerator(key_op, Slice(state_param, {1}, {2}, {1}),
                                    data_shape);
      break;
    case RandomAlgorithm::RNG_PHILOX:
      output = PhiloxBitGenerator(
          key_op, GetPhiloxStateOp(state_param, state_shape), data_shape);
      output.state = GetPhiloxOutputStateOp(output.state, state_shape);
      break;
    default:
      return Unimplemented("Unsupported random algorthm: %s",
                           RandomAlgorithm_Name(algorithm));
  }

  XlaOp final_state =
      ConcatInDim(&builder, {Reshape(key_op, {1}), output.state}, 0);
  Tuple(&builder, {final_state, output.value});
  TF_ASSIGN_OR_RETURN(XlaComputation xla_computation, builder.Build());

  TF_ASSIGN_OR_RETURN(ProgramShape program_shape,
                      xla_computation.GetProgramShape());
  HloModuleConfig config(program_shape);
  TF_ASSIGN_OR_RETURN(auto new_module, HloModule::CreateFromProto(
                                           xla_computation.proto(), config));
  HloCloneContext context(module);
  HloComputation* new_computation =
      module->DeepCloneComputation(new_module->entry_computation(), &context);
  computation_cache_.emplace(cache_key, new_computation);
  return new_computation;
}

StatusOr<HloInstruction*> RngBitGeneratorExpander::ExpandInstruction(
    HloInstruction* hlo) {
  HloRngBitGeneratorInstruction* rng = Cast<HloRngBitGeneratorInstruction>(hlo);
  RandomAlgorithm algorithm = rng->algorithm();
  if (algorithm == RandomAlgorithm::RNG_DEFAULT) {
    algorithm = default_algorithm_;
  }

  HloModule* module = hlo->parent()->parent();
  const Shape& data_shape = rng->shape().tuple_shapes(1);
  const Shape& state_shape = rng->operand(0)->shape();
  TF_ASSIGN_OR_RETURN(
      HloComputation * generator_computation,
      GetGeneratorComputation(data_shape, state_shape, algorithm, module));
  return hlo->parent()->AddInstruction(HloInstruction::CreateCall(
      ShapeUtil::MakeTupleShape({state_shape, data_shape}),
      {hlo->mutable_operand(0)}, generator_computation));
}

}  // namespace xla
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Frameworks_Modbus_Server_inl_
#define _Stroika_Frameworks_Modbus_Server_inl_   1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../../Foundation/Configuration/Endian.h"
#include    "../../Foundation/Debug/Assertions.h"

namespace   Stroika {
    namespace   Frameworks {
        namespace   Modbus {

            /*
             ********************************************************************************
             *************************** Modbus::SplitSrcAcrossOutputs **********************
             ********************************************************************************
             */
            template    <typename MODBUS_REGISTER_DESCRIPTOR, typename SRC_TYPE>
            void    SplitSrcAcrossOutputs (const SRC_TYPE& s, typename MODBUS_REGISTER_DESCRIPTOR::NameType baseRegister, Containers::Mapping<typename MODBUS_REGISTER_DESCRIPTOR::NameType, typename MODBUS_REGISTER_DESCRIPTOR::ValueType>* update)
            {
                using   VT = typename MODBUS_REGISTER_DESCRIPTOR::ValueType;
                constexpr   size_t  kNElts_  =   sizeof (SRC_TYPE) / sizeof (VT);
                static_assert (kNElts_ * sizeof (VT) == sizeof (SRC_TYPE), ""); // only works if divides evenly
                RequireNotNull (update);
                const VT* arr = reinterpret_cast<const VT*> (&s);
                for (size_t i = 0; i < kNElts_; ++i) {
                    // high order addressed elements first - big endian (@todo - is there a better way to byte swap if needed - in general case)?
                    update->Add (baseRegister + i, arr[(Configuration::GetEndianness () == Configuration::Endian::eBig) ? (kNElts_ -  i - 1) : i]);
                }
            }

        }
    }
}
#endif  /*_Stroika_Frameworks_Modbus_Server_inl_*/
<commit_msg>backwards SplitSrcAcrossOutputs () Endianness test (still hack either way)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#ifndef _Stroika_Frameworks_Modbus_Server_inl_
#define _Stroika_Frameworks_Modbus_Server_inl_   1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../../Foundation/Configuration/Endian.h"
#include    "../../Foundation/Debug/Assertions.h"

namespace   Stroika {
    namespace   Frameworks {
        namespace   Modbus {

            /*
             ********************************************************************************
             *************************** Modbus::SplitSrcAcrossOutputs **********************
             ********************************************************************************
             */
            template    <typename MODBUS_REGISTER_DESCRIPTOR, typename SRC_TYPE>
            void    SplitSrcAcrossOutputs (const SRC_TYPE& s, typename MODBUS_REGISTER_DESCRIPTOR::NameType baseRegister, Containers::Mapping<typename MODBUS_REGISTER_DESCRIPTOR::NameType, typename MODBUS_REGISTER_DESCRIPTOR::ValueType>* update)
            {
                using   VT = typename MODBUS_REGISTER_DESCRIPTOR::ValueType;
                constexpr   size_t  kNElts_  =   sizeof (SRC_TYPE) / sizeof (VT);
                static_assert (kNElts_ * sizeof (VT) == sizeof (SRC_TYPE), ""); // only works if divides evenly
                RequireNotNull (update);
                const VT* arr = reinterpret_cast<const VT*> (&s);
                for (size_t i = 0; i < kNElts_; ++i) {
                    // high order addressed elements first - big endian (@todo - is there a better way to byte swap if needed - in general case)?
                    update->Add (baseRegister + i, arr[(Configuration::GetEndianness () == Configuration::Endian::eLittle) ? (kNElts_ -  i - 1) : i]);
                }
            }

        }
    }
}
#endif  /*_Stroika_Frameworks_Modbus_Server_inl_*/
<|endoftext|>


<commit_before>#include "runtime_internal.h"

extern "C" {

extern void *malloc(size_t);
extern void free(void *);

}

namespace Halide { namespace Runtime { namespace Internal {

WEAK void *default_malloc(void *user_context, size_t x) {
    void *orig = malloc(x+40);
    if (orig == NULL) {
        // Will result in a failed assertion and a call to halide_error
        return NULL;
    }
    // Round up to next multiple of 32. Should add at least 8 bytes so we can fit the original pointer.
    void *ptr = (void *)((((size_t)orig + 32) >> 5) << 5);
    ((void **)ptr)[-1] = orig;
    return ptr;
}

WEAK void default_free(void *user_context, void *ptr) {
    free(((void**)ptr)[-1]);
}

WEAK void *(*custom_malloc)(void *, size_t) = default_malloc;
WEAK void (*custom_free)(void *, void *) = default_free;

}}} // namespace Halide::Runtime::Internal

extern "C" {

WEAK void *(*halide_set_custom_malloc(void *(*user_malloc)(void *, size_t)))(void *, size_t) {
    void *(*result)(void *, size_t) = custom_malloc;
    custom_malloc = user_malloc;
    return result;
}

WEAK void (*halide_set_custom_free(void (*user_free)(void *, void *)))(void *, void *) {
    void (*result)(void *, void *) = custom_free;
    custom_free = user_free;
    return result;
}

WEAK void *halide_malloc(void *user_context, size_t x) {
    return custom_malloc(user_context, x);
}

WEAK void halide_free(void *user_context, void *ptr) {
    custom_free(user_context, ptr);
}

}
<commit_msg>Align memory on the heap to a 128 byte boundary.<commit_after>#include "runtime_internal.h"

extern "C" {

extern void *malloc(size_t);
extern void free(void *);

}

namespace Halide { namespace Runtime { namespace Internal {

WEAK void *default_malloc(void *user_context, size_t x) {
    void *orig = malloc(x+136);
    if (orig == NULL) {
        // Will result in a failed assertion and a call to halide_error
        return NULL;
    }
    // Round up to next multiple of 128. Should add at least 8 bytes so we can fit the original pointer.
    void *ptr = (void *)((((size_t)orig + 128) >> 7) << 7);
    ((void **)ptr)[-1] = orig;
    return ptr;
}

WEAK void default_free(void *user_context, void *ptr) {
    free(((void**)ptr)[-1]);
}

WEAK void *(*custom_malloc)(void *, size_t) = default_malloc;
WEAK void (*custom_free)(void *, void *) = default_free;

}}} // namespace Halide::Runtime::Internal

extern "C" {

WEAK void *(*halide_set_custom_malloc(void *(*user_malloc)(void *, size_t)))(void *, size_t) {
    void *(*result)(void *, size_t) = custom_malloc;
    custom_malloc = user_malloc;
    return result;
}

WEAK void (*halide_set_custom_free(void (*user_free)(void *, void *)))(void *, void *) {
    void (*result)(void *, void *) = custom_free;
    custom_free = user_free;
    return result;
}

WEAK void *halide_malloc(void *user_context, size_t x) {
    return custom_malloc(user_context, x);
}

WEAK void halide_free(void *user_context, void *ptr) {
    custom_free(user_context, ptr);
}

}
<|endoftext|>


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

#include "../headers/DS_Protocol.h"

DS_Protocol::DS_Protocol() {
    p_team = 0;
    p_robotCode = false;
    p_robotCommunication = false;
    p_alliance = DS_AllianceRed1;
    p_controlMode = DS_ControlDisabled;
    p_joysticks = new QList<DS_Joystick*>;

    restartWatchdog();
    connect (&p_watchDog, SIGNAL (timeout()), this, SLOT (reset()));
}

DS_Protocol::~DS_Protocol() {
    delete p_joysticks;
}

bool DS_Protocol::robotCode() const {
    return p_robotCode;
}

bool DS_Protocol::robotCommunication() const {
    return p_robotCommunication;
}

DS_Alliance DS_Protocol::alliance() const {
    return p_alliance;
}

DS_ControlMode DS_Protocol::controlMode() const {
    return p_controlMode;
}

void DS_Protocol::setTeamNumber (int team) {
    p_team = team;
}

void DS_Protocol::setRobotAddress (QString address) {
    p_robotAddress = address;
}

void DS_Protocol::setAlliance (DS_Alliance alliance) {
    p_alliance = alliance;
}

void DS_Protocol::setControlMode (DS_ControlMode mode) {
    p_controlMode = mode;
    emit controlModeChanged (mode);
}

void DS_Protocol::setJoysticks (QList<DS_Joystick*>* joysticks) {
    p_joysticks = joysticks;
}

QByteArray DS_Protocol::bitsToBytes (QBitArray bits) {
    QByteArray bytes (bits.count() / 8, 0);

    for (int i = 0; i < bits.count(); ++i)
        bytes [i / 8] = (bytes.at (i / 8) | ((bits [i] ? 1 : 0) << (i % 8)));

    return bytes;
}

void DS_Protocol::restartWatchdog() {
    p_watchDog.stop();
    p_watchDog.start (1000);
}
<commit_msg>Ensure robot is disabled if there is no communication<commit_after>/*
 * Copyright (c) 2015 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "../headers/DS_Protocol.h"

DS_Protocol::DS_Protocol() {
    p_team = 0;
    p_robotCode = false;
    p_robotCommunication = false;
    p_alliance = DS_AllianceRed1;
    p_controlMode = DS_ControlDisabled;
    p_joysticks = new QList<DS_Joystick*>;

    restartWatchdog();
    connect (&p_watchDog, SIGNAL (timeout()), this, SLOT (reset()));
}

DS_Protocol::~DS_Protocol() {
    delete p_joysticks;
}

bool DS_Protocol::robotCode() const {
    return p_robotCode;
}

bool DS_Protocol::robotCommunication() const {
    return p_robotCommunication;
}

DS_Alliance DS_Protocol::alliance() const {
    return p_alliance;
}

DS_ControlMode DS_Protocol::controlMode() const {
    return p_controlMode;
}

void DS_Protocol::setTeamNumber (int team) {
    p_team = team;
}

void DS_Protocol::setRobotAddress (QString address) {
    p_robotAddress = address;
}

void DS_Protocol::setAlliance (DS_Alliance alliance) {
    p_alliance = alliance;
}

void DS_Protocol::setControlMode (DS_ControlMode mode) {
    p_controlMode = p_robotCommunication ? mode : DS_ControlDisabled;
    emit controlModeChanged (mode);
}

void DS_Protocol::setJoysticks (QList<DS_Joystick*>* joysticks) {
    p_joysticks = joysticks;
}

QByteArray DS_Protocol::bitsToBytes (QBitArray bits) {
    QByteArray bytes (bits.count() / 8, 0);

    for (int i = 0; i < bits.count(); ++i)
        bytes [i / 8] = (bytes.at (i / 8) | ((bits [i] ? 1 : 0) << (i % 8)));

    return bytes;
}

void DS_Protocol::restartWatchdog() {
    p_watchDog.stop();
    p_watchDog.start (1000);
}
<|endoftext|>


<commit_before>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et sw=4 ts=4 sts=4: */
#include "ut_wallpaperbusinesslogic.h"

#include "wallpaperbusinesslogic.h"
#include "wallpapercurrentdescriptor.h"
#include "wallpaperitrans.h"

#include <QPixmap>

#include <MApplication>
#include <MGConfItem>

#define DEBUG
#include "../../src/debug.h"

static const QString PortraitKey =
    "/desktop/meego/background/portrait/picture_filename";
static const QString LandscapeKey =
    "/desktop/meego/background/landscape/picture_filename";

/******************************************************************************
 * Ut_WallpaperBusinessLogic implementation.
 */
void
Ut_WallpaperBusinessLogic::init()
{
}

void
Ut_WallpaperBusinessLogic::cleanup()
{
}

static int argc = 1;
static char* app_name = (char*) "./Ut_WallpaperBusinessLogic";

void
Ut_WallpaperBusinessLogic::initTestCase()
{
    m_App = new MApplication (argc, &app_name);
    m_Api = new WallpaperBusinessLogic;

    QVERIFY (m_Api->m_EditedImage == 0);
}

void
Ut_WallpaperBusinessLogic::cleanupTestCase()
{
    delete m_App;
    delete m_Api;
}

/*!
 * Checks if the GConfItem objects are created with the right keys.
 */
void
Ut_WallpaperBusinessLogic::testGConfItems ()
{
    QVERIFY (m_Api->m_LandscapeGConfItem != 0);
    QVERIFY (m_Api->m_LandscapeGConfItem->key() == LandscapeKey);

    QVERIFY (m_Api->m_PortraitGConfItem != 0);
    QVERIFY (m_Api->m_PortraitGConfItem->key() == PortraitKey);
}

/*!
 * Checks if the dirpath the businesslogic uses as a target directory to save
 * fiels is actually an absolute path inside the /home directory. Please note
 * that this test will not actually create this directory, hence this test is in
 * the unit test set.
 */
void
Ut_WallpaperBusinessLogic::testDirPath ()
{
    QString path = m_Api->dirPath ();

    SYS_DEBUG ("*** dirPath() = %s", SYS_STR(path));
    QVERIFY (!path.isEmpty());
    QVERIFY (path.startsWith("/home"));
    QVERIFY (path.endsWith("/"));
}

/*!
 * Checks the low level WallpaperITrans class, its tag methods and overloaded
 * operators.
 */
void
Ut_WallpaperBusinessLogic::testITrans ()
{
    WallpaperITrans trans1, trans2;

    SYS_DEBUG ("Checking default values of WallpaperITrans...");
    QVERIFY (trans1.x() == 0);
    QVERIFY (trans1.y() == 0);
    QVERIFY (trans1.scale() == 1.0);
    QVERIFY (trans1.orientation() == M::Landscape);

    SYS_DEBUG ("Checking the set functions...");
    trans2.setOffset (QPointF(10, 11));
    trans2.setScale (2.0);
    trans2.setOrientation (M::Portrait);
    trans2.setExpectedSize (QSize(864, 480));

    QVERIFY (trans2.x() == 10);
    QVERIFY (trans2.y() == 11);
    QVERIFY (trans2.scale() == 2.0);
    QVERIFY (trans2.orientation() == M::Portrait);
    QVERIFY (trans2.expectedWidth() == 864);
    QVERIFY (trans2.expectedHeight() == 480);

    SYS_DEBUG ("Testing the copy constructor.");
    WallpaperITrans trans3 (trans2);
    QVERIFY (trans3.x() == 10);
    QVERIFY (trans3.y() == 11);
    QVERIFY (trans3.scale() == 2.0);
    QVERIFY (trans3.orientation() == M::Portrait);
    QVERIFY (trans3.expectedWidth() == 864);
    QVERIFY (trans3.expectedHeight() == 480);

    SYS_DEBUG ("testing operator=...");
    trans1 = trans2;
    QVERIFY (trans1.x() == 10);
    QVERIFY (trans1.y() == 11);
    QVERIFY (trans1.scale() == 2.0);
    QVERIFY (trans1.orientation() == M::Portrait);
    QVERIFY (trans1.expectedWidth() == 864);
    QVERIFY (trans1.expectedHeight() == 480);

    SYS_DEBUG ("Testing operator*...");
    SYS_DEBUG ("*** trans1.scale() = %d", trans2 * 2);
    QVERIFY (trans2 * 2 == 4);
}

/******************************************************************************
 * Private functions.
 */

QTEST_APPLESS_MAIN(Ut_WallpaperBusinessLogic)

<commit_msg>Fixed test.<commit_after>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et sw=4 ts=4 sts=4: */
#include "ut_wallpaperbusinesslogic.h"

#include "wallpaperbusinesslogic.h"
#include "wallpapercurrentdescriptor.h"
#include "wallpaperitrans.h"

#include <QPixmap>

#include <MApplication>
#include <MGConfItem>

#define DEBUG
#include "../../src/debug.h"

static const QString PortraitKey =
    "/desktop/meego/background/portrait/picture_filename";
static const QString LandscapeKey =
    "/desktop/meego/background/landscape/picture_filename";

/******************************************************************************
 * Ut_WallpaperBusinessLogic implementation.
 */
void
Ut_WallpaperBusinessLogic::init()
{
}

void
Ut_WallpaperBusinessLogic::cleanup()
{
}

static int argc = 1;
static char* app_name = (char*) "./Ut_WallpaperBusinessLogic";

void
Ut_WallpaperBusinessLogic::initTestCase()
{
    m_App = new MApplication (argc, &app_name);
    m_Api = new WallpaperBusinessLogic;

    QVERIFY (m_Api->m_EditedImage == 0);
}

void
Ut_WallpaperBusinessLogic::cleanupTestCase()
{
    delete m_App;
    delete m_Api;
}

/*!
 * Checks if the GConfItem objects are created with the right keys.
 */
void
Ut_WallpaperBusinessLogic::testGConfItems ()
{
    QVERIFY (m_Api->m_LandscapeGConfItem != 0);
    QVERIFY (m_Api->m_LandscapeGConfItem->key() == LandscapeKey);

    QVERIFY (m_Api->m_PortraitGConfItem != 0);
    QVERIFY (m_Api->m_PortraitGConfItem->key() == PortraitKey);
}

/*!
 * Checks if the dirpath the businesslogic uses as a target directory to save
 * fiels is actually an absolute path inside the /home directory. Please note
 * that this test will not actually create this directory, hence this test is in
 * the unit test set.
 */
void
Ut_WallpaperBusinessLogic::testDirPath ()
{
    QString path = m_Api->dirPath ();

    SYS_DEBUG ("*** dirPath() = %s", SYS_STR(path));
    QVERIFY (!path.isEmpty());
    QVERIFY (path.startsWith("/home") || path.startsWith("/root"));
    QVERIFY (path.endsWith("/"));
}

/*!
 * Checks the low level WallpaperITrans class, its tag methods and overloaded
 * operators.
 */
void
Ut_WallpaperBusinessLogic::testITrans ()
{
    WallpaperITrans trans1, trans2;

    SYS_DEBUG ("Checking default values of WallpaperITrans...");
    QVERIFY (trans1.x() == 0);
    QVERIFY (trans1.y() == 0);
    QVERIFY (trans1.scale() == 1.0);
    QVERIFY (trans1.orientation() == M::Landscape);

    SYS_DEBUG ("Checking the set functions...");
    trans2.setOffset (QPointF(10, 11));
    trans2.setScale (2.0);
    trans2.setOrientation (M::Portrait);
    trans2.setExpectedSize (QSize(864, 480));

    QVERIFY (trans2.x() == 10);
    QVERIFY (trans2.y() == 11);
    QVERIFY (trans2.scale() == 2.0);
    QVERIFY (trans2.orientation() == M::Portrait);
    QVERIFY (trans2.expectedWidth() == 864);
    QVERIFY (trans2.expectedHeight() == 480);

    SYS_DEBUG ("Testing the copy constructor.");
    WallpaperITrans trans3 (trans2);
    QVERIFY (trans3.x() == 10);
    QVERIFY (trans3.y() == 11);
    QVERIFY (trans3.scale() == 2.0);
    QVERIFY (trans3.orientation() == M::Portrait);
    QVERIFY (trans3.expectedWidth() == 864);
    QVERIFY (trans3.expectedHeight() == 480);

    SYS_DEBUG ("testing operator=...");
    trans1 = trans2;
    QVERIFY (trans1.x() == 10);
    QVERIFY (trans1.y() == 11);
    QVERIFY (trans1.scale() == 2.0);
    QVERIFY (trans1.orientation() == M::Portrait);
    QVERIFY (trans1.expectedWidth() == 864);
    QVERIFY (trans1.expectedHeight() == 480);

    SYS_DEBUG ("Testing operator*...");
    SYS_DEBUG ("*** trans1.scale() = %d", trans2 * 2);
    QVERIFY (trans2 * 2 == 4);
}

/******************************************************************************
 * Private functions.
 */

QTEST_APPLESS_MAIN(Ut_WallpaperBusinessLogic)

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pyuno_impl.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: jbu $ $Date: 2003-05-24 23:28:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Ralph Thomas
 *
 *   Copyright: 2000 by Sun Microsystems, Inc.
 *
 *   All Rights Reserved.
 *
 *   Contributor(s): Ralph Thomas, Joerg Budischewski
 *
 *
 ************************************************************************/
#ifndef _PYUNO_IMPL_
#define _PYUNO_IMPL_

#include <hash_map>
#include <hash_set>

#include <pyuno/pyuno.hxx>

#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/script/XTypeConverter.hpp>
#include <com/sun/star/script/XInvocation2.hpp>
#include <com/sun/star/script/XInvocationAdapterFactory2.hpp>

#include <com/sun/star/reflection/XIdlReflection.hpp>

#include <com/sun/star/container/XHierarchicalNameAccess.hpp>

#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>

#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/weakref.hxx>

namespace pyuno
{

typedef ::std::hash_map
<
    PyRef,
    com::sun::star::uno::WeakReference< com::sun::star::uno::XInterface >,
    PyRef::Hash,
    std::equal_to< PyRef >
> PyRef2Adapter;

typedef ::std::hash_map
<
rtl::OUString,
PyRef,
rtl::OUStringHash,
std::equal_to<rtl::OUString>
> ExceptionClassMap;

typedef ::std::hash_set< PyRef , PyRef::Hash , std::equal_to<PyRef> > ClassSet;

PyObject* PyUNO_new(
    const com::sun::star::uno::Any & targetInterface,
    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);

PyObject* PyUNO_new_UNCHECKED (
    const com::sun::star::uno::Any & targetInterface,
    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);

typedef struct
{
    com::sun::star::uno::Reference <com::sun::star::script::XInvocation2> xInvocation;
    com::sun::star::uno::Any wrappedObject;
} PyUNOInternals;

typedef struct
{
    PyObject_HEAD
    PyUNOInternals* members;
} PyUNO;

PyRef ustring2PyUnicode( const rtl::OUString &source );
PyRef ustring2PyString( const ::rtl::OUString & source );
rtl::OUString pyString2ustring( PyObject *str );

PyRef AnyToPyObject (const com::sun::star::uno::Any & a, const Runtime &r )
    throw ( com::sun::star::uno::RuntimeException );

com::sun::star::uno::Any PyObjectToAny (PyObject* o)
    throw ( com::sun::star::uno::RuntimeException );

void raiseInvocationTargetExceptionWhenNeeded( const Runtime &runtime )
    throw ( com::sun::star::reflection::InvocationTargetException );

// bool CheckPyObjectTypes (PyObject* o, Sequence<Type> types);
// bool CheckPyObjectType (PyObject* o, Type type); //Only check 1 object.

com::sun::star::uno::TypeClass StringToTypeClass (char* string);

PyRef PyUNO_callable_new (
    const com::sun::star::uno::Reference<com::sun::star::script::XInvocation2> &xInv,
    const rtl::OUString &methodName,
    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> &ssf,
    const com::sun::star::uno::Reference<com::sun::star::script::XTypeConverter> &tc,
    ConversionMode mode = REJECT_UNO_ANY );

PyObject* PyUNO_Type_new (const char *typeName , com::sun::star::uno::TypeClass t , const Runtime &r );
PyObject* PyUNO_Enum_new( const char *enumBase, const char *enumValue, const Runtime &r );
PyObject* PyUNO_char_new (sal_Unicode c , const Runtime &r);
PyObject *PyUNO_ByteSequence_new( const com::sun::star::uno::Sequence< sal_Int8 > &, const Runtime &r );

PyObject *importToGlobal( PyObject *typeName, PyObject *dict, PyObject *targetName );

PyRef getTypeClass( const Runtime &);
PyRef getEnumClass( const Runtime &);
PyRef getBoolClass( const Runtime &);
PyRef getCharClass( const Runtime &);
PyRef getByteSequenceClass( const Runtime & );
PyRef getPyUnoClass( const Runtime &);
PyRef getClass( const rtl::OUString & name , const Runtime & runtime );
PyRef getAnyClass( const Runtime &);
PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args );

com::sun::star::uno::Any PyEnum2Enum( PyObject *obj, const Runtime & r )
    throw ( com::sun::star::uno::RuntimeException );
sal_Bool PyBool2Bool( PyObject *o, const Runtime & r )
    throw ( com::sun::star::uno::RuntimeException );
sal_Unicode PyChar2Unicode( PyObject *o, const Runtime & r )
    throw ( com::sun::star::uno::RuntimeException );
com::sun::star::uno::Type PyType2Type( PyObject * o, const Runtime & r )
    throw( com::sun::star::uno::RuntimeException );

void raisePyExceptionWithAny( const com::sun::star::uno::Any &a );
const char *typeClassToString( com::sun::star::uno::TypeClass t );

PyRef getObjectFromUnoModule( const Runtime &runtime, const char * object )
    throw ( com::sun::star::uno::RuntimeException );

sal_Bool isInterfaceClass( const Runtime &, PyObject *obj );
sal_Bool isInstanceOfStructOrException( const Runtime & runtime, PyObject *obj);
com::sun::star::uno::Sequence<com::sun::star::uno::Type> implementsInterfaces(
    const Runtime & runtime, PyObject *obj );

struct RuntimeCargo
{
    com::sun::star::uno::Reference< com::sun::star::lang::XSingleServiceFactory > xInvocation;
    com::sun::star::uno::Reference< com::sun::star::script::XTypeConverter> xTypeConverter;
    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > xContext;
    com::sun::star::uno::Reference< com::sun::star::reflection::XIdlReflection > xCoreReflection;
    com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess > xTdMgr;
    com::sun::star::uno::Reference< com::sun::star::script::XInvocationAdapterFactory2 > xAdapterFactory;
    com::sun::star::uno::Reference< com::sun::star::beans::XIntrospection > xIntrospection;
    PyRef dictUnoModule;
    bool valid;
    ExceptionClassMap exceptionMap;
    ClassSet interfaceSet;
    PyRef2Adapter mappedObjects;

    PyRef getUnoModule();
};

struct stRuntimeImpl
{
    PyObject_HEAD
    struct RuntimeCargo *cargo;
public:
    static void del( PyObject *self );

    static PyRef create(
        const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > & xContext )
        throw ( com::sun::star::uno::RuntimeException );
};

class Adapter : public cppu::WeakImplHelper2<
    com::sun::star::script::XInvocation, com::sun::star::lang::XUnoTunnel >
{
    PyRef mWrappedObject;
    PyInterpreterState *mInterpreter;  // interpreters don't seem to be refcounted !
    com::sun::star::uno::WeakReference< com::sun::star::uno::XInterface > mWeakUnoAdapter;
    com::sun::star::uno::Reference< com::sun::star::beans::XIntrospectionAccess > mIntrospectionAccess;
public:
    Adapter( const PyRef &obj, const Runtime & );

    // should be called directly after construction of the adapter
    // implementation stores a weak reference to it until it has
    // created a reflection. (Ensure, that there is already a refcount
    // on the Adapter object !)
    void setUnoAdapter( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface > &itr);

    static com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId();
    PyRef getWrappedObject() { return mWrappedObject; }
    virtual ~Adapter();

    // XInvocation
    virtual com::sun::star::uno::Reference< ::com::sun::star::beans::XIntrospectionAccess >
           SAL_CALL getIntrospection(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Any SAL_CALL invoke(
        const ::rtl::OUString& aFunctionName,
        const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams,
        ::com::sun::star::uno::Sequence< sal_Int16 >& aOutParamIndex,
        ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aOutParam )
        throw (::com::sun::star::lang::IllegalArgumentException,
               ::com::sun::star::script::CannotConvertException,
               ::com::sun::star::reflection::InvocationTargetException,
               ::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL setValue(
        const ::rtl::OUString& aPropertyName,
        const ::com::sun::star::uno::Any& aValue )
        throw (::com::sun::star::beans::UnknownPropertyException,
               ::com::sun::star::script::CannotConvertException,
               ::com::sun::star::reflection::InvocationTargetException,
               ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName )
        throw (::com::sun::star::beans::UnknownPropertyException,
               ::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName )
        throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName )
        throw (::com::sun::star::uno::RuntimeException);

    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething(
        const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw (::com::sun::star::uno::RuntimeException);
};

/** releases a refcount on the interpreter object and on another given python object.

   The function can be called from any thread regardless of whether the global
   interpreter lock is held.

 */
void decreaseRefCount( PyInterpreterState *interpreter, PyObject *object );

#ifdef PYUNO_DEBUG
#define PYUNO_DEBUG_1( msg ) fprintf( stdout, msg )
#define PYUNO_DEBUG_2( msg, arg1 ) fprintf( stdout, msg ,  arg1 )
#define PYUNO_DEBUG_3( msg, arg1 , arg2 ) fprintf( stdout, msg, arg1, arg2 )
#else
#define PYUNO_DEBUG_1(msg) ((void)0)
#define PYUNO_DEBUG_2(msg,arg1) ((void)0)
#define PYUNO_DEBUG_3(msg,arg2,arg3) ((void)0)
#endif

}

#endif
<commit_msg>INTEGRATION: CWS geordi2q14 (1.2.34); FILE MERGED 2004/01/29 18:09:56 hr 1.2.34.1: #111934#: merge CWS ooo111fix2<commit_after>/*************************************************************************
 *
 *  $RCSfile: pyuno_impl.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-02 19:30:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Ralph Thomas
 *
 *   Copyright: 2000 by Sun Microsystems, Inc.
 *
 *   All Rights Reserved.
 *
 *   Contributor(s): Ralph Thomas, Joerg Budischewski
 *
 *
 ************************************************************************/
#ifndef _PYUNO_IMPL_
#define _PYUNO_IMPL_

#include <hash_map>
#include <hash_set>

#include <pyuno/pyuno.hxx>

#include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/script/XTypeConverter.hpp>
#include <com/sun/star/script/XInvocation2.hpp>
#include <com/sun/star/script/XInvocationAdapterFactory2.hpp>

#include <com/sun/star/reflection/XIdlReflection.hpp>

#include <com/sun/star/container/XHierarchicalNameAccess.hpp>

#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>

#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/weakref.hxx>

namespace pyuno
{

typedef ::std::hash_map
<
    PyRef,
    com::sun::star::uno::WeakReference< com::sun::star::script::XInvocation >,
    PyRef::Hash,
    std::equal_to< PyRef >
> PyRef2Adapter;

typedef ::std::hash_map
<
rtl::OUString,
PyRef,
rtl::OUStringHash,
std::equal_to<rtl::OUString>
> ExceptionClassMap;

typedef ::std::hash_map
<
    rtl::OUString,
    com::sun::star::uno::Sequence< sal_Int16 >,
    rtl::OUStringHash,
    std::equal_to< rtl::OUString >
> MethodOutIndexMap;

typedef ::std::hash_set< PyRef , PyRef::Hash , std::equal_to<PyRef> > ClassSet;

PyObject* PyUNO_new(
    const com::sun::star::uno::Any & targetInterface,
    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);

PyObject* PyUNO_new_UNCHECKED (
    const com::sun::star::uno::Any & targetInterface,
    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);

typedef struct
{
    com::sun::star::uno::Reference <com::sun::star::script::XInvocation2> xInvocation;
    com::sun::star::uno::Any wrappedObject;
} PyUNOInternals;

typedef struct
{
    PyObject_HEAD
    PyUNOInternals* members;
} PyUNO;

PyRef ustring2PyUnicode( const rtl::OUString &source );
PyRef ustring2PyString( const ::rtl::OUString & source );
rtl::OUString pyString2ustring( PyObject *str );

PyRef AnyToPyObject (const com::sun::star::uno::Any & a, const Runtime &r )
    throw ( com::sun::star::uno::RuntimeException );

com::sun::star::uno::Any PyObjectToAny (PyObject* o)
    throw ( com::sun::star::uno::RuntimeException );

void raiseInvocationTargetExceptionWhenNeeded( const Runtime &runtime )
    throw ( com::sun::star::reflection::InvocationTargetException );

// bool CheckPyObjectTypes (PyObject* o, Sequence<Type> types);
// bool CheckPyObjectType (PyObject* o, Type type); //Only check 1 object.

com::sun::star::uno::TypeClass StringToTypeClass (char* string);

PyRef PyUNO_callable_new (
    const com::sun::star::uno::Reference<com::sun::star::script::XInvocation2> &xInv,
    const rtl::OUString &methodName,
    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> &ssf,
    const com::sun::star::uno::Reference<com::sun::star::script::XTypeConverter> &tc,
    ConversionMode mode = REJECT_UNO_ANY );

PyObject* PyUNO_Type_new (const char *typeName , com::sun::star::uno::TypeClass t , const Runtime &r );
PyObject* PyUNO_Enum_new( const char *enumBase, const char *enumValue, const Runtime &r );
PyObject* PyUNO_char_new (sal_Unicode c , const Runtime &r);
PyObject *PyUNO_ByteSequence_new( const com::sun::star::uno::Sequence< sal_Int8 > &, const Runtime &r );

PyObject *importToGlobal( PyObject *typeName, PyObject *dict, PyObject *targetName );

PyRef getTypeClass( const Runtime &);
PyRef getEnumClass( const Runtime &);
PyRef getBoolClass( const Runtime &);
PyRef getCharClass( const Runtime &);
PyRef getByteSequenceClass( const Runtime & );
PyRef getPyUnoClass( const Runtime &);
PyRef getClass( const rtl::OUString & name , const Runtime & runtime );
PyRef getAnyClass( const Runtime &);
PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args );

com::sun::star::uno::Any PyEnum2Enum( PyObject *obj, const Runtime & r )
    throw ( com::sun::star::uno::RuntimeException );
sal_Bool PyBool2Bool( PyObject *o, const Runtime & r )
    throw ( com::sun::star::uno::RuntimeException );
sal_Unicode PyChar2Unicode( PyObject *o, const Runtime & r )
    throw ( com::sun::star::uno::RuntimeException );
com::sun::star::uno::Type PyType2Type( PyObject * o, const Runtime & r )
    throw( com::sun::star::uno::RuntimeException );

void raisePyExceptionWithAny( const com::sun::star::uno::Any &a );
const char *typeClassToString( com::sun::star::uno::TypeClass t );

PyRef getObjectFromUnoModule( const Runtime &runtime, const char * object )
    throw ( com::sun::star::uno::RuntimeException );

sal_Bool isInterfaceClass( const Runtime &, PyObject *obj );
sal_Bool isInstanceOfStructOrException( const Runtime & runtime, PyObject *obj);
com::sun::star::uno::Sequence<com::sun::star::uno::Type> implementsInterfaces(
    const Runtime & runtime, PyObject *obj );

struct RuntimeCargo
{
    com::sun::star::uno::Reference< com::sun::star::lang::XSingleServiceFactory > xInvocation;
    com::sun::star::uno::Reference< com::sun::star::script::XTypeConverter> xTypeConverter;
    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > xContext;
    com::sun::star::uno::Reference< com::sun::star::reflection::XIdlReflection > xCoreReflection;
    com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess > xTdMgr;
    com::sun::star::uno::Reference< com::sun::star::script::XInvocationAdapterFactory2 > xAdapterFactory;
    com::sun::star::uno::Reference< com::sun::star::beans::XIntrospection > xIntrospection;
    PyRef dictUnoModule;
    bool valid;
    ExceptionClassMap exceptionMap;
    ClassSet interfaceSet;
    PyRef2Adapter mappedObjects;

    PyRef getUnoModule();
};

struct stRuntimeImpl
{
    PyObject_HEAD
    struct RuntimeCargo *cargo;
public:
    static void del( PyObject *self );

    static PyRef create(
        const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > & xContext )
        throw ( com::sun::star::uno::RuntimeException );
};

class Adapter : public cppu::WeakImplHelper2<
    com::sun::star::script::XInvocation, com::sun::star::lang::XUnoTunnel >
{
    PyRef mWrappedObject;
    PyInterpreterState *mInterpreter;  // interpreters don't seem to be refcounted !
    com::sun::star::uno::Sequence< com::sun::star::uno::Type > mTypes;
    MethodOutIndexMap m_methodOutIndexMap;

private:
    com::sun::star::uno::Sequence< sal_Int16 > getOutIndexes( const rtl::OUString & functionName );

public:
public:
    Adapter( const PyRef &obj, const Runtime &,
             const com::sun::star::uno::Sequence< com::sun::star::uno::Type > & types );

    static com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId();
    PyRef getWrappedObject() { return mWrappedObject; }
    com::sun::star::uno::Sequence< com::sun::star::uno::Type > getWrappedTypes() { return mTypes; }
    virtual ~Adapter();

    // XInvocation
    virtual com::sun::star::uno::Reference< ::com::sun::star::beans::XIntrospectionAccess >
           SAL_CALL getIntrospection(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Any SAL_CALL invoke(
        const ::rtl::OUString& aFunctionName,
        const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams,
        ::com::sun::star::uno::Sequence< sal_Int16 >& aOutParamIndex,
        ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aOutParam )
        throw (::com::sun::star::lang::IllegalArgumentException,
               ::com::sun::star::script::CannotConvertException,
               ::com::sun::star::reflection::InvocationTargetException,
               ::com::sun::star::uno::RuntimeException);

    virtual void SAL_CALL setValue(
        const ::rtl::OUString& aPropertyName,
        const ::com::sun::star::uno::Any& aValue )
        throw (::com::sun::star::beans::UnknownPropertyException,
               ::com::sun::star::script::CannotConvertException,
               ::com::sun::star::reflection::InvocationTargetException,
               ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName )
        throw (::com::sun::star::beans::UnknownPropertyException,
               ::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName )
        throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName )
        throw (::com::sun::star::uno::RuntimeException);

    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething(
        const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw (::com::sun::star::uno::RuntimeException);
};

/** releases a refcount on the interpreter object and on another given python object.

   The function can be called from any thread regardless of whether the global
   interpreter lock is held.

 */
void decreaseRefCount( PyInterpreterState *interpreter, PyObject *object );

#ifdef PYUNO_DEBUG
#define PYUNO_DEBUG_1( msg ) fprintf( stdout, msg )
#define PYUNO_DEBUG_2( msg, arg1 ) fprintf( stdout, msg ,  arg1 )
#define PYUNO_DEBUG_3( msg, arg1 , arg2 ) fprintf( stdout, msg, arg1, arg2 )
#else
#define PYUNO_DEBUG_1(msg) ((void)0)
#define PYUNO_DEBUG_2(msg,arg1) ((void)0)
#define PYUNO_DEBUG_3(msg,arg2,arg3) ((void)0)
#endif

}

#endif
<|endoftext|>