<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief memory_slice_view expression implementation
 */

#pragma once

namespace etl {

/*!
 * \brief View that shows a slice of an expression
 * \tparam T The type of expression on which the view is made
 */
template <typename T, bool Aligned>
struct memory_slice_view {
    using sub_type          = T;                                                                    ///< The sub type
    using value_type        = value_t<sub_type>;                                                    ///< The value contained in the expression
    using memory_type       = value_type*;                                                          ///< The memory acess type
    using const_memory_type = const value_type*;                                                    ///< The const memory access type
    using return_type       = return_helper<sub_type, decltype(std::declval<sub_type>()[0])>;       ///< The type returned by the view
    using const_return_type = const_return_helper<sub_type, decltype(std::declval<sub_type>()[0])>; ///< The const type return by the view

private:
    T sub;              ///< The Sub expression
    const size_t first; ///< The index
    const size_t last;  ///< The last index

    friend struct etl_traits<memory_slice_view>;

public:

    /*!
     * \brief The vectorization type for V
     */
    template<typename V = default_vec>
    using vec_type               = typename V::template vec_type<value_type>;

    /*!
     * \brief Construct a new memory_slice_view over the given sub expression
     * \param sub The sub expression
     * \param first The first index
     * \param last The last index
     */
    memory_slice_view(sub_type sub, size_t first, size_t last)
            : sub(sub), first(first), last(last) {}

    /*!
     * \brief Returns the element at the given index
     * \param j The index
     * \return a reference to the element at the given index.
     */
    const_return_type operator[](size_t j) const {
        return sub[first + j];
    }

    /*!
     * \brief Returns the element at the given index
     * \param j The index
     * \return a reference to the element at the given index.
     */
    return_type operator[](size_t j) {
        return sub[first + j];
    }

    /*!
     * \brief Returns the value at the given index
     * This function never has side effects.
     * \param j The index
     * \return the value at the given index.
     */
    value_type read_flat(size_t j) const noexcept {
        return sub[first + j];
    }

    //Note(CPP17): Use if constexpr for alignment

    /*!
     * \brief Load several elements of the expression at once
     * \param x The position at which to start.
     * \tparam V The vectorization mode to use
     * \return a vector containing several elements of the expression
     */
    template <typename V = default_vec, bool A = Aligned, cpp_enable_if(A)>
    auto load(size_t x) const noexcept {
        return sub.template load<V>(x + first );
    }

    /*!
     * \brief Load several elements of the expression at once
     * \param x The position at which to start.
     * \tparam V The vectorization mode to use
     * \return a vector containing several elements of the expression
     */
    template <typename V = default_vec, bool A = Aligned, cpp_disable_if(A)>
    auto load(size_t x) const noexcept {
        return sub.template loadu<V>(x + first );
    }

    /*!
     * \brief Load several elements of the expression at once
     * \param x The position at which to start.
     * \tparam V The vectorization mode to use
     * \return a vector containing several elements of the expression
     */
    template <typename V = default_vec>
    auto loadu(size_t x) const noexcept {
        return sub.template loadu<V>(x + first );
    }

    /*!
     * \brief Store several elements in the matrix at once
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec, bool A = Aligned, cpp_enable_if(A)>
    void store(vec_type<V> in, size_t i) noexcept {
        sub.template store<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec, bool A = Aligned, cpp_disable_if(A)>
    void store(vec_type<V> in, size_t i) noexcept {
        sub.template storeu<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec>
    void storeu(vec_type<V> in, size_t i) noexcept {
        sub.template storeu<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once, using non-temporal store
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec>
    void stream(vec_type<V> in, size_t i) noexcept {
        sub.template storeu<V>(in, first + i);
    }

    /*!
     * \brief Test if this expression aliases with the given expression
     * \param rhs The other expression to test
     * \return true if the two expressions aliases, false otherwise
     */
    template <typename E>
    bool alias(const E& rhs) const noexcept {
        return sub.alias(rhs);
    }

    /*!
     * \brief Returns a pointer to the first element in memory.
     * \return a pointer tot the first element in memory.
     */
    memory_type memory_start() noexcept {
        return sub.memory_start() + first ;
    }

    /*!
     * \brief Returns a pointer to the first element in memory.
     * \return a pointer tot the first element in memory.
     */
    const_memory_type memory_start() const noexcept {
        return sub.memory_start() + first ;
    }

    /*!
     * \brief Returns a pointer to the past-the-end element in memory.
     * \return a pointer tot the past-the-end element in memory.
     */
    memory_type memory_end() noexcept {
        return sub.memory_start() + last ;
    }

    /*!
     * \brief Returns a pointer to the past-the-end element in memory.
     * \return a pointer tot the past-the-end element in memory.
     */
    const_memory_type memory_end() const noexcept {
        return sub.memory_start() + last;
    }

    // Assignment functions

    /*!
     * \brief Assign to the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_to(L&& lhs)  const {
        std_assign_evaluate(*this, lhs);
    }

    /*!
     * \brief Add to the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_add_to(L&& lhs)  const {
        std_add_evaluate(*this, lhs);
    }

    /*!
     * \brief Sub from the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_sub_to(L&& lhs)  const {
        std_sub_evaluate(*this, lhs);
    }

    /*!
     * \brief Multiply the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_mul_to(L&& lhs)  const {
        std_mul_evaluate(*this, lhs);
    }

    /*!
     * \brief Divide the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_div_to(L&& lhs)  const {
        std_div_evaluate(*this, lhs);
    }

    /*!
     * \brief Modulo the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_mod_to(L&& lhs)  const {
        std_mod_evaluate(*this, lhs);
    }

    // Internals

    /*!
     * \brief Apply the given visitor to this expression and its descendants.
     * \param visitor The visitor to apply
     */
    void visit(const detail::back_propagate_visitor& visitor) const {
        sub.visit(visitor);
    }

    /*!
     * \brief Apply the given visitor to this expression and its descendants.
     * \param visitor The visitor to apply
     */
    void visit(const detail::temporary_allocator_visitor& visitor) const {
        sub.visit(visitor);
    }

    /*!
     * \brief Apply the given visitor to this expression and its descendants.
     * \param visitor The visitor to apply
     */
    void visit(detail::evaluator_visitor& visitor) const {
        bool old_need_value = visitor.need_value;
        visitor.need_value = true;
        sub.visit(visitor);
        visitor.need_value = old_need_value;
    }
};

/*!
 * \brief Specialization for memory_slice_view
 */
template <typename T, bool Aligned>
struct etl_traits<etl::memory_slice_view<T, Aligned>> {
    using expr_t     = etl::memory_slice_view<T, Aligned>; ///< The expression type
    using sub_expr_t = std::decay_t<T>;    ///< The sub expression type
    using value_type = typename etl_traits<sub_expr_t>::value_type; ///< The value type

    static constexpr bool is_etl          = true;                                    ///< Indicates if the type is an ETL expression
    static constexpr bool is_transformer  = false;                                   ///< Indicates if the type is a transformer
    static constexpr bool is_view         = true;                                    ///< Indicates if the type is a view
    static constexpr bool is_magic_view   = false;                                   ///< Indicates if the type is a magic view
    static constexpr bool is_fast         = false;                                   ///< Indicates if the expression is fast
    static constexpr bool is_linear       = etl_traits<sub_expr_t>::is_linear;       ///< Indicates if the expression is linear
    static constexpr bool is_thread_safe  = etl_traits<sub_expr_t>::is_thread_safe;  ///< Indicates if the expression is thread safe
    static constexpr bool is_value        = false;                                   ///< Indicates if the expression is of value type
    static constexpr bool is_direct       = etl_traits<sub_expr_t>::is_direct;       ///< Indicates if the expression has direct memory access
    static constexpr bool is_generator    = false;                                   ///< Indicates if the expression is a generator
    static constexpr bool is_padded       = false;                                   ///< Indicates if the expression is padded
    static constexpr bool is_aligned      = Aligned;                                   ///< Indicates if the expression is padded
    static constexpr bool needs_evaluator = etl_traits<sub_expr_t>::needs_evaluator; ///< Indicates if the exxpression needs a evaluator visitor
    static constexpr order storage_order  = etl_traits<sub_expr_t>::storage_order;   ///< The expression's storage order

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    using vectorizable = cpp::bool_constant<decay_traits<sub_expr_t>::template vectorizable<V>::value>;

    /*!
     * \brief Returns the size of the given expression
     * \param v The expression to get the size for
     * \returns the size of the given expression
     */
    static size_t size(const expr_t& v) {
        return v.last - v.first;
    }

    /*!
     * \brief Returns the dth dimension of the given expression
     * \param v The expression
     * \param d The dimension to get
     * \return The dth dimension of the given expression
     */
    static size_t dim(const expr_t& v, size_t d) {
        cpp_unused(d);
        return v.last - v.first;
    }

    /*!
     * \brief Returns the number of expressions for this type
     * \return the number of dimensions of this type
     */
    static constexpr size_t dimensions() {
        return 1;
    }
};

/*!
 * \brief Returns view representing a memory slice view of the given expression.
 * \param value The ETL expression
 * \param first The first index
 * \param last The last index
 * \return a view expression representing a sub dimensional view of the given expression
 */
template <bool Aligned = false, typename E>
auto memory_slice(E&& value, size_t first, size_t last) -> detail::identity_helper<E, memory_slice_view<detail::build_identity_type<E>, Aligned>> {
    static_assert(is_etl_expr<E>::value, "etl::memory_slice can only be used on ETL expressions");
    return detail::identity_helper<E, memory_slice_view<detail::build_identity_type<E>, Aligned>>{{value, first, last}};
}

} //end of namespace etl
<commit_msg>Allow non-temporal stores in aligned memory slices<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file
 * \brief memory_slice_view expression implementation
 */

#pragma once

namespace etl {

/*!
 * \brief View that shows a slice of an expression
 * \tparam T The type of expression on which the view is made
 */
template <typename T, bool Aligned>
struct memory_slice_view {
    using sub_type          = T;                                                                    ///< The sub type
    using value_type        = value_t<sub_type>;                                                    ///< The value contained in the expression
    using memory_type       = value_type*;                                                          ///< The memory acess type
    using const_memory_type = const value_type*;                                                    ///< The const memory access type
    using return_type       = return_helper<sub_type, decltype(std::declval<sub_type>()[0])>;       ///< The type returned by the view
    using const_return_type = const_return_helper<sub_type, decltype(std::declval<sub_type>()[0])>; ///< The const type return by the view

private:
    T sub;              ///< The Sub expression
    const size_t first; ///< The index
    const size_t last;  ///< The last index

    friend struct etl_traits<memory_slice_view>;

public:

    /*!
     * \brief The vectorization type for V
     */
    template<typename V = default_vec>
    using vec_type               = typename V::template vec_type<value_type>;

    /*!
     * \brief Construct a new memory_slice_view over the given sub expression
     * \param sub The sub expression
     * \param first The first index
     * \param last The last index
     */
    memory_slice_view(sub_type sub, size_t first, size_t last)
            : sub(sub), first(first), last(last) {}

    /*!
     * \brief Returns the element at the given index
     * \param j The index
     * \return a reference to the element at the given index.
     */
    const_return_type operator[](size_t j) const {
        return sub[first + j];
    }

    /*!
     * \brief Returns the element at the given index
     * \param j The index
     * \return a reference to the element at the given index.
     */
    return_type operator[](size_t j) {
        return sub[first + j];
    }

    /*!
     * \brief Returns the value at the given index
     * This function never has side effects.
     * \param j The index
     * \return the value at the given index.
     */
    value_type read_flat(size_t j) const noexcept {
        return sub[first + j];
    }

    //Note(CPP17): Use if constexpr for alignment

    /*!
     * \brief Load several elements of the expression at once
     * \param x The position at which to start.
     * \tparam V The vectorization mode to use
     * \return a vector containing several elements of the expression
     */
    template <typename V = default_vec, bool A = Aligned, cpp_enable_if(A)>
    auto load(size_t x) const noexcept {
        return sub.template load<V>(x + first );
    }

    /*!
     * \brief Load several elements of the expression at once
     * \param x The position at which to start.
     * \tparam V The vectorization mode to use
     * \return a vector containing several elements of the expression
     */
    template <typename V = default_vec, bool A = Aligned, cpp_disable_if(A)>
    auto load(size_t x) const noexcept {
        return sub.template loadu<V>(x + first );
    }

    /*!
     * \brief Load several elements of the expression at once
     * \param x The position at which to start.
     * \tparam V The vectorization mode to use
     * \return a vector containing several elements of the expression
     */
    template <typename V = default_vec>
    auto loadu(size_t x) const noexcept {
        return sub.template loadu<V>(x + first );
    }

    /*!
     * \brief Store several elements in the matrix at once
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec, bool A = Aligned, cpp_enable_if(A)>
    void store(vec_type<V> in, size_t i) noexcept {
        sub.template store<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec, bool A = Aligned, cpp_disable_if(A)>
    void store(vec_type<V> in, size_t i) noexcept {
        sub.template storeu<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec>
    void storeu(vec_type<V> in, size_t i) noexcept {
        sub.template storeu<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once, using non-temporal store
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec, bool A = Aligned, cpp_enable_if(A)>
    void stream(vec_type<V> in, size_t i) noexcept {
        sub.template stream<V>(in, first + i);
    }

    /*!
     * \brief Store several elements in the matrix at once, using non-temporal store
     * \param in The several elements to store
     * \param i The position at which to start. This will be aligned from the beginning (multiple of the vector size).
     * \tparam V The vectorization mode to use
     */
    template <typename V = default_vec, bool A = Aligned, cpp_disable_if(A)>
    void stream(vec_type<V> in, size_t i) noexcept {
        sub.template storeu<V>(in, first + i);
    }

    /*!
     * \brief Test if this expression aliases with the given expression
     * \param rhs The other expression to test
     * \return true if the two expressions aliases, false otherwise
     */
    template <typename E>
    bool alias(const E& rhs) const noexcept {
        return sub.alias(rhs);
    }

    /*!
     * \brief Returns a pointer to the first element in memory.
     * \return a pointer tot the first element in memory.
     */
    memory_type memory_start() noexcept {
        return sub.memory_start() + first ;
    }

    /*!
     * \brief Returns a pointer to the first element in memory.
     * \return a pointer tot the first element in memory.
     */
    const_memory_type memory_start() const noexcept {
        return sub.memory_start() + first ;
    }

    /*!
     * \brief Returns a pointer to the past-the-end element in memory.
     * \return a pointer tot the past-the-end element in memory.
     */
    memory_type memory_end() noexcept {
        return sub.memory_start() + last ;
    }

    /*!
     * \brief Returns a pointer to the past-the-end element in memory.
     * \return a pointer tot the past-the-end element in memory.
     */
    const_memory_type memory_end() const noexcept {
        return sub.memory_start() + last;
    }

    // Assignment functions

    /*!
     * \brief Assign to the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_to(L&& lhs)  const {
        std_assign_evaluate(*this, lhs);
    }

    /*!
     * \brief Add to the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_add_to(L&& lhs)  const {
        std_add_evaluate(*this, lhs);
    }

    /*!
     * \brief Sub from the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_sub_to(L&& lhs)  const {
        std_sub_evaluate(*this, lhs);
    }

    /*!
     * \brief Multiply the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_mul_to(L&& lhs)  const {
        std_mul_evaluate(*this, lhs);
    }

    /*!
     * \brief Divide the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_div_to(L&& lhs)  const {
        std_div_evaluate(*this, lhs);
    }

    /*!
     * \brief Modulo the given left-hand-side expression
     * \param lhs The expression to which assign
     */
    template<typename L>
    void assign_mod_to(L&& lhs)  const {
        std_mod_evaluate(*this, lhs);
    }

    // Internals

    /*!
     * \brief Apply the given visitor to this expression and its descendants.
     * \param visitor The visitor to apply
     */
    void visit(const detail::back_propagate_visitor& visitor) const {
        sub.visit(visitor);
    }

    /*!
     * \brief Apply the given visitor to this expression and its descendants.
     * \param visitor The visitor to apply
     */
    void visit(const detail::temporary_allocator_visitor& visitor) const {
        sub.visit(visitor);
    }

    /*!
     * \brief Apply the given visitor to this expression and its descendants.
     * \param visitor The visitor to apply
     */
    void visit(detail::evaluator_visitor& visitor) const {
        bool old_need_value = visitor.need_value;
        visitor.need_value = true;
        sub.visit(visitor);
        visitor.need_value = old_need_value;
    }
};

/*!
 * \brief Specialization for memory_slice_view
 */
template <typename T, bool Aligned>
struct etl_traits<etl::memory_slice_view<T, Aligned>> {
    using expr_t     = etl::memory_slice_view<T, Aligned>; ///< The expression type
    using sub_expr_t = std::decay_t<T>;    ///< The sub expression type
    using value_type = typename etl_traits<sub_expr_t>::value_type; ///< The value type

    static constexpr bool is_etl          = true;                                    ///< Indicates if the type is an ETL expression
    static constexpr bool is_transformer  = false;                                   ///< Indicates if the type is a transformer
    static constexpr bool is_view         = true;                                    ///< Indicates if the type is a view
    static constexpr bool is_magic_view   = false;                                   ///< Indicates if the type is a magic view
    static constexpr bool is_fast         = false;                                   ///< Indicates if the expression is fast
    static constexpr bool is_linear       = etl_traits<sub_expr_t>::is_linear;       ///< Indicates if the expression is linear
    static constexpr bool is_thread_safe  = etl_traits<sub_expr_t>::is_thread_safe;  ///< Indicates if the expression is thread safe
    static constexpr bool is_value        = false;                                   ///< Indicates if the expression is of value type
    static constexpr bool is_direct       = etl_traits<sub_expr_t>::is_direct;       ///< Indicates if the expression has direct memory access
    static constexpr bool is_generator    = false;                                   ///< Indicates if the expression is a generator
    static constexpr bool is_padded       = false;                                   ///< Indicates if the expression is padded
    static constexpr bool is_aligned      = Aligned;                                   ///< Indicates if the expression is padded
    static constexpr bool needs_evaluator = etl_traits<sub_expr_t>::needs_evaluator; ///< Indicates if the exxpression needs a evaluator visitor
    static constexpr order storage_order  = etl_traits<sub_expr_t>::storage_order;   ///< The expression's storage order

    /*!
     * \brief Indicates if the expression is vectorizable using the
     * given vector mode
     * \tparam V The vector mode
     */
    template <vector_mode_t V>
    using vectorizable = cpp::bool_constant<decay_traits<sub_expr_t>::template vectorizable<V>::value>;

    /*!
     * \brief Returns the size of the given expression
     * \param v The expression to get the size for
     * \returns the size of the given expression
     */
    static size_t size(const expr_t& v) {
        return v.last - v.first;
    }

    /*!
     * \brief Returns the dth dimension of the given expression
     * \param v The expression
     * \param d The dimension to get
     * \return The dth dimension of the given expression
     */
    static size_t dim(const expr_t& v, size_t d) {
        cpp_unused(d);
        return v.last - v.first;
    }

    /*!
     * \brief Returns the number of expressions for this type
     * \return the number of dimensions of this type
     */
    static constexpr size_t dimensions() {
        return 1;
    }
};

/*!
 * \brief Returns view representing a memory slice view of the given expression.
 * \param value The ETL expression
 * \param first The first index
 * \param last The last index
 * \return a view expression representing a sub dimensional view of the given expression
 */
template <bool Aligned = false, typename E>
auto memory_slice(E&& value, size_t first, size_t last) -> detail::identity_helper<E, memory_slice_view<detail::build_identity_type<E>, Aligned>> {
    static_assert(is_etl_expr<E>::value, "etl::memory_slice can only be used on ETL expressions");
    return detail::identity_helper<E, memory_slice_view<detail::build_identity_type<E>, Aligned>>{{value, first, last}};
}

} //end of namespace etl
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
#include <stdarg.h>
#include "user_log.c++.h"
#include <time.h>
#include "condor_uid.h"

static char *_FileName_ = __FILE__;

static const char SynchDelimiter[] = "...\n";

static void display_ids();
extern "C" char *find_env (const char *, const char *);
extern "C" char *get_env_val (const char *);

UserLog::UserLog (const char *owner, const char *file, int c, int p, int s)
{
	UserLog();
	initialize (owner, file, c, p, s);
}

/* --- The following two functions are taken from the shadow's ulog.c --- */
/*
  Find the value of an environment value, given the condor style envrionment
  string which may contain several variable definitions separated by
  semi-colons.
*/
char *
find_env( const char * name, const char * env )
{
    const char  *ptr;

    for( ptr=env; *ptr; ptr++ ) {
        if( strncmp(name,ptr,strlen(name)) == 0 ) {
            return get_env_val( ptr );
        }
    }
    return NULL;
}

/*
  Given a pointer to the a particular environment substring string
  containing the desired value, pick out the value and return a
  pointer to it.  N.B. this is copied into a static data area to
  avoid introducing NULL's into the original environment string,
  and a pointer into the static area is returned.
*/
char *
get_env_val( const char *str )
{
    const char  *src;
    char *dst;
    static char answer[512];

        /* Find the '=' */
    for( src=str; *src && *src != '='; src++ )
        ;
    if( *src != '=' ) {
        return NULL;
    }

        /* Skip over any white space */
    src += 1;
    while( *src && isspace(*src) ) {
        src++;
    }

        /* Now we are at beginning of result */
    dst = answer;
    while( *src && !isspace(*src) && *src != ';' ) {
        *dst++ = *src++;
    }
    *dst = '\0';

    return answer;
}

void UserLog::
initialize( const char *file, int c, int p, int s )
{
	int 			fd;

		// Save parameter info
	path = new char[ strlen(file) + 1 ];
	strcpy( path, file );
	in_block = FALSE;

	if (fp) fclose(fp);

#ifndef WIN32
	if( (fd = open( path, O_CREAT | O_WRONLY, 0664 )) < 0 ) {
		dprintf( D_ALWAYS,
			"UserLog::initialize: open(%s) failed - errno %d", path, errno );
		return;
	}

		// attach it to stdio stream
	if( (fp = fdopen(fd,"a")) == NULL ) {
		dprintf( D_ALWAYS,
			"UserLog::initialize: fdopen() failed - errno %d", path, errno );
	}
#else
	if( (fp = fopen(path,"a+t")) == NULL ) {
		dprintf( D_ALWAYS,
			"UserLog::initialize: fopen failed - errno %d", path, errno );
	}

	fd = _fileno(fp);
#endif

		// set the stdio stream for line buffering
	if( setvbuf(fp,NULL,_IOLBF,BUFSIZ) < 0 ) {
		dprintf( D_ALWAYS, "setvbuf failed in UserLog::initialize" );
	}

	// prepare to lock the file
	lock = new FileLock( fd );

	initialize(c, p, s);
}

void UserLog::
initialize( const char *owner, const char *file, int c, int p, int s )
{
	priv_state		priv;

	init_user_ids(owner);

		// switch to user priv, saving the current user
	priv = set_user_priv();

		// initialize log file
	initialize(file,c,p,s);

		// get back to whatever UID and GID we started with
	set_priv(priv);
}

void UserLog::
initialize( int c, int p, int s )
{
	cluster = c;
	proc = p;
	subproc = s;
}

UserLog::~UserLog()
{
	delete [] path;
	delete lock;
	if (fp != 0) fclose( fp );
}

void
UserLog::display()
{
	dprintf( D_ALWAYS, "Path = \"%s\"\n", path );
	dprintf( D_ALWAYS, "Job = %d.%d.%d\n", proc, cluster, subproc );
	dprintf( D_ALWAYS, "fp = 0x%x\n", fp );
	lock->display();
	dprintf( D_ALWAYS, "in_block = %s\n", in_block ? "TRUE" : "FALSE" );
}

int UserLog::
writeEvent (ULogEvent *event)
{
	// the the log is not initialized, don't bother --- just return OK
	if (!fp) return 1;
	if (!lock) return 0;
	if (!event) return 0;

	int retval;
	priv_state priv = set_user_priv();

	// fill in event context
	event->cluster = cluster;
	event->proc = proc;
	event->subproc = subproc;

	lock->obtain (WRITE_LOCK);
	fseek (fp, 0, SEEK_END);
	retval = event->putEvent (fp);
	if (!retval) fputc ('\n', fp);
	if (fprintf (fp, SynchDelimiter) < 0) retval = 0;
	lock->release ();
	set_priv( priv );
	return retval;
}

void
UserLog::put( const char *fmt, ... )
{
	va_list		ap;
	va_start( ap, fmt );

	if( !fp ) {
		return;
	}

	if( !in_block ) {
		lock->obtain( WRITE_LOCK );
		fseek( fp, 0, SEEK_END );
	}

	output_header();
	vfprintf( fp, fmt, ap );

	if( !in_block ) {
		lock->release();
	}
}

void
UserLog::begin_block()
{
	struct tm	*tm;
	time_t		clock;

	if( !fp ) {
		return;
	}

	lock->obtain( WRITE_LOCK );
	fseek( fp, 0, SEEK_END );

	(void)time(  (time_t *)&clock );
	tm = localtime( (time_t *)&clock );
	fprintf( fp, "(%d.%d.%d) %d/%d %02d:%02d:%02d\n",
		cluster, proc, subproc,
		tm->tm_mon + 1, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec
	);
	in_block = TRUE;
}

void
UserLog::end_block()
{
	if( !fp ) {
		return;
	}

	in_block = FALSE;
	lock->release();
}

void
UserLog::output_header()
{
	struct tm	*tm;
	time_t		clock;

	if( !fp ) {
		return;
	}

	if( in_block ) {
		fprintf( fp, "(%d.%d.%d) ", cluster, proc, subproc );
	} else {
		(void)time(  (time_t *)&clock );
		tm = localtime( (time_t *)&clock );
		fprintf( fp, "(%d.%d.%d) %d/%d %02d:%02d:%02d ",
			cluster, proc, subproc,
			tm->tm_mon + 1, tm->tm_mday,
			tm->tm_hour, tm->tm_min, tm->tm_sec
		);
	}
}

extern "C" LP *
InitUserLog( const char *own, const char *file, int c, int p, int s )
{
	UserLog	*answer;

	answer = new UserLog( own, file, c, p, s );
	return (LP *)answer;
}

extern "C" void
CloseUserLog( LP *lp )
{
	delete lp;
}

extern "C" void
PutUserLog( LP *lp, const char *fmt, ... )
{
	va_list		ap;
	char	buf[1024];

	if( !lp ) {
		return;
	}
	va_start( ap, fmt );
	vsprintf( buf, fmt, ap );

	((UserLog *)lp) -> put( buf );
}

extern "C" void
BeginUserLogBlock( LP *lp )
{
	if( !lp ) {
		return;
	}
	((UserLog *)lp) -> begin_block();
}

extern "C" void
EndUserLogBlock( LP *lp )
{
	if( !lp ) {
		return;
	}
	((UserLog *)lp) -> end_block();
}

// ReadUserLog class

ReadUserLog::
ReadUserLog (const char * filename)
{
    if (!initialize(filename))
		dprintf(D_ALWAYS, "Failed to open %s", filename);
}

bool ReadUserLog::
initialize (const char *filename)
{
	if ((_fd = open (filename, O_RDONLY, 0)) == -1) return false;
	if ((_fp = fdopen (_fd, "r")) == NULL) return false;
	return true;
}

ULogEventOutcome ReadUserLog::
readEvent (ULogEvent *& event)
{
	long   filepos;
	int    eventnumber;
	int    retval1, retval2;

	// store file position so that if we are unable to read the event, we can
	// rewind to this location
	if (!_fp || ((filepos = ftell(_fp)) == -1L))
		return ULOG_UNK_ERROR;

	retval1 = fscanf (_fp, "%d", &eventnumber);

	// so we don't dump core if the above fscanf failed
	if (retval1 != 1) eventnumber = 1;

	// allocate event object; check if allocated successfully
	event = instantiateEvent ((ULogEventNumber) eventnumber);
	if (!event)
	{
		return ULOG_UNK_ERROR;
	}

	// read event from file; check for result
	retval2 = event->getEvent (_fp);

	// check if error in reading event
	if (!retval1 || !retval2)
	{
		// try to synchronize the log
		if (synchronize())
		{
			// if synchronization was successful, reset file position and ...
			if (fseek (_fp, filepos, SEEK_SET))
			{
				dprintf(D_ALWAYS, "fseek() failed in ReadUserLog::readEvent");
				return ULOG_UNK_ERROR;
			}

			// ... attempt to read the event again
			clearerr (_fp);
			retval1 = fscanf (_fp, "%d", &eventnumber);
			retval2 = event->getEvent (_fp);

			// if failed again, we have a parse error
			if (!retval1 || !retval2)
			{
				delete event;
				event = NULL;  // To prevent FMR: Free memory read
				synchronize ();
				return ULOG_RD_ERROR;
			}
			else
			{
				return ULOG_OK;
			}
		}
		else
		{
			// if we could not synchronize the log, we don't have the full
			// event in the stream yet; restore file position and return
			if (fseek (_fp, filepos, SEEK_SET))
			{
				dprintf(D_ALWAYS, "fseek() failed in ReadUserLog::readEvent");
				return ULOG_UNK_ERROR;
			}
			clearerr (_fp);
			delete event;
			event = NULL;  // To prevent FMR: Free memory read
			return ULOG_NO_EVENT;
		}
	}
	else
	{
		// got the event successfully -- synchronize the log
		if (synchronize ())
		{
			return ULOG_OK;
		}
		else
		{
			// got the event, but could not synchronize!!  treat as incomplete
			// event
			delete event;
			event = NULL;  // To prevent FMR: Free memory read
			clearerr (_fp);
			return ULOG_NO_EVENT;
		}
	}

	// will not reach here
	return ULOG_UNK_ERROR;
}

bool ReadUserLog::
synchronize ()
{
	char buffer[32];
	while (1) {
		if (fgets (buffer, 32, _fp) == NULL)      return false;
		if (strcmp (buffer, SynchDelimiter) == 0) return true;
	}
    return false;
}
<commit_msg>+ fixed bug: now we actually flush the user log after writing each event via fflush().<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
#include <stdarg.h>
#include "user_log.c++.h"
#include <time.h>
#include "condor_uid.h"

static char *_FileName_ = __FILE__;

static const char SynchDelimiter[] = "...\n";

static void display_ids();
extern "C" char *find_env (const char *, const char *);
extern "C" char *get_env_val (const char *);

UserLog::UserLog (const char *owner, const char *file, int c, int p, int s)
{
	UserLog();
	initialize (owner, file, c, p, s);
}

/* --- The following two functions are taken from the shadow's ulog.c --- */
/*
  Find the value of an environment value, given the condor style envrionment
  string which may contain several variable definitions separated by
  semi-colons.
*/
char *
find_env( const char * name, const char * env )
{
    const char  *ptr;

    for( ptr=env; *ptr; ptr++ ) {
        if( strncmp(name,ptr,strlen(name)) == 0 ) {
            return get_env_val( ptr );
        }
    }
    return NULL;
}

/*
  Given a pointer to the a particular environment substring string
  containing the desired value, pick out the value and return a
  pointer to it.  N.B. this is copied into a static data area to
  avoid introducing NULL's into the original environment string,
  and a pointer into the static area is returned.
*/
char *
get_env_val( const char *str )
{
    const char  *src;
    char *dst;
    static char answer[512];

        /* Find the '=' */
    for( src=str; *src && *src != '='; src++ )
        ;
    if( *src != '=' ) {
        return NULL;
    }

        /* Skip over any white space */
    src += 1;
    while( *src && isspace(*src) ) {
        src++;
    }

        /* Now we are at beginning of result */
    dst = answer;
    while( *src && !isspace(*src) && *src != ';' ) {
        *dst++ = *src++;
    }
    *dst = '\0';

    return answer;
}

void UserLog::
initialize( const char *file, int c, int p, int s )
{
	int 			fd;

		// Save parameter info
	path = new char[ strlen(file) + 1 ];
	strcpy( path, file );
	in_block = FALSE;

	if (fp) fclose(fp);

#ifndef WIN32
	// Unix
	if( (fd = open( path, O_CREAT | O_WRONLY, 0664 )) < 0 ) {
		dprintf( D_ALWAYS,
			"UserLog::initialize: open(%s) failed - errno %d", path, errno );
		return;
	}

		// attach it to stdio stream
	if( (fp = fdopen(fd,"a")) == NULL ) {
		dprintf( D_ALWAYS,
			"UserLog::initialize: fdopen() failed - errno %d", path, errno );
	}
#else
	// Windows (Visual C++)
	if( (fp = fopen(path,"a+tc")) == NULL ) {
		dprintf( D_ALWAYS,
			"UserLog::initialize: fopen failed - errno %d", path, errno );
	}

	fd = _fileno(fp);
#endif

		// set the stdio stream for line buffering
	if( setvbuf(fp,NULL,_IOLBF,BUFSIZ) < 0 ) {
		dprintf( D_ALWAYS, "setvbuf failed in UserLog::initialize" );
	}

	// prepare to lock the file
	lock = new FileLock( fd );

	initialize(c, p, s);
}

void UserLog::
initialize( const char *owner, const char *file, int c, int p, int s )
{
	priv_state		priv;

	init_user_ids(owner);

		// switch to user priv, saving the current user
	priv = set_user_priv();

		// initialize log file
	initialize(file,c,p,s);

		// get back to whatever UID and GID we started with
	set_priv(priv);
}

void UserLog::
initialize( int c, int p, int s )
{
	cluster = c;
	proc = p;
	subproc = s;
}

UserLog::~UserLog()
{
	delete [] path;
	delete lock;
	if (fp != 0) fclose( fp );
}

void
UserLog::display()
{
	dprintf( D_ALWAYS, "Path = \"%s\"\n", path );
	dprintf( D_ALWAYS, "Job = %d.%d.%d\n", proc, cluster, subproc );
	dprintf( D_ALWAYS, "fp = 0x%x\n", fp );
	lock->display();
	dprintf( D_ALWAYS, "in_block = %s\n", in_block ? "TRUE" : "FALSE" );
}

int UserLog::
writeEvent (ULogEvent *event)
{
	// the the log is not initialized, don't bother --- just return OK
	if (!fp) return 1;
	if (!lock) return 0;
	if (!event) return 0;

	int retval;
	priv_state priv = set_user_priv();

	// fill in event context
	event->cluster = cluster;
	event->proc = proc;
	event->subproc = subproc;

	lock->obtain (WRITE_LOCK);
	fseek (fp, 0, SEEK_END);
	retval = event->putEvent (fp);
	if (!retval) fputc ('\n', fp);
	if (fprintf (fp, SynchDelimiter) < 0) retval = 0;
	fflush(fp);
	lock->release ();
	set_priv( priv );
	return retval;
}

void
UserLog::put( const char *fmt, ... )
{
	va_list		ap;
	va_start( ap, fmt );

	if( !fp ) {
		return;
	}

	if( !in_block ) {
		lock->obtain( WRITE_LOCK );
		fseek( fp, 0, SEEK_END );
	}

	output_header();
	vfprintf( fp, fmt, ap );

	if( !in_block ) {
		lock->release();
	}
}

void
UserLog::begin_block()
{
	struct tm	*tm;
	time_t		clock;

	if( !fp ) {
		return;
	}

	lock->obtain( WRITE_LOCK );
	fseek( fp, 0, SEEK_END );

	(void)time(  (time_t *)&clock );
	tm = localtime( (time_t *)&clock );
	fprintf( fp, "(%d.%d.%d) %d/%d %02d:%02d:%02d\n",
		cluster, proc, subproc,
		tm->tm_mon + 1, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec
	);
	in_block = TRUE;
}

void
UserLog::end_block()
{
	if( !fp ) {
		return;
	}

	in_block = FALSE;
	lock->release();
}

void
UserLog::output_header()
{
	struct tm	*tm;
	time_t		clock;

	if( !fp ) {
		return;
	}

	if( in_block ) {
		fprintf( fp, "(%d.%d.%d) ", cluster, proc, subproc );
	} else {
		(void)time(  (time_t *)&clock );
		tm = localtime( (time_t *)&clock );
		fprintf( fp, "(%d.%d.%d) %d/%d %02d:%02d:%02d ",
			cluster, proc, subproc,
			tm->tm_mon + 1, tm->tm_mday,
			tm->tm_hour, tm->tm_min, tm->tm_sec
		);
	}
}

extern "C" LP *
InitUserLog( const char *own, const char *file, int c, int p, int s )
{
	UserLog	*answer;

	answer = new UserLog( own, file, c, p, s );
	return (LP *)answer;
}

extern "C" void
CloseUserLog( LP *lp )
{
	delete lp;
}

extern "C" void
PutUserLog( LP *lp, const char *fmt, ... )
{
	va_list		ap;
	char	buf[1024];

	if( !lp ) {
		return;
	}
	va_start( ap, fmt );
	vsprintf( buf, fmt, ap );

	((UserLog *)lp) -> put( buf );
}

extern "C" void
BeginUserLogBlock( LP *lp )
{
	if( !lp ) {
		return;
	}
	((UserLog *)lp) -> begin_block();
}

extern "C" void
EndUserLogBlock( LP *lp )
{
	if( !lp ) {
		return;
	}
	((UserLog *)lp) -> end_block();
}

// ReadUserLog class

ReadUserLog::
ReadUserLog (const char * filename)
{
    if (!initialize(filename))
		dprintf(D_ALWAYS, "Failed to open %s", filename);
}

bool ReadUserLog::
initialize (const char *filename)
{
	if ((_fd = open (filename, O_RDONLY, 0)) == -1) return false;
	if ((_fp = fdopen (_fd, "r")) == NULL) return false;
	return true;
}

ULogEventOutcome ReadUserLog::
readEvent (ULogEvent *& event)
{
	long   filepos;
	int    eventnumber;
	int    retval1, retval2;

	// store file position so that if we are unable to read the event, we can
	// rewind to this location
	if (!_fp || ((filepos = ftell(_fp)) == -1L))
		return ULOG_UNK_ERROR;

	retval1 = fscanf (_fp, "%d", &eventnumber);

	// so we don't dump core if the above fscanf failed
	if (retval1 != 1) eventnumber = 1;

	// allocate event object; check if allocated successfully
	event = instantiateEvent ((ULogEventNumber) eventnumber);
	if (!event)
	{
		return ULOG_UNK_ERROR;
	}

	// read event from file; check for result
	retval2 = event->getEvent (_fp);

	// check if error in reading event
	if (!retval1 || !retval2)
	{
		// try to synchronize the log
		if (synchronize())
		{
			// if synchronization was successful, reset file position and ...
			if (fseek (_fp, filepos, SEEK_SET))
			{
				dprintf(D_ALWAYS, "fseek() failed in ReadUserLog::readEvent");
				return ULOG_UNK_ERROR;
			}

			// ... attempt to read the event again
			clearerr (_fp);
			retval1 = fscanf (_fp, "%d", &eventnumber);
			retval2 = event->getEvent (_fp);

			// if failed again, we have a parse error
			if (!retval1 || !retval2)
			{
				delete event;
				event = NULL;  // To prevent FMR: Free memory read
				synchronize ();
				return ULOG_RD_ERROR;
			}
			else
			{
				return ULOG_OK;
			}
		}
		else
		{
			// if we could not synchronize the log, we don't have the full
			// event in the stream yet; restore file position and return
			if (fseek (_fp, filepos, SEEK_SET))
			{
				dprintf(D_ALWAYS, "fseek() failed in ReadUserLog::readEvent");
				return ULOG_UNK_ERROR;
			}
			clearerr (_fp);
			delete event;
			event = NULL;  // To prevent FMR: Free memory read
			return ULOG_NO_EVENT;
		}
	}
	else
	{
		// got the event successfully -- synchronize the log
		if (synchronize ())
		{
			return ULOG_OK;
		}
		else
		{
			// got the event, but could not synchronize!!  treat as incomplete
			// event
			delete event;
			event = NULL;  // To prevent FMR: Free memory read
			clearerr (_fp);
			return ULOG_NO_EVENT;
		}
	}

	// will not reach here
	return ULOG_UNK_ERROR;
}

bool ReadUserLog::
synchronize ()
{
	char buffer[32];
	while (1) {
		if (fgets (buffer, 32, _fp) == NULL)      return false;
		if (strcmp (buffer, SynchDelimiter) == 0) return true;
	}
    return false;
}
<|endoftext|>


<commit_before>#ifndef MOS_RENDER_TARGET_HPP
#define MOS_RENDER_TARGET_HPP

#include <memory>
#include <atomic>
#include <optional.hpp>
#include <glm/glm.hpp>
#include <mos/render/texture_2d.hpp>
#include <mos/render/texture_cube.hpp>

namespace mos {
  class RenderTarget;
  using OptTarget = std::experimental::optional<RenderTarget>;
/**
 * @brief The RenderTarget class
 *
 * Represents a rendertarget, with asociated texture. For off screen rendering.
 */
class RenderTarget {
public:

  /**
   * @brief Target
   * @param resolution
   */
  explicit RenderTarget(const SharedTexture2D & texture,
                        const SharedTexture2D & depth_texture,
                        const SharedTextureCube texture_cube);

  /**
   * @brief The texture that is rendered to.
   */
  const SharedTexture2D texture;

  /**
   * @brief The depth texture that is rendered to.
   */
  const SharedTexture2D depth_texture;

  /**
   * @brief Cube texture that can be rendered to.
   */
  const SharedTextureCube texture_cube;

  int width() const;
  int height() const;

  /**
   * @brief unique id
   * @return id
   */
  unsigned int id() const;

private:
  unsigned int id_;
  static std::atomic_uint current_id_;
};
}
#endif // MOS_RENDER_TARGET_HPP
<commit_msg>Working.<commit_after>#ifndef MOS_RENDER_TARGET_HPP
#define MOS_RENDER_TARGET_HPP

#include <memory>
#include <atomic>
#include <optional.hpp>
#include <glm/glm.hpp>
#include <mos/render/texture_2d.hpp>
#include <mos/render/texture_cube.hpp>

namespace mos {
  class RenderTarget;
  using OptTarget = std::experimental::optional<RenderTarget>;
/**
 * @brief The RenderTarget class
 *
 * Represents a rendertarget, with asociated texture. For off screen rendering.
 */
class RenderTarget {
public:

  /**
   * @brief Target
   * @param resolution
   */
  explicit RenderTarget(const SharedTexture2D & texture = nullptr,
                        const SharedTexture2D & depth_texture = nullptr,
                        const SharedTextureCube texture_cube = nullptr);

  /**
   * @brief The texture that is rendered to.
   */
  const SharedTexture2D texture;

  /**
   * @brief The depth texture that is rendered to.
   */
  const SharedTexture2D depth_texture;

  /**
   * @brief Cube texture that can be rendered to.
   */
  const SharedTextureCube texture_cube;

  int width() const;
  int height() const;

  /**
   * @brief unique id
   * @return id
   */
  unsigned int id() const;

private:
  unsigned int id_;
  static std::atomic_uint current_id_;
};
}
#endif // MOS_RENDER_TARGET_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dpsdbtab.hxx,v $
 * $Revision: 1.4 $
 *
 * 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 SC_DPSDBTAB_HXX
#define SC_DPSDBTAB_HXX

#include <com/sun/star/uno/Reference.hxx>

namespace com { namespace sun { namespace star {
    namespace lang {
        class XMultiServiceFactory;
    }
}}}
#include "dptabdat.hxx"

// --------------------------------------------------------------------
//
//  implementation of ScDPTableData with database data
//

struct ScImportSourceDesc
{
    String  aDBName;
    String  aObject;
    USHORT  nType;          // enum DataImportMode
    BOOL    bNative;

    BOOL operator== ( const ScImportSourceDesc& rOther ) const
        { return aDBName == rOther.aDBName &&
                 aObject == rOther.aObject &&
                 nType   == rOther.nType &&
                 bNative == rOther.bNative; }
};

class ScDatabaseDPData_Impl;

class ScDatabaseDPData : public ScDPTableData
{
private:
    ScDatabaseDPData_Impl* pImpl;

    BOOL            OpenDatabase();
    void            InitAllColumnEntries();

public:
                    ScDatabaseDPData(
                        ::com::sun::star::uno::Reference<
                            ::com::sun::star::lang::XMultiServiceFactory > xSMgr,
                        const ScImportSourceDesc& rImport );
    virtual         ~ScDatabaseDPData();

    virtual long                    GetColumnCount();
    virtual const TypedStrCollection&   GetColumnEntries(long nColumn);
    virtual String                  getDimensionName(long nColumn);
    virtual BOOL                    getIsDataLayoutDimension(long nColumn);
    virtual BOOL                    IsDateDimension(long nDim);
    virtual void                    DisposeData();
    virtual void                    SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty );

    virtual void                    ResetIterator();
    virtual BOOL                    GetNextRow( const ScDPTableIteratorParam& rParam );
};

#endif

<commit_msg>INTEGRATION: CWS koheidatapilot01 (1.3.570); FILE MERGED 2008/04/25 20:59:10 kohei 1.3.570.5: RESYNC: (1.3-1.4); FILE MERGED 2008/04/24 23:26:38 kohei 1.3.570.4: * fixed a regression on page field filtering by the empty string value. * fixed an incorrect drill-down table with number groups (i88531). * moved the shared string storage out of ScDPCacheTable to make it more generic. 2008/04/17 13:10:39 kohei 1.3.570.3: Used ScDPItemData to store cell values to allow numerical comparison where appropriate.  Also fixed the regression involving drill-down on group names. 2007/12/06 07:06:15 kohei 1.3.570.2: removed all previously invisible code. 2007/10/29 17:44:39 kohei 1.3.570.1: initial checkin<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dpsdbtab.hxx,v $
 * $Revision: 1.5 $
 *
 * 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 SC_DPSDBTAB_HXX
#define SC_DPSDBTAB_HXX

#include <com/sun/star/uno/Reference.hxx>

namespace com { namespace sun { namespace star {
    namespace lang {
        class XMultiServiceFactory;
    }
}}}
#include "dptabdat.hxx"

#include <vector>
#include <set>

class ScDPCacheTable;

// --------------------------------------------------------------------
//
//  implementation of ScDPTableData with database data
//

struct ScImportSourceDesc
{
    String  aDBName;
    String  aObject;
    USHORT  nType;          // enum DataImportMode
    BOOL    bNative;

    BOOL operator== ( const ScImportSourceDesc& rOther ) const
        { return aDBName == rOther.aDBName &&
                 aObject == rOther.aObject &&
                 nType   == rOther.nType &&
                 bNative == rOther.bNative; }
};

class ScDatabaseDPData_Impl;

class ScDatabaseDPData : public ScDPTableData
{
private:
    ScDatabaseDPData_Impl* pImpl;

    BOOL            OpenDatabase();

public:
                    ScDatabaseDPData(
                        ::com::sun::star::uno::Reference<
                            ::com::sun::star::lang::XMultiServiceFactory > xSMgr,
                        const ScImportSourceDesc& rImport );
    virtual         ~ScDatabaseDPData();

    virtual long                    GetColumnCount();
    virtual const TypedStrCollection&   GetColumnEntries(long nColumn);
    virtual String                  getDimensionName(long nColumn);
    virtual BOOL                    getIsDataLayoutDimension(long nColumn);
    virtual BOOL                    IsDateDimension(long nDim);
    virtual void                    DisposeData();
    virtual void                    SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty );

    virtual void                    CreateCacheTable();
    virtual void                    FilterCacheTable(const ::std::vector<ScDPDimension*>& rPageDims);
    virtual void                    GetDrillDownData(const ::std::vector<ScDPCacheTable::Criterion>& rCriteria,
                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow);
    virtual const ScDPCacheTable&   GetCacheTable() const;
};

#endif

<|endoftext|>


<commit_before>#pragma once

namespace rc {

template<typename T>
class Arbitrary : public gen::Generator<T>
{
public:
    static_assert(std::is_integral<T>::value,
                  "No specialization of Arbitrary for type");

    T generate() const override
    {
        using namespace detail;

        int size = std::min(gen::currentSize(), gen::kNominalSize);
        RandomEngine::Atom r;
        // TODO this switching shouldn't be done here. pickAtom?
        ImplicitParam<param::CurrentNode> currentNode;
        if (*currentNode != nullptr) {
            r = currentNode->atom();
        } else {
            ImplicitParam<param::RandomEngine> randomEngine;
            r = randomEngine->nextAtom();
        }

        // We vary the size by using different number of bits. This way, we can be
        // that the max value can also be generated.
        int nBits = (size * std::numeric_limits<T>::digits) / gen::kNominalSize;
        if (nBits == 0)
            return 0;
        constexpr RandomEngine::Atom randIntMax =
            std::numeric_limits<RandomEngine::Atom>::max();
        RandomEngine::Atom mask = ~((randIntMax - 1) << (nBits - 1));

        T x = static_cast<T>(r & mask);
        if (std::numeric_limits<T>::is_signed)
        {
            // Use the topmost bit as the signed bit. Even in the case of a signed
            // 64-bit integer, it won't be used since it actually IS the sign bit.
            constexpr int basicBits =
                std::numeric_limits<RandomEngine::Atom>::digits;
            x *= ((r >> (basicBits - 1)) == 0) ? 1 : -1;
        }

        return x;
    }

    shrink::IteratorUP<T> shrink(T value) const override
    {
        std::vector<T> constants;
        if (value < 0)
            constants.push_back(-value);

        return shrink::sequentially(
            shrink::constant(constants),
            shrink::towards(value, static_cast<T>(0)));
    }
};

// Base for float and double arbitrary instances
template<typename T>
class ArbitraryReal : public gen::Generator<T>
{
public:
    T generate() const override
    {
        int64_t i = *gen::arbitrary<int64_t>();
        T x = static_cast<T>(i) / std::numeric_limits<int64_t>::max();
        return std::pow<T>(1.2, gen::currentSize()) * x;
    }

    shrink::IteratorUP<T> shrink(T value) const override
    {
        std::vector<T> constants;

        if (value < 0)
            constants.push_back(-value);

        T truncated = std::trunc(value);
        if (std::abs(truncated) < std::abs(value))
            constants.push_back(truncated);

        return shrink::constant(constants);
    }
};

template<>
class Arbitrary<float> : public ArbitraryReal<float> {};

template<>
class Arbitrary<double> : public ArbitraryReal<double> {};

template<>
class Arbitrary<bool> : public gen::Generator<bool>
{
public:
    bool generate() const override
    {
        return (*gen::resize(gen::kNominalSize,
                                 gen::arbitrary<uint8_t>()) & 0x1) == 0;
    }

    shrink::IteratorUP<bool> shrink(bool value)
    {
        if (value)
            return shrink::constant<bool>({false});
        else
            return shrink::nothing<bool>();
    }
};

template<typename ...Types>
class Arbitrary<std::tuple<Types...>>
    : public gen::TupleOf<Arbitrary<Types>...>
{
public:
    Arbitrary() : gen::TupleOf<Arbitrary<Types>...>(
            gen::arbitrary<Types>()...) {}
};

template<typename T1, typename T2>
class Arbitrary<std::pair<T1, T2>>
    : public gen::PairOf<Arbitrary<detail::DecayT<T1>>,
                         Arbitrary<detail::DecayT<T2>>>
{
public:
    Arbitrary()
        : gen::PairOf<Arbitrary<detail::DecayT<T1>>,
                      Arbitrary<detail::DecayT<T2>>>(
            gen::arbitrary<detail::DecayT<T1>>(),
            gen::arbitrary<detail::DecayT<T2>>()) {}
};

// Base template class for collection types
template<typename Coll, typename ValueType>
class ArbitraryCollection : public gen::Collection<Coll, Arbitrary<ValueType>>
{
public:
    typedef gen::Collection<Coll, Arbitrary<ValueType>> CollectionGen;
    ArbitraryCollection() : CollectionGen(gen::arbitrary<ValueType>()) {}
};

// std::vector
template<typename T, typename Allocator>
class Arbitrary<std::vector<T, Allocator>>
    : public ArbitraryCollection<std::vector<T, Allocator>, T> {};

// std::deque
template<typename T, typename Allocator>
class Arbitrary<std::deque<T, Allocator>>
    : public ArbitraryCollection<std::deque<T, Allocator>, T> {};

// std::forward_list
template<typename T, typename Allocator>
class Arbitrary<std::forward_list<T, Allocator>>
    : public ArbitraryCollection<std::forward_list<T, Allocator>, T> {};

// std::list
template<typename T, typename Allocator>
class Arbitrary<std::list<T, Allocator>>
    : public ArbitraryCollection<std::list<T, Allocator>, T> {};

// std::set
template<typename Key, typename Compare, typename Allocator>
class Arbitrary<std::set<Key, Compare, Allocator>>
    : public ArbitraryCollection<std::set<Key, Compare, Allocator>, Key> {};

// std::map
template<typename Key, typename T, typename Compare, typename Allocator>
class Arbitrary<std::map<Key, T, Compare, Allocator>>
    : public ArbitraryCollection<std::map<Key, T, Compare, Allocator>,
                                 std::pair<Key, T>> {};

// std::multiset
template<typename Key, typename Compare, typename Allocator>
class Arbitrary<std::multiset<Key, Compare, Allocator>>
    : public ArbitraryCollection<std::multiset<Key, Compare, Allocator>, Key> {};

// std::multimap
template<typename Key, typename T, typename Compare, typename Allocator>
class Arbitrary<std::multimap<Key, T, Compare, Allocator>>
    : public ArbitraryCollection<std::multimap<Key, T, Compare, Allocator>,
                                 std::pair<Key, T>> {};

// std::unordered_set
template<typename Key, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_set<Key, Hash, KeyEqual, Allocator>,
                                 Key> {};

// std::unordered_map
template<typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>,
                                 std::pair<Key, T>> {};

// std::unordered_multiset
template<typename Key, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>,
                                 Key> {};

// std::unordered_multimap
template<typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>,
                                 std::pair<Key, T>> {};

// std::basic_string
template<typename T, typename Traits, typename Allocator>
class Arbitrary<std::basic_string<T, Traits, Allocator>>
    : public gen::Collection<std::basic_string<T, Traits, Allocator>, gen::Character<T>>
{
public:
    typedef std::basic_string<T, Traits, Allocator> StringType;
    Arbitrary() : gen::Collection<StringType, gen::Character<T>>(
        gen::character<T>()) {}
};

// std::array
template<typename T, std::size_t N>
class Arbitrary<std::array<T, N>>
    : public ArbitraryCollection<std::array<T, N>, T> {};

} // namespace rc
<commit_msg>Fix a test which broke because of new RandomEngine<commit_after>#pragma once

namespace rc {

template<typename T>
class Arbitrary : public gen::Generator<T>
{
public:
    static_assert(std::is_integral<T>::value,
                  "No specialization of Arbitrary for type");

    T generate() const override
    {
        using namespace detail;

        int size = std::min(gen::currentSize(), gen::kNominalSize);
        RandomEngine::Atom r;
        // TODO this switching shouldn't be done here. pickAtom?
        ImplicitParam<param::CurrentNode> currentNode;
        if (*currentNode != nullptr) {
            r = currentNode->atom();
        } else {
            ImplicitParam<param::RandomEngine> randomEngine;
            r = randomEngine->nextAtom();
        }

        // We vary the size by using different number of bits. This way, we can be
        // that the max value can also be generated.
        int nBits = (size * std::numeric_limits<T>::digits) / gen::kNominalSize;
        if (nBits == 0)
            return 0;
        constexpr RandomEngine::Atom randIntMax =
            std::numeric_limits<RandomEngine::Atom>::max();
        RandomEngine::Atom mask = ~((randIntMax - 1) << (nBits - 1));

        T x = static_cast<T>(r & mask);
        if (std::numeric_limits<T>::is_signed)
        {
            // Use the topmost bit as the signed bit. Even in the case of a signed
            // 64-bit integer, it won't be used since it actually IS the sign bit.
            constexpr int basicBits =
                std::numeric_limits<RandomEngine::Atom>::digits;
            x *= ((r >> (basicBits - 1)) == 0) ? 1 : -1;
        }

        return x;
    }

    shrink::IteratorUP<T> shrink(T value) const override
    {
        std::vector<T> constants;
        if (value < 0)
            constants.push_back(-value);

        return shrink::sequentially(
            shrink::constant(constants),
            shrink::towards(value, static_cast<T>(0)));
    }
};

// Base for float and double arbitrary instances
template<typename T>
class ArbitraryReal : public gen::Generator<T>
{
public:
    T generate() const override
    {
        int64_t i = *gen::arbitrary<int64_t>();
        T x = static_cast<T>(i) / std::numeric_limits<int64_t>::max();
        return std::pow<T>(1.1, gen::currentSize()) * x;
    }

    shrink::IteratorUP<T> shrink(T value) const override
    {
        std::vector<T> constants;

        if (value < 0)
            constants.push_back(-value);

        T truncated = std::trunc(value);
        if (std::abs(truncated) < std::abs(value))
            constants.push_back(truncated);

        return shrink::constant(constants);
    }
};

template<>
class Arbitrary<float> : public ArbitraryReal<float> {};

template<>
class Arbitrary<double> : public ArbitraryReal<double> {};

template<>
class Arbitrary<bool> : public gen::Generator<bool>
{
public:
    bool generate() const override
    {
        return (*gen::resize(gen::kNominalSize,
                                 gen::arbitrary<uint8_t>()) & 0x1) == 0;
    }

    shrink::IteratorUP<bool> shrink(bool value)
    {
        if (value)
            return shrink::constant<bool>({false});
        else
            return shrink::nothing<bool>();
    }
};

template<typename ...Types>
class Arbitrary<std::tuple<Types...>>
    : public gen::TupleOf<Arbitrary<Types>...>
{
public:
    Arbitrary() : gen::TupleOf<Arbitrary<Types>...>(
            gen::arbitrary<Types>()...) {}
};

template<typename T1, typename T2>
class Arbitrary<std::pair<T1, T2>>
    : public gen::PairOf<Arbitrary<detail::DecayT<T1>>,
                         Arbitrary<detail::DecayT<T2>>>
{
public:
    Arbitrary()
        : gen::PairOf<Arbitrary<detail::DecayT<T1>>,
                      Arbitrary<detail::DecayT<T2>>>(
            gen::arbitrary<detail::DecayT<T1>>(),
            gen::arbitrary<detail::DecayT<T2>>()) {}
};

// Base template class for collection types
template<typename Coll, typename ValueType>
class ArbitraryCollection : public gen::Collection<Coll, Arbitrary<ValueType>>
{
public:
    typedef gen::Collection<Coll, Arbitrary<ValueType>> CollectionGen;
    ArbitraryCollection() : CollectionGen(gen::arbitrary<ValueType>()) {}
};

// std::vector
template<typename T, typename Allocator>
class Arbitrary<std::vector<T, Allocator>>
    : public ArbitraryCollection<std::vector<T, Allocator>, T> {};

// std::deque
template<typename T, typename Allocator>
class Arbitrary<std::deque<T, Allocator>>
    : public ArbitraryCollection<std::deque<T, Allocator>, T> {};

// std::forward_list
template<typename T, typename Allocator>
class Arbitrary<std::forward_list<T, Allocator>>
    : public ArbitraryCollection<std::forward_list<T, Allocator>, T> {};

// std::list
template<typename T, typename Allocator>
class Arbitrary<std::list<T, Allocator>>
    : public ArbitraryCollection<std::list<T, Allocator>, T> {};

// std::set
template<typename Key, typename Compare, typename Allocator>
class Arbitrary<std::set<Key, Compare, Allocator>>
    : public ArbitraryCollection<std::set<Key, Compare, Allocator>, Key> {};

// std::map
template<typename Key, typename T, typename Compare, typename Allocator>
class Arbitrary<std::map<Key, T, Compare, Allocator>>
    : public ArbitraryCollection<std::map<Key, T, Compare, Allocator>,
                                 std::pair<Key, T>> {};

// std::multiset
template<typename Key, typename Compare, typename Allocator>
class Arbitrary<std::multiset<Key, Compare, Allocator>>
    : public ArbitraryCollection<std::multiset<Key, Compare, Allocator>, Key> {};

// std::multimap
template<typename Key, typename T, typename Compare, typename Allocator>
class Arbitrary<std::multimap<Key, T, Compare, Allocator>>
    : public ArbitraryCollection<std::multimap<Key, T, Compare, Allocator>,
                                 std::pair<Key, T>> {};

// std::unordered_set
template<typename Key, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_set<Key, Hash, KeyEqual, Allocator>,
                                 Key> {};

// std::unordered_map
template<typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_map<Key, T, Hash, KeyEqual, Allocator>,
                                 std::pair<Key, T>> {};

// std::unordered_multiset
template<typename Key, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>,
                                 Key> {};

// std::unordered_multimap
template<typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
class Arbitrary<std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>>
    : public ArbitraryCollection<std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>,
                                 std::pair<Key, T>> {};

// std::basic_string
template<typename T, typename Traits, typename Allocator>
class Arbitrary<std::basic_string<T, Traits, Allocator>>
    : public gen::Collection<std::basic_string<T, Traits, Allocator>, gen::Character<T>>
{
public:
    typedef std::basic_string<T, Traits, Allocator> StringType;
    Arbitrary() : gen::Collection<StringType, gen::Character<T>>(
        gen::character<T>()) {}
};

// std::array
template<typename T, std::size_t N>
class Arbitrary<std::array<T, N>>
    : public ArbitraryCollection<std::array<T, N>, T> {};

} // namespace rc
<|endoftext|>


<commit_before>#include <Engine/Renderer/Texture/TextureManager.hpp>

#include <cstdio>

#include <FreeImage.h>

#include <Engine/Renderer/Texture/Texture.hpp>

namespace Ra
{
    namespace Engine
    {
        TextureManager::TextureManager()
            : m_verbose( false )
        {
        }

        TextureManager::~TextureManager()
        {
            for ( auto& tex : m_textures )
            {
                delete tex.second;
            }
            m_textures.clear();
        }

        void TextureManager::addTexture( const std::string& name, int width, int height, void* data )
        {
            TextureData texData;
            texData.name = name;
            texData.width = width;
            texData.height = height;
            texData.data = data;

            m_pendingTextures[name] = texData;
        }

        Texture* TextureManager::addTexture( const std::string& filename )
        {
            Texture* ret = nullptr;

            FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
            FIBITMAP* dib = nullptr; // TODO This name is nonsense, change it

            // Find format from file signature
            fif = FreeImage_GetFileType( filename.c_str(), 0 );

            if ( FIF_UNKNOWN == fif )
            {
                // Find format from file extension
                fif = FreeImage_GetFIFFromFilename( filename.c_str() );
            }

            if ( FIF_UNKNOWN == fif )
            {
                // Still unknown
                std::string error = "Cannot determine " + filename + " image format.";
                LOG( logERROR ) << error;
                return nullptr;
            }

            if ( FreeImage_FIFSupportsReading( fif ) )
            {
                dib = FreeImage_Load( fif, filename.c_str() );
            }

            std::string error = "Something went wrong while trying to load " + filename + ".";

            if ( nullptr == dib )
            {
                LOG( logERROR ) << error;
                return nullptr;
            }

            ret = new Texture( filename, GL_TEXTURE_2D );
            unsigned char* data = FreeImage_GetBits( dib );

            int bpp = FreeImage_GetBPP( dib );
            int format = 0, internal = 0;
            switch ( bpp )
            {
                case 8:
                {
                    // FIXME(Charly): Debug this
                    format = GL_RED;
                    internal = GL_RED;
                } break;

                case 24:
                {
                    format = GL_BGR;
                    internal = GL_RGB;
                } break;

                case 32:
                {
                    format = GL_BGRA;
                    internal = GL_RGBA;
                } break;

                default:
                {
                    LOG( logERROR ) << "Unknow bytes per pixel format : " << bpp;
                }
            }

            int w = FreeImage_GetWidth( dib );
            int h = FreeImage_GetHeight( dib );

            if ( m_verbose )
            {
                LOG( logINFO ) << "Image stats (" << filename << ") :\n"
                               << "\tBPP    : 0x" << std::hex << bpp << std::dec << std::endl
                               << "\tFormat : 0x" << std::hex << format << std::dec << std::endl
                               << "\tSize   : " << w << ", " << h;
            }

            CORE_ASSERT( data, "Data is null" );

            ret->initGL( internal, w, h, format, GL_UNSIGNED_BYTE, data );
            ret->genMipmap( GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR );

            m_textures.insert( TexturePair( filename, ret ) );

            FreeImage_Unload( dib );

            return ret;
        }

        Texture* TextureManager::getOrLoadTexture( const std::string& filename )
        {
            Texture* ret = nullptr;
            auto it = m_textures.find( filename );

            if ( it != m_textures.end() )
            {
                ret = it->second;
            }
            else
            {
                auto pending = m_pendingTextures.find( filename );
                if ( pending != m_pendingTextures.end() )
                {
                    ret = new Texture( filename, GL_TEXTURE_2D );
                    ret->initGL( GL_RGBA, pending->second.width, pending->second.height,
                                 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pending->second.data );

                    ret->genMipmap( GL_LINEAR, GL_LINEAR );
                    ret->setClamp( GL_CLAMP, GL_CLAMP );

                    m_pendingTextures.erase( filename );
                    m_textures[filename] = ret;
                }
                else
                {
                    ret = addTexture( filename );
                }
            }

            return ret;
        }

        void TextureManager::deleteTexture( const std::string& filename )
        {
            auto it = m_textures.find( filename );

            if ( it != m_textures.end() )
            {
                delete it->second;
                m_textures.erase( it );
            }
        }

        void TextureManager::deleteTexture( Texture* texture )
        {
            deleteTexture( texture->getName() );
        }

        void TextureManager::updateTexture( const std::string& texture, void* data )
        {
            CORE_ASSERT( m_textures.find( texture ) != m_textures.end(),
                         "Trying to update non existing texture" );
            m_pendingData[texture] = data;
        }

        void TextureManager::updateTextures()
        {
            if ( m_pendingData.empty() )
            {
                return;
            }

            for ( auto& data : m_pendingData )
            {
                m_textures[data.first]->updateData( data.second );
            }
            m_pendingData.clear();
        }

        RA_SINGLETON_IMPLEMENTATION(TextureManager);
    }
} // namespace Ra
<commit_msg>Set the clamping to clamp by default on loading textures<commit_after>#include <Engine/Renderer/Texture/TextureManager.hpp>

#include <cstdio>

#include <FreeImage.h>

#include <Engine/Renderer/Texture/Texture.hpp>

namespace Ra
{
    namespace Engine
    {
        TextureManager::TextureManager()
            : m_verbose( false )
        {
        }

        TextureManager::~TextureManager()
        {
            for ( auto& tex : m_textures )
            {
                delete tex.second;
            }
            m_textures.clear();
        }

        void TextureManager::addTexture( const std::string& name, int width, int height, void* data )
        {
            TextureData texData;
            texData.name = name;
            texData.width = width;
            texData.height = height;
            texData.data = data;

            m_pendingTextures[name] = texData;
        }

        Texture* TextureManager::addTexture( const std::string& filename )
        {
            Texture* ret = nullptr;

            FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
            FIBITMAP* dib = nullptr; // TODO This name is nonsense, change it

            // Find format from file signature
            fif = FreeImage_GetFileType( filename.c_str(), 0 );

            if ( FIF_UNKNOWN == fif )
            {
                // Find format from file extension
                fif = FreeImage_GetFIFFromFilename( filename.c_str() );
            }

            if ( FIF_UNKNOWN == fif )
            {
                // Still unknown
                std::string error = "Cannot determine " + filename + " image format.";
                LOG( logERROR ) << error;
                return nullptr;
            }

            if ( FreeImage_FIFSupportsReading( fif ) )
            {
                dib = FreeImage_Load( fif, filename.c_str() );
            }

            std::string error = "Something went wrong while trying to load " + filename + ".";

            if ( nullptr == dib )
            {
                LOG( logERROR ) << error;
                return nullptr;
            }

            ret = new Texture( filename, GL_TEXTURE_2D );
            unsigned char* data = FreeImage_GetBits( dib );

            int bpp = FreeImage_GetBPP( dib );
            int format = 0, internal = 0;
            switch ( bpp )
            {
                case 8:
                {
                    // FIXME(Charly): Debug this
                    format = GL_RED;
                    internal = GL_RED;
                } break;

                case 24:
                {
                    format = GL_BGR;
                    internal = GL_RGB;
                } break;

                case 32:
                {
                    format = GL_BGRA;
                    internal = GL_RGBA;
                } break;

                default:
                {
                    LOG( logERROR ) << "Unknow bytes per pixel format : " << bpp;
                }
            }

            int w = FreeImage_GetWidth( dib );
            int h = FreeImage_GetHeight( dib );

            if ( m_verbose )
            {
                LOG( logINFO ) << "Image stats (" << filename << ") :\n"
                               << "\tBPP    : 0x" << std::hex << bpp << std::dec << std::endl
                               << "\tFormat : 0x" << std::hex << format << std::dec << std::endl
                               << "\tSize   : " << w << ", " << h;
            }

            CORE_ASSERT( data, "Data is null" );

            ret->initGL( internal, w, h, format, GL_UNSIGNED_BYTE, data );
            ret->genMipmap( GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR );

            m_textures.insert( TexturePair( filename, ret ) );

            FreeImage_Unload( dib );

            return ret;
        }

        Texture* TextureManager::getOrLoadTexture( const std::string& filename )
        {
            Texture* ret = nullptr;
            auto it = m_textures.find( filename );

            if ( it != m_textures.end() )
            {
                ret = it->second;
            }
            else
            {
                auto pending = m_pendingTextures.find( filename );
                if ( pending != m_pendingTextures.end() )
                {
                    ret = new Texture( filename, GL_TEXTURE_2D );
                    ret->initGL( GL_RGBA, pending->second.width, pending->second.height,
                                 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pending->second.data );

                    ret->genMipmap( GL_LINEAR, GL_LINEAR );
                    ret->setClamp( GL_CLAMP, GL_CLAMP );

                    m_pendingTextures.erase( filename );
                    m_textures[filename] = ret;
                }
                else
                {
                    ret = addTexture( filename );
                    ret->setClamp( GL_CLAMP, GL_CLAMP );
                }
            }

            return ret;
        }

        void TextureManager::deleteTexture( const std::string& filename )
        {
            auto it = m_textures.find( filename );

            if ( it != m_textures.end() )
            {
                delete it->second;
                m_textures.erase( it );
            }
        }

        void TextureManager::deleteTexture( Texture* texture )
        {
            deleteTexture( texture->getName() );
        }

        void TextureManager::updateTexture( const std::string& texture, void* data )
        {
            CORE_ASSERT( m_textures.find( texture ) != m_textures.end(),
                         "Trying to update non existing texture" );
            m_pendingData[texture] = data;
        }

        void TextureManager::updateTextures()
        {
            if ( m_pendingData.empty() )
            {
                return;
            }

            for ( auto& data : m_pendingData )
            {
                m_textures[data.first]->updateData( data.second );
            }
            m_pendingData.clear();
        }

        RA_SINGLETON_IMPLEMENTATION(TextureManager);
    }
} // namespace Ra
<|endoftext|>