<commit_before>/*
 * Copyright (C) 2014 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace utils {
/**
 * This class implements an add-only vector that ensures that the elements are
 * unique.
 *
 * This class provides a similar functionality to the Java's LinkedHashSet
 * class.
 */
template<typename T>
struct sequenced_set {
    typedef typename std::vector<T>::iterator iterator;

    void push_back(const T& val) {
        if (_set.find(val) != _set.end()) {
            return;
        }

        _set.insert(val);
        _vec.push_back(val);
    }

    size_t size() {
        return _vec.size();
    }

    iterator begin() {
        return _vec.begin();
    }

    iterator end() {
        return _vec.end();
    }

    const std::vector<T>& get_vector() const {
        return _vec;
    }

    std::vector<T>& get_vector() {
        return _vec;
    }

    void reserve(size_t sz) {
        _set.reserve(sz);
        _vec.reserve(sz);
    }

private:
    std::unordered_set<T> _set;
    std::vector<T> _vec;
};
} // namespace utils

<commit_msg>sequenced_set: Add "insert" method, following std::set semantics<commit_after>/*
 * Copyright (C) 2014 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace utils {
/**
 * This class implements an add-only vector that ensures that the elements are
 * unique.
 *
 * This class provides a similar functionality to the Java's LinkedHashSet
 * class.
 */
template<typename T>
struct sequenced_set {
    typedef typename std::vector<T>::iterator iterator;

    void push_back(const T& val) {
        insert(val);
    }

    std::pair<iterator, bool> insert(const T& t) {
        auto r = _set.insert(t);
        if (r.second) {
            try {
                _vec.push_back(t);
                return std::make_pair(std::prev(_vec.end()), true);
            } catch (...) {
                _set.erase(r.first);
                throw;
            }
        }
        return std::make_pair(_vec.end(), false);
    }

    size_t size() {
        return _vec.size();
    }

    iterator begin() {
        return _vec.begin();
    }

    iterator end() {
        return _vec.end();
    }

    const std::vector<T>& get_vector() const {
        return _vec;
    }

    std::vector<T>& get_vector() {
        return _vec;
    }

    void reserve(size_t sz) {
        _set.reserve(sz);
        _vec.reserve(sz);
    }

private:
    std::unordered_set<T> _set;
    std::vector<T> _vec;
};
} // namespace utils

<|endoftext|>


<commit_before><commit_msg>Fix of the initial locale set.<commit_after><|endoftext|>


<commit_before><commit_msg>Fix language switch ignored changing RTL-ness.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_INTERNAL_FILESYSTEM_HPP
#define TAO_PEGTL_INTERNAL_FILESYSTEM_HPP

#include "../config.hpp"

#if defined( TAO_PEGTL_STD_EXPERIMENTAL_FILESYSTEM )

#include <experimental/filesystem>

namespace TAO_PEGTL_NAMESPACE::internal::filesystem = ::std::experimental::filesystem;

#elseif defined( TAO_PEGTL_BOOST_FILESYSTEM )

#define BOOST_FILESYSTEM_NO_DEPRECATED

#include <boost/filesystem.hpp>

namespace TAO_PEGTL_NAMESPACE::internal::filesystem = ::boost::filesystem;

#else

#include <filesystem>

namespace TAO_PEGTL_NAMESPACE::internal
{
    namespace filesystem = ::std::filesystem;
}

#endif

#endif
<commit_msg>Fixup internal header<commit_after>// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_INTERNAL_FILESYSTEM_HPP
#define TAO_PEGTL_INTERNAL_FILESYSTEM_HPP

#include "../config.hpp"

#if defined( TAO_PEGTL_STD_EXPERIMENTAL_FILESYSTEM )

#include <experimental/filesystem>

namespace TAO_PEGTL_NAMESPACE::internal
{
    namespace filesystem = ::std::experimental::filesystem;
}

#elif defined( TAO_PEGTL_BOOST_FILESYSTEM )

#define BOOST_FILESYSTEM_NO_DEPRECATED

#include <boost/filesystem.hpp>

namespace TAO_PEGTL_NAMESPACE::internal
{
    namespace filesystem = ::boost::filesystem;
}

#else

#include <filesystem>

namespace TAO_PEGTL_NAMESPACE::internal
{
    namespace filesystem = ::std::filesystem;
}

#endif

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012, Andre Caron (andre.l.caron@gmail.com)
// 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.
//
// 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
// HOLDER 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.
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the accompanying "license.txt" file
// for more details.
//

#include "PreparedStatement.hpp"
#include "Connection.hpp"
#include "Diagnostic.hpp"

// Since ::SQLBindParameter() does not have a const-correct interface. It's 3rd
// parameter indicates if it should read or write to the given location. If this
// value is SQL_PARAM_INPUT, the data is not modified, even though it requires
// write-access to the value. Do not be surprised to see const casts to discard
// qualifiers.

namespace sql {

    PreparedStatement::PreparedStatement (
        Connection& connection, const string& query
        )
        : Statement(connection), myNext(1)
    {
            // Indicate the statement will be using bound parameters.
        ::SQLRETURN result = ::SQLPrepare(
            handle().value(), const_cast<character*>(query.data()), SQL_NTS
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
    }

    PreparedStatement& PreparedStatement::execute ()
    {
            // Execute query with currently bound parameters.
        Statement::execute();

            // Prepare for re-execution of the same query.
        return (reset());
    }

    PreparedStatement& PreparedStatement::reset ()
    {
        myNext = 1; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Null& )
    {
        ::SQLLEN length = SQL_NULL_DATA;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT,
            0, 0, 0, 0, 0, 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int8& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_STINYINT,
            SQL_TINYINT, 0, 0, const_cast<int8*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint8& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_UTINYINT,
            SQL_TINYINT, 0, 0, const_cast<uint8*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int16& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_SSHORT,
            SQL_SMALLINT, 0, 0, const_cast<int16*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint16& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_USHORT,
            SQL_SMALLINT, 0, 0, const_cast<uint16*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int32& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
            0, 0, const_cast<int32*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint32& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
            0, 0, const_cast<uint32*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int64& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_SBIGINT,
            SQL_BIGINT, 0, 0, const_cast<int64*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint64& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_UBIGINT,
            SQL_BIGINT, 0, 0, const_cast<uint64*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const float& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL,
            0, 0, const_cast<float*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const double& value )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE,
            0, 0, const_cast<double*>(&value), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const string& value )
    {
        ::SQLLEN length = SQL_NTS;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
            value.length(), 0, const_cast<character*>(value.data()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const wstring& value )
    {
        ::SQLLEN length = SQL_NTS;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR,
            value.length(), 0, const_cast<wcharacter*>(value.data()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Date& date )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_TYPE_DATE,
            SQL_TYPE_TIME, sizeof(::SQL_DATE_STRUCT), 0,
            const_cast<::SQL_DATE_STRUCT*>(&date.value()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Guid& guid )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_GUID,
            SQL_GUID, sizeof(::SQLGUID), 0,
            const_cast<::SQLGUID*>(&guid.value()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Numeric& numeric )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_NUMERIC,
            SQL_NUMERIC, sizeof(::SQL_NUMERIC_STRUCT), 0,
            const_cast<::SQL_NUMERIC_STRUCT*>(&numeric.value()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Time& time )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_TYPE_TIME,
            SQL_TYPE_TIME, sizeof(::SQL_TIME_STRUCT), 0,
            const_cast<::SQL_TIME_STRUCT*>(&time.value()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Timestamp& timestamp )
    {
        ::SQLLEN length = 0;
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP,
            SQL_TYPE_TIMESTAMP, sizeof(::SQL_TIMESTAMP_STRUCT), 0,
            const_cast<::SQL_TIMESTAMP_STRUCT*>(&timestamp.value()), 0, &length
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& reset ( PreparedStatement& statement )
    {
        return (statement.reset());
    }

    PreparedStatement& execute ( PreparedStatement& statement )
    {
        return (statement.execute());
    }

}
<commit_msg>Prevents 'SQL_NEED_DATA' on 'SQLExecute()'.<commit_after>// Copyright (c) 2009-2012, Andre Caron (andre.l.caron@gmail.com)
// 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.
//
// 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
// HOLDER 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.
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the accompanying "license.txt" file
// for more details.
//

#include "PreparedStatement.hpp"
#include "Connection.hpp"
#include "Diagnostic.hpp"

// Since ::SQLBindParameter() does not have a const-correct interface. It's 3rd
// parameter indicates if it should read or write to the given location. If this
// value is SQL_PARAM_INPUT, the data is not modified, even though it requires
// write-access to the value. Do not be surprised to see const casts to discard
// qualifiers.

namespace {

    // Shared between all null values.  Must be available between calls
    // to PreparedStatement::bind() and PreparedStatement::execute().
    ::SQLLEN null_value = SQL_NULL_DATA;

    // Shared between all string parameters.  Must be available between calls
    // to PreparedStatement::bind() and PreparedStatement::execute().
    ::SQLLEN null_terminated = SQL_NTS;

}

namespace sql {

    PreparedStatement::PreparedStatement (
        Connection& connection, const string& query
        )
        : Statement(connection), myNext(1)
    {
            // Indicate the statement will be using bound parameters.
        ::SQLRETURN result = ::SQLPrepare(
            handle().value(), const_cast<character*>(query.data()), SQL_NTS
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
    }

    PreparedStatement& PreparedStatement::execute ()
    {
            // Execute query with currently bound parameters.
        Statement::execute();

            // Prepare for re-execution of the same query.
        return (reset());
    }

    PreparedStatement& PreparedStatement::reset ()
    {
        myNext = 1; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Null& )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT,
            0, 0, 0, 0, 0, 0, &::null_value
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int8& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_STINYINT,
            SQL_TINYINT, 0, 0, const_cast<int8*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint8& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_UTINYINT,
            SQL_TINYINT, 0, 0, const_cast<uint8*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int16& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_SSHORT,
            SQL_SMALLINT, 0, 0, const_cast<int16*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint16& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_USHORT,
            SQL_SMALLINT, 0, 0, const_cast<uint16*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int32& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_SLONG,
            SQL_INTEGER, 0, 0, const_cast<int32*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint32& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
            0, 0, const_cast<uint32*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const int64& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_SBIGINT,
            SQL_BIGINT, 0, 0, const_cast<int64*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const uint64& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_UBIGINT,
            SQL_BIGINT, 0, 0, const_cast<uint64*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const float& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_REAL,
            0, 0, const_cast<float*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const double& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE,
            0, 0, const_cast<double*>(&value), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const string& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
            value.length(), 0, const_cast<character*>(value.data()), 0,
            &::null_terminated
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const wstring& value )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR,
            value.length(), 0, const_cast<wcharacter*>(value.data()), 0,
            &::null_terminated
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Date& date )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_TYPE_DATE,
            SQL_TYPE_DATE, SQL_DATE_LEN, 0,
            const_cast<::SQL_DATE_STRUCT*>(&date.value()), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Guid& guid )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_GUID,
            SQL_GUID, sizeof(::SQLGUID), 0,
            const_cast<::SQLGUID*>(&guid.value()), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Numeric& numeric )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_NUMERIC,
            SQL_NUMERIC, sizeof(::SQL_NUMERIC_STRUCT), 0,
            const_cast<::SQL_NUMERIC_STRUCT*>(&numeric.value()), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Time& time )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_TYPE_TIME,
            SQL_TYPE_TIME, SQL_TIME_LEN, 0,
            const_cast<::SQL_TIME_STRUCT*>(&time.value()), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& PreparedStatement::bind ( const Timestamp& timestamp )
    {
        ::SQLRETURN result = ::SQLBindParameter(
            handle().value(), myNext, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP,
            SQL_TYPE_TIMESTAMP, sizeof(::SQL_TIMESTAMP_STRUCT), 0,
            const_cast<::SQL_TIMESTAMP_STRUCT*>(&timestamp.value()), 0, 0
            );
        if ( result != SQL_SUCCESS ) {
            throw (Diagnostic(handle()));
        }
        ++myNext; return (*this);
    }

    PreparedStatement& reset ( PreparedStatement& statement )
    {
        return (statement.reset());
    }

    PreparedStatement& execute ( PreparedStatement& statement )
    {
        return (statement.execute());
    }

}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/arraysize.h"
#include "webrtc/base/safe_conversions.h"
#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h"
#include "webrtc/modules/audio_coding/main/acm2/codec_owner.h"

namespace webrtc {
namespace acm2 {

using ::testing::Return;
using ::testing::InSequence;

namespace {
const int kDataLengthSamples = 80;
const int kPacketSizeSamples = 2 * kDataLengthSamples;
const int16_t kZeroData[kDataLengthSamples] = {0};
const CodecInst kDefaultCodecInst =
    {0, "pcmu", 8000, kPacketSizeSamples, 1, 64000};
const int kCngPt = 13;
}  // namespace

class CodecOwnerTest : public ::testing::Test {
 protected:
  CodecOwnerTest() : timestamp_(0) {}

  void CreateCodec() {
    codec_owner_.SetEncoders(kDefaultCodecInst, kCngPt, VADNormal, -1);
  }

  void EncodeAndVerify(size_t expected_out_length,
                       uint32_t expected_timestamp,
                       int expected_payload_type,
                       int expected_send_even_if_empty) {
    uint8_t out[kPacketSizeSamples];
    AudioEncoder::EncodedInfo encoded_info;
    encoded_info = codec_owner_.Encoder()->Encode(
        timestamp_, kZeroData, kDataLengthSamples, kPacketSizeSamples, out);
    timestamp_ += kDataLengthSamples;
    EXPECT_TRUE(encoded_info.redundant.empty());
    EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
    EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp);
    if (expected_payload_type >= 0)
      EXPECT_EQ(expected_payload_type, encoded_info.payload_type);
    if (expected_send_even_if_empty >= 0)
      EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty),
                encoded_info.send_even_if_empty);
  }

  CodecOwner codec_owner_;
  uint32_t timestamp_;
};

// This test verifies that CNG frames are delivered as expected. Since the frame
// size is set to 20 ms, we expect the first encode call to produce no output
// (which is signaled as 0 bytes output of type kNoEncoding). The next encode
// call should produce one SID frame of 9 bytes. The third call should not
// result in any output (just like the first one). The fourth and final encode
// call should produce an "empty frame", which is like no output, but with
// AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to
// produce an empty frame is to drive sending of DTMF packets in the RTP/RTCP
// module.)
TEST_F(CodecOwnerTest, VerifyCngFrames) {
  CreateCodec();
  uint32_t expected_timestamp = timestamp_;
  // Verify no frame.
  {
    SCOPED_TRACE("First encoding");
    EncodeAndVerify(0, expected_timestamp, -1, -1);
  }

  // Verify SID frame delivered.
  {
    SCOPED_TRACE("Second encoding");
    EncodeAndVerify(9, expected_timestamp, kCngPt, 1);
  }

  // Verify no frame.
  {
    SCOPED_TRACE("Third encoding");
    EncodeAndVerify(0, expected_timestamp, -1, -1);
  }

  // Verify NoEncoding.
  expected_timestamp += 2 * kDataLengthSamples;
  {
    SCOPED_TRACE("Fourth encoding");
    EncodeAndVerify(0, expected_timestamp, kCngPt, 1);
  }
}

TEST_F(CodecOwnerTest, ExternalEncoder) {
  MockAudioEncoder external_encoder;
  codec_owner_.SetEncoders(&external_encoder, -1, VADNormal, -1);
  const int kSampleRateHz = 8000;
  const int kPacketSizeSamples = kSampleRateHz / 100;
  int16_t audio[kPacketSizeSamples] = {0};
  uint8_t encoded[kPacketSizeSamples];
  AudioEncoder::EncodedInfo info;
  EXPECT_CALL(external_encoder, SampleRateHz())
      .WillRepeatedly(Return(kSampleRateHz));

  {
    InSequence s;
    info.encoded_timestamp = 0;
    EXPECT_CALL(external_encoder,
                EncodeInternal(0, audio, arraysize(encoded), encoded))
        .WillOnce(Return(info));
    EXPECT_CALL(external_encoder, Mark("A"));
    EXPECT_CALL(external_encoder, Mark("B"));
    info.encoded_timestamp = 2;
    EXPECT_CALL(external_encoder,
                EncodeInternal(2, audio, arraysize(encoded), encoded))
        .WillOnce(Return(info));
    EXPECT_CALL(external_encoder, Die());
  }

  info = codec_owner_.Encoder()->Encode(0, audio, arraysize(audio),
                                        arraysize(encoded), encoded);
  EXPECT_EQ(0u, info.encoded_timestamp);
  external_encoder.Mark("A");

  // Change to internal encoder.
  CodecInst codec_inst = kDefaultCodecInst;
  codec_inst.pacsize = kPacketSizeSamples;
  codec_owner_.SetEncoders(codec_inst, -1, VADNormal, -1);
  // Don't expect any more calls to the external encoder.
  info = codec_owner_.Encoder()->Encode(1, audio, arraysize(audio),
                                        arraysize(encoded), encoded);
  external_encoder.Mark("B");

  // Change back to external encoder again.
  codec_owner_.SetEncoders(&external_encoder, -1, VADNormal, -1);
  info = codec_owner_.Encoder()->Encode(2, audio, arraysize(audio),
                                        arraysize(encoded), encoded);
  EXPECT_EQ(2u, info.encoded_timestamp);
}

}  // namespace acm2
}  // namespace webrtc
<commit_msg>ACM CodecOwner: Test that we reset speech encoder when enabling CNG or RED<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/arraysize.h"
#include "webrtc/base/safe_conversions.h"
#include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h"
#include "webrtc/modules/audio_coding/main/acm2/codec_owner.h"

namespace webrtc {
namespace acm2 {

using ::testing::Return;
using ::testing::InSequence;

namespace {
const int kDataLengthSamples = 80;
const int kPacketSizeSamples = 2 * kDataLengthSamples;
const int16_t kZeroData[kDataLengthSamples] = {0};
const CodecInst kDefaultCodecInst =
    {0, "pcmu", 8000, kPacketSizeSamples, 1, 64000};
const int kCngPt = 13;
}  // namespace

class CodecOwnerTest : public ::testing::Test {
 protected:
  CodecOwnerTest() : timestamp_(0) {}

  void CreateCodec() {
    codec_owner_.SetEncoders(kDefaultCodecInst, kCngPt, VADNormal, -1);
  }

  void EncodeAndVerify(size_t expected_out_length,
                       uint32_t expected_timestamp,
                       int expected_payload_type,
                       int expected_send_even_if_empty) {
    uint8_t out[kPacketSizeSamples];
    AudioEncoder::EncodedInfo encoded_info;
    encoded_info = codec_owner_.Encoder()->Encode(
        timestamp_, kZeroData, kDataLengthSamples, kPacketSizeSamples, out);
    timestamp_ += kDataLengthSamples;
    EXPECT_TRUE(encoded_info.redundant.empty());
    EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
    EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp);
    if (expected_payload_type >= 0)
      EXPECT_EQ(expected_payload_type, encoded_info.payload_type);
    if (expected_send_even_if_empty >= 0)
      EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty),
                encoded_info.send_even_if_empty);
  }

  // Verify that the speech encoder's Reset method is called when CNG or RED
  // (or both) are switched on, but not when they're switched off.
  void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) {
    MockAudioEncoder speech_encoder;
    EXPECT_CALL(speech_encoder, NumChannels())
        .WillRepeatedly(Return(1));
    EXPECT_CALL(speech_encoder, Max10MsFramesInAPacket())
        .WillRepeatedly(Return(2));
    EXPECT_CALL(speech_encoder, SampleRateHz())
        .WillRepeatedly(Return(8000));
    {
      InSequence s;
      EXPECT_CALL(speech_encoder, Mark("start off"));
      EXPECT_CALL(speech_encoder, Mark("switch on"));
      if (use_cng || use_red)
        EXPECT_CALL(speech_encoder, Reset());
      EXPECT_CALL(speech_encoder, Mark("start on"));
      if (use_cng || use_red)
        EXPECT_CALL(speech_encoder, Reset());
      EXPECT_CALL(speech_encoder, Mark("switch off"));
      EXPECT_CALL(speech_encoder, Die());
    }

    int cng_pt = use_cng ? 17 : -1;
    int red_pt = use_red ? 19 : -1;
    speech_encoder.Mark("start off");
    codec_owner_.SetEncoders(&speech_encoder, -1, VADNormal, -1);
    speech_encoder.Mark("switch on");
    codec_owner_.ChangeCngAndRed(cng_pt, VADNormal, red_pt);
    speech_encoder.Mark("start on");
    codec_owner_.SetEncoders(&speech_encoder, cng_pt, VADNormal, red_pt);
    speech_encoder.Mark("switch off");
    codec_owner_.ChangeCngAndRed(-1, VADNormal, -1);
  }

  CodecOwner codec_owner_;
  uint32_t timestamp_;
};

// This test verifies that CNG frames are delivered as expected. Since the frame
// size is set to 20 ms, we expect the first encode call to produce no output
// (which is signaled as 0 bytes output of type kNoEncoding). The next encode
// call should produce one SID frame of 9 bytes. The third call should not
// result in any output (just like the first one). The fourth and final encode
// call should produce an "empty frame", which is like no output, but with
// AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to
// produce an empty frame is to drive sending of DTMF packets in the RTP/RTCP
// module.)
TEST_F(CodecOwnerTest, VerifyCngFrames) {
  CreateCodec();
  uint32_t expected_timestamp = timestamp_;
  // Verify no frame.
  {
    SCOPED_TRACE("First encoding");
    EncodeAndVerify(0, expected_timestamp, -1, -1);
  }

  // Verify SID frame delivered.
  {
    SCOPED_TRACE("Second encoding");
    EncodeAndVerify(9, expected_timestamp, kCngPt, 1);
  }

  // Verify no frame.
  {
    SCOPED_TRACE("Third encoding");
    EncodeAndVerify(0, expected_timestamp, -1, -1);
  }

  // Verify NoEncoding.
  expected_timestamp += 2 * kDataLengthSamples;
  {
    SCOPED_TRACE("Fourth encoding");
    EncodeAndVerify(0, expected_timestamp, kCngPt, 1);
  }
}

TEST_F(CodecOwnerTest, ExternalEncoder) {
  MockAudioEncoder external_encoder;
  codec_owner_.SetEncoders(&external_encoder, -1, VADNormal, -1);
  const int kSampleRateHz = 8000;
  const int kPacketSizeSamples = kSampleRateHz / 100;
  int16_t audio[kPacketSizeSamples] = {0};
  uint8_t encoded[kPacketSizeSamples];
  AudioEncoder::EncodedInfo info;
  EXPECT_CALL(external_encoder, SampleRateHz())
      .WillRepeatedly(Return(kSampleRateHz));

  {
    InSequence s;
    info.encoded_timestamp = 0;
    EXPECT_CALL(external_encoder,
                EncodeInternal(0, audio, arraysize(encoded), encoded))
        .WillOnce(Return(info));
    EXPECT_CALL(external_encoder, Mark("A"));
    EXPECT_CALL(external_encoder, Mark("B"));
    info.encoded_timestamp = 2;
    EXPECT_CALL(external_encoder,
                EncodeInternal(2, audio, arraysize(encoded), encoded))
        .WillOnce(Return(info));
    EXPECT_CALL(external_encoder, Die());
  }

  info = codec_owner_.Encoder()->Encode(0, audio, arraysize(audio),
                                        arraysize(encoded), encoded);
  EXPECT_EQ(0u, info.encoded_timestamp);
  external_encoder.Mark("A");

  // Change to internal encoder.
  CodecInst codec_inst = kDefaultCodecInst;
  codec_inst.pacsize = kPacketSizeSamples;
  codec_owner_.SetEncoders(codec_inst, -1, VADNormal, -1);
  // Don't expect any more calls to the external encoder.
  info = codec_owner_.Encoder()->Encode(1, audio, arraysize(audio),
                                        arraysize(encoded), encoded);
  external_encoder.Mark("B");

  // Change back to external encoder again.
  codec_owner_.SetEncoders(&external_encoder, -1, VADNormal, -1);
  info = codec_owner_.Encoder()->Encode(2, audio, arraysize(audio),
                                        arraysize(encoded), encoded);
  EXPECT_EQ(2u, info.encoded_timestamp);
}

TEST_F(CodecOwnerTest, CngResetsSpeechEncoder) {
  TestCngAndRedResetSpeechEncoder(true, false);
}

TEST_F(CodecOwnerTest, RedResetsSpeechEncoder) {
  TestCngAndRedResetSpeechEncoder(false, true);
}

TEST_F(CodecOwnerTest, CngAndRedResetsSpeechEncoder) {
  TestCngAndRedResetSpeechEncoder(true, true);
}

TEST_F(CodecOwnerTest, NoCngAndRedNoSpeechEncoderReset) {
  TestCngAndRedResetSpeechEncoder(false, false);
}

}  // namespace acm2
}  // namespace webrtc
<|endoftext|>


<commit_before>#include <iostream>
//#include "FunctorNew.h"

//#include "Math/IGenFunction.h"
#include "Math/WrappedFunction.h"
//#include "Fit/WrappedTF1.h"
#include "TStopwatch.h"
#include <cmath>
#include "TRandom2.h"
#include "TF1.h"
#include "TF2.h"
#include "Math/WrappedTF1.h"
#include "Math/WrappedMultiTF1.h"

#ifdef HAVE_ROOFIT
#include "RooRealVar.h"
#include "RooArgList.h"
#include "RooExponential.h"
#endif

#include "Math/IFunctionfwd.h"
#include "Math/IFunction.h"
#include "Math/Functor.h"

#include <functional>

#define NLOOP 100
#define NTIMES 1000000
#define FUNC x[0]+x[1]
//#define FUNC x[0]*std::exp(x[1])
//#define FUNC 100 * (x[1]-x[0]*x[0])*(x[1]-x[0]*x[0]) + (1.-x[0])*(1-x[0])

#define FUNC1D x+x;
//#define FUNC1D std::exp(x);

double freeFunction(const double * x ) {
   return FUNC;
   //return ;
}

double freeRootFunc2D(double *x, double *){
   return FUNC;
}
double freeRootFunc1D(double *xx, double *){
   double x = *xx;
   return FUNC1D;
}

double freeFunction1D(double  x ) {
   return FUNC1D;
}

class MyFunction {

public:
   double operator()(const double *x) const {
      return FUNC;
      //return x[0]*std::exp(x[1]);
   }

   double Derivative(const double * x, int /* icoord */) const { return FUNC; }
   double Eval(const double * x) const { return FUNC; }
};

class MyFunction1D {

public:

   double operator()(double x) const {
      return FUNC1D;
   }

   double operator()(const double * x) const {
      return (*this)(*x);
   }

   double Derivative(double x) const { return FUNC1D; }
};

class DerivFunction : public ROOT::Math::IMultiGenFunction {

public:

   unsigned int NDim() const { return 2; }

   DerivFunction *  Clone() const {
      return new DerivFunction();
   }

private:

   double DoEval(const double *x) const {
      return FUNC;
   }

};

class DerivFunction1D : public ROOT::Math::IGenFunction {

public:

   DerivFunction1D *  Clone() const {
      return new DerivFunction1D();
   }

private:

   double DoEval(double x) const {
      return FUNC1D;
   }

};

struct F1D {
   double Eval(double x)  {
      return FUNC1D;
   }
};

const int Ntimes = NTIMES;

template <class Func>
void TestTime(const Func & f) {
   double x[Ntimes];
   TStopwatch w;
   TRandom2 r;
   r.RndmArray(Ntimes,x);
   w. Start();
   double s=0;
   for (int ipass = 0; ipass <NLOOP; ++ipass) {
      for (int i = 0; i < Ntimes-1; ++i) {
         double y = f(&x[i]);
         s+= y;
      }
   }
   w.Stop();
   std::cout << "Time for " << typeid(f).name() << "\t:  " << w.RealTime() << "  " << w.CpuTime() << std::endl;
   std::cout << s << std::endl;
}

void TestTimeGF(const ROOT::Math::IGenFunction & f) {
   TestTime(f);
}

void TestTimeTF1(TF1 & f) {
   double x[Ntimes];
   TStopwatch w;
   TRandom2 r;
   r.RndmArray(Ntimes,x);
   w. Start();
   double s=0;
   for (int ipass = 0; ipass <NLOOP; ++ipass) {
      for (int i = 0; i < Ntimes-1; ++i) {
         double y = f.EvalPar(&x[i],0);
         s+= y;
      }
   }
   w.Stop();
   std::cout << "Time for " << "TF1\t\t" << "\t:  " << w.RealTime() << "  " << w.CpuTime() << std::endl;
   std::cout << s << std::endl;
}

#ifdef HAVE_ROOFIT
void TestTimeRooPdf(RooAbsPdf & f, RooRealVar * vars) {
   double x[Ntimes];
   TStopwatch w;
   TRandom2 r;
   r.RndmArray(Ntimes,x);
   w. Start();
   double s=0;
//    RooArgSet * varSet = f.getVariables();
//    RooArgList varList(*varSet);
//    delete varSet;
//    RooAbsArg & arg = varList[0];
//    RooRealVar * vars = dynamic_cast<RooRealVar * > (&arg);
//    assert(x != 0);
   for (int ipass = 0; ipass <NLOOP; ++ipass) {
      for (int i = 0; i < Ntimes-1; ++i) {
         vars->setVal(x[i+1]);
         double y = x[i]*f.getVal();
         s+= y;
      }
   }
   w.Stop();
   std::cout << "Time for " << "RooPdf\t\t" << "\t:  " << w.RealTime() << "  " << w.CpuTime() << std::endl;
   std::cout << s << std::endl;
}
#endif

int main() {

   MyFunction myf;
   TestTime(myf);

   MyFunction1D myf1;
   TestTime(myf1);

   ROOT::Math::Functor<ROOT::Math::IMultiGradFunction>  f1(myf,2);
   TestTime(f1);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f2(&freeFunction,2);
   TestTime(f2);

   DerivFunction f3;
   TestTime(f3);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f4(&myf,&MyFunction::Eval,2);
   TestTime(f4);

   //1D

   ROOT::Math::Functor1D<ROOT::Math::IGradFunction>  f11(myf1);
   TestTime(f11);

   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f12(&freeFunction1D);
   TestTime(f12);

   DerivFunction1D f13;
   TestTime(f13);

   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f14(&myf1,&MyFunction1D::Derivative);
   TestTime(f14);

   //TestTimeGF(f3);
   typedef double( * FreeFunc ) (double );
   ROOT::Math::WrappedFunction<> f5(freeFunction1D);
   TestTime(f5);

   F1D fobj;
   //std::cout << typeid(&F1D::Eval).name() << std::endl;
   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f6(std::bind1st(std::mem_fun(&F1D::Eval), &fobj) );
   TestTime(f6);

   ROOT::Math::WrappedFunction<std::binder1st<std::mem_fun1_t<double, F1D, double> > >  f6a((std::bind1st(std::mem_fun(&F1D::Eval), &fobj)));
   TestTime(f6a);

   //ROOT::Math::WrappedMemFunction<F1D,FreeFunc>  f6b(&fobj, &F1D::Eval, );

//    typedef double (F1D::*MemFun)(double);
//    double (F1D::*p1 )(double) = &F1D::Eval;
//    std::cout << typeid(p1).name() << std::endl;
   ROOT::Math::WrappedMemFunction<F1D, double (F1D::*)(double) >  f6b(fobj, &F1D::Eval );
   TestTime(f6b);

   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f6c(&fobj, &F1D::Eval );
   TestTime(f6c);

#ifdef LATER
   FunctorNV<GradFunc, MyFunction> f5(myf);
   TestTime(f5);

   // test of virtuality two times
   Functor<GenFunc> f6(f3);
   TestTime(f6);
#endif

   TF1 tf1("tf1",freeRootFunc2D,0,1,0);
   //TF2 tf1("tf1","x+y",0,1,0,1);
   TestTimeTF1(tf1);

//    ROOT::Fit::WrappedTF1 f7(&tf1);
//    TestTime(f7);

   ROOT::Math::WrappedMultiTF1 f7b(tf1);
   TestTime(f7b);

   TF1 tf2("tf2",freeRootFunc1D,0,1,0);
   TestTimeTF1(tf2);

   ROOT::Math::WrappedTF1 f7c(tf2);
   TestTime(f7c);

//    double xx[1] = {2};
//    f7(xx);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f8(f7b,f7b.NDim());
   TestTime(f8);

// this does not compile oin Windows, since it does not understand the default arguments
#ifndef _WIN32
   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f9(&tf1,&TF1::Eval);
   TestTime(f9);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f10(&tf1,&TF1::EvalPar,tf1.GetNdim());
   TestTime(f10);
#endif

   // test with rootit
#ifdef HAVE_ROOFIT
   RooRealVar x("x","x",0);
   RooRealVar c("c","c",1.,1.,1.);
   RooExponential rooExp("exp","exponential",x,c);
   TestTimeRooPdf(rooExp,&x);
#endif

   return 0;
}
<commit_msg>fix a problem on Windows due to too large allocated stack memory<commit_after>#include <iostream>
//#include "FunctorNew.h"

//#include "Math/IGenFunction.h"
#include "Math/WrappedFunction.h"
//#include "Fit/WrappedTF1.h"
#include "TStopwatch.h"
#include <cmath>
#include "TRandom2.h"
#include "TF1.h"
#include "TF2.h"
#include "Math/WrappedTF1.h"
#include "Math/WrappedMultiTF1.h"

#ifdef HAVE_ROOFIT
#include "RooRealVar.h"
#include "RooArgList.h"
#include "RooExponential.h"
#endif

#include "Math/IFunctionfwd.h"
#include "Math/IFunction.h"
#include "Math/Functor.h"

#include <functional>
#include <vector>

#define NLOOP 100
#define NTIMES 500000
#define FUNC x[0]+x[1]
//#define FUNC x[0]*std::exp(x[1])
//#define FUNC 100 * (x[1]-x[0]*x[0])*(x[1]-x[0]*x[0]) + (1.-x[0])*(1-x[0])

#define FUNC1D x+x;
//#define FUNC1D std::exp(x);

double freeFunction(const double * x ) {
   return FUNC;
   //return ;
}

double freeRootFunc2D(double *x, double *){
   return FUNC;
}
double freeRootFunc1D(double *xx, double *){
   double x = *xx;
   return FUNC1D;
}

double freeFunction1D(double  x ) {
   return FUNC1D;
}

class MyFunction {

public:
   double operator()(const double *x) const {
      return FUNC;
      //return x[0]*std::exp(x[1]);
   }

   double Derivative(const double * x, int /* icoord */) const { return FUNC; }
   double Eval(const double * x) const { return FUNC; }
};

class MyFunction1D {

public:

   double operator()(double x) const {
      return FUNC1D;
   }

   double operator()(const double * x) const {
      return (*this)(*x);
   }

   double Derivative(double x) const { return FUNC1D; }
};

class DerivFunction : public ROOT::Math::IMultiGenFunction {

public:

   unsigned int NDim() const { return 2; }

   DerivFunction *  Clone() const {
      return new DerivFunction();
   }

private:

   double DoEval(const double *x) const {
      return FUNC;
   }

};

class DerivFunction1D : public ROOT::Math::IGenFunction {

public:

   DerivFunction1D *  Clone() const {
      return new DerivFunction1D();
   }

private:

   double DoEval(double x) const {
      return FUNC1D;
   }

};

struct F1D {
   double Eval(double x)  {
      return FUNC1D;
   }
};

const int Ntimes = NTIMES;

template <class Func>
void TestTime(const Func & f) {
  //double x[Ntimes];
  // use std::vector's to avoid crashes on Windows
   std::vector<double> x(Ntimes);
   TStopwatch w;
   TRandom2 r;
   r.RndmArray(Ntimes,&x[0]);
   w. Start();
   double s=0;
   for (int ipass = 0; ipass <NLOOP; ++ipass) {
      for (int i = 0; i < Ntimes-1; ++i) {
         double y = f(&x[i]);
         s+= y;
      }
   }
   w.Stop();
   std::cout << "Time for " << typeid(f).name() << "\t:  " << w.RealTime() << "  " << w.CpuTime() << std::endl;
   std::cout << s << std::endl;
}

void TestTimeGF(const ROOT::Math::IGenFunction & f) {
   TestTime(f);
}

void TestTimeTF1(TF1 & f) {
  //double x[Ntimes];
   std::vector<double> x(Ntimes);
   TStopwatch w;
   TRandom2 r;
   r.RndmArray(Ntimes,&x[0]);
   w. Start();
   double s=0;
   for (int ipass = 0; ipass <NLOOP; ++ipass) {
      for (int i = 0; i < Ntimes-1; ++i) {
         double y = f.EvalPar(&x[i],0);
         s+= y;
      }
   }
   w.Stop();
   std::cout << "Time for " << "TF1\t\t" << "\t:  " << w.RealTime() << "  " << w.CpuTime() << std::endl;
   std::cout << s << std::endl;
}

#ifdef HAVE_ROOFIT
void TestTimeRooPdf(RooAbsPdf & f, RooRealVar * vars) {
   //double x[Ntimes];
   std::vector<double> x(Ntimes);
   TStopwatch w;
   TRandom2 r;
   r.RndmArray(Ntimes,&x[0]);
   w. Start();
   double s=0;
//    RooArgSet * varSet = f.getVariables();
//    RooArgList varList(*varSet);
//    delete varSet;
//    RooAbsArg & arg = varList[0];
//    RooRealVar * vars = dynamic_cast<RooRealVar * > (&arg);
//    assert(x != 0);
   for (int ipass = 0; ipass <NLOOP; ++ipass) {
      for (int i = 0; i < Ntimes-1; ++i) {
         vars->setVal(x[i+1]);
         double y = x[i]*f.getVal();
         s+= y;
      }
   }
   w.Stop();
   std::cout << "Time for " << "RooPdf\t\t" << "\t:  " << w.RealTime() << "  " << w.CpuTime() << std::endl;
   std::cout << s << std::endl;
}
#endif

int main() {

   MyFunction myf;
   TestTime(myf);

   MyFunction1D myf1;
   TestTime(myf1);

   ROOT::Math::Functor<ROOT::Math::IMultiGradFunction>  f1(myf,2);
   TestTime(f1);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f2(&freeFunction,2);
   TestTime(f2);

   DerivFunction f3;
   TestTime(f3);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f4(&myf,&MyFunction::Eval,2);
   TestTime(f4);

   //1D

   ROOT::Math::Functor1D<ROOT::Math::IGradFunction>  f11(myf1);
   TestTime(f11);

   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f12(&freeFunction1D);
   TestTime(f12);

   DerivFunction1D f13;
   TestTime(f13);

   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f14(&myf1,&MyFunction1D::Derivative);
   TestTime(f14);

   //TestTimeGF(f3);
   typedef double( * FreeFunc ) (double );
   ROOT::Math::WrappedFunction<> f5(freeFunction1D);
   TestTime(f5);

   F1D fobj;
   //std::cout << typeid(&F1D::Eval).name() << std::endl;
   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f6(std::bind1st(std::mem_fun(&F1D::Eval), &fobj) );
   TestTime(f6);

   ROOT::Math::WrappedFunction<std::binder1st<std::mem_fun1_t<double, F1D, double> > >  f6a((std::bind1st(std::mem_fun(&F1D::Eval), &fobj)));
   TestTime(f6a);

   //ROOT::Math::WrappedMemFunction<F1D,FreeFunc>  f6b(&fobj, &F1D::Eval, );

//    typedef double (F1D::*MemFun)(double);
//    double (F1D::*p1 )(double) = &F1D::Eval;
//    std::cout << typeid(p1).name() << std::endl;
   ROOT::Math::WrappedMemFunction<F1D, double (F1D::*)(double) >  f6b(fobj, &F1D::Eval );
   TestTime(f6b);

   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f6c(&fobj, &F1D::Eval );
   TestTime(f6c);

#ifdef LATER
   FunctorNV<GradFunc, MyFunction> f5(myf);
   TestTime(f5);

   // test of virtuality two times
   Functor<GenFunc> f6(f3);
   TestTime(f6);
#endif

   TF1 tf1("tf1",freeRootFunc2D,0,1,0);
   //TF2 tf1("tf1","x+y",0,1,0,1);
   TestTimeTF1(tf1);

//    ROOT::Fit::WrappedTF1 f7(&tf1);
//    TestTime(f7);

   ROOT::Math::WrappedMultiTF1 f7b(tf1);
   TestTime(f7b);

   TF1 tf2("tf2",freeRootFunc1D,0,1,0);
   TestTimeTF1(tf2);

   ROOT::Math::WrappedTF1 f7c(tf2);
   TestTime(f7c);

//    double xx[1] = {2};
//    f7(xx);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f8(f7b,f7b.NDim());
   TestTime(f8);

// this does not compile oin Windows, since it does not understand the default arguments
#ifndef _WIN32
   ROOT::Math::Functor1D<ROOT::Math::IGenFunction> f9(&tf1,&TF1::Eval);
   TestTime(f9);

   ROOT::Math::Functor<ROOT::Math::IMultiGenFunction> f10(&tf1,&TF1::EvalPar,tf1.GetNdim());
   TestTime(f10);
#endif

   // test with rootit
#ifdef HAVE_ROOFIT
   RooRealVar x("x","x",0);
   RooRealVar c("c","c",1.,1.,1.);
   RooExponential rooExp("exp","exponential",x,c);
   TestTimeRooPdf(rooExp,&x);
#endif

   return 0;
}
<|endoftext|>


<commit_before>/*
 * jcom.parameter
 * External for Jamoma: parameter definition
 * By Tim Place and Théo de la Hogue, Copyright © 2011
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTModularClassWrapperMax.h"

#define data_out 0
#define	dump_out 1

// Definitions
void		WrapTTDataClass(WrappedClassPtr c);
void		WrappedDataClass_new(TTPtr self, AtomCount argc, AtomPtr argv);

void		data_assist(TTPtr self, TTPtr b, long msg, AtomCount arg, char *dst);

void		data_new_address(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		data_subscribe(TTPtr self, SymbolPtr address, AtomCount argc, AtomPtr argv);
void		data_address(TTPtr self, SymbolPtr name);

#ifndef JMOD_RETURN
void		data_return_value(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
#endif

#ifndef JMOD_MESSAGE
void		WrappedDataClass_anything(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		data_bang(TTPtr self);
void		data_int(TTPtr self, long value);
void		data_float(TTPtr self, double value);
void		data_list(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);

void		data_inc(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		data_dec(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
#endif

int TTCLASSWRAPPERMAX_EXPORT main(void)
{
	ModularSpec *spec = new ModularSpec;
	spec->_wrap = &WrapTTDataClass;
	spec->_new = &WrappedDataClass_new;
	spec->_free = NULL;
#ifndef JMOD_MESSAGE
	spec->_any = &WrappedDataClass_anything;
#else
	spec->_any = NULL;
#endif

#ifdef JMOD_MESSAGE
	return wrapTTModularClassAsMaxClass(kTTSym_Data, "jcom.message", NULL, spec);
#endif

#ifdef JMOD_RETURN
	return wrapTTModularClassAsMaxClass(kTTSym_Data, "jcom.return", NULL, spec);
#endif

#ifndef JMOD_MESSAGE
#ifndef JMOD_RETURN
	return wrapTTModularClassAsMaxClass(kTTSym_Data, "jcom.parameter", NULL, spec);
#endif
#endif
}

void WrapTTDataClass(WrappedClassPtr c)
{
	class_addmethod(c->maxClass, (method)data_assist,						"assist",				A_CANT, 0L);

#ifndef JMOD_RETURN
	class_addmethod(c->maxClass, (method)data_return_value,					"return_value",			A_CANT, 0);
#endif

#ifndef JMOD_MESSAGE
	class_addmethod(c->maxClass, (method)data_bang,							"bang",					0L);
	class_addmethod(c->maxClass, (method)data_int,							"int",					A_LONG, 0);
	class_addmethod(c->maxClass, (method)data_float,						"float",				A_FLOAT, 0);
	class_addmethod(c->maxClass, (method)data_list,							"list",					A_GIMME, 0);

	class_addmethod(c->maxClass, (method)data_inc,							"+",					A_GIMME, 0);
	class_addmethod(c->maxClass, (method)data_dec,							"-",					A_GIMME, 0);
#endif

	class_addmethod(c->maxClass, (method)data_address,						"address",				A_SYM,0);
}

void WrappedDataClass_new(TTPtr self, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	SymbolPtr					relativeAddress;
	long						attrstart = attr_args_offset(argc, argv);			// support normal arguments

	// check address argument
	relativeAddress = _sym_nothing;
	if (attrstart && argv)
		if (atom_gettype(argv) == A_SYM)
			relativeAddress = atom_getsym(argv);

	if (relativeAddress == _sym_nothing) {
		object_error((ObjectPtr)x, "needs a name as first argument");
		return;
	}

	// Make outlets (before attr_args_process)
	/////////////////////////////////////////////////////////////////////////////////
#ifndef JMOD_RETURN

	// Don't create outlets during dynamic changes
		x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 2);
		x->outlets[data_out] = outlet_new(x, NULL);						// anything outlet to output data

#endif

	data_new_address(self, relativeAddress, argc--, argv++);
}

void data_new_address(TTPtr self, SymbolPtr relativeAddress, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	x->useInternals = false;

	// create the data
#ifdef JMOD_MESSAGE
	jamoma_data_create((ObjectPtr)x, &x->wrappedObject, kTTSym_message);
#endif

#if JMOD_RETURN
	jamoma_data_create((ObjectPtr)x, &x->wrappedObject, kTTSym_return);
#endif

#ifndef JMOD_MESSAGE
#ifndef JMOD_RETURN
	jamoma_data_create((ObjectPtr)x, &x->wrappedObject, kTTSym_parameter);
#endif
#endif

    if (argc && argv)
        attr_args_process(x, argc, argv);

	// The following must be deferred because we have to interrogate our box,
	// and our box is not yet valid until we have finished instantiating the object.
	// Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
	defer_low((ObjectPtr)x, (method)data_subscribe, relativeAddress, argc, argv);
}

void data_subscribe(TTPtr self, SymbolPtr relativeAddress, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	// for relative address
	if (TTAddress(relativeAddress->s_name).getType() == kAddressRelative) {
		jamoma_subscriber_create((ObjectPtr)x, x->wrappedObject, TTAddress(jamoma_parse_dieze((ObjectPtr)x, relativeAddress)->s_name), &x->subscriberObject);

	}
	else
		object_error((ObjectPtr)x, "can't register because %s is not a relative address", relativeAddress->s_name);
}

void data_address(TTPtr self, SymbolPtr address)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	// unregister wrapped object (or internals)
	wrappedModularClass_unregister(x);

	// rebuild wrapped object (or internals)
	defer_low(self,(method)data_new_address, address, 0, NULL); // TODO : give all @attribute too
}

// Method for Assistance Messages
void data_assist(TTPtr self, TTPtr b, long msg, AtomCount arg, char *dst)
{
	if (msg==1) 						// Inlet
		strcpy(dst, "input");
	else {							// Outlets
		switch(arg) {
			case data_out:
				strcpy(dst, "direct: values");
				break;
			case dump_out:
				strcpy(dst, "dumpout");
				break;
		}
 	}
}

#ifndef JMOD_MESSAGE
void data_bang(TTPtr self)
{
	data_list(self, _sym_bang, 0, NULL);
}

void data_int(TTPtr self, long value)
{
	t_atom a;

	atom_setlong(&a, value);
	data_list(self, _sym_int, 1, &a);
}

void data_float(TTPtr self, double value)
{
	t_atom a;

	atom_setfloat(&a, value);
	data_list(self, _sym_float, 1, &a);
}

void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	jamoma_data_command((TTDataPtr)selectedObject, msg, argc, argv);
}

void WrappedDataClass_anything(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	jamoma_data_command((TTDataPtr)selectedObject, msg, argc, argv);
}
#endif

#ifndef JMOD_RETURN
void data_return_value(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	// avoid blank before data
	if (msg == _sym_nothing)
		outlet_atoms(x->outlets[data_out], argc, argv);
	else
		outlet_anything(x->outlets[data_out], msg, argc, argv);
}
#endif

#ifndef JMOD_MESSAGE
void data_inc(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	TTValue v;

	jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
	selectedObject->sendMessage(TTSymbol("Inc"), v, kTTValNONE);
}

void data_dec(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	TTValue v;

	jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
	selectedObject->sendMessage(TTSymbol("Dec"), v, kTTValNONE);
}
#endif<commit_msg>Storing arguments to recall them when address change<commit_after>/*
 * jcom.parameter
 * External for Jamoma: parameter definition
 * By Tim Place and Théo de la Hogue, Copyright © 2011
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTModularClassWrapperMax.h"

#define data_out 0
#define	dump_out 1

// This is used to store extra data
typedef struct extra {

	TTValue         arrayArgs;		// store arguments

} t_extra;
#define EXTRA ((t_extra*)x->extra)

// Definitions
void		WrapTTDataClass(WrappedClassPtr c);
void		WrappedDataClass_new(TTPtr self, AtomCount argc, AtomPtr argv);
void        WrappedDataClass_free(TTPtr self);

void		data_assist(TTPtr self, TTPtr b, long msg, AtomCount arg, char *dst);

void		data_new_address(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		data_subscribe(TTPtr self, SymbolPtr address, AtomCount argc, AtomPtr argv);
void		data_address(TTPtr self, SymbolPtr name);

#ifndef JMOD_RETURN
void		data_return_value(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
#endif

#ifndef JMOD_MESSAGE
void		WrappedDataClass_anything(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		data_bang(TTPtr self);
void		data_int(TTPtr self, long value);
void		data_float(TTPtr self, double value);
void		data_list(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);

void		data_inc(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		data_dec(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv);
#endif

int TTCLASSWRAPPERMAX_EXPORT main(void)
{
	ModularSpec *spec = new ModularSpec;
	spec->_wrap = &WrapTTDataClass;
	spec->_new = &WrappedDataClass_new;
	spec->_free = &WrappedDataClass_free;
#ifndef JMOD_MESSAGE
	spec->_any = &WrappedDataClass_anything;
#else
	spec->_any = NULL;
#endif

#ifdef JMOD_MESSAGE
	return wrapTTModularClassAsMaxClass(kTTSym_Data, "jcom.message", NULL, spec);
#endif

#ifdef JMOD_RETURN
	return wrapTTModularClassAsMaxClass(kTTSym_Data, "jcom.return", NULL, spec);
#endif

#ifndef JMOD_MESSAGE
#ifndef JMOD_RETURN
	return wrapTTModularClassAsMaxClass(kTTSym_Data, "jcom.parameter", NULL, spec);
#endif
#endif
}

void WrapTTDataClass(WrappedClassPtr c)
{
	class_addmethod(c->maxClass, (method)data_assist,						"assist",				A_CANT, 0L);

#ifndef JMOD_RETURN
	class_addmethod(c->maxClass, (method)data_return_value,					"return_value",			A_CANT, 0);
#endif

#ifndef JMOD_MESSAGE
	class_addmethod(c->maxClass, (method)data_bang,							"bang",					0L);
	class_addmethod(c->maxClass, (method)data_int,							"int",					A_LONG, 0);
	class_addmethod(c->maxClass, (method)data_float,						"float",				A_FLOAT, 0);
	class_addmethod(c->maxClass, (method)data_list,							"list",					A_GIMME, 0);

	class_addmethod(c->maxClass, (method)data_inc,							"+",					A_GIMME, 0);
	class_addmethod(c->maxClass, (method)data_dec,							"-",					A_GIMME, 0);
#endif

	class_addmethod(c->maxClass, (method)data_address,						"address",				A_SYM,0);
}

void WrappedDataClass_new(TTPtr self, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	SymbolPtr					relativeAddress;
	long						attrstart = attr_args_offset(argc, argv);			// support normal arguments

	// check address argument
	relativeAddress = _sym_nothing;
	if (attrstart && argv)
		if (atom_gettype(argv) == A_SYM)
			relativeAddress = atom_getsym(argv);

	if (relativeAddress == _sym_nothing) {
		object_error((ObjectPtr)x, "needs a name as first argument");
		return;
	}

	// Make outlets (before attr_args_process)
	/////////////////////////////////////////////////////////////////////////////////
#ifndef JMOD_RETURN

	// Don't create outlets during dynamic changes
		x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 2);
		x->outlets[data_out] = outlet_new(x, NULL);						// anything outlet to output data

#endif

    // Prepare extra data
	x->extra = (t_extra*)malloc(sizeof(t_extra));

    EXTRA->arrayArgs = kTTValNONE;

    // Store arguments
	if (argc > 1 && argv)
        jamoma_ttvalue_from_Atom(EXTRA->arrayArgs, _sym_list, argc--, argv++);

	data_new_address(self, relativeAddress, argc--, argv++);
}

void WrappedDataClass_free(TTPtr self)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	free(EXTRA);
}

void data_new_address(TTPtr self, SymbolPtr relativeAddress, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	x->useInternals = false;

	// create the data
#ifdef JMOD_MESSAGE
	jamoma_data_create((ObjectPtr)x, &x->wrappedObject, kTTSym_message);
#endif

#if JMOD_RETURN
	jamoma_data_create((ObjectPtr)x, &x->wrappedObject, kTTSym_return);
#endif

#ifndef JMOD_MESSAGE
#ifndef JMOD_RETURN
	jamoma_data_create((ObjectPtr)x, &x->wrappedObject, kTTSym_parameter);
#endif
#endif

    if (argc && argv)
        attr_args_process(x, argc, argv);

	// The following must be deferred because we have to interrogate our box,
	// and our box is not yet valid until we have finished instantiating the object.
	// Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
	defer_low((ObjectPtr)x, (method)data_subscribe, relativeAddress, argc, argv);
}

void data_subscribe(TTPtr self, SymbolPtr relativeAddress, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	// for relative address
	if (TTAddress(relativeAddress->s_name).getType() == kAddressRelative) {

		jamoma_subscriber_create((ObjectPtr)x, x->wrappedObject, TTAddress(jamoma_parse_dieze((ObjectPtr)x, relativeAddress)->s_name), &x->subscriberObject);

	}
	else
		object_error((ObjectPtr)x, "can't register because %s is not a relative address", relativeAddress->s_name);
}

void data_address(TTPtr self, SymbolPtr address)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
    AtomCount					argc = 0;
	AtomPtr						argv = NULL;

	// unregister wrapped object (or internals)
	wrappedModularClass_unregister(x);

    // use stored arguments
    jamoma_ttvalue_to_Atom(EXTRA->arrayArgs, &argc, &argv);

	// rebuild wrapped object (or internals)
	defer_low(self,(method)data_new_address, address, argc, argv);
}

// Method for Assistance Messages
void data_assist(TTPtr self, TTPtr b, long msg, AtomCount arg, char *dst)
{
	if (msg==1) 						// Inlet
		strcpy(dst, "input");
	else {							// Outlets
		switch(arg) {
			case data_out:
				strcpy(dst, "direct: values");
				break;
			case dump_out:
				strcpy(dst, "dumpout");
				break;
		}
 	}
}

#ifndef JMOD_MESSAGE
void data_bang(TTPtr self)
{
	data_list(self, _sym_bang, 0, NULL);
}

void data_int(TTPtr self, long value)
{
	t_atom a;

	atom_setlong(&a, value);
	data_list(self, _sym_int, 1, &a);
}

void data_float(TTPtr self, double value)
{
	t_atom a;

	atom_setfloat(&a, value);
	data_list(self, _sym_float, 1, &a);
}

void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	jamoma_data_command((TTDataPtr)selectedObject, msg, argc, argv);
}

void WrappedDataClass_anything(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	jamoma_data_command((TTDataPtr)selectedObject, msg, argc, argv);
}
#endif

#ifndef JMOD_RETURN
void data_return_value(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;

	// avoid blank before data
	if (msg == _sym_nothing)
		outlet_atoms(x->outlets[data_out], argc, argv);
	else
		outlet_anything(x->outlets[data_out], msg, argc, argv);
}
#endif

#ifndef JMOD_MESSAGE
void data_inc(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	TTValue v;

	jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
	selectedObject->sendMessage(TTSymbol("Inc"), v, kTTValNONE);
}

void data_dec(TTPtr self, SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	TTValue v;

	jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
	selectedObject->sendMessage(TTSymbol("Dec"), v, kTTValNONE);
}
#endif<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SV_GLYPHCACHE_HXX
#define _SV_GLYPHCACHE_HXX

#include <vcl/dllapi.h>

class GlyphCache;
class GlyphMetric;
class GlyphData;
class ServerFont;
class GlyphCachePeer;
class ServerFontLayoutEngine;
class ServerFontLayout;
class ExtraKernInfo;
struct ImplKernPairData;
class ImplFontOptions;

#include <tools/gen.hxx>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/shared_ptr.hpp>

namespace basegfx { class B2DPolyPolygon; }

class RawBitmap;

#include <outfont.hxx>
#include <impfont.hxx>

class ServerFontLayout;
#include <sallayout.hxx>

namespace vcl
{
    struct FontCapabilities;
}

// =======================================================================

class VCL_PLUGIN_PUBLIC GlyphCache
{
public:
    explicit                    GlyphCache( GlyphCachePeer& );
    /*virtual*/                 ~GlyphCache();

    static GlyphCache&      GetInstance();

    void                        AddFontFile( const rtl::OString& rNormalizedName,
                                    int nFaceNum, sal_IntPtr nFontId, const ImplDevFontAttributes&,
                                    const ExtraKernInfo* = NULL );
    void                        AnnounceFonts( ImplDevFontList* ) const;

    ServerFont*                 CacheFont( const ImplFontSelectData& );
    void                        UncacheFont( ServerFont& );
    void                        InvalidateAllGlyphs();

protected:
    GlyphCachePeer&             mrPeer;

private:
    friend class ServerFont;
    // used by ServerFont class only
    void                        AddedGlyph( ServerFont&, GlyphData& );
    void                        RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
    void                        UsingGlyph( ServerFont&, GlyphData& );
    void                        GrowNotify();

private:
    void                        GarbageCollect();

    // the GlyphCache's FontList matches a font request to a serverfont instance
    // the FontList key's mpFontData member is reinterpreted as integer font id
    struct IFSD_Equal{  bool operator()( const ImplFontSelectData&, const ImplFontSelectData& ) const; };
    struct IFSD_Hash{ size_t operator()( const ImplFontSelectData& ) const; };
    typedef ::boost::unordered_map<ImplFontSelectData,ServerFont*,IFSD_Hash,IFSD_Equal > FontList;
    FontList                    maFontList;
    sal_uLong                       mnMaxSize;      // max overall cache size in bytes
    mutable sal_uLong               mnBytesUsed;
    mutable long                mnLruIndex;
    mutable int                 mnGlyphCount;
    ServerFont*                 mpCurrentGCFont;

    class FreetypeManager*      mpFtManager;
};

// =======================================================================

class GlyphMetric
{
public:
    Point                   GetOffset() const   { return maOffset; }
    Point                   GetDelta() const    { return maDelta; }
    Size                    GetSize() const     { return maSize; }
    long                    GetCharWidth() const { return mnAdvanceWidth; }

protected:
    friend class GlyphData;
    void                    SetOffset( int nX, int nY ) { maOffset = Point( nX, nY); }
    void                    SetDelta( int nX, int nY )  { maDelta = Point( nX, nY); }
    void                    SetSize( const Size& s )    { maSize = s; }
    void                    SetCharWidth( long nW )     { mnAdvanceWidth = nW; }

private:
    long                    mnAdvanceWidth;
    Point                   maDelta;
    Point                   maOffset;
    Size                    maSize;
};

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

// the glyph specific data needed by a GlyphCachePeer is usually trivial,
// not attaching it to the corresponding GlyphData would be overkill
struct ExtGlyphData
{
    int     meInfo;
    void*   mpData;

    ExtGlyphData() : meInfo(0), mpData(NULL) {}
};

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

class GlyphData
{
public:
    const GlyphMetric&      GetMetric() const           { return maMetric; }
    Size                    GetSize() const             { return maMetric.GetSize(); }

    void                    SetSize( const Size& s)     { maMetric.SetSize( s ); }
    void                    SetOffset( int nX, int nY ) { maMetric.SetOffset( nX, nY ); }
    void                    SetDelta( int nX, int nY )  { maMetric.SetDelta( nX, nY ); }
    void                    SetCharWidth( long nW )     { maMetric.SetCharWidth( nW ); }

    void                    SetLruValue( int n ) const  { mnLruValue = n; }
    long                    GetLruValue() const         { return mnLruValue;}

    ExtGlyphData&           ExtDataRef()                { return maExtData; }
    const ExtGlyphData&     ExtDataRef() const          { return maExtData; }

private:
    GlyphMetric             maMetric;
    ExtGlyphData            maExtData;

    // used by GlyphCache for cache LRU algorithm
    mutable long            mnLruValue;
};

// =======================================================================

class VCL_PLUGIN_PUBLIC ServerFont
{
public:
    virtual const ::rtl::OString*   GetFontFileName() const { return NULL; }
    virtual int                 GetFontFaceNumber() const   { return 0; }
    virtual bool                TestFont() const            { return true; }
    virtual void*               GetFtFace() const { return 0; }
    virtual int                 GetLoadFlags() const { return 0; }
    virtual void                SetFontOptions( boost::shared_ptr<ImplFontOptions> ) {}
    virtual boost::shared_ptr<ImplFontOptions> GetFontOptions() const
        { return boost::shared_ptr<ImplFontOptions>(); }
    virtual bool                NeedsArtificialBold() const { return false; }
    virtual bool                NeedsArtificialItalic() const { return false; }

    const ImplFontSelectData&   GetFontSelData() const      { return maFontSelData; }

    virtual void                FetchFontMetric( ImplFontMetricData&, long& rFactor ) const = 0;
    virtual sal_uLong               GetKernPairs( ImplKernPairData** ) const      { return 0; }
    virtual int                 GetGlyphKernValue( int, int ) const           { return 0; }
    virtual const ImplFontCharMap* GetImplFontCharMap() const = 0;
    virtual bool                GetFontCapabilities(vcl::FontCapabilities &) const { return false; }
    Point                       TransformPoint( const Point& ) const;

    GlyphData&                  GetGlyphData( int nGlyphIndex );
    const GlyphMetric&          GetGlyphMetric( int nGlyphIndex )
                                { return GetGlyphData( nGlyphIndex ).GetMetric(); }

    virtual int                 GetGlyphIndex( sal_UCS4 ) const = 0;
    virtual bool                GetGlyphOutline( int nGlyphIndex, ::basegfx::B2DPolyPolygon& ) const = 0;
    virtual bool                GetAntialiasAdvice( void ) const = 0;
    bool                        IsGlyphInvisible( int nGlyphIndex );
    virtual bool                GetGlyphBitmap1( int nGlyphIndex, RawBitmap& ) const = 0;
    virtual bool                GetGlyphBitmap8( int nGlyphIndex, RawBitmap& ) const = 0;

    void                        SetExtended( int nInfo, void* ppVoid );
    int                         GetExtInfo() { return mnExtInfo; }
    void*                       GetExtPointer() { return mpExtData; }

protected:
    friend class GlyphCache;
    friend class ServerFontLayout;
    explicit                    ServerFont( const ImplFontSelectData& );
    virtual                     ~ServerFont();

    void                        AddRef() const      { ++mnRefCount; }
    long                        GetRefCount() const { return mnRefCount; }
    long                        Release() const;
    sal_uLong                       GetByteCount() const { return mnBytesUsed; }

    virtual void                InitGlyphData( int nGlyphIndex, GlyphData& ) const = 0;
    virtual void                GarbageCollect( long );
    void                        ReleaseFromGarbageCollect();

    virtual ServerFontLayoutEngine* GetLayoutEngine() { return NULL; }

private:
    typedef ::boost::unordered_map<int,GlyphData> GlyphList;
    mutable GlyphList           maGlyphList;

    const ImplFontSelectData    maFontSelData;

    // info for GlyphcachePeer
    int                         mnExtInfo;
    void*                       mpExtData;

    // used by GlyphCache for cache LRU algorithm
    mutable long                mnRefCount;
    mutable sal_uLong               mnBytesUsed;

    ServerFont*                 mpPrevGCFont;
    ServerFont*                 mpNextGCFont;

protected:
    // 16.16 fixed point values used for a rotated font
    long                        mnCos;
    long                        mnSin;
private:
    int                         mnZWJ;
    int                         mnZWNJ;
    bool                        mbCollectedZW;
};

// =======================================================================

// a class for cache entries for physical font instances that are based on serverfonts
class VCL_PLUGIN_PUBLIC ImplServerFontEntry : public ImplFontEntry
{
private:
    ServerFont*    mpServerFont;
    boost::shared_ptr<ImplFontOptions> mpFontOptions;
    bool           mbGotFontOptions;

public:
                   ImplServerFontEntry( ImplFontSelectData& );
    virtual        ~ImplServerFontEntry();
    void           SetServerFont( ServerFont* p) { mpServerFont = p; }
    void           HandleFontOptions();
};

// =======================================================================

class VCL_PLUGIN_PUBLIC ServerFontLayout : public GenericSalLayout
{
private:
    ServerFont&     mrServerFont;

    // enforce proper copy semantic
    SAL_DLLPRIVATE  ServerFontLayout( const ServerFontLayout& );
    SAL_DLLPRIVATE  ServerFontLayout& operator=( const ServerFontLayout& );

public:
                    ServerFontLayout( ServerFont& );
    virtual bool    LayoutText( ImplLayoutArgs& );
    virtual void    AdjustLayout( ImplLayoutArgs& );
    virtual void    DrawText( SalGraphics& ) const;
    ServerFont&     GetServerFont() const   { return mrServerFont; }
};

// =======================================================================

class ServerFontLayoutEngine
{
public:
    virtual         ~ServerFontLayoutEngine() {}
    virtual bool    operator()( ServerFontLayout&, ImplLayoutArgs& );
};

// =======================================================================

class GlyphCachePeer
{
protected:
                    GlyphCachePeer() : mnBytesUsed(0) {}
    virtual         ~GlyphCachePeer() {}

public:
    sal_Int32       GetByteCount() const { return mnBytesUsed; }
    virtual void    RemovingFont( ServerFont& ) {}
    virtual void    RemovingGlyph( ServerFont&, GlyphData&, int ) {}

protected:
    sal_Int32       mnBytesUsed;
};

// =======================================================================

class VCL_PLUGIN_PUBLIC RawBitmap
{
public:
                    RawBitmap();
                    ~RawBitmap();
    bool            Rotate( int nAngle );

public:
    unsigned char*  mpBits;
    sal_uLong           mnAllocated;

    sal_uLong           mnWidth;
    sal_uLong           mnHeight;

    sal_uLong           mnScanlineSize;
    sal_uLong           mnBitCount;

    int             mnXOffset;
    int             mnYOffset;
};

// =======================================================================

inline void ServerFont::SetExtended( int nInfo, void* pVoid )
{
    mnExtInfo = nInfo;
    mpExtData = pVoid;
}

// =======================================================================

// ExtraKernInfo allows an on-demand query of extra kerning info #i29881#
// The kerning values have to be scaled to match the font size before use
class VCL_PLUGIN_PUBLIC ExtraKernInfo
{
public:
    ExtraKernInfo( sal_IntPtr nFontId );
    virtual ~ExtraKernInfo() {}

    bool    HasKernPairs() const;
    int     GetUnscaledKernPairs( ImplKernPairData** ) const;
    int     GetUnscaledKernValue( sal_Unicode cLeft, sal_Unicode cRight ) const;

protected:
    mutable bool mbInitialized;
    virtual void Initialize() const = 0;

protected:
    sal_IntPtr     mnFontId;

    // container to map a unicode pair to an unscaled kerning value
    struct PairEqual{ int operator()(const ImplKernPairData& rA, const ImplKernPairData& rB) const
                          { return (rA.mnChar1 == rB.mnChar1) && (rA.mnChar2 == rB.mnChar2); } };
    struct PairHash{ int operator()(const ImplKernPairData& rA) const
                         { return (rA.mnChar1) * 256 ^ rA.mnChar2; } };
    typedef boost::unordered_set< ImplKernPairData, PairHash, PairEqual > UnicodeKernPairs;
    mutable UnicodeKernPairs maUnicodeKernPairs;
};

// =======================================================================

#endif // _SV_GLYPHCACHE_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>make these pure virtual to prove all implemented in sole sub-class<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SV_GLYPHCACHE_HXX
#define _SV_GLYPHCACHE_HXX

#include <vcl/dllapi.h>

class GlyphCache;
class GlyphMetric;
class GlyphData;
class ServerFont;
class GlyphCachePeer;
class ServerFontLayoutEngine;
class ServerFontLayout;
class ExtraKernInfo;
struct ImplKernPairData;
class ImplFontOptions;

#include <tools/gen.hxx>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/shared_ptr.hpp>

namespace basegfx { class B2DPolyPolygon; }

class RawBitmap;

#include <outfont.hxx>
#include <impfont.hxx>

class ServerFontLayout;
#include <sallayout.hxx>

namespace vcl
{
    struct FontCapabilities;
}

// =======================================================================

class VCL_PLUGIN_PUBLIC GlyphCache
{
public:
    explicit                    GlyphCache( GlyphCachePeer& );
    /*virtual*/                 ~GlyphCache();

    static GlyphCache&      GetInstance();

    void                        AddFontFile( const rtl::OString& rNormalizedName,
                                    int nFaceNum, sal_IntPtr nFontId, const ImplDevFontAttributes&,
                                    const ExtraKernInfo* = NULL );
    void                        AnnounceFonts( ImplDevFontList* ) const;

    ServerFont*                 CacheFont( const ImplFontSelectData& );
    void                        UncacheFont( ServerFont& );
    void                        InvalidateAllGlyphs();

protected:
    GlyphCachePeer&             mrPeer;

private:
    friend class ServerFont;
    // used by ServerFont class only
    void                        AddedGlyph( ServerFont&, GlyphData& );
    void                        RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
    void                        UsingGlyph( ServerFont&, GlyphData& );
    void                        GrowNotify();

private:
    void                        GarbageCollect();

    // the GlyphCache's FontList matches a font request to a serverfont instance
    // the FontList key's mpFontData member is reinterpreted as integer font id
    struct IFSD_Equal{  bool operator()( const ImplFontSelectData&, const ImplFontSelectData& ) const; };
    struct IFSD_Hash{ size_t operator()( const ImplFontSelectData& ) const; };
    typedef ::boost::unordered_map<ImplFontSelectData,ServerFont*,IFSD_Hash,IFSD_Equal > FontList;
    FontList                    maFontList;
    sal_uLong                       mnMaxSize;      // max overall cache size in bytes
    mutable sal_uLong               mnBytesUsed;
    mutable long                mnLruIndex;
    mutable int                 mnGlyphCount;
    ServerFont*                 mpCurrentGCFont;

    class FreetypeManager*      mpFtManager;
};

// =======================================================================

class GlyphMetric
{
public:
    Point                   GetOffset() const   { return maOffset; }
    Point                   GetDelta() const    { return maDelta; }
    Size                    GetSize() const     { return maSize; }
    long                    GetCharWidth() const { return mnAdvanceWidth; }

protected:
    friend class GlyphData;
    void                    SetOffset( int nX, int nY ) { maOffset = Point( nX, nY); }
    void                    SetDelta( int nX, int nY )  { maDelta = Point( nX, nY); }
    void                    SetSize( const Size& s )    { maSize = s; }
    void                    SetCharWidth( long nW )     { mnAdvanceWidth = nW; }

private:
    long                    mnAdvanceWidth;
    Point                   maDelta;
    Point                   maOffset;
    Size                    maSize;
};

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

// the glyph specific data needed by a GlyphCachePeer is usually trivial,
// not attaching it to the corresponding GlyphData would be overkill
struct ExtGlyphData
{
    int     meInfo;
    void*   mpData;

    ExtGlyphData() : meInfo(0), mpData(NULL) {}
};

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

class GlyphData
{
public:
    const GlyphMetric&      GetMetric() const           { return maMetric; }
    Size                    GetSize() const             { return maMetric.GetSize(); }

    void                    SetSize( const Size& s)     { maMetric.SetSize( s ); }
    void                    SetOffset( int nX, int nY ) { maMetric.SetOffset( nX, nY ); }
    void                    SetDelta( int nX, int nY )  { maMetric.SetDelta( nX, nY ); }
    void                    SetCharWidth( long nW )     { maMetric.SetCharWidth( nW ); }

    void                    SetLruValue( int n ) const  { mnLruValue = n; }
    long                    GetLruValue() const         { return mnLruValue;}

    ExtGlyphData&           ExtDataRef()                { return maExtData; }
    const ExtGlyphData&     ExtDataRef() const          { return maExtData; }

private:
    GlyphMetric             maMetric;
    ExtGlyphData            maExtData;

    // used by GlyphCache for cache LRU algorithm
    mutable long            mnLruValue;
};

// =======================================================================

class VCL_PLUGIN_PUBLIC ServerFont
{
public:
    virtual const ::rtl::OString*   GetFontFileName() const = 0;
    virtual int                 GetFontFaceNumber() const = 0;
    virtual bool                TestFont() const = 0;
    virtual void*               GetFtFace() const = 0;
    virtual int                 GetLoadFlags() const  = 0;
    virtual void                SetFontOptions( boost::shared_ptr<ImplFontOptions> ) = 0;
    virtual boost::shared_ptr<ImplFontOptions> GetFontOptions() const = 0;
    virtual bool                NeedsArtificialBold() const = 0;
    virtual bool                NeedsArtificialItalic() const = 0;

    const ImplFontSelectData&   GetFontSelData() const      { return maFontSelData; }

    virtual void                FetchFontMetric( ImplFontMetricData&, long& rFactor ) const = 0;
    virtual sal_uLong               GetKernPairs( ImplKernPairData** ) const = 0;
    virtual int                 GetGlyphKernValue( int, int ) const = 0;
    virtual const ImplFontCharMap* GetImplFontCharMap() const = 0;
    virtual bool                GetFontCapabilities(vcl::FontCapabilities &) const = 0;
    Point                       TransformPoint( const Point& ) const;

    GlyphData&                  GetGlyphData( int nGlyphIndex );
    const GlyphMetric&          GetGlyphMetric( int nGlyphIndex )
                                { return GetGlyphData( nGlyphIndex ).GetMetric(); }

    virtual int                 GetGlyphIndex( sal_UCS4 ) const = 0;
    virtual bool                GetGlyphOutline( int nGlyphIndex, ::basegfx::B2DPolyPolygon& ) const = 0;
    virtual bool                GetAntialiasAdvice( void ) const = 0;
    bool                        IsGlyphInvisible( int nGlyphIndex );
    virtual bool                GetGlyphBitmap1( int nGlyphIndex, RawBitmap& ) const = 0;
    virtual bool                GetGlyphBitmap8( int nGlyphIndex, RawBitmap& ) const = 0;

    void                        SetExtended( int nInfo, void* ppVoid );
    int                         GetExtInfo() { return mnExtInfo; }
    void*                       GetExtPointer() { return mpExtData; }

protected:
    friend class GlyphCache;
    friend class ServerFontLayout;
    explicit                    ServerFont( const ImplFontSelectData& );
    virtual                     ~ServerFont();

    void                        AddRef() const      { ++mnRefCount; }
    long                        GetRefCount() const { return mnRefCount; }
    long                        Release() const;
    sal_uLong                       GetByteCount() const { return mnBytesUsed; }

    virtual void                InitGlyphData( int nGlyphIndex, GlyphData& ) const = 0;
    virtual void                GarbageCollect( long );
    void                        ReleaseFromGarbageCollect();

    virtual ServerFontLayoutEngine* GetLayoutEngine() = 0;

private:
    typedef ::boost::unordered_map<int,GlyphData> GlyphList;
    mutable GlyphList           maGlyphList;

    const ImplFontSelectData    maFontSelData;

    // info for GlyphcachePeer
    int                         mnExtInfo;
    void*                       mpExtData;

    // used by GlyphCache for cache LRU algorithm
    mutable long                mnRefCount;
    mutable sal_uLong               mnBytesUsed;

    ServerFont*                 mpPrevGCFont;
    ServerFont*                 mpNextGCFont;

protected:
    // 16.16 fixed point values used for a rotated font
    long                        mnCos;
    long                        mnSin;
private:
    int                         mnZWJ;
    int                         mnZWNJ;
    bool                        mbCollectedZW;
};

// =======================================================================

// a class for cache entries for physical font instances that are based on serverfonts
class VCL_PLUGIN_PUBLIC ImplServerFontEntry : public ImplFontEntry
{
private:
    ServerFont*    mpServerFont;
    boost::shared_ptr<ImplFontOptions> mpFontOptions;
    bool           mbGotFontOptions;

public:
                   ImplServerFontEntry( ImplFontSelectData& );
    virtual        ~ImplServerFontEntry();
    void           SetServerFont( ServerFont* p) { mpServerFont = p; }
    void           HandleFontOptions();
};

// =======================================================================

class VCL_PLUGIN_PUBLIC ServerFontLayout : public GenericSalLayout
{
private:
    ServerFont&     mrServerFont;

    // enforce proper copy semantic
    SAL_DLLPRIVATE  ServerFontLayout( const ServerFontLayout& );
    SAL_DLLPRIVATE  ServerFontLayout& operator=( const ServerFontLayout& );

public:
                    ServerFontLayout( ServerFont& );
    virtual bool    LayoutText( ImplLayoutArgs& );
    virtual void    AdjustLayout( ImplLayoutArgs& );
    virtual void    DrawText( SalGraphics& ) const;
    ServerFont&     GetServerFont() const   { return mrServerFont; }
};

// =======================================================================

class ServerFontLayoutEngine
{
public:
    virtual         ~ServerFontLayoutEngine() {}
    virtual bool    operator()( ServerFontLayout&, ImplLayoutArgs& );
};

// =======================================================================

class GlyphCachePeer
{
protected:
                    GlyphCachePeer() : mnBytesUsed(0) {}
    virtual         ~GlyphCachePeer() {}

public:
    sal_Int32       GetByteCount() const { return mnBytesUsed; }
    virtual void    RemovingFont( ServerFont& ) {}
    virtual void    RemovingGlyph( ServerFont&, GlyphData&, int ) {}

protected:
    sal_Int32       mnBytesUsed;
};

// =======================================================================

class VCL_PLUGIN_PUBLIC RawBitmap
{
public:
                    RawBitmap();
                    ~RawBitmap();
    bool            Rotate( int nAngle );

public:
    unsigned char*  mpBits;
    sal_uLong           mnAllocated;

    sal_uLong           mnWidth;
    sal_uLong           mnHeight;

    sal_uLong           mnScanlineSize;
    sal_uLong           mnBitCount;

    int             mnXOffset;
    int             mnYOffset;
};

// =======================================================================

inline void ServerFont::SetExtended( int nInfo, void* pVoid )
{
    mnExtInfo = nInfo;
    mpExtData = pVoid;
}

// =======================================================================

// ExtraKernInfo allows an on-demand query of extra kerning info #i29881#
// The kerning values have to be scaled to match the font size before use
class VCL_PLUGIN_PUBLIC ExtraKernInfo
{
public:
    ExtraKernInfo( sal_IntPtr nFontId );
    virtual ~ExtraKernInfo() {}

    bool    HasKernPairs() const;
    int     GetUnscaledKernPairs( ImplKernPairData** ) const;
    int     GetUnscaledKernValue( sal_Unicode cLeft, sal_Unicode cRight ) const;

protected:
    mutable bool mbInitialized;
    virtual void Initialize() const = 0;

protected:
    sal_IntPtr     mnFontId;

    // container to map a unicode pair to an unscaled kerning value
    struct PairEqual{ int operator()(const ImplKernPairData& rA, const ImplKernPairData& rB) const
                          { return (rA.mnChar1 == rB.mnChar1) && (rA.mnChar2 == rB.mnChar2); } };
    struct PairHash{ int operator()(const ImplKernPairData& rA) const
                         { return (rA.mnChar1) * 256 ^ rA.mnChar2; } };
    typedef boost::unordered_set< ImplKernPairData, PairHash, PairEqual > UnicodeKernPairs;
    mutable UnicodeKernPairs maUnicodeKernPairs;
};

// =======================================================================

#endif // _SV_GLYPHCACHE_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>