<commit_before>#ifndef ENTT_CORE_TYPE_TRAITS_HPP
#define ENTT_CORE_TYPE_TRAITS_HPP

#include <cstddef>
#include <utility>
#include <type_traits>
#include "../config/config.h"
#include "fwd.hpp"

namespace entt {

/**
 * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
 * @tparam Type The type of which to return the size.
 * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
 */
template<typename Type, typename = void>
struct size_of: std::integral_constant<std::size_t, 0u> {};

/*! @copydoc size_of */
template<typename Type>
struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
    : std::integral_constant<std::size_t, sizeof(Type)>
{};

/**
 * @brief Helper variable template.
 * @tparam Type The type of which to return the size.
 */
template<class Type>
inline constexpr auto size_of_v = size_of<Type>::value;

/**
 * @brief Using declaration to be used to _repeat_ the same type a number of
 * times equal to the size of a given parameter pack.
 * @tparam Type A type to repeat.
 */
template<typename Type, typename>
using unpack_as_t = Type;

/**
 * @brief Helper variable template to be used to _repeat_ the same value a
 * number of times equal to the size of a given parameter pack.
 * @tparam Value A value to repeat.
 */
template<auto Value, typename>
inline constexpr auto unpack_as_v = Value;

/**
 * @brief Wraps a static constant.
 * @tparam Value A static constant.
 */
template<auto Value>
using integral_constant = std::integral_constant<decltype(Value), Value>;

/**
 * @brief Alias template to facilitate the creation of named values.
 * @tparam Value A constant value at least convertible to `id_type`.
 */
template<id_type Value>
using tag = integral_constant<Value>;

/**
 * @brief Utility class to disambiguate overloaded functions.
 * @tparam N Number of choices available.
 */
template<std::size_t N>
struct choice_t
        // Unfortunately, doxygen cannot parse such a construct.
        /*! @cond TURN_OFF_DOXYGEN */
        : choice_t<N-1>
        /*! @endcond */
{};

/*! @copybrief choice_t */
template<>
struct choice_t<0> {};

/**
 * @brief Variable template for the choice trick.
 * @tparam N Number of choices available.
 */
template<std::size_t N>
inline constexpr choice_t<N> choice{};

/**
 * @brief A class to use to push around lists of types, nothing more.
 * @tparam Type Types provided by the type list.
 */
template<typename... Type>
struct type_list {
    /*! @brief Type list type. */
    using type = type_list;
    /*! @brief Compile-time number of elements in the type list. */
    static constexpr auto size = sizeof...(Type);
};

/**
 * @brief Concatenates multiple type lists.
 * @tparam Type Types provided by the first type list.
 * @tparam Other Types provided by the second type list.
 * @return A type list composed by the types of both the type lists.
 */
template<typename... Type, typename... Other>
constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) { return {}; }

/*! @brief Primary template isn't defined on purpose. */
template<typename...>
struct type_list_cat;

/*! @brief Concatenates multiple type lists. */
template<>
struct type_list_cat<> {
    /*! @brief A type list composed by the types of all the type lists. */
    using type = type_list<>;
};

/**
 * @brief Concatenates multiple type lists.
 * @tparam Type Types provided by the first type list.
 * @tparam Other Types provided by the second type list.
 * @tparam List Other type lists, if any.
 */
template<typename... Type, typename... Other, typename... List>
struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
    /*! @brief A type list composed by the types of all the type lists. */
    using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
};

/**
 * @brief Concatenates multiple type lists.
 * @tparam Type Types provided by the type list.
 */
template<typename... Type>
struct type_list_cat<type_list<Type...>> {
    /*! @brief A type list composed by the types of all the type lists. */
    using type = type_list<Type...>;
};

/**
 * @brief Helper type.
 * @tparam List Type lists to concatenate.
 */
template<typename... List>
using type_list_cat_t = typename type_list_cat<List...>::type;

/*! @brief Primary template isn't defined on purpose. */
template<typename>
struct type_list_unique;

/**
 * @brief Removes duplicates types from a type list.
 * @tparam Type One of the types provided by the given type list.
 * @tparam Other The other types provided by the given type list.
 */
template<typename Type, typename... Other>
struct type_list_unique<type_list<Type, Other...>> {
    /*! @brief A type list without duplicate types. */
    using type = std::conditional_t<
        std::disjunction_v<std::is_same<Type, Other>...>,
        typename type_list_unique<type_list<Other...>>::type,
        type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>
    >;
};

/*! @brief Removes duplicates types from a type list. */
template<>
struct type_list_unique<type_list<>> {
    /*! @brief A type list without duplicate types. */
    using type = type_list<>;
};

/**
 * @brief Helper type.
 * @tparam Type A type list.
 */
template<typename Type>
using type_list_unique_t = typename type_list_unique<Type>::type;

/**
 * @brief Provides the member constant `value` to true if a type list contains a
 * given type, false otherwise.
 * @tparam List Type list.
 * @tparam Type Type to look for.
 */
template<typename List, typename Type>
struct type_list_contains;

/**
 * @copybrief type_list_contains
 * @tparam Type Types provided by the type list.
 * @tparam Other Type to look for.
 */
template<typename... Type, typename Other>
struct type_list_contains<type_list<Type...>, Other>: std::disjunction<std::is_same<Type, Other>...> {};

/**
 * @brief Helper variable template.
 * @tparam List Type list.
 * @tparam Type Type to look for.
 */
template<class List, typename Type>
inline constexpr auto type_list_contains_v = type_list_contains<List, Type>::value;

/**
 * @brief Provides the member constant `value` to true if a given type is
 * equality comparable, false otherwise.
 * @tparam Type Potentially equality comparable type.
 */
template<typename Type, typename = void>
struct is_equality_comparable: std::false_type {};

/*! @copydoc is_equality_comparable */
template<typename Type>
struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
        : std::true_type
{};

/**
 * @brief Helper variable template.
 * @tparam Type Potentially equality comparable type.
 */
template<class Type>
inline constexpr auto is_equality_comparable_v = is_equality_comparable<Type>::value;

/*! @brief Same as std::is_invocable, but with tuples. */
template<typename, typename>
struct is_applicable: std::false_type {};

/**
 * @copybrief is_applicable
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Func, typename... Args>
struct is_applicable<Func, std::tuple<Args...>>: std::is_invocable<Func, Args...> {};

/**
 * @brief Helper variable template.
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Func, typename Args>
inline constexpr auto is_applicable_v = is_applicable<Func, Args>::value;

/*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
template<typename, typename, typename>
struct is_applicable_r: std::false_type {};

/**
 * @copybrief is_applicable_r
 * @tparam Ret The type to which the return type of the function should be
 * convertible.
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Ret, typename Func, typename... Args>
struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};

/**
 * @brief Helper variable template.
 * @tparam Ret The type to which the return type of the function should be
 * convertible.
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Ret, typename Func, typename Args>
inline constexpr auto is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;

/**
 * @brief Provides the member constant `value` to true if a given type is empty
 * and the empty type optimization is enabled, false otherwise.
 * @tparam Type Potential empty type.
 */
template<typename Type, typename = void>
struct is_empty
    : ENTT_IS_EMPTY(Type)
{};

/**
 * @brief Helper variable template.
 * @tparam Type Potential empty type.
 */
template<typename Type>
inline constexpr auto is_empty_v = is_empty<Type>::value;

/**
 * @brief Transcribes the constness of a type to another type.
 * @tparam To The type to which to transcribe the constness.
 * @tparam From The type from which to transcribe the constness.
 */
template<typename To, typename From>
struct constness_as {
    using type = std::remove_const_t<To>;
};

/*! @copydoc constness_as */
template<typename To, typename From>
struct constness_as<To, const From> {
    using type = std::add_const_t<To>;
};

/**
 * @brief Alias template to facilitate the transcription of the constness.
 * @tparam To The type to which to transcribe the constness.
 * @tparam From The type from which to transcribe the constness.
 */
template<typename To, typename From>
using constness_as_t = typename constness_as<To, From>::type;

/**
 * @brief Extracts the class of a non-static member object or function.
 * @tparam Member A pointer to a non-static member object or function.
 */
template<typename Member>
class member_class {
    static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");

    template<typename Class, typename Ret, typename... Args>
    static Class * clazz(Ret(Class:: *)(Args...));

    template<typename Class, typename Ret, typename... Args>
    static Class * clazz(Ret(Class:: *)(Args...) const);

    template<typename Class, typename Type>
    static Class * clazz(Type Class:: *);

public:
    /*! @brief The class of the given non-static member object or function. */
    using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
};

/**
 * @brief Helper type.
 * @tparam Member A pointer to a non-static member object or function.
 */
template<typename Member>
using member_class_t = typename member_class<Member>::type;

}

#endif
<commit_msg>constness_as: updated doc<commit_after>#ifndef ENTT_CORE_TYPE_TRAITS_HPP
#define ENTT_CORE_TYPE_TRAITS_HPP

#include <cstddef>
#include <utility>
#include <type_traits>
#include "../config/config.h"
#include "fwd.hpp"

namespace entt {

/**
 * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
 * @tparam Type The type of which to return the size.
 * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
 */
template<typename Type, typename = void>
struct size_of: std::integral_constant<std::size_t, 0u> {};

/*! @copydoc size_of */
template<typename Type>
struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
    : std::integral_constant<std::size_t, sizeof(Type)>
{};

/**
 * @brief Helper variable template.
 * @tparam Type The type of which to return the size.
 */
template<class Type>
inline constexpr auto size_of_v = size_of<Type>::value;

/**
 * @brief Using declaration to be used to _repeat_ the same type a number of
 * times equal to the size of a given parameter pack.
 * @tparam Type A type to repeat.
 */
template<typename Type, typename>
using unpack_as_t = Type;

/**
 * @brief Helper variable template to be used to _repeat_ the same value a
 * number of times equal to the size of a given parameter pack.
 * @tparam Value A value to repeat.
 */
template<auto Value, typename>
inline constexpr auto unpack_as_v = Value;

/**
 * @brief Wraps a static constant.
 * @tparam Value A static constant.
 */
template<auto Value>
using integral_constant = std::integral_constant<decltype(Value), Value>;

/**
 * @brief Alias template to facilitate the creation of named values.
 * @tparam Value A constant value at least convertible to `id_type`.
 */
template<id_type Value>
using tag = integral_constant<Value>;

/**
 * @brief Utility class to disambiguate overloaded functions.
 * @tparam N Number of choices available.
 */
template<std::size_t N>
struct choice_t
        // Unfortunately, doxygen cannot parse such a construct.
        /*! @cond TURN_OFF_DOXYGEN */
        : choice_t<N-1>
        /*! @endcond */
{};

/*! @copybrief choice_t */
template<>
struct choice_t<0> {};

/**
 * @brief Variable template for the choice trick.
 * @tparam N Number of choices available.
 */
template<std::size_t N>
inline constexpr choice_t<N> choice{};

/**
 * @brief A class to use to push around lists of types, nothing more.
 * @tparam Type Types provided by the type list.
 */
template<typename... Type>
struct type_list {
    /*! @brief Type list type. */
    using type = type_list;
    /*! @brief Compile-time number of elements in the type list. */
    static constexpr auto size = sizeof...(Type);
};

/**
 * @brief Concatenates multiple type lists.
 * @tparam Type Types provided by the first type list.
 * @tparam Other Types provided by the second type list.
 * @return A type list composed by the types of both the type lists.
 */
template<typename... Type, typename... Other>
constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) { return {}; }

/*! @brief Primary template isn't defined on purpose. */
template<typename...>
struct type_list_cat;

/*! @brief Concatenates multiple type lists. */
template<>
struct type_list_cat<> {
    /*! @brief A type list composed by the types of all the type lists. */
    using type = type_list<>;
};

/**
 * @brief Concatenates multiple type lists.
 * @tparam Type Types provided by the first type list.
 * @tparam Other Types provided by the second type list.
 * @tparam List Other type lists, if any.
 */
template<typename... Type, typename... Other, typename... List>
struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
    /*! @brief A type list composed by the types of all the type lists. */
    using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
};

/**
 * @brief Concatenates multiple type lists.
 * @tparam Type Types provided by the type list.
 */
template<typename... Type>
struct type_list_cat<type_list<Type...>> {
    /*! @brief A type list composed by the types of all the type lists. */
    using type = type_list<Type...>;
};

/**
 * @brief Helper type.
 * @tparam List Type lists to concatenate.
 */
template<typename... List>
using type_list_cat_t = typename type_list_cat<List...>::type;

/*! @brief Primary template isn't defined on purpose. */
template<typename>
struct type_list_unique;

/**
 * @brief Removes duplicates types from a type list.
 * @tparam Type One of the types provided by the given type list.
 * @tparam Other The other types provided by the given type list.
 */
template<typename Type, typename... Other>
struct type_list_unique<type_list<Type, Other...>> {
    /*! @brief A type list without duplicate types. */
    using type = std::conditional_t<
        std::disjunction_v<std::is_same<Type, Other>...>,
        typename type_list_unique<type_list<Other...>>::type,
        type_list_cat_t<type_list<Type>, typename type_list_unique<type_list<Other...>>::type>
    >;
};

/*! @brief Removes duplicates types from a type list. */
template<>
struct type_list_unique<type_list<>> {
    /*! @brief A type list without duplicate types. */
    using type = type_list<>;
};

/**
 * @brief Helper type.
 * @tparam Type A type list.
 */
template<typename Type>
using type_list_unique_t = typename type_list_unique<Type>::type;

/**
 * @brief Provides the member constant `value` to true if a type list contains a
 * given type, false otherwise.
 * @tparam List Type list.
 * @tparam Type Type to look for.
 */
template<typename List, typename Type>
struct type_list_contains;

/**
 * @copybrief type_list_contains
 * @tparam Type Types provided by the type list.
 * @tparam Other Type to look for.
 */
template<typename... Type, typename Other>
struct type_list_contains<type_list<Type...>, Other>: std::disjunction<std::is_same<Type, Other>...> {};

/**
 * @brief Helper variable template.
 * @tparam List Type list.
 * @tparam Type Type to look for.
 */
template<class List, typename Type>
inline constexpr auto type_list_contains_v = type_list_contains<List, Type>::value;

/**
 * @brief Provides the member constant `value` to true if a given type is
 * equality comparable, false otherwise.
 * @tparam Type Potentially equality comparable type.
 */
template<typename Type, typename = void>
struct is_equality_comparable: std::false_type {};

/*! @copydoc is_equality_comparable */
template<typename Type>
struct is_equality_comparable<Type, std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>
        : std::true_type
{};

/**
 * @brief Helper variable template.
 * @tparam Type Potentially equality comparable type.
 */
template<class Type>
inline constexpr auto is_equality_comparable_v = is_equality_comparable<Type>::value;

/*! @brief Same as std::is_invocable, but with tuples. */
template<typename, typename>
struct is_applicable: std::false_type {};

/**
 * @copybrief is_applicable
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Func, typename... Args>
struct is_applicable<Func, std::tuple<Args...>>: std::is_invocable<Func, Args...> {};

/**
 * @brief Helper variable template.
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Func, typename Args>
inline constexpr auto is_applicable_v = is_applicable<Func, Args>::value;

/*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
template<typename, typename, typename>
struct is_applicable_r: std::false_type {};

/**
 * @copybrief is_applicable_r
 * @tparam Ret The type to which the return type of the function should be
 * convertible.
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Ret, typename Func, typename... Args>
struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};

/**
 * @brief Helper variable template.
 * @tparam Ret The type to which the return type of the function should be
 * convertible.
 * @tparam Func A valid function type.
 * @tparam Args The list of arguments to use to probe the function type.
 */
template<typename Ret, typename Func, typename Args>
inline constexpr auto is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;

/**
 * @brief Provides the member constant `value` to true if a given type is empty
 * and the empty type optimization is enabled, false otherwise.
 * @tparam Type Potential empty type.
 */
template<typename Type, typename = void>
struct is_empty
    : ENTT_IS_EMPTY(Type)
{};

/**
 * @brief Helper variable template.
 * @tparam Type Potential empty type.
 */
template<typename Type>
inline constexpr auto is_empty_v = is_empty<Type>::value;

/**
 * @brief Transcribes the constness of a type to another type.
 * @tparam To The type to which to transcribe the constness.
 * @tparam From The type from which to transcribe the constness.
 */
template<typename To, typename From>
struct constness_as {
    /*! @brief The type resulting from the transcription of the constness */
    using type = std::remove_const_t<To>;
};

/*! @copydoc constness_as */
template<typename To, typename From>
struct constness_as<To, const From> {
    /*! @brief The type resulting from the transcription of the constness */
    using type = std::add_const_t<To>;
};

/**
 * @brief Alias template to facilitate the transcription of the constness.
 * @tparam To The type to which to transcribe the constness.
 * @tparam From The type from which to transcribe the constness.
 */
template<typename To, typename From>
using constness_as_t = typename constness_as<To, From>::type;

/**
 * @brief Extracts the class of a non-static member object or function.
 * @tparam Member A pointer to a non-static member object or function.
 */
template<typename Member>
class member_class {
    static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");

    template<typename Class, typename Ret, typename... Args>
    static Class * clazz(Ret(Class:: *)(Args...));

    template<typename Class, typename Ret, typename... Args>
    static Class * clazz(Ret(Class:: *)(Args...) const);

    template<typename Class, typename Type>
    static Class * clazz(Type Class:: *);

public:
    /*! @brief The class of the given non-static member object or function. */
    using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
};

/**
 * @brief Helper type.
 * @tparam Member A pointer to a non-static member object or function.
 */
template<typename Member>
using member_class_t = typename member_class<Member>::type;

}

#endif
<|endoftext|>


<commit_before>/****************************************************************************
 * **
 * ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 * ** Contact: http://www.qt-project.org/legal
 * **
 * ** This file is part of the qmake spec of the Qt Toolkit.
 * **
 * ** $QT_BEGIN_LICENSE:LGPL21$
 * ** Commercial License Usage
 * ** Licensees holding valid commercial Qt licenses may use this file in
 * ** accordance with the commercial license agreement provided with the
 * ** Software or, alternatively, in accordance with the terms contained in
 * ** a written agreement between you and Digia. For licensing terms and
 * ** conditions see http://qt.digia.com/licensing. For further information
 * ** use the contact form at http://qt.digia.com/contact-us.
 * **
 * ** GNU Lesser General Public License Usage
 * ** Alternatively, this file may be used under the terms of the GNU Lesser
 * ** General Public License version 2.1 or version 3 as published by the Free
 * ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
 * ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
 * ** following information to ensure the GNU Lesser General Public License
 * ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 * ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 * **
 * ** In addition, as a special exception, Digia gives you certain additional
 * ** rights. These rights are described in the Digia Qt LGPL Exception
 * ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 * **
 * ** $QT_END_LICENSE$
 * **
 * ****************************************************************************/

#include "qeglfshooks.h"
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <unistd.h>

QT_BEGIN_NAMESPACE

class QEglFSZynqMPHooks : public QEglFSHooks
{
	public:
		virtual QSize screenSize() const;
		virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format);
		virtual void destroyNativeWindow(EGLNativeWindowType window);
};

QSize QEglFSZynqMPHooks::screenSize() const
{
	int fd = open("/dev/fb0", O_RDONLY);
	if (fd == -1) {
		qFatal("Failed to open fb to detect screen resolution!");
	}

	struct fb_var_screeninfo vinfo;
	if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
		qFatal("Could not get variable screen info");
	}

	close(fd);

	return QSize(vinfo.xres, vinfo.yres);
}

EGLNativeWindowType QEglFSZynqMPHooks::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format)
{
	Q_UNUSED(window);
	Q_UNUSED(format);

	fbdev_window *fbwin = new fbdev_window;
	fbwin->width = size.width();
	fbwin->height = size.height();

	return fbwin;
}

void QEglFSZynqMPHooks::destroyNativeWindow(EGLNativeWindowType window)
{
	delete window;
}

QEglFSZynqMPHooks eglFSZynqMPHooks;
QEglFSHooks *platformHooks = &eglFSZynqMPHooks;

QT_END_NAMESPACE
<commit_msg>qeglfshooks_zynqmp.cpp: Fix hook file for fbdev<commit_after>/****************************************************************************
 * **
 * ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 * ** Contact: http://www.qt-project.org/legal
 * **
 * ** This file is part of the qmake spec of the Qt Toolkit.
 * **
 * ** $QT_BEGIN_LICENSE:LGPL21$
 * ** Commercial License Usage
 * ** Licensees holding valid commercial Qt licenses may use this file in
 * ** accordance with the commercial license agreement provided with the
 * ** Software or, alternatively, in accordance with the terms contained in
 * ** a written agreement between you and Digia. For licensing terms and
 * ** conditions see http://qt.digia.com/licensing. For further information
 * ** use the contact form at http://qt.digia.com/contact-us.
 * **
 * ** GNU Lesser General Public License Usage
 * ** Alternatively, this file may be used under the terms of the GNU Lesser
 * ** General Public License version 2.1 or version 3 as published by the Free
 * ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
 * ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
 * ** following information to ensure the GNU Lesser General Public License
 * ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 * ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 * **
 * ** In addition, as a special exception, Digia gives you certain additional
 * ** rights. These rights are described in the Digia Qt LGPL Exception
 * ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 * **
 * ** $QT_END_LICENSE$
 * **
 * ****************************************************************************/

#include "qeglfshooks.h"
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <unistd.h>

QT_BEGIN_NAMESPACE

typedef struct fbdev_window
{
	unsigned short width;
	unsigned short height;
} fbdev_window;

class QEglFSZynqMPHooks : public QEglFSHooks
{
	public:
		virtual QSize screenSize() const;
		virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format);
		virtual void destroyNativeWindow(EGLNativeWindowType window);
};

QSize QEglFSZynqMPHooks::screenSize() const
{
	int fd = open("/dev/fb0", O_RDONLY);
	if (fd == -1) {
		qFatal("Failed to open fb to detect screen resolution!");
	}

	struct fb_var_screeninfo vinfo;
	if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
		qFatal("Could not get variable screen info");
	}

	close(fd);

	return QSize(vinfo.xres, vinfo.yres);
}

EGLNativeWindowType QEglFSZynqMPHooks::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format)
{
	Q_UNUSED(window);
	Q_UNUSED(format);

	fbdev_window *fbwin = new fbdev_window;
	fbwin->width = size.width();
	fbwin->height = size.height();

	return (EGLNativeWindowType)fbwin;
}

void QEglFSZynqMPHooks::destroyNativeWindow(EGLNativeWindowType window)
{
	delete (struct fbdev_window*) window;
}

QEglFSZynqMPHooks eglFSZynqMPHooks;
QEglFSHooks *platformHooks = &eglFSZynqMPHooks;

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "File.h"
#include "logging/Logger.h"

#include <sys/types.h>
#include <sys/stat.h>

#include <stdexcept>
#include <system_error>

#include <windows.h>

namespace medialibrary
{

namespace fs
{

File::File( const std::string &filePath )
    : CommonFile( filePath )
{
    struct _stat s;
    if ( _stat( m_fullPath.c_str(), &s ) != 0 )
    {
        LOG_ERROR( "Failed to get ", m_fullPath, " stats" );
        throw std::system_error( GetLastError(), std::generic_category(), "Failed to get stats" );
    }

    m_lastModificationDate = s.st_mtime;
    m_size = s.st_size;
}

unsigned int File::lastModificationDate() const
{
    return m_lastModificationDate;
}

unsigned int File::size() const
{
    return m_size;
}

}

}
<commit_msg>win32: File: Use errno instead of GetLastError after _stat()<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "File.h"
#include "logging/Logger.h"

#include <sys/types.h>
#include <sys/stat.h>

#include <stdexcept>
#include <system_error>

#include <windows.h>

namespace medialibrary
{

namespace fs
{

File::File( const std::string &filePath )
    : CommonFile( filePath )
{
    struct _stat s;
    if ( _stat( m_fullPath.c_str(), &s ) != 0 )
    {
        LOG_ERROR( "Failed to get ", m_fullPath, " stats" );
        throw std::system_error( errno, std::generic_category(), "Failed to get stats" );
    }

    m_lastModificationDate = s.st_mtime;
    m_size = s.st_size;
}

unsigned int File::lastModificationDate() const
{
    return m_lastModificationDate;
}

unsigned int File::size() const
{
    return m_size;
}

}

}
<|endoftext|>


<commit_before>#include "common.th"
#include "errno.th"

#define RANK_0_LOG 4
#define RANK_0_SIZE (1 << RANK_0_LOG)
#define RANKS 3

// NOTE there are some assumptions in the below code that NPER * BPER = 32,
// notably in DIFF()
#define NPERBITS 4
#define BPERBITS 1

#define NPER (1 << NPERBITS)
#define BPER (1 << BPERBITS)

#define TN 0

// TODO size `nodes' appropriately
// TODO implement .lcomm and use it for this
nodes:
    .word 0

// TODO size `pool' appropriately
#define POOL    rel(pool)
pool:
    .word 0

// TODO initialise counts appropriately
counts:
    .word 0, 0, 1

// Type `SZ' is a word-wide unsigned integer (some places used as a boolean).
// Type `NP' is a word-wide struct, where the word is split into a 28-bit word
// index into `nodes` and a 4-bit index into the word indexed.

ilog2:
    B   <- 0
    push(D)
L_ilog2_top:
    C   <- C >> 1
    D   <- C == 0
    jnzrel(D, L_ilog2_done)
    B   <- B + 1
    goto(L_ilog2_top)
L_ilog2_done:
    pop(D)
    ret

// NODE gets SZ index in C, returns NP node in B, clobbers C
#define NODE(B,C)               \
    B   <- C << BPERBITS      ; \
    B   <- B + TN             ; \
    C   <- C & (BPER - 1)     ; \
    B   <- B | C              ; \
    //

// IRANK gets SZ rank in C, returns SZ inverted-rank in B
#define IRANK(B,C)              \
    B   <- - C + (RANKS - 1)  ; \
    //

// DIFF gets NP a in C, NP b in D, returns SZ distance in B
#define DIFF(B,C,D)             \
    B   <- C - D              ; \
    //

// INDEX gets NP n in C, returns SZ distance from TN in B
#define INDEX(B,C)              \
    DIFF(B,C,TN)              ; \
    //

// LLINK gets NP n in C, returns NP left-child in B, clobbers C
#define LLINK(B,C)              \
    INDEX(B,C)                ; \
    C   <- B << 1             ; \
    C   <- C +  1             ; \
    NODE(B,C)                 ; \
    //

// RLINK gets NP n in C, returns NP right-child in B, clobbers C
#define RLINK(B,C)              \
    INDEX(B,C)                ; \
    C   <- B << 1             ; \
    C   <- C +  2             ; \
    NODE(B,C)                 ; \
    //

// ISLEFT gets NP n in C, returns SZ leftness in B
#define ISLEFT(B,C)             \
    INDEX(B,C)                ; \
    B   <- B & 1              ; \
    B   <- B == 1             ; \
    //

// ISRIGHT gets NP n in C, returns SZ rightness in B
#define ISRIGHT(B,C)            \
    INDEX(B,C)                ; \
    B   <- B & 1              ; \
    B   <- B == 0             ; \
    //

// PARENT gets NP n in C, returns NP parent in B, clobbers C
#define PARENT(B,C)             \
    INDEX(B,C)                ; \
    C   <- B -  1             ; \
    C   <- C >> 1             ; \
    NODE(B,C)                 ; \
    //

// SIBLING gets NP n in C, returns NP sibling in B, clobbers C
#define SIBLING(B,C)            \
    INDEX(B,C)                ; \
    ISLEFT(C,B)               ; \
    B   <- B - C              ; \
    C   <- ~ C                ; \
    B   <- B + C              ; \
    //

// NODE2RANK gets NP n in C, returns SZ rank in B
#define NODE2RANK(B,C)          \
    call(NODE2RANK_func)      ; \
    //

NODE2RANK_func:
    push(D)
    D   <- 0
L_NODE2RANK_top:
    INDEX(B,C)
    B   <- B == 0
    jnzrel(B, L_NODE2RANK_done)
    D   <- D + 1
    B   <- C
    PARENT(C,B)
    goto(L_NODE2RANK_top)
L_NODE2RANK_done:
    B   <- - D + (RANKS - 1)
    pop(D)
    ret

#define SIZE2RANK(B,C) \
    call(SIZE2RANK_func)
    //

SIZE2RANK_func:
    B   <- C <> 0
    jzrel(B, L_SIZE2RANK_zero)
    C   <- C - 1
    C   <- C >> RANK_0_LOG
    call(ilog2)
    B   <- B + 1
L_SIZE2RANK_zero:
    ret

// RANK2WORDS gets SZ rank in C, returns SZ word-count in B, clobbers C
#define RANK2WORDS(B,C)         \
    C   <- C + RANK_0_LOG     ; \
    B   <- 1                  ; \
    B   <- B << C             ; \
    //

// GET_COUNT gets SZ rank in C, returns SZ free-count in B
#define GET_COUNT(B,C)          \
    B   <- [C + rel(counts)]  ; \
    //

// SET_COUNT gets SZ rank in C, SZ free-count in D, returns nothing
#define SET_COUNT(C,D)          \
    D   -> [C + rel(counts)]  ; \
    //

// GET_NODE gets NP n in C, returns SZ shifted-word in B, clobbers C
#define GET_NODE(B,C)           \
    B   <- C >> BPERBITS      ; \
    C   <- C & (BPER - 1)     ; \
    C   <- C << BPERBITS      ; \
    B   <- [B + rel(nodes)]   ; \
    B   <- B >> C             ; \
    //

// SET_NODE gets NP n in C, SZ pre-shift-word in D, clobbers C and D
#define SET_NODE(C,D,T0,T1)                                                 \
    T0  <- C & (BPER - 1)       /* T0 is shift count in nodes        */   ; \
    T0  <- T0 << BPERBITS       /* T0 is shift count in bits         */   ; \
    D   <- D << T0              /* D  is now shifted over            */   ; \
    T1  <- (BPER - 1)           /* T1 is mask                        */   ; \
    T1  <- T1 << T0             /* T1 is shifted mask                */   ; \
    T0  <- C >> BPERBITS        /* T0 is index into node array       */   ; \
    C   <- [T0 + rel(nodes)]    /* C  is current word                */   ; \
    C   <- C &~ T1              /* C  is word with node masked out   */   ; \
    C   <- C | D                /* C  is word with new node included */   ; \
    C   -> [T0 + rel(nodes)]    /* C  gets written back to node      */   ; \
    //

// GET_LEAF gets NP n in C, returns SZ leafiness in B, clobbers C
#define GET_LEAF(B,C)           \
    GET_NODE(B,C)             ; \
    B   <- B &  1             ; \
    B   <- B == 0             ; \
    //

// GET_FULL gets NP n in C, returns SZ fullness in B, clobbers C
#define GET_FULL(B,C)           \
    GET_NODE(B,C)             ; \
    B   <- B &  2             ; \
    B   <- B == 2             ; \
    //

// GET_VALID gets NP n in C, returns SZ validity in B
#define GET_VALID(B,C,T0)       \
    T0  <- C                  ; \
    INDEX(B,C)                ; \
    PARENT(C,T0)              ; \
    GET_LEAF(T0,C)            ; \
    B   <- B &~ T0            ; \
    //

// TODO SET_LEAF
// SET_LEAF gets NP n in C, SZ truth in D, returns nothing, clobbers C
// We take a shortcut ; either we are setting the leaf true from false, and it
// is therefore not full, or we are setting it false from true, and fullness
// has no meaning. This allows us to avoid reading and rewriting the fullness
// value.
#define SET_LEAF(C,D,T0,T1)     \
    D   <- D & 1              ; \
    SET_NODE(C,D,T0,T1)       ; \
    //

// TODO SET_FULL
#define SET_FULL(C,D) \
    //
// TODO NODE2ADDR
// ADDR2NODE gets SZ addr in C, returns NP node in B
#define ADDR2NODE(B,C)          \
    call(ADDR2NODE_func)      ; \
    //

// C is key
ADDR2NODE_func:
    pushall(D,E,F,G,H)
    D   <- (RANKS - 1)  // D is current rank
    E   <- POOL         // E is base being built
    F   <- C            // F is a scratch register
    G   <- TN           // G is the node being checked
    H   <- G            // H is another scratch
L_ADDR2NODE_looptop:
    GET_LEAF(B,H)
    jnzrel(B,L_ADDR2NODE_loopdone)
    RANK2WORDS(B,F)
    H   <- C - E        // H is (key - base)
    F   <- H < B        // if true, then left-link
    jnzrel(F,L_ADDR2NODE_left)
    H   <- G
    RLINK(G,H)          // n = RLINK(n)
    E   <- E + B        // base += RANK2WORDS(rank)
    goto(L_ADDR2NODE_loopbottom)
L_ADDR2NODE_left:
    H   <- G
    LLINK(G,H)          // n = LLINK(n)
    // fallthrough

L_ADDR2NODE_loopbottom:
    D   <- D - 1
    goto(L_ADDR2NODE_looptop)

L_ADDR2NODE_loopdone:
    B   <- C == E
    jnzrel(B,L_ADDR2NODE_done)
    call(abort)

L_ADDR2NODE_done:
    popall(D,E,F,G,H)
    ret

.global buddy_malloc
buddy_malloc:
    goto(buddy_alloc)

.global buddy_calloc
buddy_calloc:
    C   <- C * D
    push(C)
    call(buddy_alloc)
    C   <- B
    D   <- 0
    pop(E)
    call(memset)
    ret

.global buddy_free
buddy_free:
    // TODO
    ret

.global buddy_realloc
buddy_realloc:
    // TODO
    ret

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

buddy_splitnode:
    // TODO
    ret

buddy_autosplit:
    // TODO
    ret

// TODO check for clobbering
// buddy_alloc gets SZ size in C, returns address or 0 in B
buddy_alloc:
    pushall(D,E,F,G)
    SIZE2RANK(B,C)
    D   <- B < RANKS
    jzrel(D,L_buddy_alloc_error)
    D   <- B
    GET_COUNT(E,D)
    D   <- E == 0
    jnzrel(D,L_buddy_alloc_do_split)
    // here is the main body, where we have a nonzero count of the needed
    // rank. B is rank, D is scratch, E is scratch and currently count
    D   <- B
    IRANK(E,D)
    F   <- 1
    F   <- F << E       // F is loop bound
    D   <- F - 1        // D is first index to check
    F   <- F + D        // F is loop bound adjust for `first'
L_buddy_alloc_loop_top:
    NODE(E,D)           // E is NODE(D)
    GET_VALID(C,E,G)    // C is validity
    jzrel(C,L_buddy_alloc_loop_bottom)
    GET_LEAF(C,E)       // C is leafiness
    jzrel(C,L_buddy_alloc_loop_bottom)
    GET_FULL(C,E)       // C is fullness
    jnzrel(C,L_buddy_alloc_loop_bottom)
    SET_FULL(E,-1)
    GET_COUNT(C,B)
    C   <- C - 1
    SET_COUNT(E,C)
    C   <- E
    ADDR2NODE(B,C)
    goto(L_buddy_alloc_done)

L_buddy_alloc_loop_bottom:
    D   <- D + 1    // D is loop index
    goto(L_buddy_alloc_loop_top)

L_buddy_alloc_do_split:
    D   <- E
    call(buddy_autosplit)
    goto(L_buddy_alloc_done)

L_buddy_alloc_error:
    D   <- ENOMEM
    D   -> errno
    B   <- 0
L_buddy_alloc_done:
    popall(D,E,F,G)
    ret

<commit_msg>Integrate mended ADDR2NODE from buddy.c<commit_after>#include "common.th"
#include "errno.th"

#define RANK_0_LOG 4
#define RANK_0_SIZE (1 << RANK_0_LOG)
#define RANKS 3

// NOTE there are some assumptions in the below code that NPER * BPER = 32,
// notably in DIFF()
#define NPERBITS 4
#define BPERBITS 1

#define NPER (1 << NPERBITS)
#define BPER (1 << BPERBITS)

#define TN 0

// TODO size `nodes' appropriately
// TODO implement .lcomm and use it for this
nodes:
    .word 0

// TODO size `pool' appropriately
#define POOL    rel(pool)
pool:
    .word 0

// TODO initialise counts appropriately
counts:
    .word 0, 0, 1

// Type `SZ' is a word-wide unsigned integer (some places used as a boolean).
// Type `NP' is a word-wide struct, where the word is split into a 28-bit word
// index into `nodes` and a 4-bit index into the word indexed.

ilog2:
    B   <- 0
    push(D)
L_ilog2_top:
    C   <- C >> 1
    D   <- C == 0
    jnzrel(D, L_ilog2_done)
    B   <- B + 1
    goto(L_ilog2_top)
L_ilog2_done:
    pop(D)
    ret

// NODE gets SZ index in C, returns NP node in B, clobbers C
#define NODE(B,C)               \
    B   <- C << BPERBITS      ; \
    B   <- B + TN             ; \
    C   <- C & (BPER - 1)     ; \
    B   <- B | C              ; \
    //

// IRANK gets SZ rank in C, returns SZ inverted-rank in B
#define IRANK(B,C)              \
    B   <- - C + (RANKS - 1)  ; \
    //

// DIFF gets NP a in C, NP b in D, returns SZ distance in B
#define DIFF(B,C,D)             \
    B   <- C - D              ; \
    //

// INDEX gets NP n in C, returns SZ distance from TN in B
#define INDEX(B,C)              \
    DIFF(B,C,TN)              ; \
    //

// LLINK gets NP n in C, returns NP left-child in B, clobbers C
#define LLINK(B,C)              \
    INDEX(B,C)                ; \
    C   <- B << 1             ; \
    C   <- C +  1             ; \
    NODE(B,C)                 ; \
    //

// RLINK gets NP n in C, returns NP right-child in B, clobbers C
#define RLINK(B,C)              \
    INDEX(B,C)                ; \
    C   <- B << 1             ; \
    C   <- C +  2             ; \
    NODE(B,C)                 ; \
    //

// ISLEFT gets NP n in C, returns SZ leftness in B
#define ISLEFT(B,C)             \
    INDEX(B,C)                ; \
    B   <- B & 1              ; \
    B   <- B == 1             ; \
    //

// ISRIGHT gets NP n in C, returns SZ rightness in B
#define ISRIGHT(B,C)            \
    INDEX(B,C)                ; \
    B   <- B & 1              ; \
    B   <- B == 0             ; \
    //

// PARENT gets NP n in C, returns NP parent in B, clobbers C
#define PARENT(B,C)             \
    INDEX(B,C)                ; \
    C   <- B -  1             ; \
    C   <- C >> 1             ; \
    NODE(B,C)                 ; \
    //

// SIBLING gets NP n in C, returns NP sibling in B, clobbers C
#define SIBLING(B,C)            \
    INDEX(B,C)                ; \
    ISLEFT(C,B)               ; \
    B   <- B - C              ; \
    C   <- ~ C                ; \
    B   <- B + C              ; \
    //

// NODE2RANK gets NP n in C, returns SZ rank in B
#define NODE2RANK(B,C)          \
    call(NODE2RANK_func)      ; \
    //

NODE2RANK_func:
    push(D)
    D   <- 0
L_NODE2RANK_top:
    INDEX(B,C)
    B   <- B == 0
    jnzrel(B, L_NODE2RANK_done)
    D   <- D + 1
    B   <- C
    PARENT(C,B)
    goto(L_NODE2RANK_top)
L_NODE2RANK_done:
    B   <- - D + (RANKS - 1)
    pop(D)
    ret

#define SIZE2RANK(B,C) \
    call(SIZE2RANK_func)
    //

SIZE2RANK_func:
    B   <- C <> 0
    jzrel(B, L_SIZE2RANK_zero)
    C   <- C - 1
    C   <- C >> RANK_0_LOG
    call(ilog2)
    B   <- B + 1
L_SIZE2RANK_zero:
    ret

// RANK2WORDS gets SZ rank in C, returns SZ word-count in B, clobbers C
#define RANK2WORDS(B,C)         \
    C   <- C + RANK_0_LOG     ; \
    B   <- 1                  ; \
    B   <- B << C             ; \
    //

// GET_COUNT gets SZ rank in C, returns SZ free-count in B
#define GET_COUNT(B,C)          \
    B   <- [C + rel(counts)]  ; \
    //

// SET_COUNT gets SZ rank in C, SZ free-count in D, returns nothing
#define SET_COUNT(C,D)          \
    D   -> [C + rel(counts)]  ; \
    //

// GET_NODE gets NP n in C, returns SZ shifted-word in B, clobbers C
#define GET_NODE(B,C)           \
    B   <- C >> BPERBITS      ; \
    C   <- C & (BPER - 1)     ; \
    C   <- C << BPERBITS      ; \
    B   <- [B + rel(nodes)]   ; \
    B   <- B >> C             ; \
    //

// SET_NODE gets NP n in C, SZ pre-shift-word in D, clobbers C and D
#define SET_NODE(C,D,T0,T1)                                                 \
    T0  <- C & (BPER - 1)       /* T0 is shift count in nodes        */   ; \
    T0  <- T0 << BPERBITS       /* T0 is shift count in bits         */   ; \
    D   <- D << T0              /* D  is now shifted over            */   ; \
    T1  <- (BPER - 1)           /* T1 is mask                        */   ; \
    T1  <- T1 << T0             /* T1 is shifted mask                */   ; \
    T0  <- C >> BPERBITS        /* T0 is index into node array       */   ; \
    C   <- [T0 + rel(nodes)]    /* C  is current word                */   ; \
    C   <- C &~ T1              /* C  is word with node masked out   */   ; \
    C   <- C | D                /* C  is word with new node included */   ; \
    C   -> [T0 + rel(nodes)]    /* C  gets written back to node      */   ; \
    //

// GET_LEAF gets NP n in C, returns SZ leafiness in B, clobbers C
#define GET_LEAF(B,C)           \
    GET_NODE(B,C)             ; \
    B   <- B &  1             ; \
    B   <- B == 0             ; \
    //

// GET_FULL gets NP n in C, returns SZ fullness in B, clobbers C
#define GET_FULL(B,C)           \
    GET_NODE(B,C)             ; \
    B   <- B &  2             ; \
    B   <- B == 2             ; \
    //

// GET_VALID gets NP n in C, returns SZ validity in B
#define GET_VALID(B,C,T0)       \
    T0  <- C                  ; \
    INDEX(B,C)                ; \
    PARENT(C,T0)              ; \
    GET_LEAF(T0,C)            ; \
    B   <- B &~ T0            ; \
    //

// TODO SET_LEAF
// SET_LEAF gets NP n in C, SZ truth in D, returns nothing, clobbers C
// We take a shortcut ; either we are setting the leaf true from false, and it
// is therefore not full, or we are setting it false from true, and fullness
// has no meaning. This allows us to avoid reading and rewriting the fullness
// value.
#define SET_LEAF(C,D,T0,T1)     \
    D   <- D & 1              ; \
    SET_NODE(C,D,T0,T1)       ; \
    //

// TODO SET_FULL
#define SET_FULL(C,D) \
    //
// TODO NODE2ADDR
// ADDR2NODE gets SZ addr in C, returns NP node in B
#define ADDR2NODE(B,C)          \
    call(ADDR2NODE_func)      ; \
    //

// C is key
ADDR2NODE_func:
    pushall(D,E,F,G,H)
    D   <- (RANKS - 2)  // D is next rank smaller than node under test
    E   <- POOL         // E is base being built
    F   <- C            // F is a scratch register
    G   <- TN           // G is the node being checked
    H   <- G            // H is another scratch
L_ADDR2NODE_looptop:
    GET_LEAF(B,H)
    jnzrel(B,L_ADDR2NODE_loopdone)
    RANK2WORDS(B,F)
    H   <- C - E        // H is (key - base)
    F   <- H < B        // if true, then left-link
    jnzrel(F,L_ADDR2NODE_left)
    H   <- G
    RLINK(G,H)          // n = RLINK(n)
    E   <- E + B        // base += RANK2WORDS(rank)
    goto(L_ADDR2NODE_loopbottom)
L_ADDR2NODE_left:
    H   <- G
    LLINK(G,H)          // n = LLINK(n)
    // fallthrough

L_ADDR2NODE_loopbottom:
    D   <- D - 1
    goto(L_ADDR2NODE_looptop)

L_ADDR2NODE_loopdone:
    B   <- C == E
    jnzrel(B,L_ADDR2NODE_done)
    call(abort)

L_ADDR2NODE_done:
    popall(D,E,F,G,H)
    ret

.global buddy_malloc
buddy_malloc:
    goto(buddy_alloc)

.global buddy_calloc
buddy_calloc:
    C   <- C * D
    push(C)
    call(buddy_alloc)
    C   <- B
    D   <- 0
    pop(E)
    call(memset)
    ret

.global buddy_free
buddy_free:
    // TODO
    ret

.global buddy_realloc
buddy_realloc:
    // TODO
    ret

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

buddy_splitnode:
    // TODO
    ret

buddy_autosplit:
    // TODO
    ret

// TODO check for clobbering
// buddy_alloc gets SZ size in C, returns address or 0 in B
buddy_alloc:
    pushall(D,E,F,G)
    SIZE2RANK(B,C)
    D   <- B < RANKS
    jzrel(D,L_buddy_alloc_error)
    D   <- B
    GET_COUNT(E,D)
    D   <- E == 0
    jnzrel(D,L_buddy_alloc_do_split)
    // here is the main body, where we have a nonzero count of the needed
    // rank. B is rank, D is scratch, E is scratch and currently count
    D   <- B
    IRANK(E,D)
    F   <- 1
    F   <- F << E       // F is loop bound
    D   <- F - 1        // D is first index to check
    F   <- F + D        // F is loop bound adjust for `first'
L_buddy_alloc_loop_top:
    NODE(E,D)           // E is NODE(D)
    GET_VALID(C,E,G)    // C is validity
    jzrel(C,L_buddy_alloc_loop_bottom)
    GET_LEAF(C,E)       // C is leafiness
    jzrel(C,L_buddy_alloc_loop_bottom)
    GET_FULL(C,E)       // C is fullness
    jnzrel(C,L_buddy_alloc_loop_bottom)
    SET_FULL(E,-1)
    GET_COUNT(C,B)
    C   <- C - 1
    SET_COUNT(E,C)
    C   <- E
    ADDR2NODE(B,C)
    goto(L_buddy_alloc_done)

L_buddy_alloc_loop_bottom:
    D   <- D + 1    // D is loop index
    goto(L_buddy_alloc_loop_top)

L_buddy_alloc_do_split:
    D   <- E
    call(buddy_autosplit)
    goto(L_buddy_alloc_done)

L_buddy_alloc_error:
    D   <- ENOMEM
    D   -> errno
    B   <- 0
L_buddy_alloc_done:
    popall(D,E,F,G)
    ret

<|endoftext|>


<commit_before>#include "stdafx.h"

static float CalcRadius(const Mesh* m)
{
	const Block& b = m->GetRawDatas();
	float maxSq = 0;
	for (auto& it : b.vertices) {
		float sq = XMVectorGetX(XMVector3LengthSq(XMLoadFloat3(&it.xyz)));
		maxSq = std::max(maxSq, sq);
	}
	return sqrt(maxSq);
}

App::App() : scale(1), lastX(-1), lastY(-1), sprite(nullptr), font(nullptr), meshTiny(nullptr), animationNumber(0)
{
	quat = XMQuaternionIdentity();
	ZeroMemory(mesh, sizeof(mesh));
}

App::~App()
{
}

void App::Init(const char* fileName)
{
	Destroy();

	debugRenderer.Init();

	g_type = "mesh";

	sprite = new SpriteBatch(deviceMan11.GetContext());
	font = new SpriteFont(deviceMan11.GetDevice(), L"resource\\font.spritefont");

	meshTiny = new MeshX("C:\\Program Files (x86)\\Microsoft DirectX SDK (August 2009)\\Samples\\Media\\Tiny\\tiny.x");

	if (fileName) {
		const char* ext = strrchr(fileName, '.');
		if (ext && !_stricmp(ext, ".bvh")) {
			mesh[0] = new Bvh(fileName);
		} else {
			mesh[0] = new MeshX(fileName);
		}
	} else {
		mesh[0] = new Bvh("D:\\github\\aachan.bvh");
	//	mesh[1] = new Bvh("D:\\github\\kashiyuka.bvh");
	//	mesh[2] = new Bvh("D:\\github\\nocchi.bvh");
	}

	float radius = CalcRadius(mesh[0]);
	scale = 1 / std::max(0.00001f, radius);

	matrixMan.Set(MatrixMan::PROJ, XMMatrixPerspectiveFovLH(45 * XM_PI / 180, (float)SCR_W / SCR_H, 0.1f, 1000.0f));

	dynamic_cast<Bvh*>(mesh[0])->FixBones("Chest");
	dynamic_cast<Bvh*>(mesh[0])->FixBones("Chest2");
	dynamic_cast<Bvh*>(mesh[0])->FixBones("Chest3");
	dynamic_cast<Bvh*>(mesh[0])->FixBones("Chest4");
	dynamic_cast<Bvh*>(mesh[0])->LinkTo("RightHip", "Chest");
	dynamic_cast<Bvh*>(mesh[0])->LinkTo("LeftHip", "Chest");
	meshTiny->ApplyXLocalAxisToBvh(dynamic_cast<Bvh*>(mesh[0]));
}

void App::MouseWheel(float delta)
{
	if (delta > 0) {
		scale *= 1.1f;
	}
	if (delta < 0) {
		scale /= 1.1f;
	}
}

void App::LButtonDown(float x, float y)
{
	lastX = x;
	lastY = y;
}

void App::LButtonUp(float x, float y)
{
	MouseMove(x, y);
	lastX = lastY = -1;
}

void App::MouseMove(float x, float y)
{
	if (lastX < 0 || lastY < 0) {
		return;
	}
	float dx = x - lastX;
	float dy = - (y - lastY);

	lastX = x;
	lastY = y;

	XMVECTOR axis = XMVectorSet(-dy, dx, 0, 0);
	float len = XMVectorGetX(XMVector2Length(axis));
	if (!len) {
		return;
	}

	XMVECTOR q = XMQuaternionRotationAxis(axis, len * -2 * XM_PI);
	quat = XMQuaternionMultiply(quat, q);
}

inline XMFLOAT2 GetScreenPos(const XMMATRIX& mLocal)
{
	XMFLOAT4X4 mViewport;
	XMMATRIX mW, mV, mP;
	matrixMan.Get(MatrixMan::WORLD, mW);
	matrixMan.Get(MatrixMan::VIEW, mV);
	matrixMan.Get(MatrixMan::PROJ, mP);
	XMStoreFloat4x4(&mViewport, XMMatrixIdentity());
	mViewport._11 = SCR_W / 2;
	mViewport._22 = -SCR_H / 2;
	mViewport._41 = SCR_W / 2;
	mViewport._42 = SCR_H / 2;

	XMMATRIX m = mLocal * mW * mV * mP * XMLoadFloat4x4(&mViewport);

	XMFLOAT2 p;
	p.x = XMVectorGetX(m.r[3]) / XMVectorGetW(m.r[3]);
	p.y = XMVectorGetY(m.r[3]) / XMVectorGetW(m.r[3]);
	return p;
}

void App::DrawBoneNames(Bvh* bvh)
{
	const std::vector<BvhFrame>& frames = bvh->GetFrames();
	for (auto& it : frames) {
		if (it.childId < 0) {
			continue;
		}
		XMFLOAT2 pos = GetScreenPos(XMLoadFloat4x4(&it.result));

		WCHAR wname[MAX_PATH];
		MultiByteToWideChar(CP_ACP, 0, it.name, -1, wname, dimof(wname));

		XMVECTOR size = font->MeasureString(wname);
		pos.x -= XMVectorGetX(size) / 2;
		pos.y -= XMVectorGetY(size) / 2;
		XMFLOAT2 origin = {0, 0};
		font->DrawString(sprite, wname, pos, Colors::Black, 0, origin, 0.7f);
		pos.x += 1.0f;
		pos.y += 1.0f;
		font->DrawString(sprite, wname, pos, Colors::White, 0, origin, 0.7f);
	}
}

void App::DrawBoneNames(MeshX* meshX)
{
	const std::vector<Frame>& frames = meshX->GetFrames();
	for (auto& it : frames) {
		XMFLOAT2 pos = GetScreenPos(XMLoadFloat4x4(&it.result));

		WCHAR wname[MAX_PATH];
		MultiByteToWideChar(CP_ACP, 0, it.name, -1, wname, dimof(wname));
		if (wname[0] == '\0') {
			wcscpy(wname, L"[NO NAME]");
		}

		XMVECTOR size = font->MeasureString(wname);
		pos.x -= XMVectorGetX(size) / 2;
		pos.y -= XMVectorGetY(size) / 2;
		XMFLOAT2 origin = {0, 0};
		font->DrawString(sprite, wname, pos, Colors::Black, 0, origin, 0.7f);
		pos.x += 1.0f;
		pos.y += 1.0f;
		font->DrawString(sprite, wname, pos, Colors::White, 0, origin, 0.7f);
	}
}

void App::Update()
{
	if (GetKeyState('P') & 0x80) {
		g_type = "pivot";
	}
	if (GetKeyState('M') & 0x80) {
		g_type = "mesh";
	}
	if (GetKeyState('B') & 0x80) {
		g_type = "bone";
	}
	for (auto& i : {'0', '1', '2', '3', '4'}) {
		if (GetKeyState(i) & 0x80) {
			animationNumber = i - '0';
		}
	}
}

void App::Draw()
{
	LARGE_INTEGER t, f;
	QueryPerformanceCounter(&t);
	QueryPerformanceFrequency(&f);
	double time = ((double)t.QuadPart / f.QuadPart);
//	float time = 0;

//	XMMATRIX mRot = XMMatrixRotationQuaternion(XMQuaternionRotationAxis(XMVectorSet(1, 0, 0, 0), time / 2 * XM_PI));
	XMMATRIX mRot = XMMatrixRotationQuaternion(quat);
	XMMATRIX mScale = XMMatrixScaling(scale, scale, scale);

	matrixMan.Set(MatrixMan::WORLD, mScale * mRot);

	float dist = 3;
//	float rot = time / 5 * XM_PI;
	float rot = XM_PI;
	matrixMan.Set(MatrixMan::VIEW, XMMatrixLookAtLH(XMVectorSet(sin(rot) * dist, 0, cos(rot) * dist, 1), XMVectorSet(0, 0, 0, 0), XMVectorSet(0, 1, 0, 0)));

    sprite->Begin();

	for (auto& it : mesh) {
		if (it && meshTiny) {
			it->Draw(0, time);

			Bvh* bvh = dynamic_cast<Bvh*>(it);

			if (bvh) {
				meshTiny->DrawBvh(bvh, time);
			//	meshTiny->Draw(animationNumber, time);
				DrawBoneNames(bvh);
			}
		}
	}

	MeshX* x = dynamic_cast<MeshX*>(meshTiny);
	if (x) {
		DrawBoneNames(x);
	}

	sprite->End();
}

void App::Destroy()
{
	SAFE_DELETE(mesh[0]);
	SAFE_DELETE(mesh[1]);
	SAFE_DELETE(mesh[2]);
	SAFE_DELETE(meshTiny);
	SAFE_DELETE(font);
	SAFE_DELETE(sprite);

	debugRenderer.Destroy();
}

std::string g_type;
<commit_msg>set bvh joint hierarchy like tiny.x<commit_after>#include "stdafx.h"

static float CalcRadius(const Mesh* m)
{
	const Block& b = m->GetRawDatas();
	float maxSq = 0;
	for (auto& it : b.vertices) {
		float sq = XMVectorGetX(XMVector3LengthSq(XMLoadFloat3(&it.xyz)));
		maxSq = std::max(maxSq, sq);
	}
	return sqrt(maxSq);
}

App::App() : scale(1), lastX(-1), lastY(-1), sprite(nullptr), font(nullptr), meshTiny(nullptr), animationNumber(0)
{
	quat = XMQuaternionIdentity();
	ZeroMemory(mesh, sizeof(mesh));
}

App::~App()
{
}

void App::Init(const char* fileName)
{
	Destroy();

	debugRenderer.Init();

	g_type = "mesh";

	sprite = new SpriteBatch(deviceMan11.GetContext());
	font = new SpriteFont(deviceMan11.GetDevice(), L"resource\\font.spritefont");

	meshTiny = new MeshX("C:\\Program Files (x86)\\Microsoft DirectX SDK (August 2009)\\Samples\\Media\\Tiny\\tiny.x");

	if (fileName) {
		const char* ext = strrchr(fileName, '.');
		if (ext && !_stricmp(ext, ".bvh")) {
			mesh[0] = new Bvh(fileName);
		} else {
			mesh[0] = new MeshX(fileName);
		}
	} else {
		mesh[0] = new Bvh("D:\\github\\aachan.bvh");
	//	mesh[1] = new Bvh("D:\\github\\kashiyuka.bvh");
	//	mesh[2] = new Bvh("D:\\github\\nocchi.bvh");
	}

	float radius = CalcRadius(mesh[0]);
	scale = 1 / std::max(0.00001f, radius);

	matrixMan.Set(MatrixMan::PROJ, XMMatrixPerspectiveFovLH(45 * XM_PI / 180, (float)SCR_W / SCR_H, 0.1f, 1000.0f));

	dynamic_cast<Bvh*>(mesh[0])->FixBones("Chest");
	dynamic_cast<Bvh*>(mesh[0])->LinkTo("RightHip", "Chest");
	dynamic_cast<Bvh*>(mesh[0])->LinkTo("LeftHip", "Chest");
	dynamic_cast<Bvh*>(mesh[0])->FixBones("Neck");
	dynamic_cast<Bvh*>(mesh[0])->LinkTo("RightCollar", "Neck");
	dynamic_cast<Bvh*>(mesh[0])->LinkTo("LeftCollar", "Neck");
	meshTiny->ApplyXLocalAxisToBvh(dynamic_cast<Bvh*>(mesh[0]));
}

void App::MouseWheel(float delta)
{
	if (delta > 0) {
		scale *= 1.1f;
	}
	if (delta < 0) {
		scale /= 1.1f;
	}
}

void App::LButtonDown(float x, float y)
{
	lastX = x;
	lastY = y;
}

void App::LButtonUp(float x, float y)
{
	MouseMove(x, y);
	lastX = lastY = -1;
}

void App::MouseMove(float x, float y)
{
	if (lastX < 0 || lastY < 0) {
		return;
	}
	float dx = x - lastX;
	float dy = - (y - lastY);

	lastX = x;
	lastY = y;

	XMVECTOR axis = XMVectorSet(-dy, dx, 0, 0);
	float len = XMVectorGetX(XMVector2Length(axis));
	if (!len) {
		return;
	}

	XMVECTOR q = XMQuaternionRotationAxis(axis, len * -2 * XM_PI);
	quat = XMQuaternionMultiply(quat, q);
}

inline XMFLOAT2 GetScreenPos(const XMMATRIX& mLocal)
{
	XMFLOAT4X4 mViewport;
	XMMATRIX mW, mV, mP;
	matrixMan.Get(MatrixMan::WORLD, mW);
	matrixMan.Get(MatrixMan::VIEW, mV);
	matrixMan.Get(MatrixMan::PROJ, mP);
	XMStoreFloat4x4(&mViewport, XMMatrixIdentity());
	mViewport._11 = SCR_W / 2;
	mViewport._22 = -SCR_H / 2;
	mViewport._41 = SCR_W / 2;
	mViewport._42 = SCR_H / 2;

	XMMATRIX m = mLocal * mW * mV * mP * XMLoadFloat4x4(&mViewport);

	XMFLOAT2 p;
	p.x = XMVectorGetX(m.r[3]) / XMVectorGetW(m.r[3]);
	p.y = XMVectorGetY(m.r[3]) / XMVectorGetW(m.r[3]);
	return p;
}

void App::DrawBoneNames(Bvh* bvh)
{
	const std::vector<BvhFrame>& frames = bvh->GetFrames();
	for (auto& it : frames) {
		if (it.childId < 0) {
			continue;
		}
		XMFLOAT2 pos = GetScreenPos(XMLoadFloat4x4(&it.result));

		WCHAR wname[MAX_PATH];
		MultiByteToWideChar(CP_ACP, 0, it.name, -1, wname, dimof(wname));

		XMVECTOR size = font->MeasureString(wname);
		pos.x -= XMVectorGetX(size) / 2;
		pos.y -= XMVectorGetY(size) / 2;
		XMFLOAT2 origin = {0, 0};
		font->DrawString(sprite, wname, pos, Colors::Black, 0, origin, 0.7f);
		pos.x += 1.0f;
		pos.y += 1.0f;
		font->DrawString(sprite, wname, pos, Colors::White, 0, origin, 0.7f);
	}
}

void App::DrawBoneNames(MeshX* meshX)
{
	const std::vector<Frame>& frames = meshX->GetFrames();
	for (auto& it : frames) {
		XMFLOAT2 pos = GetScreenPos(XMLoadFloat4x4(&it.result));

		WCHAR wname[MAX_PATH];
		MultiByteToWideChar(CP_ACP, 0, it.name, -1, wname, dimof(wname));
		if (wname[0] == '\0') {
			wcscpy(wname, L"[NO NAME]");
		}

		XMVECTOR size = font->MeasureString(wname);
		pos.x -= XMVectorGetX(size) / 2;
		pos.y -= XMVectorGetY(size) / 2;
		XMFLOAT2 origin = {0, 0};
		font->DrawString(sprite, wname, pos, Colors::Black, 0, origin, 0.7f);
		pos.x += 1.0f;
		pos.y += 1.0f;
		font->DrawString(sprite, wname, pos, Colors::White, 0, origin, 0.7f);
	}
}

void App::Update()
{
	if (GetKeyState('P') & 0x80) {
		g_type = "pivot";
	}
	if (GetKeyState('M') & 0x80) {
		g_type = "mesh";
	}
	if (GetKeyState('B') & 0x80) {
		g_type = "bone";
	}
	for (auto& i : {'0', '1', '2', '3', '4'}) {
		if (GetKeyState(i) & 0x80) {
			animationNumber = i - '0';
		}
	}
}

void App::Draw()
{
	LARGE_INTEGER t, f;
	QueryPerformanceCounter(&t);
	QueryPerformanceFrequency(&f);
	double time = ((double)t.QuadPart / f.QuadPart);
//	float time = 0;

//	XMMATRIX mRot = XMMatrixRotationQuaternion(XMQuaternionRotationAxis(XMVectorSet(1, 0, 0, 0), time / 2 * XM_PI));
	XMMATRIX mRot = XMMatrixRotationQuaternion(quat);
	XMMATRIX mScale = XMMatrixScaling(scale, scale, scale);

	matrixMan.Set(MatrixMan::WORLD, mScale * mRot);

	float dist = 3;
//	float rot = time / 5 * XM_PI;
	float rot = XM_PI;
	matrixMan.Set(MatrixMan::VIEW, XMMatrixLookAtLH(XMVectorSet(sin(rot) * dist, 0, cos(rot) * dist, 1), XMVectorSet(0, 0, 0, 0), XMVectorSet(0, 1, 0, 0)));

    sprite->Begin();

	for (auto& it : mesh) {
		if (it && meshTiny) {
			it->Draw(0, time);

			Bvh* bvh = dynamic_cast<Bvh*>(it);

			if (bvh) {
				meshTiny->DrawBvh(bvh, time);
			//	meshTiny->Draw(animationNumber, time);
				DrawBoneNames(bvh);
			}
		}
	}

	MeshX* x = dynamic_cast<MeshX*>(meshTiny);
	if (x) {
		DrawBoneNames(x);
	}

	sprite->End();
}

void App::Destroy()
{
	SAFE_DELETE(mesh[0]);
	SAFE_DELETE(mesh[1]);
	SAFE_DELETE(mesh[2]);
	SAFE_DELETE(meshTiny);
	SAFE_DELETE(font);
	SAFE_DELETE(sprite);

	debugRenderer.Destroy();
}

std::string g_type;
<|endoftext|>


<commit_before>// @(#)root/graf:$Name:  $:$Id: TFrame.cxx,v 1.5 2002/05/18 08:21:59 brun Exp $
// Author: Rene Brun   31/10/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "TROOT.h"
#include "TVirtualPad.h"
#include "TFrame.h"

ClassImp(TFrame)

//______________________________________________________________________________
//
// a TFrame is a TWbox for drawing histogram frames.
//

//______________________________________________________________________________
TFrame::TFrame(): TWbox()
{
//*-*-*-*-*-*-*-*-*-*-*frame default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ========================

}

//______________________________________________________________________________
TFrame::TFrame(Double_t x1, Double_t y1,Double_t x2, Double_t  y2)
       :TWbox(x1,y1,x2,y2)
{
//*-*-*-*-*-*-*-*-*-*-*frame normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =======================
}

//______________________________________________________________________________
TFrame::TFrame(const TFrame &frame) : TWbox(frame)
{
   ((TFrame&)frame).Copy(*this);
}

//______________________________________________________________________________
TFrame::~TFrame()
{
//*-*-*-*-*-*-*-*-*-*-*wbox default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =======================

}

//______________________________________________________________________________
void TFrame::Copy(TObject &frame) const
{
//*-*-*-*-*-*-*-*-*-*-*Copy this frame to frame*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ======================
   TWbox::Copy(frame);
}

//______________________________________________________________________________
void TFrame::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this wbox with its current attributes*-*-*-*-*-*-*
//*-*                  ==========================================

   AppendPad(option);

}

//______________________________________________________________________________
void TFrame::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-*                  =========================================
//  This member function is called when a TFrame object is clicked.
//

   if (!gPad->IsEditable()) return;

   TWbox::ExecuteEvent(event, px, py);

   if (event != kButton1Up) return;
// update pad margins
   Double_t xmin = gPad->GetUxmin();
   Double_t xmax = gPad->GetUxmax();
   Double_t ymin = gPad->GetUymin();
   Double_t ymax = gPad->GetUymax();
   Double_t dx   = xmax-xmin;
   Double_t dy   = ymax-ymin;
   gPad->SetLeftMargin((fX1-gPad->GetX1())/(gPad->GetX2()-gPad->GetX1()));
   gPad->SetRightMargin((gPad->GetX2()-fX2)/(gPad->GetX2()-gPad->GetX1()));
   gPad->SetBottomMargin((fY1-gPad->GetY1())/(gPad->GetY2()-gPad->GetY1()));
   gPad->SetTopMargin((gPad->GetY2()-fY2)/(gPad->GetY2()-gPad->GetY1()));
   Double_t dxr  = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
   Double_t dyr  = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());

   // Range() could change the size of the pad pixmap and therefore should
   // be called before the other paint routines
   gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
                      ymin - dyr*gPad->GetBottomMargin(),
                      xmax + dxr*gPad->GetRightMargin(),
                      ymax + dyr*gPad->GetTopMargin());
   gPad->RangeAxis(xmin, ymin, xmax, ymax);
   fX1 = xmin;
   fY1 = ymin;
   fX2 = xmax;
   fY2 = ymax;
}

//______________________________________________________________________________
void TFrame::Paint(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Paint this wbox with its current attributes*-*-*-*-*-*-*
//*-*                  ===========================================

   TWbox::Paint(option);
   gPad->PaintLine(fX1,fY1,fX2,fY1);
   gPad->PaintLine(fX2,fY1,fX2,fY2);
   gPad->PaintLine(fX2,fY2,fX1,fY2);
   gPad->PaintLine(fX1,fY2,fX1,fY1);
}

//______________________________________________________________________________
void TFrame::Pop()
{
   // Do not pop frame's, if allowed they would cover the picture they frame.
}

//______________________________________________________________________________
void TFrame::SavePrimitive(ofstream &, Option_t *)
{
    // Save primitive as a C++ statement(s) on output stream out

}
<commit_msg>In TFrame::Paint use Tpad::PaintBox instead of 4 calls to PaintLine. This improves the quality of the frame in case of large line widths<commit_after>// @(#)root/graf:$Name:  $:$Id: TFrame.cxx,v 1.6 2002/10/31 07:27:35 brun Exp $
// Author: Rene Brun   31/10/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "TROOT.h"
#include "TVirtualPad.h"
#include "TFrame.h"

ClassImp(TFrame)

//______________________________________________________________________________
//
// a TFrame is a TWbox for drawing histogram frames.
//

//______________________________________________________________________________
TFrame::TFrame(): TWbox()
{
//*-*-*-*-*-*-*-*-*-*-*frame default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ========================

}

//______________________________________________________________________________
TFrame::TFrame(Double_t x1, Double_t y1,Double_t x2, Double_t  y2)
       :TWbox(x1,y1,x2,y2)
{
//*-*-*-*-*-*-*-*-*-*-*frame normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =======================
}

//______________________________________________________________________________
TFrame::TFrame(const TFrame &frame) : TWbox(frame)
{
   ((TFrame&)frame).Copy(*this);
}

//______________________________________________________________________________
TFrame::~TFrame()
{
//*-*-*-*-*-*-*-*-*-*-*wbox default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =======================

}

//______________________________________________________________________________
void TFrame::Copy(TObject &frame) const
{
//*-*-*-*-*-*-*-*-*-*-*Copy this frame to frame*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ======================
   TWbox::Copy(frame);
}

//______________________________________________________________________________
void TFrame::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this wbox with its current attributes*-*-*-*-*-*-*
//*-*                  ==========================================

   AppendPad(option);

}

//______________________________________________________________________________
void TFrame::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-*                  =========================================
//  This member function is called when a TFrame object is clicked.
//

   if (!gPad->IsEditable()) return;

   TWbox::ExecuteEvent(event, px, py);

   if (event != kButton1Up) return;
// update pad margins
   Double_t xmin = gPad->GetUxmin();
   Double_t xmax = gPad->GetUxmax();
   Double_t ymin = gPad->GetUymin();
   Double_t ymax = gPad->GetUymax();
   Double_t dx   = xmax-xmin;
   Double_t dy   = ymax-ymin;
   gPad->SetLeftMargin((fX1-gPad->GetX1())/(gPad->GetX2()-gPad->GetX1()));
   gPad->SetRightMargin((gPad->GetX2()-fX2)/(gPad->GetX2()-gPad->GetX1()));
   gPad->SetBottomMargin((fY1-gPad->GetY1())/(gPad->GetY2()-gPad->GetY1()));
   gPad->SetTopMargin((gPad->GetY2()-fY2)/(gPad->GetY2()-gPad->GetY1()));
   Double_t dxr  = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
   Double_t dyr  = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());

   // Range() could change the size of the pad pixmap and therefore should
   // be called before the other paint routines
   gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
                      ymin - dyr*gPad->GetBottomMargin(),
                      xmax + dxr*gPad->GetRightMargin(),
                      ymax + dyr*gPad->GetTopMargin());
   gPad->RangeAxis(xmin, ymin, xmax, ymax);
   fX1 = xmin;
   fY1 = ymin;
   fX2 = xmax;
   fY2 = ymax;
}

//______________________________________________________________________________
void TFrame::Paint(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Paint this wbox with its current attributes*-*-*-*-*-*-*
//*-*                  ===========================================

   TWbox::Paint(option);

   Int_t style = gVirtualX->GetFillStyle();
   gVirtualX->SetFillStyle(0);
   gPad->PaintBox(fX1,fY1,fX2,fY2);
   gVirtualX->SetFillStyle(style);
}

//______________________________________________________________________________
void TFrame::Pop()
{
   // Do not pop frame's, if allowed they would cover the picture they frame.
}

//______________________________________________________________________________
void TFrame::SavePrimitive(ofstream &, Option_t *)
{
    // Save primitive as a C++ statement(s) on output stream out

}
<|endoftext|>


<commit_before>//Tests for the Zmqio Module

#include "include/factory_zmq.h"
#include "include/factory/zmq_interface.h"

#include <iostream>

int main()
{

  //Set up the underlying variables
  Zmqio *zmqo;
  Zmqio *zmqi;
  ZmqComponentFactory zmq_factory;

  //Set up the ZMQ Clients
  zmqo = zmq_factory.get_zmq_outbound_interface("tcp://localhost:5555");
  zmqi = zmq_factory.get_zmq_inbound_interface("tcp://*:5555");

  //Send a Message
  std::string msg = "Test";
  zmqo->send(msg);
  bool keep_going = true;

  while (keep_going) {

    //Convert the OMQ message into a string to be passed on the event
    std::string req_string = zmqi->recv();
    std::cout << req_string << std::endl;
    assert ( req_string == "Test" );
    std::string resp = "success";
    //  Send reply back to client
    zmqi->send(resp);

    keep_going = false;

  }

  std::string response = zmqo->recv();
  std::cout << response << std::endl;
  assert ( response = "success" );

  //Cleanup
  delete zmqi;
  delete zmqo;

  return 0;

}
<commit_msg>Test Scripts fixes<commit_after>//Tests for the Zmqio Module

#include "include/factory_zmq.h"
#include "include/factory/zmq_interface.h"

#include <iostream>

int main()
{

  //Set up the underlying variables
  Zmqio *zmqo;
  Zmqio *zmqi;
  ZmqComponentFactory zmq_factory;

  //Set up the ZMQ Clients
  zmqo = zmq_factory.get_zmq_outbound_interface("tcp://localhost:5555");
  zmqi = zmq_factory.get_zmq_inbound_interface("tcp://*:5555");

  //Send a Message
  std::string msg = "Test";
  zmqo->send(msg);
  bool keep_going = true;

  while (keep_going) {

    //Convert the OMQ message into a string to be passed on the event
    std::string req_string = zmqi->recv();
    std::cout << req_string << std::endl;
    assert ( req_string == "Test" );
    std::string resp = "success";
    //  Send reply back to client
    zmqi->send(resp);

    keep_going = false;

  }

  std::string response = zmqo->recv();
  std::cout << response << std::endl;
  assert ( response == "success" );

  //Cleanup
  delete zmqi;
  delete zmqo;

  return 0;

}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RLP.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "RLP.h"
using namespace std;
using namespace dev;

bytes dev::RLPNull = rlp("");
bytes dev::RLPEmptyList = rlpList();

RLP::RLP(bytesConstRef _d, Strictness _s):
	m_data(_d)
{
	if ((_s & FailIfTooBig) && actualSize() < _d.size())
	{
		if (_s & ThrowOnFail)
			BOOST_THROW_EXCEPTION(OversizeRLP());
		else
			m_data.reset();
	}
	if ((_s & FailIfTooSmall) && actualSize() > _d.size())
	{
		if (_s & ThrowOnFail)
			BOOST_THROW_EXCEPTION(UndersizeRLP());
		else
			m_data.reset();
	}
}

RLP::iterator& RLP::iterator::operator++()
{
	if (m_remaining)
	{
		m_lastItem.retarget(m_lastItem.next().data(), m_remaining);
		m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem, ThrowOnFail | FailIfTooSmall).actualSize());
		m_remaining -= std::min<unsigned>(m_remaining, m_lastItem.size());
	}
	else
		m_lastItem.retarget(m_lastItem.next().data(), 0);
	return *this;
}

RLP::iterator::iterator(RLP const& _parent, bool _begin)
{
	if (_begin && _parent.isList())
	{
		auto pl = _parent.payload();
		m_lastItem = pl.cropped(0, RLP(pl, ThrowOnFail | FailIfTooSmall).actualSize());
		m_remaining = pl.size() - m_lastItem.size();
	}
	else
	{
		m_lastItem = _parent.data().cropped(_parent.data().size());
		m_remaining = 0;
	}
}

RLP RLP::operator[](unsigned _i) const
{
	if (_i < m_lastIndex)
	{
		m_lastEnd = RLP(payload(), ThrowOnFail | FailIfTooSmall).actualSize();
		m_lastItem = payload().cropped(0, m_lastEnd);
		m_lastIndex = 0;
	}
	for (; m_lastIndex < _i && m_lastItem.size(); ++m_lastIndex)
	{
		m_lastItem = payload().cropped(m_lastEnd);
		m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem, ThrowOnFail | FailIfTooSmall).actualSize());
		m_lastEnd += m_lastItem.size();
	}
	return RLP(m_lastItem, ThrowOnFail | FailIfTooSmall);
}

RLPs RLP::toList() const
{
	RLPs ret;
	if (!isList())
		return ret;
	for (auto const& i: *this)
		ret.push_back(i);
	return ret;
}

unsigned RLP::actualSize() const
{
	if (isNull())
		return 0;
	if (isSingleByte())
		return 1;
	if (isData() || isList())
		return payloadOffset() + length();
	return 0;
}

void RLP::requireGood() const
{
	if (isNull())
		BOOST_THROW_EXCEPTION(BadRLP());
	byte n = m_data[0];
	if (n != c_rlpDataImmLenStart + 1)
		return;
	if (m_data.size() < 2)
		BOOST_THROW_EXCEPTION(BadRLP());
	if (m_data[1] < c_rlpDataImmLenStart)
		BOOST_THROW_EXCEPTION(BadRLP());
}

bool RLP::isInt() const
{
	if (isNull())
		return false;
	requireGood();
	byte n = m_data[0];
	if (n < c_rlpDataImmLenStart)
		return !!n;
	else if (n == c_rlpDataImmLenStart)
		return true;
	else if (n <= c_rlpDataIndLenZero)
	{
		if (m_data.size() <= 1)
			BOOST_THROW_EXCEPTION(BadRLP());
		return m_data[1] != 0;
	}
	else if (n < c_rlpListStart)
	{
		if ((int)m_data.size() <= 1 + n - c_rlpDataIndLenZero)
			BOOST_THROW_EXCEPTION(BadRLP());
		return m_data[1 + n - c_rlpDataIndLenZero] != 0;
	}
	else
		return false;
	return false;
}

unsigned RLP::length() const
{
	if (isNull())
		return 0;
	requireGood();
	unsigned ret = 0;
	byte n = m_data[0];
	if (n < c_rlpDataImmLenStart)
		return 1;
	else if (n <= c_rlpDataIndLenZero)
		return n - c_rlpDataImmLenStart;
	else if (n < c_rlpListStart)
	{
		if ((int)m_data.size() <= n - c_rlpDataIndLenZero)
			BOOST_THROW_EXCEPTION(BadRLP());
		if ((int)m_data.size() > 1)
			if (m_data[1] == 0)
				BOOST_THROW_EXCEPTION(BadRLP());
		for (int i = 0; i < n - c_rlpDataIndLenZero; ++i)
			ret = (ret << 8) | m_data[i + 1];
	}
	else if (n <= c_rlpListIndLenZero)
		return n - c_rlpListStart;
	else
	{
		if ((int)m_data.size() <= n - c_rlpListIndLenZero)
			BOOST_THROW_EXCEPTION(BadRLP());
		if ((int)m_data.size() > 1)
			if (m_data[1] == 0)
				BOOST_THROW_EXCEPTION(BadRLP());
		for (int i = 0; i < n - c_rlpListIndLenZero; ++i)
			ret = (ret << 8) | m_data[i + 1];
	}
	return ret;
}

unsigned RLP::items() const
{
	if (isList())
	{
		bytesConstRef d = payload().cropped(0, length());
		unsigned i = 0;
		for (; d.size(); ++i)
			d = d.cropped(RLP(d, ThrowOnFail | FailIfTooSmall).actualSize());
		return i;
	}
	return 0;
}

RLPStream& RLPStream::appendRaw(bytesConstRef _s, unsigned _itemCount)
{
	unsigned os = m_out.size();
	m_out.resize(os + _s.size());
	memcpy(m_out.data() + os, _s.data(), _s.size());
	noteAppended(_itemCount);
	return *this;
}

void RLPStream::noteAppended(unsigned _itemCount)
{
	if (!_itemCount)
		return;
//	cdebug << "noteAppended(" << _itemCount << ")";
	while (m_listStack.size())
	{
		if (m_listStack.back().first < _itemCount)
			BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large") << RequirementError((bigint)m_listStack.back().first, (bigint)_itemCount));
		m_listStack.back().first -= _itemCount;
		if (m_listStack.back().first)
			break;
		else
		{
			auto p = m_listStack.back().second;
			m_listStack.pop_back();
			unsigned s = m_out.size() - p;		// list size
			auto brs = bytesRequired(s);
			unsigned encodeSize = s < c_rlpListImmLenCount ? 1 : (1 + brs);
//			cdebug << "s: " << s << ", p: " << p << ", m_out.size(): " << m_out.size() << ", encodeSize: " << encodeSize << " (br: " << brs << ")";
			auto os = m_out.size();
			m_out.resize(os + encodeSize);
			memmove(m_out.data() + p + encodeSize, m_out.data() + p, os - p);
			if (s < c_rlpListImmLenCount)
				m_out[p] = (byte)(c_rlpListStart + s);
			else
			{
				m_out[p] = (byte)(c_rlpListIndLenZero + brs);
				byte* b = &(m_out[p + brs]);
				for (; s; s >>= 8)
					*(b--) = (byte)s;
			}
		}
		_itemCount = 1;	// for all following iterations, we've effectively appended a single item only since we completed a list.
	}
}

RLPStream& RLPStream::appendList(unsigned _items)
{
//	cdebug << "appendList(" << _items << ")";
	if (_items)
		m_listStack.push_back(std::make_pair(_items, m_out.size()));
	else
		appendList(bytes());
	return *this;
}

RLPStream& RLPStream::appendList(bytesConstRef _rlp)
{
	if (_rlp.size() < c_rlpListImmLenCount)
		m_out.push_back((byte)(_rlp.size() + c_rlpListStart));
	else
		pushCount(_rlp.size(), c_rlpListIndLenZero);
	appendRaw(_rlp, 1);
	return *this;
}

RLPStream& RLPStream::append(bytesConstRef _s, bool _compact)
{
	unsigned s = _s.size();
	byte const* d = _s.data();
	if (_compact)
		for (unsigned i = 0; i < _s.size() && !*d; ++i, --s, ++d) {}

	if (s == 1 && *d < c_rlpDataImmLenStart)
		m_out.push_back(*d);
	else
	{
		if (s < c_rlpDataImmLenCount)
			m_out.push_back((byte)(s + c_rlpDataImmLenStart));
		else
			pushCount(s, c_rlpDataIndLenZero);
		appendRaw(bytesConstRef(d, s), 0);
	}
	noteAppended();
	return *this;
}

RLPStream& RLPStream::append(bigint _i)
{
	if (!_i)
		m_out.push_back(c_rlpDataImmLenStart);
	else if (_i < c_rlpDataImmLenStart)
		m_out.push_back((byte)_i);
	else
	{
		unsigned br = bytesRequired(_i);
		if (br < c_rlpDataImmLenCount)
			m_out.push_back((byte)(br + c_rlpDataImmLenStart));
		else
		{
			auto brbr = bytesRequired(br);
			m_out.push_back((byte)(c_rlpDataIndLenZero + brbr));
			pushInt(br, brbr);
		}
		pushInt(_i, br);
	}
	noteAppended();
	return *this;
}

void RLPStream::pushCount(unsigned _count, byte _base)
{
	auto br = bytesRequired(_count);
	m_out.push_back((byte)(br + _base));	// max 8 bytes.
	pushInt(_count, br);
}

std::ostream& dev::operator<<(std::ostream& _out, RLP const& _d)
{
	if (_d.isNull())
		_out << "null";
	else if (_d.isInt())
		_out << std::showbase << std::hex << std::nouppercase << _d.toInt<bigint>(RLP::LaisezFaire) << dec;
	else if (_d.isData())
		_out << escaped(_d.toString(), false);
	else if (_d.isList())
	{
		_out << "[";
		int j = 0;
		for (auto i: _d)
			_out << (j++ ? ", " : " ") << i;
		_out << " ]";
	}

	return _out;
}
<commit_msg>Eliminate undefied behavior in RLPStream.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RLP.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "RLP.h"
using namespace std;
using namespace dev;

bytes dev::RLPNull = rlp("");
bytes dev::RLPEmptyList = rlpList();

RLP::RLP(bytesConstRef _d, Strictness _s):
	m_data(_d)
{
	if ((_s & FailIfTooBig) && actualSize() < _d.size())
	{
		if (_s & ThrowOnFail)
			BOOST_THROW_EXCEPTION(OversizeRLP());
		else
			m_data.reset();
	}
	if ((_s & FailIfTooSmall) && actualSize() > _d.size())
	{
		if (_s & ThrowOnFail)
			BOOST_THROW_EXCEPTION(UndersizeRLP());
		else
			m_data.reset();
	}
}

RLP::iterator& RLP::iterator::operator++()
{
	if (m_remaining)
	{
		m_lastItem.retarget(m_lastItem.next().data(), m_remaining);
		m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem, ThrowOnFail | FailIfTooSmall).actualSize());
		m_remaining -= std::min<unsigned>(m_remaining, m_lastItem.size());
	}
	else
		m_lastItem.retarget(m_lastItem.next().data(), 0);
	return *this;
}

RLP::iterator::iterator(RLP const& _parent, bool _begin)
{
	if (_begin && _parent.isList())
	{
		auto pl = _parent.payload();
		m_lastItem = pl.cropped(0, RLP(pl, ThrowOnFail | FailIfTooSmall).actualSize());
		m_remaining = pl.size() - m_lastItem.size();
	}
	else
	{
		m_lastItem = _parent.data().cropped(_parent.data().size());
		m_remaining = 0;
	}
}

RLP RLP::operator[](unsigned _i) const
{
	if (_i < m_lastIndex)
	{
		m_lastEnd = RLP(payload(), ThrowOnFail | FailIfTooSmall).actualSize();
		m_lastItem = payload().cropped(0, m_lastEnd);
		m_lastIndex = 0;
	}
	for (; m_lastIndex < _i && m_lastItem.size(); ++m_lastIndex)
	{
		m_lastItem = payload().cropped(m_lastEnd);
		m_lastItem = m_lastItem.cropped(0, RLP(m_lastItem, ThrowOnFail | FailIfTooSmall).actualSize());
		m_lastEnd += m_lastItem.size();
	}
	return RLP(m_lastItem, ThrowOnFail | FailIfTooSmall);
}

RLPs RLP::toList() const
{
	RLPs ret;
	if (!isList())
		return ret;
	for (auto const& i: *this)
		ret.push_back(i);
	return ret;
}

unsigned RLP::actualSize() const
{
	if (isNull())
		return 0;
	if (isSingleByte())
		return 1;
	if (isData() || isList())
		return payloadOffset() + length();
	return 0;
}

void RLP::requireGood() const
{
	if (isNull())
		BOOST_THROW_EXCEPTION(BadRLP());
	byte n = m_data[0];
	if (n != c_rlpDataImmLenStart + 1)
		return;
	if (m_data.size() < 2)
		BOOST_THROW_EXCEPTION(BadRLP());
	if (m_data[1] < c_rlpDataImmLenStart)
		BOOST_THROW_EXCEPTION(BadRLP());
}

bool RLP::isInt() const
{
	if (isNull())
		return false;
	requireGood();
	byte n = m_data[0];
	if (n < c_rlpDataImmLenStart)
		return !!n;
	else if (n == c_rlpDataImmLenStart)
		return true;
	else if (n <= c_rlpDataIndLenZero)
	{
		if (m_data.size() <= 1)
			BOOST_THROW_EXCEPTION(BadRLP());
		return m_data[1] != 0;
	}
	else if (n < c_rlpListStart)
	{
		if ((int)m_data.size() <= 1 + n - c_rlpDataIndLenZero)
			BOOST_THROW_EXCEPTION(BadRLP());
		return m_data[1 + n - c_rlpDataIndLenZero] != 0;
	}
	else
		return false;
	return false;
}

unsigned RLP::length() const
{
	if (isNull())
		return 0;
	requireGood();
	unsigned ret = 0;
	byte n = m_data[0];
	if (n < c_rlpDataImmLenStart)
		return 1;
	else if (n <= c_rlpDataIndLenZero)
		return n - c_rlpDataImmLenStart;
	else if (n < c_rlpListStart)
	{
		if ((int)m_data.size() <= n - c_rlpDataIndLenZero)
			BOOST_THROW_EXCEPTION(BadRLP());
		if ((int)m_data.size() > 1)
			if (m_data[1] == 0)
				BOOST_THROW_EXCEPTION(BadRLP());
		for (int i = 0; i < n - c_rlpDataIndLenZero; ++i)
			ret = (ret << 8) | m_data[i + 1];
	}
	else if (n <= c_rlpListIndLenZero)
		return n - c_rlpListStart;
	else
	{
		if ((int)m_data.size() <= n - c_rlpListIndLenZero)
			BOOST_THROW_EXCEPTION(BadRLP());
		if ((int)m_data.size() > 1)
			if (m_data[1] == 0)
				BOOST_THROW_EXCEPTION(BadRLP());
		for (int i = 0; i < n - c_rlpListIndLenZero; ++i)
			ret = (ret << 8) | m_data[i + 1];
	}
	return ret;
}

unsigned RLP::items() const
{
	if (isList())
	{
		bytesConstRef d = payload().cropped(0, length());
		unsigned i = 0;
		for (; d.size(); ++i)
			d = d.cropped(RLP(d, ThrowOnFail | FailIfTooSmall).actualSize());
		return i;
	}
	return 0;
}

RLPStream& RLPStream::appendRaw(bytesConstRef _s, unsigned _itemCount)
{
	m_out.insert(m_out.end(), _s.begin(), _s.end());
	noteAppended(_itemCount);
	return *this;
}

void RLPStream::noteAppended(unsigned _itemCount)
{
	if (!_itemCount)
		return;
//	cdebug << "noteAppended(" << _itemCount << ")";
	while (m_listStack.size())
	{
		if (m_listStack.back().first < _itemCount)
			BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large") << RequirementError((bigint)m_listStack.back().first, (bigint)_itemCount));
		m_listStack.back().first -= _itemCount;
		if (m_listStack.back().first)
			break;
		else
		{
			auto p = m_listStack.back().second;
			m_listStack.pop_back();
			unsigned s = m_out.size() - p;		// list size
			auto brs = bytesRequired(s);
			unsigned encodeSize = s < c_rlpListImmLenCount ? 1 : (1 + brs);
//			cdebug << "s: " << s << ", p: " << p << ", m_out.size(): " << m_out.size() << ", encodeSize: " << encodeSize << " (br: " << brs << ")";
			auto os = m_out.size();
			m_out.resize(os + encodeSize);
			memmove(m_out.data() + p + encodeSize, m_out.data() + p, os - p);
			if (s < c_rlpListImmLenCount)
				m_out[p] = (byte)(c_rlpListStart + s);
			else
			{
				m_out[p] = (byte)(c_rlpListIndLenZero + brs);
				byte* b = &(m_out[p + brs]);
				for (; s; s >>= 8)
					*(b--) = (byte)s;
			}
		}
		_itemCount = 1;	// for all following iterations, we've effectively appended a single item only since we completed a list.
	}
}

RLPStream& RLPStream::appendList(unsigned _items)
{
//	cdebug << "appendList(" << _items << ")";
	if (_items)
		m_listStack.push_back(std::make_pair(_items, m_out.size()));
	else
		appendList(bytes());
	return *this;
}

RLPStream& RLPStream::appendList(bytesConstRef _rlp)
{
	if (_rlp.size() < c_rlpListImmLenCount)
		m_out.push_back((byte)(_rlp.size() + c_rlpListStart));
	else
		pushCount(_rlp.size(), c_rlpListIndLenZero);
	appendRaw(_rlp, 1);
	return *this;
}

RLPStream& RLPStream::append(bytesConstRef _s, bool _compact)
{
	unsigned s = _s.size();
	byte const* d = _s.data();
	if (_compact)
		for (unsigned i = 0; i < _s.size() && !*d; ++i, --s, ++d) {}

	if (s == 1 && *d < c_rlpDataImmLenStart)
		m_out.push_back(*d);
	else
	{
		if (s < c_rlpDataImmLenCount)
			m_out.push_back((byte)(s + c_rlpDataImmLenStart));
		else
			pushCount(s, c_rlpDataIndLenZero);
		appendRaw(bytesConstRef(d, s), 0);
	}
	noteAppended();
	return *this;
}

RLPStream& RLPStream::append(bigint _i)
{
	if (!_i)
		m_out.push_back(c_rlpDataImmLenStart);
	else if (_i < c_rlpDataImmLenStart)
		m_out.push_back((byte)_i);
	else
	{
		unsigned br = bytesRequired(_i);
		if (br < c_rlpDataImmLenCount)
			m_out.push_back((byte)(br + c_rlpDataImmLenStart));
		else
		{
			auto brbr = bytesRequired(br);
			m_out.push_back((byte)(c_rlpDataIndLenZero + brbr));
			pushInt(br, brbr);
		}
		pushInt(_i, br);
	}
	noteAppended();
	return *this;
}

void RLPStream::pushCount(unsigned _count, byte _base)
{
	auto br = bytesRequired(_count);
	m_out.push_back((byte)(br + _base));	// max 8 bytes.
	pushInt(_count, br);
}

std::ostream& dev::operator<<(std::ostream& _out, RLP const& _d)
{
	if (_d.isNull())
		_out << "null";
	else if (_d.isInt())
		_out << std::showbase << std::hex << std::nouppercase << _d.toInt<bigint>(RLP::LaisezFaire) << dec;
	else if (_d.isData())
		_out << escaped(_d.toString(), false);
	else if (_d.isList())
	{
		_out << "[";
		int j = 0;
		for (auto i: _d)
			_out << (j++ ? ", " : " ") << i;
		_out << " ]";
	}

	return _out;
}
<|endoftext|>