<commit_before>/*
 * Copyright (C) LinBox
 *
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
 * LinBox 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
 * ========LICENCE========
 */

#include <linbox/matrix/random-matrix.h>
#include <linbox/solutions/solve.h>

using namespace LinBox;

namespace {
    template <class Matrix>
    struct TypeToString {
        static constexpr const char* value = "Blackbox";
    };

    template <class Field>
    struct TypeToString<DenseMatrix<Field>> {
        static constexpr const char* value = "DenseMatrix";
    };

    template <class... MatrixArgs>
    struct TypeToString<SparseMatrix<MatrixArgs...>> {
        static constexpr const char* value = "SparseMatrix";
    };

    template <class Matrix>
    inline const char* type_to_string(const Matrix& A)
    {
        return TypeToString<Matrix>::value;
    }

    template <class SolveMethod, class ResultVector, class Matrix, class Vector>
    void print_error(const ResultVector& x, const Matrix& A, const Vector& b, std::string reason)
    {
        std::cerr << "/!\\ " << SolveMethod::name() << " on " << type_to_string(A) << " over ";
        A.field().write(std::cerr);
        std::cerr << " of size " << A.rowdim() << "x" << A.coldim() << " FAILS (" << reason << ")" << std::endl;
    }

    template <class Matrix, class Domain>
    void generateMatrix(Domain& D, Matrix& A, int bitSize, int seed)
    {
        // @note RandomDenseMatrix can also fill a SparseMatrix, it has just a sparsity of 0.
        typename Domain::RandIter randIter(D, bitSize, seed);
        LinBox::RandomDenseMatrix<typename Domain::RandIter, Domain> RDM(D, randIter);

        // @note Within our test m == n implies invertible,
        // but for the rectangular case, we pass whatever.
        if (A.rowdim() == A.coldim()) {
            RDM.randomFullRank(A);
        }
        else {
            RDM.random(A);
        }
    }

    template <class Matrix, class Vector, class Domain>
    void generateVector(Domain& D, const Matrix& A, Vector& b, int vectorBitSize, int seed)
    {
        typename Domain::RandIter vectorRandIter(D, vectorBitSize, seed);

        // @note For the rectangular cases,
        // we set b so that the system is not inconsistent
        if (A.rowdim() == A.coldim()) {
            b.random(vectorRandIter);
        }
        else {
            Vector x(D, A.coldim());
            x.random(vectorRandIter);
            A.apply(b, x); // b <- Ax
        }
    }
}

template <class SolveMethod, class Matrix, class Vector, class ResultDomain>
bool test_solve(MethodBase& methodBase, Matrix& A, Vector& b, ResultDomain& RD, bool verbose)
{
    using ResultVector = DenseVector<ResultDomain>;

    if (verbose) {
        std::cout << "--- Testing " << SolveMethod::name() << " on " << type_to_string(A) << " over ";
        A.field().write(std::cout) << " of size " << A.rowdim() << "x" << A.coldim() << std::endl;
    }

    //
    // Copying data for final check
    //

    using ResultMatrix = typename Matrix::template rebind<ResultDomain>::other;

    // @note The following const_cast prevents this ambiguity warning:
    // warning: ISO C++ says that these are ambiguous
    // - linbox/matrix/sparsematrix/sparse-sequence-vector.h:660:3: note: candidate 1
    //      SparseMatrix (const SparseMatrix<_Tp1, _Rw1> &Mat, const Field& F)
    // - linbox/matrix/sparsematrix/sparse-sequence-vector.h:643:3: note: candidate 2
    //      SparseMatrix (const Field &F, VectStream &stream)
    ResultMatrix RA(A, const_cast<const ResultDomain&>(RD));
    ResultVector Rb(RD, b);

    //
    // Solving
    //

    SolveMethod method(methodBase);
    ResultVector x(RD, A.coldim());

    try {
        solve(x, A, b, method);
        solveInPlace(x, A, b, method);
    } catch (...) {
        print_error<SolveMethod>(x, RA, b, "throws error");
        return false;
    }

    //
    // Checking result is correct
    //

    ResultVector RAx(RD, b.size());
    RA.apply(RAx, x);

    VectorDomain<ResultDomain> VD(RD);
    if (!VD.areEqual(RAx, Rb)) {
        print_error<SolveMethod>(x, RA, Rb, "Ax != b");
        return false;
    }

    return true;
}

template <class SolveMethod, class Domain, class ResultDomain>
bool test_dense_solve(MethodBase& method, Domain& D, ResultDomain& RD, int m, int n, int bitSize, int vectorBitSize, int seed,
                      bool verbose)
{
    using Vector = DenseVector<Domain>;

    DenseMatrix<Domain> A(D, m, n);
    Vector b(D, A.rowdim());

    generateMatrix(D, A, bitSize, seed);
    generateVector(D, A, b, vectorBitSize, seed + 1);

    return test_solve<SolveMethod>(method, A, b, RD, verbose);
}

template <class SolveMethod, class Domain, class ResultDomain>
bool test_sparse_solve(MethodBase& method, Domain& D, ResultDomain& RD, int m, int n, int bitSize, int vectorBitSize, int seed,
                       bool verbose)
{
    using Vector = DenseVector<Domain>;

    SparseMatrix<Domain> A(D, m, n);
    Vector b(D, A.rowdim());

    generateMatrix(D, A, bitSize, seed);
    generateVector(D, A, b, vectorBitSize, seed + 1);

    return test_solve<SolveMethod>(method, A, b, RD, verbose);
}

template <class SolveMethod, class Domain, class ResultDomain>
bool test_blackbox_solve(MethodBase& method, Domain& D, ResultDomain& RD, int m, int n, int bitSize, int vectorBitSize, int seed,
                         bool verbose)
{
    using Vector = DenseVector<Domain>;

    DenseMatrix<Domain> AData(D, n, m);
    generateMatrix(D, AData, bitSize, seed);

    // We're using a Transpose to use our blackbox interface
    Transpose<DenseMatrix<Domain>> A(AData);
    Vector b(D, A.rowdim());
    generateVector(D, A, b, vectorBitSize, seed + 1);

    return test_solve<SolveMethod>(method, A, b, RD, verbose);
}

int main(int argc, char** argv)
{
    Integer q = 131071;
    bool verbose = false;
    bool loop = false;
    int seed = -1;
    int bitSize = 100;
    int vectorBitSize = -1;
    int m = 32;
    int n = 24;
    std::string dispatchString = "AUTO";

    static Argument args[] = {
        {'q', "-q", "Field characteristic.", TYPE_INTEGER, &q},
        {'v', "-v", "Enable verbose mode.", TYPE_BOOL, &verbose},
        {'l', "-l", "Infinite loop of tests.", TYPE_BOOL, &loop},
        {'s', "-s", "Seed for randomness.", TYPE_INT, &seed},
        {'b', "-b", "Bit size for rational solve tests.", TYPE_INT, &bitSize},
        {'B', "-B", "Vector bit size for rational solve tests (defaults to -b if not specified).", TYPE_INT, &vectorBitSize},
        {'m', "-m", "Row dimension of matrices.", TYPE_INT, &m},
        {'n', "-n", "Column dimension of matrices.", TYPE_INT, &n},
        {'d', "-d", "Dispatch mode (either AUTO, SEQ, SMP or MPI).", TYPE_STR, &dispatchString},
        END_OF_ARGUMENTS};

    parseArguments(argc, argv, args);

    // Setting up context

    Communicator communicator(0, nullptr);

    MethodBase method;
    method.pCommunicator = &communicator;
    method.dispatch = Dispatch::Auto;
    if (dispatchString == "MPI")
        method.dispatch = Dispatch::Distributed;
    else if (dispatchString == "SEQ")
        method.dispatch = Dispatch::Sequential;
    else if (dispatchString == "SMP")
        method.dispatch = Dispatch::SMP;
    else if (dispatchString != "AUTO") {
        std::cerr << "-d Dispatch mode should be either AUTO, SEQ, SMP or MPI" << std::endl;
        return EXIT_FAILURE;
    }

    if (vectorBitSize < 0) {
        vectorBitSize = bitSize;
    }

    if (seed < 0) {
        seed = time(nullptr);
    }

    if (verbose) {
        commentator().setReportStream(std::cout);
    }

    Givaro::ZRing<Givaro::Integer> ZZ;
    Givaro::QField<Givaro::Rational> QQ;
    Givaro::Modular<double> F(q);

    bool ok = true;
    do {
        // ----- Rational Auto
        ok &= test_dense_solve<Method::Auto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        ok &= test_sparse_solve<Method::Auto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        // @fixme Dixon<Wiedemann> does not compile
        // ok &= test_blackbox_solve<Method::Auto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);

        // ----- Rational CRA
        // @fixme @bug When bitSize = 5 and vectorBitSize = 50, CRA fails
        ok &= test_dense_solve<Method::CRAAuto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        ok &= test_sparse_solve<Method::CRAAuto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        // ok &= test_blackbox_solve<Method::CRAAuto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed,
        // verbose);

        // ----- Rational Dixon
        ok &= test_dense_solve<Method::Dixon>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        ok &= test_sparse_solve<Method::Dixon>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        // @fixme Dixon<Wiedemann> does not compile
        // ok &= test_blackbox_solve<Method::Dixon>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);

        // ----- Rational SymbolicNumeric
        // @note SymbolicNumeric methods are only implemented on DenseMatrix
        // @fixme Singular case fails
        // ok &= test_dense_solve<Method::SymbolicNumericOverlap>(method, ZZ, QQ, m, n, bitSize, vectorBitSize,
        // seed, verbose);
        // @fixme Fails
        // ok &= test_sparse_solve<Method::SymbolicNumericNorm>(method, ZZ, QQ, m, n, bitSize, vectorBitSize,
        // seed, verbose);

        // ----- Modular Auto
        ok &= test_dense_solve<Method::Auto>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::Auto>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::Auto>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Blackbox
        ok &= test_dense_solve<Method::Blackbox>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::Blackbox>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::Blackbox>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular DenseElimination
        ok &= test_dense_solve<Method::DenseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::DenseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::DenseElimination>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular SparseElimination
        ok &= test_dense_solve<Method::SparseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::SparseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::SparseElimination>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Wiedemann
        ok &= test_dense_solve<Method::Wiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::Wiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::Wiedemann>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Lanczos
        // @fixme Dense is segfaulting
        // ok &= test_dense_solve<Method::Lanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // @fixme Singular case fails
        // ok &= test_sparse_solve<Method::Lanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_sparse_blackbox_solve<Method::Lanczos>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular BlockLanczos
        // @fixme Dense does not compile
        // ok &= test_dense_solve<Method::BlockLanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // @fixme Sparse is segfaulting
        // ok &= test_sparse_solve<Method::BlockLanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_blackbox_solve<Method::BlockLanczos>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular BlockWiedemann
        // @deprecated These do not compile anymore
        // ok &= test_dense_solve<Method::BlockWiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_sparse_solve<Method::BlockWiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_blackbox_solve<Method::BlockWiedemann>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Coppersmith
        // @deprecated These do not compile anymore
        // ok &= test_dense_solve<Method::Coppersmith>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_sparse_solve<Method::Coppersmith>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_blackbox_solve<Method::Coppersmith>(method, F, F, m, n, 0, 0, seed, verbose);

        if (!ok) {
            std::cerr << "Failed with seed: " << seed << std::endl;
        }

        seed += 1;
    } while (ok && loop);

    return EXIT_SUCCESS;
}
<commit_msg>Updated comment<commit_after>/*
 * Copyright (C) LinBox
 *
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
 * LinBox 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
 * ========LICENCE========
 */

#include <linbox/matrix/random-matrix.h>
#include <linbox/solutions/solve.h>

using namespace LinBox;

namespace {
    template <class Matrix>
    struct TypeToString {
        static constexpr const char* value = "Blackbox";
    };

    template <class Field>
    struct TypeToString<DenseMatrix<Field>> {
        static constexpr const char* value = "DenseMatrix";
    };

    template <class... MatrixArgs>
    struct TypeToString<SparseMatrix<MatrixArgs...>> {
        static constexpr const char* value = "SparseMatrix";
    };

    template <class Matrix>
    inline const char* type_to_string(const Matrix& A)
    {
        return TypeToString<Matrix>::value;
    }

    template <class SolveMethod, class ResultVector, class Matrix, class Vector>
    void print_error(const ResultVector& x, const Matrix& A, const Vector& b, std::string reason)
    {
        std::cerr << "/!\\ " << SolveMethod::name() << " on " << type_to_string(A) << " over ";
        A.field().write(std::cerr);
        std::cerr << " of size " << A.rowdim() << "x" << A.coldim() << " FAILS (" << reason << ")" << std::endl;
    }

    template <class Matrix, class Domain>
    void generateMatrix(Domain& D, Matrix& A, int bitSize, int seed)
    {
        // @note RandomDenseMatrix can also fill a SparseMatrix, it has just a sparsity of 0.
        typename Domain::RandIter randIter(D, bitSize, seed);
        LinBox::RandomDenseMatrix<typename Domain::RandIter, Domain> RDM(D, randIter);

        // @note Within our test m == n implies invertible,
        // but for the rectangular case, we pass whatever.
        if (A.rowdim() == A.coldim()) {
            RDM.randomFullRank(A);
        }
        else {
            RDM.random(A);
        }
    }

    template <class Matrix, class Vector, class Domain>
    void generateVector(Domain& D, const Matrix& A, Vector& b, int vectorBitSize, int seed)
    {
        typename Domain::RandIter vectorRandIter(D, vectorBitSize, seed);

        // @note For the rectangular cases,
        // we set b so that the system is not inconsistent
        if (A.rowdim() == A.coldim()) {
            b.random(vectorRandIter);
        }
        else {
            Vector x(D, A.coldim());
            x.random(vectorRandIter);
            A.apply(b, x); // b <- Ax
        }
    }
}

template <class SolveMethod, class Matrix, class Vector, class ResultDomain>
bool test_solve(MethodBase& methodBase, Matrix& A, Vector& b, ResultDomain& RD, bool verbose)
{
    using ResultVector = DenseVector<ResultDomain>;

    if (verbose) {
        std::cout << "--- Testing " << SolveMethod::name() << " on " << type_to_string(A) << " over ";
        A.field().write(std::cout) << " of size " << A.rowdim() << "x" << A.coldim() << std::endl;
    }

    //
    // Copying data for final check
    //

    using ResultMatrix = typename Matrix::template rebind<ResultDomain>::other;

    // @note The following const_cast prevents this ambiguity warning:
    // warning: ISO C++ says that these are ambiguous
    // - linbox/matrix/sparsematrix/sparse-sequence-vector.h:660:3: note: candidate 1
    //      SparseMatrix (const SparseMatrix<_Tp1, _Rw1> &Mat, const Field& F)
    // - linbox/matrix/sparsematrix/sparse-sequence-vector.h:643:3: note: candidate 2
    //      SparseMatrix (const Field &F, VectStream &stream)
    ResultMatrix RA(A, const_cast<const ResultDomain&>(RD));
    ResultVector Rb(RD, b);

    //
    // Solving
    //

    SolveMethod method(methodBase);
    ResultVector x(RD, A.coldim());

    try {
        solve(x, A, b, method);
        solveInPlace(x, A, b, method);
    } catch (...) {
        print_error<SolveMethod>(x, RA, b, "throws error");
        return false;
    }

    //
    // Checking result is correct
    //

    ResultVector RAx(RD, b.size());
    RA.apply(RAx, x);

    VectorDomain<ResultDomain> VD(RD);
    if (!VD.areEqual(RAx, Rb)) {
        print_error<SolveMethod>(x, RA, Rb, "Ax != b");
        return false;
    }

    return true;
}

template <class SolveMethod, class Domain, class ResultDomain>
bool test_dense_solve(MethodBase& method, Domain& D, ResultDomain& RD, int m, int n, int bitSize, int vectorBitSize, int seed,
                      bool verbose)
{
    using Vector = DenseVector<Domain>;

    DenseMatrix<Domain> A(D, m, n);
    Vector b(D, A.rowdim());

    generateMatrix(D, A, bitSize, seed);
    generateVector(D, A, b, vectorBitSize, seed + 1);

    return test_solve<SolveMethod>(method, A, b, RD, verbose);
}

template <class SolveMethod, class Domain, class ResultDomain>
bool test_sparse_solve(MethodBase& method, Domain& D, ResultDomain& RD, int m, int n, int bitSize, int vectorBitSize, int seed,
                       bool verbose)
{
    using Vector = DenseVector<Domain>;

    SparseMatrix<Domain> A(D, m, n);
    Vector b(D, A.rowdim());

    generateMatrix(D, A, bitSize, seed);
    generateVector(D, A, b, vectorBitSize, seed + 1);

    return test_solve<SolveMethod>(method, A, b, RD, verbose);
}

template <class SolveMethod, class Domain, class ResultDomain>
bool test_blackbox_solve(MethodBase& method, Domain& D, ResultDomain& RD, int m, int n, int bitSize, int vectorBitSize, int seed,
                         bool verbose)
{
    using Vector = DenseVector<Domain>;

    DenseMatrix<Domain> AData(D, n, m);
    generateMatrix(D, AData, bitSize, seed);

    // We're using a Transpose to use our blackbox interface
    Transpose<DenseMatrix<Domain>> A(AData);
    Vector b(D, A.rowdim());
    generateVector(D, A, b, vectorBitSize, seed + 1);

    return test_solve<SolveMethod>(method, A, b, RD, verbose);
}

int main(int argc, char** argv)
{
    Integer q = 131071;
    bool verbose = false;
    bool loop = false;
    int seed = -1;
    int bitSize = 100;
    int vectorBitSize = -1;
    int m = 32;
    int n = 24;
    std::string dispatchString = "AUTO";

    static Argument args[] = {
        {'q', "-q", "Field characteristic.", TYPE_INTEGER, &q},
        {'v', "-v", "Enable verbose mode.", TYPE_BOOL, &verbose},
        {'l', "-l", "Infinite loop of tests.", TYPE_BOOL, &loop},
        {'s', "-s", "Seed for randomness.", TYPE_INT, &seed},
        {'b', "-b", "Bit size for rational solve tests.", TYPE_INT, &bitSize},
        {'B', "-B", "Vector bit size for rational solve tests (defaults to -b if not specified).", TYPE_INT, &vectorBitSize},
        {'m', "-m", "Row dimension of matrices.", TYPE_INT, &m},
        {'n', "-n", "Column dimension of matrices.", TYPE_INT, &n},
        {'d', "-d", "Dispatch mode (either AUTO, SEQ, SMP or MPI).", TYPE_STR, &dispatchString},
        END_OF_ARGUMENTS};

    parseArguments(argc, argv, args);

    // Setting up context

    Communicator communicator(0, nullptr);

    MethodBase method;
    method.pCommunicator = &communicator;
    method.dispatch = Dispatch::Auto;
    if (dispatchString == "MPI")
        method.dispatch = Dispatch::Distributed;
    else if (dispatchString == "SEQ")
        method.dispatch = Dispatch::Sequential;
    else if (dispatchString == "SMP")
        method.dispatch = Dispatch::SMP;
    else if (dispatchString != "AUTO") {
        std::cerr << "-d Dispatch mode should be either AUTO, SEQ, SMP or MPI" << std::endl;
        return EXIT_FAILURE;
    }

    if (vectorBitSize < 0) {
        vectorBitSize = bitSize;
    }

    if (seed < 0) {
        seed = time(nullptr);
    }

    if (verbose) {
        commentator().setReportStream(std::cout);
    }

    Givaro::ZRing<Givaro::Integer> ZZ;
    Givaro::QField<Givaro::Rational> QQ;
    Givaro::Modular<double> F(q);

    bool ok = true;
    do {
        // ----- Rational Auto
        ok &= test_dense_solve<Method::Auto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        ok &= test_sparse_solve<Method::Auto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        // @fixme Dixon<Wiedemann> does not compile
        // ok &= test_blackbox_solve<Method::Auto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);

        // ----- Rational CRA
        // @fixme @bug When bitSize = 5 and vectorBitSize = 50, CRA fails
        ok &= test_dense_solve<Method::CRAAuto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        ok &= test_sparse_solve<Method::CRAAuto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        // ok &= test_blackbox_solve<Method::CRAAuto>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed,
        // verbose);

        // ----- Rational Dixon
        ok &= test_dense_solve<Method::Dixon>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        ok &= test_sparse_solve<Method::Dixon>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);
        // @fixme Dixon<Wiedemann> does not compile
        // ok &= test_blackbox_solve<Method::Dixon>(method, ZZ, QQ, m, n, bitSize, vectorBitSize, seed, verbose);

        // ----- Rational SymbolicNumeric
        // @note SymbolicNumeric methods are only implemented on DenseMatrix
        // @fixme Singular case fails
        // ok &= test_dense_solve<Method::SymbolicNumericOverlap>(method, ZZ, QQ, m, n, bitSize, vectorBitSize,
        // seed, verbose);
        // @fixme Fails
        // ok &= test_sparse_solve<Method::SymbolicNumericNorm>(method, ZZ, QQ, m, n, bitSize, vectorBitSize,
        // seed, verbose);

        // ----- Modular Auto
        ok &= test_dense_solve<Method::Auto>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::Auto>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::Auto>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Blackbox
        ok &= test_dense_solve<Method::Blackbox>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::Blackbox>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::Blackbox>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular DenseElimination
        ok &= test_dense_solve<Method::DenseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::DenseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::DenseElimination>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular SparseElimination
        ok &= test_dense_solve<Method::SparseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::SparseElimination>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::SparseElimination>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Wiedemann
        ok &= test_dense_solve<Method::Wiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_sparse_solve<Method::Wiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        ok &= test_blackbox_solve<Method::Wiedemann>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Lanczos
        // @fixme Dense is segfaulting
        // ok &= test_dense_solve<Method::Lanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // @fixme Singular case fails
        // ok &= test_sparse_solve<Method::Lanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_sparse_blackbox_solve<Method::Lanczos>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular BlockLanczos
        // @fixme Dense does not compile
        // ok &= test_dense_solve<Method::BlockLanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // @fixme Sparse is segfaulting
        // ok &= test_sparse_solve<Method::BlockLanczos>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_blackbox_solve<Method::BlockLanczos>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular BlockWiedemann
        // @deprecated These do not compile anymore @fixme In test-solve, it works
        // ok &= test_dense_solve<Method::BlockWiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_sparse_solve<Method::BlockWiedemann>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_blackbox_solve<Method::BlockWiedemann>(method, F, F, m, n, 0, 0, seed, verbose);

        // ----- Modular Coppersmith
        // @deprecated These do not compile anymore
        // ok &= test_dense_solve<Method::Coppersmith>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_sparse_solve<Method::Coppersmith>(method, F, F, m, n, 0, 0, seed, verbose);
        // ok &= test_blackbox_solve<Method::Coppersmith>(method, F, F, m, n, 0, 0, seed, verbose);

        if (!ok) {
            std::cerr << "Failed with seed: " << seed << std::endl;
        }

        seed += 1;
    } while (ok && loop);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/**
 * @file llurlentry.cpp
 * @author Martin Reddy
 * @brief Describes the Url types that can be registered in LLUrlRegistry
 *
 * $LicenseInfo:firstyear=2009&license=viewergpl$
 *
 * Copyright (c) 2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llurlentryagent.h"

#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"

//
// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
//
LLUrlEntryAgent::LLUrlEntryAgent()
{
	mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/\\w+",
							boost::regex::perl|boost::regex::icase);
	mMenuName = "menu_url_agent.xml";
	mIcon = "Generic_Person";
	mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
}

// IDEVO demo code
static std::string clean_name(const std::string& first, const std::string& last)
{
	std::string displayname;
	if (first == "miyazaki23") // IDEVO demo code
	{
		// miyazaki
		displayname += (char)(0xE5);
		displayname += (char)(0xAE);
		displayname += (char)(0xAE);
		displayname += (char)(0xE5);
		displayname += (char)(0xB4);
		displayname += (char)(0x8E);
		// hayao
		displayname += (char)(0xE9);
		displayname += (char)(0xA7);
		displayname += (char)(0xBF);
		// san
		displayname += (char)(0xE3);
		displayname += (char)(0x81);
		displayname += (char)(0x95);
		displayname += (char)(0xE3);
		displayname += (char)(0x82);
		displayname += (char)(0x93);
	}
	else if (first == "Jim")
	{
		displayname = "Jos";
		displayname += (char)(0xC3);
		displayname += (char)(0xA9);
		displayname += " Sanchez";
	}
	else if (first == "James")
	{
		displayname = "James Cook";
	}

	std::string fullname = first;
	if (!last.empty())
	{
		fullname += ' ';
		fullname += last;
	}

	std::string final;
	if (!displayname.empty())
	{
		final = displayname + " (" + fullname + ")";
	}
	else
	{
		final = fullname;
	}
	return final;
}

void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
										  const std::string& first,
										  const std::string& last,
										  BOOL is_group)
{
	std::string final = clean_name(first, last);
	// received the agent name from the server - tell our observers
	callObservers(id.asString(), final);
}

std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
	if (!gCacheName)
	{
		// probably at the login screen, use short string for layout
		return LLTrans::getString("LoadingData");
	}

	std::string agent_id_string = getIDStringFromUrl(url);
	if (agent_id_string.empty())
	{
		// something went wrong, just give raw url
		return unescapeUrl(url);
	}

	LLUUID agent_id(agent_id_string);
	std::string first, last;
	if (agent_id.isNull())
	{
		return LLTrans::getString("AvatarNameNobody");
	}
	else if (gCacheName->getName(agent_id, first, last))
	{
		return clean_name(first, last);
	}
	else
	{
		gCacheName->get(agent_id, FALSE,
			boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
				this, _1, _2, _3, _4));
		addObserver(agent_id_string, url, cb);
		return LLTrans::getString("LoadingData");
	}
}
<commit_msg>Fixed typo in SLURL name conversion for "Resident"<commit_after>/**
 * @file llurlentry.cpp
 * @author Martin Reddy
 * @brief Describes the Url types that can be registered in LLUrlRegistry
 *
 * $LicenseInfo:firstyear=2009&license=viewergpl$
 *
 * Copyright (c) 2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llurlentryagent.h"

#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"

//
// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
//
LLUrlEntryAgent::LLUrlEntryAgent()
{
	mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/\\w+",
							boost::regex::perl|boost::regex::icase);
	mMenuName = "menu_url_agent.xml";
	mIcon = "Generic_Person";
	mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
}

// IDEVO demo code
static std::string clean_name(const std::string& first, const std::string& last)
{
	std::string displayname;
	if (first == "miyazaki23") // IDEVO demo code
	{
		// miyazaki
		displayname += (char)(0xE5);
		displayname += (char)(0xAE);
		displayname += (char)(0xAE);
		displayname += (char)(0xE5);
		displayname += (char)(0xB4);
		displayname += (char)(0x8E);
		// hayao
		displayname += (char)(0xE9);
		displayname += (char)(0xA7);
		displayname += (char)(0xBF);
		// san
		displayname += (char)(0xE3);
		displayname += (char)(0x81);
		displayname += (char)(0x95);
		displayname += (char)(0xE3);
		displayname += (char)(0x82);
		displayname += (char)(0x93);
	}
	else if (first == "Jim")
	{
		displayname = "Jos";
		displayname += (char)(0xC3);
		displayname += (char)(0xA9);
		displayname += " Sanchez";
	}
	else if (first == "James")
	{
		displayname = "James Cook";
	}

	std::string fullname = first;
	if (!last.empty()
		&& last != "Resident")
	{
		fullname += ' ';
		fullname += last;
	}

	std::string final;
	if (!displayname.empty())
	{
		final = displayname + " (" + fullname + ")";
	}
	else
	{
		final = fullname;
	}
	return final;
}

void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
										  const std::string& first,
										  const std::string& last,
										  BOOL is_group)
{
	std::string final = clean_name(first, last);
	// received the agent name from the server - tell our observers
	callObservers(id.asString(), final);
}

std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
	if (!gCacheName)
	{
		// probably at the login screen, use short string for layout
		return LLTrans::getString("LoadingData");
	}

	std::string agent_id_string = getIDStringFromUrl(url);
	if (agent_id_string.empty())
	{
		// something went wrong, just give raw url
		return unescapeUrl(url);
	}

	LLUUID agent_id(agent_id_string);
	std::string first, last;
	if (agent_id.isNull())
	{
		return LLTrans::getString("AvatarNameNobody");
	}
	else if (gCacheName->getName(agent_id, first, last))
	{
		return clean_name(first, last);
	}
	else
	{
		gCacheName->get(agent_id, FALSE,
			boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
				this, _1, _2, _3, _4));
		addObserver(agent_id_string, url, cb);
		return LLTrans::getString("LoadingData");
	}
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2012-2016 Alex Zhondin <lexxmark.dev@gmail.com>

   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 "PropertyDelegateSliderBox.h"
#include "../../PropertyView.h"

#include <QMouseEvent>
#include <QVariantAnimation>

QtnPropertyDelegateSlideBox::QtnPropertyDelegateSlideBox()
    : m_boxFillColor(QColor::fromRgb(200, 200, 255)),
      m_liveUpdate(false),
      m_drawBorder(true),
      m_updateByScroll(true),
      m_animate(false),
      m_dragValuePart(0),
      m_oldValuePart(0),
      m_animateWidget(nullptr)
{
}

QtnPropertyDelegateSlideBox::~QtnPropertyDelegateSlideBox()
{
    m_animation.reset();
}

void QtnPropertyDelegateSlideBox::applyAttributesImpl(const QtnPropertyDelegateAttributes& attributes)
{
    qtnGetAttribute(attributes, "fillColor", m_boxFillColor);
    qtnGetAttribute(attributes, "liveUpdate", m_liveUpdate);
    qtnGetAttribute(attributes, "drawBorder", m_drawBorder);
    qtnGetAttribute(attributes, "updateByScroll", m_updateByScroll);
    qtnGetAttribute(attributes, "animate", m_animate);
    qtnGetAttribute(attributes, "toolTip", m_itemToolTip);
}

bool QtnPropertyDelegateSlideBox::createSubItemValueImpl(QtnDrawContext& context, QtnSubItem& subItemValue)
{
    subItemValue.trackState();
    subItemValue.setTextAsTooltip(m_itemToolTip);
    subItemValue.drawHandler = qtnMemFn(this, &QtnPropertyDelegateSlideBox::draw);
    subItemValue.eventHandler = qtnMemFn(this, &QtnPropertyDelegateSlideBox::event);

    if (m_animate)
    {
        m_dragValuePart = propertyValuePart();
        m_animation.reset(new QVariantAnimation());
        m_animateWidget = context.widget->viewport();
        m_c1 = QObject::connect(property(), &QtnPropertyBase::propertyWillChange, qtnMemFn(this, &QtnPropertyDelegateSlideBox::onPropertyWillChange));
        m_c2 = QObject::connect(property(), &QtnPropertyBase::propertyDidChange, qtnMemFn(this, &QtnPropertyDelegateSlideBox::onPropertyDidChange));
    }

    return true;
}

void QtnPropertyDelegateSlideBox::draw(QtnDrawContext& context, const QtnSubItem& item)
{
    float valuePart = (item.state() == QtnSubItemStatePushed
                       || (m_animate && m_animation->state() == QAbstractAnimation::Running)) ? dragValuePart() : propertyValuePart();
    if (valuePart < 0)
        return;

    auto boxBorderColor = (item.state() == QtnSubItemStateNone) ? m_boxFillColor : m_boxFillColor.darker(150);

    auto boxRect = item.rect;
    boxRect.adjust(2, 2, -2, -2);

    auto valueRect = boxRect;
    valueRect.setWidth(int(valuePart * valueRect.width()));

    auto& painter = *context.painter;

    painter.save();

    painter.fillRect(valueRect, m_boxFillColor);

    painter.setPen(boxBorderColor);
    painter.drawRect(valueRect);
    if (m_drawBorder)
        painter.drawRect(boxRect);

    painter.restore();

    boxRect.adjust(context.widget->valueLeftMargin(), 0, 0, 0);
    qtnDrawValueText(valuePartToStr(valuePart), painter, boxRect, state(context.isActive, item.state()), nullptr);
}

bool QtnPropertyDelegateSlideBox::event(QtnEventContext& context, const QtnSubItem& item)
{
    switch (context.eventType())
    {
    case QEvent::KeyPress:
    {
        int key = context.eventAs<QKeyEvent>()->key();

        if ((key == Qt::Key_Plus) || (key == Qt::Key_Equal))
            incrementPropertyValue(1);
        else if ((key == Qt::Key_Minus) || (key == Qt::Key_Underscore))
            incrementPropertyValue(-1);
        else
            return false;

        return true;
    } break;

    case QEvent::Wheel:
    {
        if (m_updateByScroll)
        {
            int steps = context.eventAs<QWheelEvent>()->angleDelta().y()/120;
            incrementPropertyValue(steps);
            return true;
        }
        else
            return false;
    } break;

    case QtnSubItemEvent::Activated:
    {
        m_oldCursor = context.widget->cursor();
        return true;
    } break;

    case QtnSubItemEvent::PressMouse:
    {
        //context.widget->setCursor(Qt::SplitHCursor);
        if (!m_animate)
        {
            updateDragValuePart(context.eventAs<QtnSubItemEvent>()->x(), item.rect);
            context.updateWidget();
        }
        return true;
    } break;

    case QEvent::MouseMove:
    {
        if (item.state() == QtnSubItemStatePushed)
        {
            if (m_liveUpdate)
            {
                updateDragValuePart(context.eventAs<QMouseEvent>()->x(), item.rect);
                setPropertyValuePart(m_dragValuePart);
            }
            else if (!m_animate)
            {
                updateDragValuePart(context.eventAs<QMouseEvent>()->x(), item.rect);
                context.updateWidget();
            }
        }
        return true;
    } break;

    case QtnSubItemEvent::ReleaseMouse:
    {
        context.widget->setCursor(m_oldCursor);
        updateDragValuePart(context.eventAs<QtnSubItemEvent>()->x(), item.rect);
        setPropertyValuePart(m_dragValuePart);
        return true;
    } break;

    default:
        return false;
    }
}

void QtnPropertyDelegateSlideBox::updateDragValuePart(int x, const QRect& rect)
{
    m_dragValuePart = float(x - rect.left()) / rect.width();
    if (m_dragValuePart < 0)
        m_dragValuePart = 0;
    else if (m_dragValuePart > 1.f)
        m_dragValuePart = 1.f;
}

void QtnPropertyDelegateSlideBox::onPropertyWillChange(const QtnPropertyBase*, const QtnPropertyBase*, QtnPropertyChangeReason, QtnPropertyValuePtr)
{
    m_oldValuePart = m_dragValuePart = propertyValuePart();
}

void QtnPropertyDelegateSlideBox::onPropertyDidChange(const QtnPropertyBase*, const QtnPropertyBase*, QtnPropertyChangeReason)
{
    m_animation->setStartValue(m_oldValuePart);
    m_animation->setEndValue(propertyValuePart());
    m_animation->setDuration(300);
    m_animation->setEasingCurve(QEasingCurve::OutCirc);
    QObject::connect(m_animation.data(), &QVariantAnimation::valueChanged, qtnMemFn(this, &QtnPropertyDelegateSlideBox::onAnimationChanged));
    m_animation->start();
}

void QtnPropertyDelegateSlideBox::onAnimationChanged(const QVariant& value)
{
    m_dragValuePart = value.toFloat();
   if (m_animateWidget)
       m_animateWidget->update();
}

<commit_msg>set tooltip default<commit_after>/*
   Copyright (c) 2012-2016 Alex Zhondin <lexxmark.dev@gmail.com>

   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 "PropertyDelegateSliderBox.h"
#include "../../PropertyView.h"

#include <QMouseEvent>
#include <QVariantAnimation>

QtnPropertyDelegateSlideBox::QtnPropertyDelegateSlideBox()
    : m_boxFillColor(QColor::fromRgb(200, 200, 255)),
      m_liveUpdate(false),
      m_drawBorder(true),
      m_updateByScroll(true),
      m_animate(false),
      m_itemToolTip(QObject::tr("Drag/Scroll mouse to change value")),
      m_dragValuePart(0),
      m_oldValuePart(0),
      m_animateWidget(nullptr)
{
}

QtnPropertyDelegateSlideBox::~QtnPropertyDelegateSlideBox()
{
    m_animation.reset();
}

void QtnPropertyDelegateSlideBox::applyAttributesImpl(const QtnPropertyDelegateAttributes& attributes)
{
    qtnGetAttribute(attributes, "fillColor", m_boxFillColor);
    qtnGetAttribute(attributes, "liveUpdate", m_liveUpdate);
    qtnGetAttribute(attributes, "drawBorder", m_drawBorder);
    qtnGetAttribute(attributes, "updateByScroll", m_updateByScroll);
    qtnGetAttribute(attributes, "animate", m_animate);
    qtnGetAttribute(attributes, "toolTip", m_itemToolTip);
}

bool QtnPropertyDelegateSlideBox::createSubItemValueImpl(QtnDrawContext& context, QtnSubItem& subItemValue)
{
    subItemValue.trackState();
    subItemValue.setTextAsTooltip(m_itemToolTip);
    subItemValue.drawHandler = qtnMemFn(this, &QtnPropertyDelegateSlideBox::draw);
    subItemValue.eventHandler = qtnMemFn(this, &QtnPropertyDelegateSlideBox::event);

    if (m_animate)
    {
        m_dragValuePart = propertyValuePart();
        m_animation.reset(new QVariantAnimation());
        m_animateWidget = context.widget->viewport();
        m_c1 = QObject::connect(property(), &QtnPropertyBase::propertyWillChange, qtnMemFn(this, &QtnPropertyDelegateSlideBox::onPropertyWillChange));
        m_c2 = QObject::connect(property(), &QtnPropertyBase::propertyDidChange, qtnMemFn(this, &QtnPropertyDelegateSlideBox::onPropertyDidChange));
    }

    return true;
}

void QtnPropertyDelegateSlideBox::draw(QtnDrawContext& context, const QtnSubItem& item)
{
    float valuePart = (item.state() == QtnSubItemStatePushed
                       || (m_animate && m_animation->state() == QAbstractAnimation::Running)) ? dragValuePart() : propertyValuePart();
    if (valuePart < 0)
        return;

    auto boxBorderColor = (item.state() == QtnSubItemStateNone) ? m_boxFillColor : m_boxFillColor.darker(150);

    auto boxRect = item.rect;
    boxRect.adjust(2, 2, -2, -2);

    auto valueRect = boxRect;
    valueRect.setWidth(int(valuePart * valueRect.width()));

    auto& painter = *context.painter;

    painter.save();

    painter.fillRect(valueRect, m_boxFillColor);

    painter.setPen(boxBorderColor);
    painter.drawRect(valueRect);
    if (m_drawBorder)
        painter.drawRect(boxRect);

    painter.restore();

    boxRect.adjust(context.widget->valueLeftMargin(), 0, 0, 0);
    qtnDrawValueText(valuePartToStr(valuePart), painter, boxRect, state(context.isActive, item.state()), nullptr);
}

bool QtnPropertyDelegateSlideBox::event(QtnEventContext& context, const QtnSubItem& item)
{
    switch (context.eventType())
    {
    case QEvent::KeyPress:
    {
        int key = context.eventAs<QKeyEvent>()->key();

        if ((key == Qt::Key_Plus) || (key == Qt::Key_Equal))
            incrementPropertyValue(1);
        else if ((key == Qt::Key_Minus) || (key == Qt::Key_Underscore))
            incrementPropertyValue(-1);
        else
            return false;

        return true;
    } break;

    case QEvent::Wheel:
    {
        if (m_updateByScroll)
        {
            int steps = context.eventAs<QWheelEvent>()->angleDelta().y()/120;
            incrementPropertyValue(steps);
            return true;
        }
        else
            return false;
    } break;

    case QtnSubItemEvent::Activated:
    {
        m_oldCursor = context.widget->cursor();
        return true;
    } break;

    case QtnSubItemEvent::PressMouse:
    {
        //context.widget->setCursor(Qt::SplitHCursor);
        if (!m_animate)
        {
            updateDragValuePart(context.eventAs<QtnSubItemEvent>()->x(), item.rect);
            context.updateWidget();
        }
        return true;
    } break;

    case QEvent::MouseMove:
    {
        if (item.state() == QtnSubItemStatePushed)
        {
            if (m_liveUpdate)
            {
                updateDragValuePart(context.eventAs<QMouseEvent>()->x(), item.rect);
                setPropertyValuePart(m_dragValuePart);
            }
            else if (!m_animate)
            {
                updateDragValuePart(context.eventAs<QMouseEvent>()->x(), item.rect);
                context.updateWidget();
            }
        }
        return true;
    } break;

    case QtnSubItemEvent::ReleaseMouse:
    {
        context.widget->setCursor(m_oldCursor);
        updateDragValuePart(context.eventAs<QtnSubItemEvent>()->x(), item.rect);
        setPropertyValuePart(m_dragValuePart);
        return true;
    } break;

    default:
        return false;
    }
}

void QtnPropertyDelegateSlideBox::updateDragValuePart(int x, const QRect& rect)
{
    m_dragValuePart = float(x - rect.left()) / rect.width();
    if (m_dragValuePart < 0)
        m_dragValuePart = 0;
    else if (m_dragValuePart > 1.f)
        m_dragValuePart = 1.f;
}

void QtnPropertyDelegateSlideBox::onPropertyWillChange(const QtnPropertyBase*, const QtnPropertyBase*, QtnPropertyChangeReason, QtnPropertyValuePtr)
{
    m_oldValuePart = m_dragValuePart = propertyValuePart();
}

void QtnPropertyDelegateSlideBox::onPropertyDidChange(const QtnPropertyBase*, const QtnPropertyBase*, QtnPropertyChangeReason)
{
    m_animation->setStartValue(m_oldValuePart);
    m_animation->setEndValue(propertyValuePart());
    m_animation->setDuration(300);
    m_animation->setEasingCurve(QEasingCurve::OutCirc);
    QObject::connect(m_animation.data(), &QVariantAnimation::valueChanged, qtnMemFn(this, &QtnPropertyDelegateSlideBox::onAnimationChanged));
    m_animation->start();
}

void QtnPropertyDelegateSlideBox::onAnimationChanged(const QVariant& value)
{
    m_dragValuePart = value.toFloat();
   if (m_animateWidget)
       m_animateWidget->update();
}

<|endoftext|>


<commit_before>/**
  This file contains a sequence of tests to perform for different instances of a templatized fixture.
  It is thus inlined several times in the .cpp test file.
  */

// ==============================
// Set/get value tests
TEST_F(TestMatrix, set_fullMat ) { ASSERT_TRUE( matrixMaxDiff(mat,fullMat) < 100*epsilon() ); }
TEST_F(TestMatrix, set_crs1 ) { ASSERT_TRUE( matrixMaxDiff( fullMat,crs1 ) < 100*epsilon() ); }
TEST_F(TestMatrix, set_crs2 ) { ASSERT_TRUE( matrixMaxDiff(fullMat,crs2) < 100*epsilon() ); }
TEST_F(TestMatrix, set_mapMat ) { ASSERT_TRUE( matrixMaxDiff(fullMat,mapMat) < 100*epsilon() ); }
TEST_F(TestMatrix, set_eiBlock1 ) { ASSERT_TRUE( matrixMaxDiff(fullMat,eiBlock1) < 100*epsilon() ); }
TEST_F(TestMatrix, set_eiBlock2 ) { ASSERT_TRUE( matrixMaxDiff(fullMat,eiBlock2) < 100*epsilon() ); }
TEST_F(TestMatrix, set_eiBase ) { ASSERT_TRUE( matrixMaxDiff(fullMat,eiBase) < 100*epsilon() ); }
TEST_F(TestMatrix, eigenMatrix_update ) { ASSERT_TRUE( checkEigenMatrixUpdate() ); }
TEST_F(TestMatrix, eigenMatrix_block_row_filling ) { ASSERT_TRUE( checkEigenMatrixBlockRowFilling() ); }
TEST_F(TestMatrix, eigenMatrixBlockFromCompressedRowSparseMatrix ) { ASSERT_TRUE( checkEigenMatrixBlockFromCompressedRowSparseMatrix() ); }
TEST_F(TestMatrix, eigenMapToDenseMatrix ) { ASSERT_TRUE( checkEigenDenseMatrix() ); }

// ==============================
// Matrix-Vector product tests
TEST_F(TestMatrix, set_fullVec_nrows_reference )
{
    ASSERT_TRUE(vectorMaxDiff(vecM,fullVec_nrows_reference) < epsilon() );
}
TEST_F(TestMatrix, fullMat_vector_product )
{
//    fullMat.opMulV(&fullVec_nrows_result,&fullVec_ncols);
    fullVec_nrows_result = fullMat * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );
}
TEST_F(TestMatrix, mapMat_vector_product )
{
//    mapMat.opMulV(&fullVec_nrows_result,&fullVec_ncols);
    fullVec_nrows_result = mapMat * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );
}
TEST_F(TestMatrix, eiBlock1_vector_product )
{
//    eiBlock1.opMulV(&fullVec_nrows_result,&fullVec_ncols);
//    eiBlock1.multVector(fullVec_nrows_result,fullVec_ncols);
    fullVec_nrows_result = eiBlock1 * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );

}
TEST_F(TestMatrix, crs1_vector_product )
{
//    EXPECT_TRUE(NROWS%BROWS==0 && NCOLS%BCOLS==0) << "Error: CompressedRowSparseMatrix * Vector crashes when the size of the matrix is not a multiple of the size of the matrix blocks. Aborting this test, and reporting a failure."; // otherwise the product crashes
//    crs1.opMulV(&fullVec_nrows_result,&fullVec_ncols);
    fullVec_nrows_result = crs1 * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );
}

// ==============================
// Matrix product tests
TEST_F(TestMatrix, full_matrix_product ) { ASSERT_TRUE( matrixMaxDiff(matMultiplication,fullMultiplication) < 100*epsilon() );  }
TEST_F(TestMatrix, crs_matrix_product ) { ASSERT_TRUE( matrixMaxDiff(fullMultiplication,crsMultiplication) < 100*epsilon() ); }
TEST_F(TestMatrix, EigenBase_matrix_product ) { ASSERT_TRUE( matrixMaxDiff(fullMultiplication,eiBaseMultiplication) < 100*epsilon() ); }
TEST_F(TestMatrix, EigenSparseDense_matrix_product ) { ASSERT_TRUE( EigenDenseMatrix(eiBaseMultiplication.compressedMatrix) == eiDenseMultiplication ); }
TEST_F(TestMatrix, full_matrix_transposeproduct ) { ASSERT_TRUE( matrixMaxDiff(matTransposeMultiplication,fullTransposeMultiplication) < 100*epsilon() ); }
TEST_F(TestMatrix, crs_matrix_transposeproduct ) { ASSERT_TRUE( matrixMaxDiff(fullTransposeMultiplication,crsTransposeMultiplication) < 100*epsilon() ); }

// Matrix addition
TEST_F(TestMatrix, crs_matrix_addition )
{
    crs2 = crs1 + crs1;
    ASSERT_TRUE( matrixMaxDiff(mat*2,crs2) < 100*epsilon() );

    crs2 += crs1;
    ASSERT_TRUE( matrixMaxDiff(mat*3,crs2) < 100*epsilon() );

    crs2 -= crs1;
//    ASSERT_TRUE( matrixMaxDiff(mat*2,crs2) < 100*epsilon() );
    ASSERT_FALSE( matrixMaxDiff(mat*2,crs2) < 100*epsilon() ); // create an error to check if I get a message from Jenkins
}
<commit_msg>META-TEST change something without fixing the test<commit_after>/**
  This file contains a sequence of tests to perform for different instances of a templatized fixture.
  It is thus inlined several times in the .cpp test file.
  */

// ==============================
// Set/get value tests
TEST_F(TestMatrix, set_fullMat ) { ASSERT_TRUE( matrixMaxDiff(mat,fullMat) < 100*epsilon() ); }
TEST_F(TestMatrix, set_crs1 ) { ASSERT_TRUE( matrixMaxDiff( fullMat,crs1 ) < 100*epsilon() ); }
TEST_F(TestMatrix, set_crs2 ) { ASSERT_TRUE( matrixMaxDiff(fullMat,crs2) < 100*epsilon() ); }
TEST_F(TestMatrix, set_mapMat ) { ASSERT_TRUE( matrixMaxDiff(fullMat,mapMat) < 100*epsilon() ); }
TEST_F(TestMatrix, set_eiBlock1 ) { ASSERT_TRUE( matrixMaxDiff(fullMat,eiBlock1) < 100*epsilon() ); }
TEST_F(TestMatrix, set_eiBlock2 ) { ASSERT_TRUE( matrixMaxDiff(fullMat,eiBlock2) < 100*epsilon() ); }
TEST_F(TestMatrix, set_eiBase ) { ASSERT_TRUE( matrixMaxDiff(fullMat,eiBase) < 100*epsilon() ); }
TEST_F(TestMatrix, eigenMatrix_update ) { ASSERT_TRUE( checkEigenMatrixUpdate() ); }
TEST_F(TestMatrix, eigenMatrix_block_row_filling ) { ASSERT_TRUE( checkEigenMatrixBlockRowFilling() ); }
TEST_F(TestMatrix, eigenMatrixBlockFromCompressedRowSparseMatrix ) { ASSERT_TRUE( checkEigenMatrixBlockFromCompressedRowSparseMatrix() ); }
TEST_F(TestMatrix, eigenMapToDenseMatrix ) { ASSERT_TRUE( checkEigenDenseMatrix() ); }

// ==============================
// Matrix-Vector product tests
TEST_F(TestMatrix, set_fullVec_nrows_reference )
{
    ASSERT_TRUE(vectorMaxDiff(vecM,fullVec_nrows_reference) < epsilon() );
}
TEST_F(TestMatrix, fullMat_vector_product )
{
//    fullMat.opMulV(&fullVec_nrows_result,&fullVec_ncols);
    fullVec_nrows_result = fullMat * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );
}
TEST_F(TestMatrix, mapMat_vector_product )
{
//    mapMat.opMulV(&fullVec_nrows_result,&fullVec_ncols);
    fullVec_nrows_result = mapMat * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );
}
TEST_F(TestMatrix, eiBlock1_vector_product )
{
//    eiBlock1.opMulV(&fullVec_nrows_result,&fullVec_ncols);
//    eiBlock1.multVector(fullVec_nrows_result,fullVec_ncols);
    fullVec_nrows_result = eiBlock1 * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );

}
TEST_F(TestMatrix, crs1_vector_product )
{
//    EXPECT_TRUE(NROWS%BROWS==0 && NCOLS%BCOLS==0) << "Error: CompressedRowSparseMatrix * Vector crashes when the size of the matrix is not a multiple of the size of the matrix blocks. Aborting this test, and reporting a failure."; // otherwise the product crashes
//    crs1.opMulV(&fullVec_nrows_result,&fullVec_ncols);
    fullVec_nrows_result = crs1 * fullVec_ncols;
    ASSERT_TRUE(vectorMaxDiff(fullVec_nrows_reference,fullVec_nrows_result) < epsilon() );
}

// ==============================
// Matrix product tests
TEST_F(TestMatrix, full_matrix_product ) { ASSERT_TRUE( matrixMaxDiff(matMultiplication,fullMultiplication) < 100*epsilon() );  }
TEST_F(TestMatrix, crs_matrix_product ) { ASSERT_TRUE( matrixMaxDiff(fullMultiplication,crsMultiplication) < 100*epsilon() ); }
TEST_F(TestMatrix, EigenBase_matrix_product ) { ASSERT_TRUE( matrixMaxDiff(fullMultiplication,eiBaseMultiplication) < 100*epsilon() ); }
TEST_F(TestMatrix, EigenSparseDense_matrix_product ) { ASSERT_TRUE( EigenDenseMatrix(eiBaseMultiplication.compressedMatrix) == eiDenseMultiplication ); }
TEST_F(TestMatrix, full_matrix_transposeproduct ) { ASSERT_TRUE( matrixMaxDiff(matTransposeMultiplication,fullTransposeMultiplication) < 100*epsilon() ); }
TEST_F(TestMatrix, crs_matrix_transposeproduct ) { ASSERT_TRUE( matrixMaxDiff(fullTransposeMultiplication,crsTransposeMultiplication) < 100*epsilon() ); }

// Matrix addition
TEST_F(TestMatrix, crs_matrix_addition )
{
    crs2 = crs1 + crs1;
    ASSERT_TRUE( matrixMaxDiff(mat*2,crs2) < 100*epsilon() );

    crs2 += crs1;
    ASSERT_TRUE( matrixMaxDiff(mat*3,crs2) < 100*epsilon() );

    crs2 -= crs1;
    ASSERT_FALSE( matrixMaxDiff(mat*2,crs2) < 100*epsilon() ); // create an error to check if I get a message from Jenkins
    //    ASSERT_TRUE( matrixMaxDiff(mat*2,crs2) < 100*epsilon() );
}
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------*\
 *                                OpenSG                                     *
 *                                                                           *
 *                                                                           *
 *           Copyright (C) 2003 by the OpenSG Forum                          *
 *                                                                           *
 *                            www.opensg.org                                 *
 *                                                                           *
 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * 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         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#define OSG_COMPILE_FIELDCONTAINERFACTORY

#include <cstdlib>
#include <cstdio>

#include "OSGConfig.h"

#include "OSGFieldContainerFactory.h"
#include "OSGSingletonHolder.ins"
#include "OSGFieldContainerType.h"

#include "OSGTypeFactory.h"

OSG_BEGIN_NAMESPACE

OSG_SINGLETON_INST(FieldContainerFactoryBase, addPostFactoryExitFunction)

template class SingletonHolder<FieldContainerFactoryBase>;

OSG_END_NAMESPACE

#include "OSGFieldContainer.h"

OSG_BEGIN_NAMESPACE

/*! \class OSG::FieldContainerFactoryBase

This class is a singleton.  It should be accessed using the typedef
for OSG::FieldContainerFactory.
*/

/*-------------------------------------------------------------------------*/
/*                            Constructors                                 */

FieldContainerFactoryBase::FieldContainerFactoryBase(void) :
     Inherited      ("FieldContainerFactory"),
#ifndef OSG_EMBEDDED
    _pStoreLock     (NULL                   ),
#endif
    _vContainerStore(                       ),
    _pMapper        (NULL                   )
{
    _vContainerStore.push_back(NULL);
}

FieldContainerFactoryBase::FieldContainerFactoryBase(
    const Char8 *szFactoryName) :

     Inherited      (szFactoryName),
#ifndef OSG_EMBEDDED
    _pStoreLock     (NULL         ),
#endif
	_vContainerStore(             ),
    _pMapper        (NULL         )
{
    _vContainerStore.push_back(NULL);
}

/*-------------------------------------------------------------------------*/
/*                             Destructor                                  */

FieldContainerFactoryBase::~FieldContainerFactoryBase(void)
{
}

/*-------------------------------------------------------------------------*/
/*                             Assignment                                  */

bool FieldContainerFactoryBase::initialize(void)
{
    if(this->_bInitialized == true)
        return true;

#ifndef OSG_EMBEDDED
    _pStoreLock = ThreadManager::the()->getLock("ContainerFactory::slock",
                                                false);

    PINFO << "Got store lock " << _pStoreLock.get() << std::endl;

    if(_pStoreLock == NULL)
    {
        return false;
    }
    else
    {
#endif
        return Inherited::initialize();
#ifndef OSG_EMBEDDED
    }
#endif
}

bool FieldContainerFactoryBase::terminate(void)
{
    bool returnValue = Inherited::terminate();

#ifndef OSG_EMBEDDED
    _pStoreLock = NULL;
#endif

    this->_bInitialized = false;

#ifdef OSG_DEBUG
    ContainerStoreIt sI = _vContainerStore.begin();
    ContainerStoreIt sE = _vContainerStore.end  ();

    for(UInt32 i = 0; sI != sE; ++sI, ++i)
    {
        if((*sI) != NULL)
        {
            FWARNING(("FieldContainerFactoryBase::terminate: "
                      "Entry [%d] is not NULL ([%p]). \n", i, *sI));

            for(UInt32 j = 0; j < (*sI)->getNumAspects(); ++j)
            {
                if((*sI)->getPtr(j) != NULL)
                {
                    FWARNING(("  [%d] [%p] [%s] [%d %d]\n",
                              j,
                              (*sI)->getPtr(j),
                              (*sI)->getPtr(j)->getType().getCName(),
                              (*sI)->getPtr(j)->getRefCount(),
                              (*sI)->getPtr(j)->getWeakRefCount() ));
                }
                else
                {
                    FWARNING(("  [%d] [%p] [] [N/A N/A]\n",
                              j,
                              (*sI)->getPtr(j)));
                }
            }
        }
    }
#endif // OSG_DEBUG

    return returnValue;
}

bool FieldContainerFactoryBase::initializeFactoryPost(void)
{
    return Inherited::initializeFactoryPost();
}

UInt32 FieldContainerFactoryBase::registerContainer(
    const ContainerPtr &pContainer)
{
#ifdef OSG_ENABLE_VALGRIND_CHECKS
    VALGRIND_CHECK_VALUE_IS_DEFINED(pContainer);
#endif

    UInt32 returnValue = 0;

#ifndef OSG_EMBEDDED
    _pStoreLock->acquire();
#endif

#ifdef OSG_MT_CPTR_ASPECT
    ContainerHandlerP pHandler = NULL;

    if(pContainer != NULL)
        pHandler = pContainer->getAspectStore();

    _vContainerStore.push_back(pHandler);
#else
    _vContainerStore.push_back(pContainer);
#endif

    returnValue = _vContainerStore.size() - 1;

#ifndef OSG_EMBEDDED
    _pStoreLock->release();
#endif

    return returnValue;
}

/*! Try to find the ptr container in the factory. Primarily used to verify
that a container is still valid and registered with the factory. As this
function does not access the ptr itself at all, it is safe to call it with
corrupted data.

\return The container's id, or -1 if not found.

\warning It uses the current thread's aspect to compare against, therefore it's not
possible with this function to verify pointers from other threads/aspects.

*/

Int32 FieldContainerFactoryBase::findContainer(ContainerPtr ptr) const
{
#ifndef OSG_EMBEDDED
    _pStoreLock->acquire();
#endif

    ContainerStore::const_iterator it, end;
    Int32 id = 0;
    Int32 returnValue = -1;

    for(it = _vContainerStore.begin(), end = _vContainerStore.end();
        it != end; ++it, ++id)
    {
#ifdef OSG_MT_CPTR_ASPECT
        if((*it)->getPtr() == ptr)
#else
        if(*it == ptr)
#endif
        {
            returnValue = id;
            break;
        }
    }

#ifndef OSG_EMBEDDED
    _pStoreLock->release();
#endif

    return returnValue;
}

/*-------------------------------------------------------------------------*/
/*                             Comparison                                  */

void FieldContainerFactoryBase::dump(void)
{
    ContainerStoreIt sI = _vContainerStore.begin();
    ContainerStoreIt sE = _vContainerStore.end  ();

    for(UInt32 i = 0; sI != sE; ++sI, ++i)
    {
        if((*sI) != NULL)
        {
            FWARNING(("FieldContainerFactoryBase::dump: "
                      "Entry [%d] is not NULL ([%p]). \n", i, *sI));

            for(UInt32 j = 0; j < (*sI)->getNumAspects(); ++j)
            {
                if((*sI)->getPtr(j) != NULL)
                {
                    FWARNING(("  [%d] [%p] [%s] [%d %d]\n",
                              j,
                              (*sI)->getPtr(j),
                              (*sI)->getPtr(j)->getType().getCName(),
                              (*sI)->getPtr(j)->getRefCount(),
                              (*sI)->getPtr(j)->getWeakRefCount() ));
                }
                else
                {
                    FWARNING(("  [%d] [%p] [] [N/A N/A]\n",
                              j,
                              (*sI)->getPtr(j)));
                }
            }
        }
    }
}

DerivedFieldContainerTypeIterator
    FieldContainerFactoryBase::begin(const FieldContainerType &oRef)
{
    return DerivedFieldContainerTypeIterator(oRef);
}

DerivedFieldContainerTypeIterator
    FieldContainerFactoryBase::end(void)
{
    return DerivedFieldContainerTypeIterator();
}

FieldContainerType *DerivedFieldContainerTypeIterator::operator->(void)
{
    return _pCurrentType;
}

FieldContainerType *DerivedFieldContainerTypeIterator::operator *(void)
{
    return _pCurrentType;
}

void DerivedFieldContainerTypeIterator::operator++ (void)
{
    _pCurrentType = NULL;

    ++_uiCurrentType;

    for(; _uiCurrentType < TypeFactory::the()->getNumTypes();
        ++_uiCurrentType)
    {
        FieldContainerType *pTestType =
            FieldContainerFactory::the()->findType(_uiCurrentType);

        if(pTestType                        != NULL)
        {
            if(pTestType->isDerivedFrom(*_pRef) == true   )
            {
                _pCurrentType = pTestType;

                break;
            }
        }
    }
}

bool DerivedFieldContainerTypeIterator::operator ==(
    const DerivedFieldContainerTypeIterator &lhs)
{
    return this->_uiCurrentType == lhs._uiCurrentType;
}

bool DerivedFieldContainerTypeIterator::operator !=(
    const DerivedFieldContainerTypeIterator &lhs)
{
    return !(*this == lhs);
}

DerivedFieldContainerTypeIterator::DerivedFieldContainerTypeIterator(void) :
    _pRef         (NULL                             ),
    _uiCurrentType(TypeFactory::the()->getNumTypes()),
    _pCurrentType (NULL                             )
{
}

DerivedFieldContainerTypeIterator::DerivedFieldContainerTypeIterator(
    const FieldContainerType &oRef) :

    _pRef         (&oRef),
    _uiCurrentType(0    ),
    _pCurrentType (NULL )
{
    ++(*this);
}

DerivedFieldContainerTypeIterator::DerivedFieldContainerTypeIterator(
    const DerivedFieldContainerTypeIterator &source) :

    _pRef         (source._pRef         ),
    _uiCurrentType(source._uiCurrentType),
    _pCurrentType (source._pCurrentType )
{
}

OSG_END_NAMESPACE

<commit_msg>fixed: missing locking in FCFactory::dump<commit_after>/*---------------------------------------------------------------------------*\
 *                                OpenSG                                     *
 *                                                                           *
 *                                                                           *
 *           Copyright (C) 2003 by the OpenSG Forum                          *
 *                                                                           *
 *                            www.opensg.org                                 *
 *                                                                           *
 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * 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         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#define OSG_COMPILE_FIELDCONTAINERFACTORY

#include <cstdlib>
#include <cstdio>

#include "OSGConfig.h"

#include "OSGFieldContainerFactory.h"
#include "OSGSingletonHolder.ins"
#include "OSGFieldContainerType.h"

#include "OSGTypeFactory.h"

OSG_BEGIN_NAMESPACE

OSG_SINGLETON_INST(FieldContainerFactoryBase, addPostFactoryExitFunction)

template class SingletonHolder<FieldContainerFactoryBase>;

OSG_END_NAMESPACE

#include "OSGFieldContainer.h"

OSG_BEGIN_NAMESPACE

/*! \class OSG::FieldContainerFactoryBase

This class is a singleton.  It should be accessed using the typedef
for OSG::FieldContainerFactory.
*/

/*-------------------------------------------------------------------------*/
/*                            Constructors                                 */

FieldContainerFactoryBase::FieldContainerFactoryBase(void) :
     Inherited      ("FieldContainerFactory"),
#ifndef OSG_EMBEDDED
    _pStoreLock     (NULL                   ),
#endif
    _vContainerStore(                       ),
    _pMapper        (NULL                   )
{
    _vContainerStore.push_back(NULL);
}

FieldContainerFactoryBase::FieldContainerFactoryBase(
    const Char8 *szFactoryName) :

     Inherited      (szFactoryName),
#ifndef OSG_EMBEDDED
    _pStoreLock     (NULL         ),
#endif
	_vContainerStore(             ),
    _pMapper        (NULL         )
{
    _vContainerStore.push_back(NULL);
}

/*-------------------------------------------------------------------------*/
/*                             Destructor                                  */

FieldContainerFactoryBase::~FieldContainerFactoryBase(void)
{
}

/*-------------------------------------------------------------------------*/
/*                             Assignment                                  */

bool FieldContainerFactoryBase::initialize(void)
{
    if(this->_bInitialized == true)
        return true;

#ifndef OSG_EMBEDDED
    _pStoreLock = ThreadManager::the()->getLock("ContainerFactory::slock",
                                                false);

    PINFO << "Got store lock " << _pStoreLock.get() << std::endl;

    if(_pStoreLock == NULL)
    {
        return false;
    }
    else
    {
#endif
        return Inherited::initialize();
#ifndef OSG_EMBEDDED
    }
#endif
}

bool FieldContainerFactoryBase::terminate(void)
{
    bool returnValue = Inherited::terminate();

#ifndef OSG_EMBEDDED
    _pStoreLock = NULL;
#endif

    this->_bInitialized = false;

#ifdef OSG_DEBUG
    ContainerStoreIt sI = _vContainerStore.begin();
    ContainerStoreIt sE = _vContainerStore.end  ();

    for(UInt32 i = 0; sI != sE; ++sI, ++i)
    {
        if((*sI) != NULL)
        {
            FWARNING(("FieldContainerFactoryBase::terminate: "
                      "Entry [%d] is not NULL ([%p]). \n", i, *sI));

            for(UInt32 j = 0; j < (*sI)->getNumAspects(); ++j)
            {
                if((*sI)->getPtr(j) != NULL)
                {
                    FWARNING(("  [%d] [%p] [%s] [%d %d]\n",
                              j,
                              (*sI)->getPtr(j),
                              (*sI)->getPtr(j)->getType().getCName(),
                              (*sI)->getPtr(j)->getRefCount(),
                              (*sI)->getPtr(j)->getWeakRefCount() ));
                }
                else
                {
                    FWARNING(("  [%d] [%p] [] [N/A N/A]\n",
                              j,
                              (*sI)->getPtr(j)));
                }
            }
        }
    }
#endif // OSG_DEBUG

    return returnValue;
}

bool FieldContainerFactoryBase::initializeFactoryPost(void)
{
    return Inherited::initializeFactoryPost();
}

UInt32 FieldContainerFactoryBase::registerContainer(
    const ContainerPtr &pContainer)
{
#ifdef OSG_ENABLE_VALGRIND_CHECKS
    VALGRIND_CHECK_VALUE_IS_DEFINED(pContainer);
#endif

    UInt32 returnValue = 0;

#ifndef OSG_EMBEDDED
    _pStoreLock->acquire();
#endif

#ifdef OSG_MT_CPTR_ASPECT
    ContainerHandlerP pHandler = NULL;

    if(pContainer != NULL)
        pHandler = pContainer->getAspectStore();

    _vContainerStore.push_back(pHandler);
#else
    _vContainerStore.push_back(pContainer);
#endif

    returnValue = _vContainerStore.size() - 1;

#ifndef OSG_EMBEDDED
    _pStoreLock->release();
#endif

    return returnValue;
}

/*! Try to find the ptr container in the factory. Primarily used to verify
that a container is still valid and registered with the factory. As this
function does not access the ptr itself at all, it is safe to call it with
corrupted data.

\return The container's id, or -1 if not found.

\warning It uses the current thread's aspect to compare against, therefore it's not
possible with this function to verify pointers from other threads/aspects.

*/

Int32 FieldContainerFactoryBase::findContainer(ContainerPtr ptr) const
{
#ifndef OSG_EMBEDDED
    _pStoreLock->acquire();
#endif

    ContainerStore::const_iterator it, end;
    Int32 id = 0;
    Int32 returnValue = -1;

    for(it = _vContainerStore.begin(), end = _vContainerStore.end();
        it != end; ++it, ++id)
    {
#ifdef OSG_MT_CPTR_ASPECT
        if((*it)->getPtr() == ptr)
#else
        if(*it == ptr)
#endif
        {
            returnValue = id;
            break;
        }
    }

#ifndef OSG_EMBEDDED
    _pStoreLock->release();
#endif

    return returnValue;
}

/*-------------------------------------------------------------------------*/
/*                             Comparison                                  */

void FieldContainerFactoryBase::dump(void)
{
#ifndef OSG_EMBEDDED
    _pStoreLock->acquire();
#endif

    ContainerStoreIt sI = _vContainerStore.begin();
    ContainerStoreIt sE = _vContainerStore.end  ();

    for(UInt32 i = 0; sI != sE; ++sI, ++i)
    {
        if((*sI) != NULL)
        {
            FWARNING(("FieldContainerFactoryBase::dump: "
                      "Entry [%d] is not NULL ([%p]). \n", i, *sI));

            for(UInt32 j = 0; j < (*sI)->getNumAspects(); ++j)
            {
                if((*sI)->getPtr(j) != NULL)
                {
                    FWARNING(("  [%d] [%p] [%s] [%d %d]\n",
                              j,
                              (*sI)->getPtr(j),
                              (*sI)->getPtr(j)->getType().getCName(),
                              (*sI)->getPtr(j)->getRefCount(),
                              (*sI)->getPtr(j)->getWeakRefCount() ));
                }
                else
                {
                    FWARNING(("  [%d] [%p] [] [N/A N/A]\n",
                              j,
                              (*sI)->getPtr(j)));
                }
            }
        }
    }

#ifndef OSG_EMBEDDED
    _pStoreLock->release();
#endif
}

DerivedFieldContainerTypeIterator
    FieldContainerFactoryBase::begin(const FieldContainerType &oRef)
{
    return DerivedFieldContainerTypeIterator(oRef);
}

DerivedFieldContainerTypeIterator
    FieldContainerFactoryBase::end(void)
{
    return DerivedFieldContainerTypeIterator();
}

FieldContainerType *DerivedFieldContainerTypeIterator::operator->(void)
{
    return _pCurrentType;
}

FieldContainerType *DerivedFieldContainerTypeIterator::operator *(void)
{
    return _pCurrentType;
}

void DerivedFieldContainerTypeIterator::operator++ (void)
{
    _pCurrentType = NULL;

    ++_uiCurrentType;

    for(; _uiCurrentType < TypeFactory::the()->getNumTypes();
        ++_uiCurrentType)
    {
        FieldContainerType *pTestType =
            FieldContainerFactory::the()->findType(_uiCurrentType);

        if(pTestType                        != NULL)
        {
            if(pTestType->isDerivedFrom(*_pRef) == true   )
            {
                _pCurrentType = pTestType;

                break;
            }
        }
    }
}

bool DerivedFieldContainerTypeIterator::operator ==(
    const DerivedFieldContainerTypeIterator &lhs)
{
    return this->_uiCurrentType == lhs._uiCurrentType;
}

bool DerivedFieldContainerTypeIterator::operator !=(
    const DerivedFieldContainerTypeIterator &lhs)
{
    return !(*this == lhs);
}

DerivedFieldContainerTypeIterator::DerivedFieldContainerTypeIterator(void) :
    _pRef         (NULL                             ),
    _uiCurrentType(TypeFactory::the()->getNumTypes()),
    _pCurrentType (NULL                             )
{
}

DerivedFieldContainerTypeIterator::DerivedFieldContainerTypeIterator(
    const FieldContainerType &oRef) :

    _pRef         (&oRef),
    _uiCurrentType(0    ),
    _pCurrentType (NULL )
{
    ++(*this);
}

DerivedFieldContainerTypeIterator::DerivedFieldContainerTypeIterator(
    const DerivedFieldContainerTypeIterator &source) :

    _pRef         (source._pRef         ),
    _uiCurrentType(source._uiCurrentType),
    _pCurrentType (source._pCurrentType )
{
}

OSG_END_NAMESPACE

<|endoftext|>


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

#include "config.h"

#include "bindings/core/v8/NPV8Object.h"
#include "bindings/core/v8/SharedPersistent.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8HTMLAppletElement.h"
#include "bindings/core/v8/V8HTMLEmbedElement.h"
#include "bindings/core/v8/V8HTMLObjectElement.h"
#include "bindings/core/v8/V8NPObject.h"
#include "core/frame/UseCounter.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"

namespace blink {

namespace {

template <typename ElementType, typename PropertyType>
void getScriptableObjectProperty(PropertyType property, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    HTMLPlugInElement* impl = ElementType::toNative(info.Holder());
    RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper();
    if (!wrapper)
        return;

    v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate());
    if (instance.IsEmpty())
        return;

    TONATIVE_VOID(v8::Local<v8::Value>, value, instance->Get(property));

    // We quit here to allow the binding code to look up general HTMLObjectElement properties
    // if they are not overriden by plugin.
    if (value->IsUndefined())
        return;

    v8SetReturnValue(info, value);
}

namespace {
void callNpObjectSetter(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    npObjectSetNamedProperty(self, name, value, info);
}

void callNpObjectSetter(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    npObjectSetIndexedProperty(self, index, value, info);
}
}

template <typename ElementType, typename PropertyType>
void setScriptableObjectProperty(PropertyType property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    HTMLPlugInElement* impl = ElementType::toNative(info.Holder());
    RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper();
    if (!wrapper)
        return;

    v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate());
    if (instance.IsEmpty())
        return;

    // We need to directly call setter on NPObject to be able to detect
    // situation where NPObject notifies it does not possess the property
    // to be able to lookup standard DOM property.
    // This information is lost when retrieving it through v8::Object.
    if (isWrappedNPObject(instance)) {
        callNpObjectSetter(instance, property, value, info);
        return;
    }

    if (instance->Set(property, value))
        v8SetReturnValue(info, value);
}
} // namespace

void V8HTMLAppletElement::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLAppletElement>(name, info);
}

void V8HTMLEmbedElement::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLEmbedElement>(name, info);
}

void V8HTMLObjectElement::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLObjectElement>(name, info);
}

void V8HTMLAppletElement::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLAppletElement>(name, value, info);
}

void V8HTMLEmbedElement::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLEmbedElement>(name, value, info);
}

void V8HTMLObjectElement::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLObjectElement>(name, value, info);
}

void V8HTMLAppletElement::indexedPropertyGetterCustom(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLAppletElement>(index, info);
}

void V8HTMLEmbedElement::indexedPropertyGetterCustom(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLEmbedElement>(index, info);
}

void V8HTMLObjectElement::indexedPropertyGetterCustom(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLObjectElement>(index, info);
}

void V8HTMLAppletElement::indexedPropertySetterCustom(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLAppletElement>(index, value, info);
}

void V8HTMLEmbedElement::indexedPropertySetterCustom(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLEmbedElement>(index, value, info);
}

void V8HTMLObjectElement::indexedPropertySetterCustom(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLObjectElement>(index, value, info);
}

namespace {

template <typename ElementType>
void invokeOnScriptableObject(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    HTMLPlugInElement* impl = ElementType::toNative(info.Holder());
    RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper();
    if (!wrapper)
        return;

    v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate());
    if (instance.IsEmpty())
        return;

    WTF::OwnPtr<v8::Handle<v8::Value>[] > arguments = adoptArrayPtr(new v8::Handle<v8::Value>[info.Length()]);
    for (int i = 0; i < info.Length(); ++i)
        arguments[i] = info[i];

    TONATIVE_VOID(v8::Local<v8::Value>, retVal, instance->CallAsFunction(info.This(), info.Length(), arguments.get()));
    v8SetReturnValue(info, retVal);
}

} // namespace

void V8HTMLAppletElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    invokeOnScriptableObject<V8HTMLAppletElement>(info);
    UseCounter::count(V8HTMLAppletElement::toNative(info.Holder())->document(), UseCounter::HTMLAppletElementLegacyCall);
}

void V8HTMLEmbedElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    invokeOnScriptableObject<V8HTMLEmbedElement>(info);
    UseCounter::count(V8HTMLEmbedElement::toNative(info.Holder())->document(), UseCounter::HTMLEmbedElementLegacyCall);
}

void V8HTMLObjectElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    invokeOnScriptableObject<V8HTMLObjectElement>(info);
    UseCounter::count(V8HTMLObjectElement::toNative(info.Holder())->document(), UseCounter::HTMLObjectElementLegacyCall);
}

} // namespace blink
<commit_msg>Don't allow setting properties on scriptable v8 plugin objects<commit_after>/*
* Copyright (C) 2009 Google Inc. All rights reserved.
* Copyright (C) 2014 Opera Software ASA. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*     * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*     * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"

#include "bindings/core/v8/NPV8Object.h"
#include "bindings/core/v8/SharedPersistent.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8HTMLAppletElement.h"
#include "bindings/core/v8/V8HTMLEmbedElement.h"
#include "bindings/core/v8/V8HTMLObjectElement.h"
#include "bindings/core/v8/V8NPObject.h"
#include "core/frame/UseCounter.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"

namespace blink {

namespace {

template <typename ElementType, typename PropertyType>
void getScriptableObjectProperty(PropertyType property, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    HTMLPlugInElement* impl = ElementType::toNative(info.Holder());
    RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper();
    if (!wrapper)
        return;

    v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate());
    if (instance.IsEmpty())
        return;

    TONATIVE_VOID(v8::Local<v8::Value>, value, instance->Get(property));

    // We quit here to allow the binding code to look up general HTMLObjectElement properties
    // if they are not overriden by plugin.
    if (value->IsUndefined())
        return;

    v8SetReturnValue(info, value);
}

namespace {
void callNpObjectSetter(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    npObjectSetNamedProperty(self, name, value, info);
}

void callNpObjectSetter(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    npObjectSetIndexedProperty(self, index, value, info);
}
}

template <typename ElementType, typename PropertyType>
void setScriptableObjectProperty(PropertyType property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    HTMLPlugInElement* impl = ElementType::toNative(info.Holder());
    RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper();
    if (!wrapper)
        return;

    v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate());
    if (instance.IsEmpty())
        return;

    // We need to directly call setter on NPObject to be able to detect
    // situation where NPObject notifies it does not possess the property
    // to be able to lookup standard DOM property.
    // This information is lost when retrieving it through v8::Object.
    if (isWrappedNPObject(instance)) {
        callNpObjectSetter(instance, property, value, info);
        return;
    }
}
} // namespace

void V8HTMLAppletElement::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLAppletElement>(name, info);
}

void V8HTMLEmbedElement::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLEmbedElement>(name, info);
}

void V8HTMLObjectElement::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLObjectElement>(name, info);
}

void V8HTMLAppletElement::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLAppletElement>(name, value, info);
}

void V8HTMLEmbedElement::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLEmbedElement>(name, value, info);
}

void V8HTMLObjectElement::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLObjectElement>(name, value, info);
}

void V8HTMLAppletElement::indexedPropertyGetterCustom(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLAppletElement>(index, info);
}

void V8HTMLEmbedElement::indexedPropertyGetterCustom(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLEmbedElement>(index, info);
}

void V8HTMLObjectElement::indexedPropertyGetterCustom(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    getScriptableObjectProperty<V8HTMLObjectElement>(index, info);
}

void V8HTMLAppletElement::indexedPropertySetterCustom(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLAppletElement>(index, value, info);
}

void V8HTMLEmbedElement::indexedPropertySetterCustom(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLEmbedElement>(index, value, info);
}

void V8HTMLObjectElement::indexedPropertySetterCustom(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
    setScriptableObjectProperty<V8HTMLObjectElement>(index, value, info);
}

namespace {

template <typename ElementType>
void invokeOnScriptableObject(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    HTMLPlugInElement* impl = ElementType::toNative(info.Holder());
    RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper();
    if (!wrapper)
        return;

    v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate());
    if (instance.IsEmpty())
        return;

    WTF::OwnPtr<v8::Handle<v8::Value>[] > arguments = adoptArrayPtr(new v8::Handle<v8::Value>[info.Length()]);
    for (int i = 0; i < info.Length(); ++i)
        arguments[i] = info[i];

    TONATIVE_VOID(v8::Local<v8::Value>, retVal, instance->CallAsFunction(info.This(), info.Length(), arguments.get()));
    v8SetReturnValue(info, retVal);
}

} // namespace

void V8HTMLAppletElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    invokeOnScriptableObject<V8HTMLAppletElement>(info);
    UseCounter::count(V8HTMLAppletElement::toNative(info.Holder())->document(), UseCounter::HTMLAppletElementLegacyCall);
}

void V8HTMLEmbedElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    invokeOnScriptableObject<V8HTMLEmbedElement>(info);
    UseCounter::count(V8HTMLEmbedElement::toNative(info.Holder())->document(), UseCounter::HTMLEmbedElementLegacyCall);
}

void V8HTMLObjectElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    invokeOnScriptableObject<V8HTMLObjectElement>(info);
    UseCounter::count(V8HTMLObjectElement::toNative(info.Holder())->document(), UseCounter::HTMLObjectElementLegacyCall);
}

} // namespace blink
<|endoftext|>