<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/notification.hxx
 *
 *   DESCRIPTION
 *      definition of the pqxx::notification_receiver functor interface.
 *   pqxx::notification_receiver handles incoming notifications.
 *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead.
 *
 * Copyright (c) 2011, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#ifndef PQXX_H_NOTIFICATION
#define PQXX_H_NOTIFICATION

#include "pqxx/compiler-public.hxx"
#include "pqxx/compiler-internal-pre.hxx"

namespace pqxx
{
class connection_base;

/// "Observer" base class for notifications.
/** @addtogroup notification Notifications and Receivers
 *
 * To listen on a notification issued using the NOTIFY command, derive your own
 * class from notification_receiver and define its function-call operator to
 * perform whatever action you wish to take when the given notification arrives.
 * Then create an object of that class and pass it to your connection.  DO NOT
 * use raw SQL to listen for notifications, or your attempts to listen won't be
 * resumed when a connection fails--and you'll have no way to notice.
 *
 * Notifications never arrive inside a transaction, not even in a
 * nontransaction.  Therefore, you are free to open a transaction of your own
 * inside your receiver's function invocation operator.
 *
 * Notifications you are listening for may arrive anywhere within libpqxx code,
 * but be aware that @b PostgreSQL @b defers @b notifications @b occurring
 * @b inside @b transactions.  (This was done for excellent reasons; just think
 * about what happens if the transaction where you happen to handle an incoming
 * notification is later rolled back for other reasons).  So if you're keeping a
 * transaction open, don't expect any of your receivers on the same connection
 * to be notified.
 *
 * Multiple receivers on the same connection may listen on a notification of the
 * same name.  An incoming notification is processed by invoking all receivers
 * (zero or more) of the same name.
 */
class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver :
  public PGSTD::binary_function<const PGSTD::string &, int, void>
{
public:
  /// Register the receiver with a connection.
  /**
   * @param channel Name of the notification to listen for.
   */
  notification_receiver(connection_base &, const PGSTD::string &channel);
  virtual ~notification_receiver();

  /// The channel that this receiver listens on.
  const PGSTD::string &channel() const { return m_channel; }

  /// Overridable: action to invoke when notification arrives.
  /**
   * @param payload On PostgreSQL 9.0 or later, an optional string that may have
   * been passed to the NOTIFY command.
   * @param be_pid Process ID of the database backend process that served our
   * connection when the notification arrived.  The actual process ID behind the
   * connection may have changed by the time this method is called.
   */
  virtual void operator()(const PGSTD::string &payload, int backend_pid) =0;

protected:
  connection_base &conn() const throw () { return m_conn; }

private:
  // Not allowed.
  notification_receiver(const notification_receiver &);
  // Not allowed.
  notification_receiver &operator=(const notification_receiver &);

  connection_base &m_conn;
  PGSTD::string m_channel;
};
}

#include "pqxx/compiler-internal-pre.hxx"
#endif
<commit_msg>Missing include (not usually noticeable).<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/notification.hxx
 *
 *   DESCRIPTION
 *      definition of the pqxx::notification_receiver functor interface.
 *   pqxx::notification_receiver handles incoming notifications.
 *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead.
 *
 * Copyright (c) 2011, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#ifndef PQXX_H_NOTIFICATION
#define PQXX_H_NOTIFICATION

#include "pqxx/compiler-public.hxx"
#include "pqxx/compiler-internal-pre.hxx"

namespace pqxx
{
class connection_base;

/// "Observer" base class for notifications.
/** @addtogroup notification Notifications and Receivers
 *
 * To listen on a notification issued using the NOTIFY command, derive your own
 * class from notification_receiver and define its function-call operator to
 * perform whatever action you wish to take when the given notification arrives.
 * Then create an object of that class and pass it to your connection.  DO NOT
 * use raw SQL to listen for notifications, or your attempts to listen won't be
 * resumed when a connection fails--and you'll have no way to notice.
 *
 * Notifications never arrive inside a transaction, not even in a
 * nontransaction.  Therefore, you are free to open a transaction of your own
 * inside your receiver's function invocation operator.
 *
 * Notifications you are listening for may arrive anywhere within libpqxx code,
 * but be aware that @b PostgreSQL @b defers @b notifications @b occurring
 * @b inside @b transactions.  (This was done for excellent reasons; just think
 * about what happens if the transaction where you happen to handle an incoming
 * notification is later rolled back for other reasons).  So if you're keeping a
 * transaction open, don't expect any of your receivers on the same connection
 * to be notified.
 *
 * Multiple receivers on the same connection may listen on a notification of the
 * same name.  An incoming notification is processed by invoking all receivers
 * (zero or more) of the same name.
 */
class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver :
  public PGSTD::binary_function<const PGSTD::string &, int, void>
{
public:
  /// Register the receiver with a connection.
  /**
   * @param channel Name of the notification to listen for.
   */
  notification_receiver(connection_base &, const PGSTD::string &channel);
  virtual ~notification_receiver();

  /// The channel that this receiver listens on.
  const PGSTD::string &channel() const { return m_channel; }

  /// Overridable: action to invoke when notification arrives.
  /**
   * @param payload On PostgreSQL 9.0 or later, an optional string that may have
   * been passed to the NOTIFY command.
   * @param be_pid Process ID of the database backend process that served our
   * connection when the notification arrived.  The actual process ID behind the
   * connection may have changed by the time this method is called.
   */
  virtual void operator()(const PGSTD::string &payload, int backend_pid) =0;

protected:
  connection_base &conn() const throw () { return m_conn; }

private:
  // Not allowed.
  notification_receiver(const notification_receiver &);
  // Not allowed.
  notification_receiver &operator=(const notification_receiver &);

  connection_base &m_conn;
  PGSTD::string m_channel;
};
}

#include "pqxx/compiler-internal-pre.hxx"
#include "pqxx/compiler-internal-post.hxx"
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2005-2020 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.

#ifndef POINTERHOLDER_HH
#define POINTERHOLDER_HH

// This class is basically std::shared_ptr but predates that by
// several years.

// This class expects to be initialized with a dynamically allocated
// object pointer.  It keeps a reference count and deletes this once
// the reference count goes to zero.  PointerHolder objects are
// explicitly safe for use in STL containers.

// It is very important that a client who pulls the pointer out of
// this holder does not let the holder go out of scope until it is
// finished with the pointer.  It is also important that exactly one
// instance of this object ever gets initialized with a given pointer.
// Otherwise, the pointer will be deleted twice, and before that, some
// objects will be left with a pointer to a deleted object.  In other
// words, the only legitimate way for two PointerHolder objects to
// contain the same pointer is for one to be a copy of the other.
// Copy and assignment semantics are well-defined and essentially
// allow you to use PointerHolder as a means to get pass-by-reference
// semantics in a pass-by-value environment without having to worry
// about memory management details.

// Comparison (== and <) are defined and operate on the internally
// stored pointers, not on the data.  This makes it possible to store
// PointerHolder objects in sorted lists or to find them in STL
// containers just as one would be able to store pointers.  Comparing
// the underlying pointers provides a well-defined, if not
// particularly meaningful, ordering.

template <class T>
class PointerHolder
{
  private:
    class Data
    {
      public:
	Data(T* pointer, bool array) :
	    pointer(pointer),
	    array(array),
	    refcount(0)
	    {
	    }
	~Data()
	    {
		if (array)
		{
		    delete [] this->pointer;
		}
		else
		{
		    delete this->pointer;
		}
	    }
	T* pointer;
	bool array;
	int refcount;
      private:
	Data(Data const&);
	Data& operator=(Data const&);
    };

  public:
    PointerHolder(T* pointer = 0)
	{
	    this->init(new Data(pointer, false));
	}
    // Special constructor indicating to free memory with delete []
    // instead of delete
    PointerHolder(bool, T* pointer)
	{
	    this->init(new Data(pointer, true));
	}
    PointerHolder(PointerHolder const& rhs)
	{
	    this->copy(rhs);
	}
    PointerHolder& operator=(PointerHolder const& rhs)
	{
	    if (this != &rhs)
	    {
		this->destroy();
		this->copy(rhs);
	    }
	    return *this;
	}
    ~PointerHolder()
	{
	    this->destroy();
	}
    bool operator==(PointerHolder const& rhs) const
    {
	return this->data->pointer == rhs.data->pointer;
    }
    bool operator<(PointerHolder const& rhs) const
    {
	return this->data->pointer < rhs.data->pointer;
    }

    // NOTE: The pointer returned by getPointer turns into a pumpkin
    // when the last PointerHolder that contains it disappears.
    T* getPointer()
	{
	    return this->data->pointer;
	}
    T const* getPointer() const
	{
	    return this->data->pointer;
	}
    int getRefcount() const
	{
	    return this->data->refcount;
	}

    T const& operator*() const
    {
        return *this->data->pointer;
    }
    T& operator*()
    {
        return *this->data->pointer;
    }

    T const* operator->() const
    {
        return this->data->pointer;
    }
    T* operator->()
    {
        return this->data->pointer;
    }

  private:
    void init(Data* data)
	{
	    this->data = data;
	    {
		++this->data->refcount;
	    }
	}
    void copy(PointerHolder const& rhs)
	{
	    this->init(rhs.data);
	}
    void destroy()
	{
	    bool gone = false;
	    {
		if (--this->data->refcount == 0)
		{
		    gone = true;
		}
	    }
	    if (gone)
	    {
		delete this->data;
	    }
	}

    Data* data;
};

#endif // POINTERHOLDER_HH
<commit_msg>Remove extraneous set of braces<commit_after>// Copyright (c) 2005-2020 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.

#ifndef POINTERHOLDER_HH
#define POINTERHOLDER_HH

// This class is basically std::shared_ptr but predates that by
// several years.

// This class expects to be initialized with a dynamically allocated
// object pointer.  It keeps a reference count and deletes this once
// the reference count goes to zero.  PointerHolder objects are
// explicitly safe for use in STL containers.

// It is very important that a client who pulls the pointer out of
// this holder does not let the holder go out of scope until it is
// finished with the pointer.  It is also important that exactly one
// instance of this object ever gets initialized with a given pointer.
// Otherwise, the pointer will be deleted twice, and before that, some
// objects will be left with a pointer to a deleted object.  In other
// words, the only legitimate way for two PointerHolder objects to
// contain the same pointer is for one to be a copy of the other.
// Copy and assignment semantics are well-defined and essentially
// allow you to use PointerHolder as a means to get pass-by-reference
// semantics in a pass-by-value environment without having to worry
// about memory management details.

// Comparison (== and <) are defined and operate on the internally
// stored pointers, not on the data.  This makes it possible to store
// PointerHolder objects in sorted lists or to find them in STL
// containers just as one would be able to store pointers.  Comparing
// the underlying pointers provides a well-defined, if not
// particularly meaningful, ordering.

template <class T>
class PointerHolder
{
  private:
    class Data
    {
      public:
	Data(T* pointer, bool array) :
	    pointer(pointer),
	    array(array),
	    refcount(0)
	    {
	    }
	~Data()
	    {
		if (array)
		{
		    delete [] this->pointer;
		}
		else
		{
		    delete this->pointer;
		}
	    }
	T* pointer;
	bool array;
	int refcount;
      private:
	Data(Data const&);
	Data& operator=(Data const&);
    };

  public:
    PointerHolder(T* pointer = 0)
	{
	    this->init(new Data(pointer, false));
	}
    // Special constructor indicating to free memory with delete []
    // instead of delete
    PointerHolder(bool, T* pointer)
	{
	    this->init(new Data(pointer, true));
	}
    PointerHolder(PointerHolder const& rhs)
	{
	    this->copy(rhs);
	}
    PointerHolder& operator=(PointerHolder const& rhs)
	{
	    if (this != &rhs)
	    {
		this->destroy();
		this->copy(rhs);
	    }
	    return *this;
	}
    ~PointerHolder()
	{
	    this->destroy();
	}
    bool operator==(PointerHolder const& rhs) const
    {
	return this->data->pointer == rhs.data->pointer;
    }
    bool operator<(PointerHolder const& rhs) const
    {
	return this->data->pointer < rhs.data->pointer;
    }

    // NOTE: The pointer returned by getPointer turns into a pumpkin
    // when the last PointerHolder that contains it disappears.
    T* getPointer()
	{
	    return this->data->pointer;
	}
    T const* getPointer() const
	{
	    return this->data->pointer;
	}
    int getRefcount() const
	{
	    return this->data->refcount;
	}

    T const& operator*() const
    {
        return *this->data->pointer;
    }
    T& operator*()
    {
        return *this->data->pointer;
    }

    T const* operator->() const
    {
        return this->data->pointer;
    }
    T* operator->()
    {
        return this->data->pointer;
    }

  private:
    void init(Data* data)
	{
	    this->data = data;
            ++this->data->refcount;
	}
    void copy(PointerHolder const& rhs)
	{
	    this->init(rhs.data);
	}
    void destroy()
	{
	    bool gone = false;
	    {
		if (--this->data->refcount == 0)
		{
		    gone = true;
		}
	    }
	    if (gone)
	    {
		delete this->data;
	    }
	}

    Data* data;
};

#endif // POINTERHOLDER_HH
<|endoftext|>


<commit_before>#ifndef TELNETPP_TELNETPP_HPP_
#define TELNETPP_TELNETPP_HPP_

// routing_visitor pulls in all of the various routers, and thus all
// of the various token types.
#include "telnetpp/routing_visitor.hpp"

// For sending commands, it's necessary to know what the commands in the
// protocol are.
#include "telnetpp/protocol.hpp"

// With the addition of the session object, the client need then only
// include the specific required options in order to have a complete Telnet
// layer.
#include "telnetpp/session.hpp"

#endif
<commit_msg>Removed routing_visitor.hpp from telnetpp.hpp.<commit_after>#ifndef TELNETPP_TELNETPP_HPP_
#define TELNETPP_TELNETPP_HPP_

// For sending commands, it's necessary to know what the commands in the
// protocol are.
#include "telnetpp/protocol.hpp"

// With the addition of the session object, the client need then only
// include the specific required options in order to have a complete Telnet
// layer.
#include "telnetpp/session.hpp"

#endif
<|endoftext|>


<commit_before>// Copyright (C) 2016 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef TYPE_SAFE_BOOLEAN_HPP_INCLUDED
#define TYPE_SAFE_BOOLEAN_HPP_INCLUDED

#include <iosfwd>
#include <type_traits>
#include <utility>

#include <type_safe/detail/force_inline.hpp>

namespace type_safe
{
    class boolean;

    /// \exclude
    namespace detail
    {
        template <typename T>
        struct is_boolean : std::false_type
        {
        };

        template <>
        struct is_boolean<bool> : std::true_type
        {
        };

        template <>
        struct is_boolean<boolean> : std::true_type
        {
        };

        template <typename T>
        using enable_boolean = typename std::enable_if<is_boolean<T>::value>::type;
    } // namespace detail

    /// A type safe boolean class.
    ///
    /// It is a tiny, no overhead wrapper over `bool`.
    /// It can only be constructed from `bool` values
    /// and does not implictly convert to integral types.
    /// \module types
    class boolean
    {
    public:
        boolean() = delete;

        /// \effects Creates a boolean from the given `value`.
        /// \notes This function does not participate in overload resolution if `T` is not a boolean type.
        /// \param 1
        /// \exclude
        template <typename T, typename = detail::enable_boolean<T>>
        TYPE_SAFE_FORCE_INLINE constexpr boolean(T value) noexcept : value_(value)
        {
        }

        /// \effects Assigns the given `value` to the boolean.
        /// \notes This function does not participate in overload resolution if `T` is not a boolean type.
        /// \param 1
        /// \exclude
        template <typename T, typename = detail::enable_boolean<T>>
        TYPE_SAFE_FORCE_INLINE boolean& operator=(T value) noexcept
        {
            value_ = value;
            return *this;
        }

        /// \returns The stored `bool` value.
        TYPE_SAFE_FORCE_INLINE explicit constexpr operator bool() const noexcept
        {
            return value_;
        }

        /// \returns The same as `!static_cast<bool>(*this)`.
        TYPE_SAFE_FORCE_INLINE constexpr boolean operator!() const noexcept
        {
            return boolean(!value_);
        }

    private:
        bool value_;
    };

    //=== comparision ===//
    /// \returns `true` if (1) both [ts::boolean]() objects have the same value,
    /// (2)/(3) the boolean has the same value as the given value,
    /// `false` otherwise.
    /// \notes (2)/(3) do not participate in overload resolution if `T` is not a boolean type.
    /// \group boolean_comp_equal
    /// \module types
    TYPE_SAFE_FORCE_INLINE constexpr bool operator==(const boolean& a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) == static_cast<bool>(b);
    }

    /// \group boolean_comp_equal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator==(const boolean& a, T b) noexcept
    {
        return static_cast<bool>(a) == static_cast<bool>(b);
    }

    /// \group boolean_comp_equal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator==(T a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) == static_cast<bool>(b);
    }

    /// \returns `false` if (1) both [ts::boolean]() objects have the same value,
    /// (2)/(3) the boolean has the same value as the given value,
    /// `true` otherwise.
    /// \notes (2)/(3) do not participate in overload resolution if `T` is not a boolean type.
    /// \group boolean_comp_unequal
    /// \module types
    TYPE_SAFE_FORCE_INLINE constexpr bool operator!=(const boolean& a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) != static_cast<bool>(b);
    }

    /// \group boolean_comp_unequal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator!=(const boolean& a, T b) noexcept
    {
        return static_cast<bool>(a) != static_cast<bool>(b);
    }

    /// \group boolean_comp_unequal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator!=(T a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) != static_cast<bool>(b);
    }

    //=== input/output ===/
    /// \effects Reads a `bool` from the [std::istream]() and assigns it to the given [ts::boolean]().
    /// \module types
    template <typename Char, class CharTraits>
    std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in,
                                                     boolean& b)
    {
        bool val;
        in >> val;
        b = val;
        return in;
    }

    /// \effects Converts the given [ts::boolean]() to `bool` and writes it to the [std::ostream]().
    /// \module types
    template <typename Char, class CharTraits>
    std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out,
                                                     const boolean& b)
    {
        return out << static_cast<bool>(b);
    }

//=== comparison functors ===//
/// \exclude
#define TYPE_SAFE_DETAIL_MAKE_PREDICATE(Name, Op)                                                  \
    struct Name                                                                                \
    {                                                                                \
        using is_transparent = int;                                                                \
                                                                                \
        template <typename T1, typename T2>                                                        \
        constexpr bool operator()(T1&& a, T2&& b) const                                            \
            noexcept(noexcept(std::forward<T1>(a) Op std::forward<T2>(b)))                         \
        {                                                                                \
            return static_cast<bool>(std::forward<T1>(a) Op std::forward<T2>(b));                  \
        }                                                                                \
    };

    /// Comparison functors similar to the `std::` version,
    /// but explictly cast the result of the comparison to `bool`.
    ///
    /// This allows using types where the comparison operator returns [ts::boolean](),
    /// as it can not be implictly converted to `bool`
    /// so, for example, [std::less]() can not be used.
    /// \notes These comparison functors are always transparent,
    /// i.e. can be used with two different types.
    /// \group comparison_functors Comparison function objects
    /// \module types
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(equal_to, ==)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(not_equal_to, !=)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(less, <)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(less_equal, <=)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(greater, >)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(greater_equal, >=)

#undef TYPE_SAFE_DETAIL_MAKE_PREDICATE
} // namespace type_safe

#endif // TYPE_SAFE_BOOLEAN_HPP_INCLUDED
<commit_msg>Update documentation of boolean.hpp<commit_after>// Copyright (C) 2016 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef TYPE_SAFE_BOOLEAN_HPP_INCLUDED
#define TYPE_SAFE_BOOLEAN_HPP_INCLUDED

#include <iosfwd>
#include <type_traits>
#include <utility>

#include <type_safe/detail/force_inline.hpp>

namespace type_safe
{
    class boolean;

    /// \exclude
    namespace detail
    {
        template <typename T>
        struct is_boolean : std::false_type
        {
        };

        template <>
        struct is_boolean<bool> : std::true_type
        {
        };

        template <>
        struct is_boolean<boolean> : std::true_type
        {
        };

        template <typename T>
        using enable_boolean = typename std::enable_if<is_boolean<T>::value>::type;
    } // namespace detail

    /// A type safe boolean class.
    ///
    /// It is a tiny, no overhead wrapper over `bool`.
    /// It can only be constructed from `bool` values
    /// and does not implictly convert to integral types.
    /// \module types
    class boolean
    {
    public:
        boolean() = delete;

        /// \effects Creates a boolean from the given `value`.
        /// \notes This function does not participate in overload resolution if `T` is not a boolean type.
        /// \param 1
        /// \exclude
        template <typename T, typename = detail::enable_boolean<T>>
        TYPE_SAFE_FORCE_INLINE constexpr boolean(T value) noexcept : value_(value)
        {
        }

        /// \effects Assigns the given `value` to the boolean.
        /// \notes This function does not participate in overload resolution if `T` is not a boolean type.
        /// \param 1
        /// \exclude
        template <typename T, typename = detail::enable_boolean<T>>
        TYPE_SAFE_FORCE_INLINE boolean& operator=(T value) noexcept
        {
            value_ = value;
            return *this;
        }

        /// \returns The stored `bool` value.
        TYPE_SAFE_FORCE_INLINE explicit constexpr operator bool() const noexcept
        {
            return value_;
        }

        /// \returns The same as `!static_cast<bool>(*this)`.
        TYPE_SAFE_FORCE_INLINE constexpr boolean operator!() const noexcept
        {
            return boolean(!value_);
        }

    private:
        bool value_;
    };

    //=== comparision ===//
    /// [ts::boolean]() equality comparison.
    /// \returns `true` if (1) both [ts::boolean]() objects have the same value,
    /// (2)/(3) the boolean has the same value as the given value,
    /// `false` otherwise.
    /// \notes (2)/(3) do not participate in overload resolution if `T` is not a boolean type.
    /// \group boolean_comp_equal Boolean comparisons
    /// \module types
    TYPE_SAFE_FORCE_INLINE constexpr bool operator==(const boolean& a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) == static_cast<bool>(b);
    }

    /// \group boolean_comp_equal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator==(const boolean& a, T b) noexcept
    {
        return static_cast<bool>(a) == static_cast<bool>(b);
    }

    /// \group boolean_comp_equal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator==(T a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) == static_cast<bool>(b);
    }

    /// [ts::boolean]() in-equality comparison.
    /// \returns `false` if (1) both [ts::boolean]() objects have the same value,
    /// (2)/(3) the boolean has the same value as the given value,
    /// `true` otherwise.
    /// \notes (2)/(3) do not participate in overload resolution if `T` is not a boolean type.
    /// \group boolean_comp_unequal
    /// \module types
    TYPE_SAFE_FORCE_INLINE constexpr bool operator!=(const boolean& a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) != static_cast<bool>(b);
    }

    /// \group boolean_comp_unequal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator!=(const boolean& a, T b) noexcept
    {
        return static_cast<bool>(a) != static_cast<bool>(b);
    }

    /// \group boolean_comp_unequal
    /// \param 1
    /// \exclude
    template <typename T, typename = detail::enable_boolean<T>>
    TYPE_SAFE_FORCE_INLINE constexpr bool operator!=(T a, const boolean& b) noexcept
    {
        return static_cast<bool>(a) != static_cast<bool>(b);
    }

    //=== input/output ===/
    /// [ts::boolean]() input operator.
    /// \effects Reads a `bool` from the [std::istream]() and assigns it to the given [ts::boolean]().
    /// \output_section Boolean input/output
    /// \module types
    template <typename Char, class CharTraits>
    std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in,
                                                     boolean& b)
    {
        bool val;
        in >> val;
        b = val;
        return in;
    }

    /// [ts::boolean]() output operator.
    /// \effects Converts the given [ts::boolean]() to `bool` and writes it to the [std::ostream]().
    /// \module types
    template <typename Char, class CharTraits>
    std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out,
                                                     const boolean& b)
    {
        return out << static_cast<bool>(b);
    }

//=== comparison functors ===//
/// \exclude
#define TYPE_SAFE_DETAIL_MAKE_PREDICATE(Name, Op)                                                  \
    struct Name                                                                                \
    {                                                                                \
        using is_transparent = int;                                                                \
                                                                                \
        template <typename T1, typename T2>                                                        \
        constexpr bool operator()(T1&& a, T2&& b) const                                            \
            noexcept(noexcept(std::forward<T1>(a) Op std::forward<T2>(b)))                         \
        {                                                                                \
            return static_cast<bool>(std::forward<T1>(a) Op std::forward<T2>(b));                  \
        }                                                                                \
    };

    /// Comparison functors similar to the `std::` version,
    /// but explictly cast the result of the comparison to `bool`.
    ///
    /// This allows using types where the comparison operator returns [ts::boolean](),
    /// as it can not be implictly converted to `bool`
    /// so, for example, [std::less]() can not be used.
    /// \notes These comparison functors are always transparent,
    /// i.e. can be used with two different types.
    /// \group comparison_functors Comparison function objects
    /// \module types
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(equal_to, ==)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(not_equal_to, !=)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(less, <)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(less_equal, <=)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(greater, >)
    /// \group comparison_functors
    TYPE_SAFE_DETAIL_MAKE_PREDICATE(greater_equal, >=)

#undef TYPE_SAFE_DETAIL_MAKE_PREDICATE
} // namespace type_safe

#endif // TYPE_SAFE_BOOLEAN_HPP_INCLUDED
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFRPROptimizerTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <vnl/vnl_math.h>
#include "itkFRPROptimizer.h"

/**
 *  The objectif function is the quadratic form:
 *
 *  1/2 x^T A x - b^T x
 *
 *  Where A is a matrix and b is a vector
 *  The system in this example is:
 *
 *     | 3  2 ||x|   | 2|   |0|
 *     | 2  6 ||y| + |-8| = |0|
 *
 *
 *   the solution is the vector | 2 -2 |
 *
 */
class FRPRGradientCostFunction : public itk::SingleValuedCostFunction
{
public:

  typedef FRPRGradientCostFunction                  Self;
  typedef itk::SingleValuedCostFunction   Superclass;
  typedef itk::SmartPointer<Self>         Pointer;
  typedef itk::SmartPointer<const Self>   ConstPointer;
  itkNewMacro( Self );
  itkTypeMacro( FRPRGradientCostFunction, SingleValuedCostFunction );

  enum { SpaceDimension=2 };

  typedef Superclass::ParametersType      ParametersType;
  typedef Superclass::DerivativeType      DerivativeType;
  typedef Superclass::MeasureType         MeasureType ;

  FRPRGradientCostFunction()
  {
  }

  MeasureType  GetValue( const ParametersType & parameters ) const
  {

    double x = parameters[0];
    double y = parameters[1];

    std::cout << "GetValue( " ;
    std::cout << x << " ";
    std::cout << y << ") = ";

    MeasureType measure = 0.5*(3*x*x+4*x*y+6*y*y) - 2*x + 8*y;

    std::cout << measure << std::endl;

    return measure;

  }

  void GetDerivative( const ParametersType & parameters,
                            DerivativeType & derivative ) const
  {

    double x = parameters[0];
    double y = parameters[1];

    std::cout << "GetDerivative( " ;
    std::cout << x << " ";
    std::cout << y << ") = ";

    DerivativeType temp(SpaceDimension);
    temp.Fill( 0 );
    derivative = temp;
    derivative[0] = 3 * x + 2 * y -2;
    derivative[1] = 2 * x + 6 * y +8;

    std::cout << derivative << std::endl;

  }

  unsigned int GetNumberOfParameters(void) const
    {
    return SpaceDimension;
    }

private:

};

int itkFRPROptimizerTest(int, char* [] )
{
  std::cout << "FRPR Optimizer Test ";
  std::cout << std::endl << std::endl;

  typedef  itk::FRPROptimizer  OptimizerType;

  typedef OptimizerType::ScalesType        ScalesType;

  // Declaration of a itkOptimizer
  OptimizerType::Pointer  itkOptimizer = OptimizerType::New();

  // Declaration of the CostFunction
  FRPRGradientCostFunction::Pointer costFunction = FRPRGradientCostFunction::New();

  itkOptimizer->SetCostFunction( costFunction.GetPointer() );

  typedef FRPRGradientCostFunction::ParametersType    ParametersType;

  const unsigned int spaceDimension =
                      costFunction->GetNumberOfParameters();

  // We start not so far from  | 2 -2 |
  ParametersType  initialPosition( spaceDimension );

  initialPosition[0] =  100;
  initialPosition[1] = -100;

  itkOptimizer->SetStepLength(0.01);
  itkOptimizer->SetMaximize(false);
  itkOptimizer->SetMaximumIteration( 50 );

  itkOptimizer->SetInitialPosition( initialPosition );

  try
    {
    itkOptimizer->StartOptimization();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cout << "Exception thrown ! " << std::endl;
    std::cout << "An error ocurred during Optimization" << std::endl;
    std::cout << "Location    = " << e.GetLocation()    << std::endl;
    std::cout << "Description = " << e.GetDescription() << std::endl;
    return EXIT_FAILURE;
    }

  ParametersType finalPosition = itkOptimizer->GetCurrentPosition();
  std::cout << "Solution        = (";
  std::cout << finalPosition[0] << "," ;
  std::cout << finalPosition[1] << ")" << std::endl;

  //
  // check results to see if it is within range
  //
  bool pass = true;
  double trueParameters[2] = { 2, -2 };
  for( unsigned int j = 0; j < 2; j++ )
    {
    if( vnl_math_abs( finalPosition[j] - trueParameters[j] ) > 0.01 )
      pass = false;
    }

  // Exercise various member functions.
  std::cout << "Maximize: " << itkOptimizer->GetMaximize() << std::endl;
  std::cout << std::endl;
  std::cout << "MaximumIteration: " << itkOptimizer->GetMaximumIteration();
  std::cout << std::endl;

  itkOptimizer->Print( std::cout );

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

}

<commit_msg>ENH: Adding explicit settings for the Fletch-Reeves and Polak-Ribiere      modes of this optimizer. Before it was necessary to uncomment a line      of code and recompile the optimizer. Now there is an enum that selects      the optimization mode. Testing was added here for both modes.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFRPROptimizerTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <vnl/vnl_math.h>
#include "itkFRPROptimizer.h"

/**
 *  The objectif function is the quadratic form:
 *
 *  1/2 x^T A x - b^T x
 *
 *  Where A is a matrix and b is a vector
 *  The system in this example is:
 *
 *     | 3  2 ||x|   | 2|   |0|
 *     | 2  6 ||y| + |-8| = |0|
 *
 *
 *   the solution is the vector | 2 -2 |
 *
 */
class FRPRGradientCostFunction : public itk::SingleValuedCostFunction
{
public:

  typedef FRPRGradientCostFunction                  Self;
  typedef itk::SingleValuedCostFunction   Superclass;
  typedef itk::SmartPointer<Self>         Pointer;
  typedef itk::SmartPointer<const Self>   ConstPointer;
  itkNewMacro( Self );
  itkTypeMacro( FRPRGradientCostFunction, SingleValuedCostFunction );

  enum { SpaceDimension=2 };

  typedef Superclass::ParametersType      ParametersType;
  typedef Superclass::DerivativeType      DerivativeType;
  typedef Superclass::MeasureType         MeasureType ;

  FRPRGradientCostFunction()
  {
  }

  MeasureType  GetValue( const ParametersType & parameters ) const
  {

    double x = parameters[0];
    double y = parameters[1];

    std::cout << "GetValue( " ;
    std::cout << x << " ";
    std::cout << y << ") = ";

    MeasureType measure = 0.5*(3*x*x+4*x*y+6*y*y) - 2*x + 8*y;

    std::cout << measure << std::endl;

    return measure;

  }

  void GetDerivative( const ParametersType & parameters,
                            DerivativeType & derivative ) const
  {

    double x = parameters[0];
    double y = parameters[1];

    std::cout << "GetDerivative( " ;
    std::cout << x << " ";
    std::cout << y << ") = ";

    DerivativeType temp(SpaceDimension);
    temp.Fill( 0 );
    derivative = temp;
    derivative[0] = 3 * x + 2 * y -2;
    derivative[1] = 2 * x + 6 * y +8;

    std::cout << derivative << std::endl;

  }

  unsigned int GetNumberOfParameters(void) const
    {
    return SpaceDimension;
    }

private:

};

int itkFRPROptimizerTest(int, char* [] )
{
  std::cout << "FRPR Optimizer Test ";
  std::cout << std::endl << std::endl;

  typedef  itk::FRPROptimizer  OptimizerType;

  typedef OptimizerType::ScalesType        ScalesType;

  // Declaration of a itkOptimizer
  OptimizerType::Pointer  itkOptimizer = OptimizerType::New();

  // Declaration of the CostFunction
  FRPRGradientCostFunction::Pointer costFunction = FRPRGradientCostFunction::New();

  itkOptimizer->SetCostFunction( costFunction.GetPointer() );

  typedef FRPRGradientCostFunction::ParametersType    ParametersType;

  const unsigned int spaceDimension =
                      costFunction->GetNumberOfParameters();

  // We start not so far from  | 2 -2 |
  ParametersType  initialPosition( spaceDimension );

  initialPosition[0] =  100;
  initialPosition[1] = -100;

  itkOptimizer->SetStepLength(0.01);
  itkOptimizer->SetMaximize(false);
  itkOptimizer->SetMaximumIteration( 50 );

  {
  // Exercise the methods that set the optimization mode
  std::cout << "Testing Fletch Reeves Mode" << std::endl;
  itkOptimizer->SetToFletchReeves();

  itkOptimizer->SetInitialPosition( initialPosition );

  try
    {
    itkOptimizer->StartOptimization();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cout << "Exception thrown ! " << std::endl;
    std::cout << "An error ocurred during Optimization" << std::endl;
    std::cout << "Location    = " << e.GetLocation()    << std::endl;
    std::cout << "Description = " << e.GetDescription() << std::endl;
    return EXIT_FAILURE;
    }

  ParametersType finalPosition = itkOptimizer->GetCurrentPosition();
  std::cout << "Solution        = (";
  std::cout << finalPosition[0] << "," ;
  std::cout << finalPosition[1] << ")" << std::endl;

  //
  // check results to see if it is within range
  //
  bool pass = true;
  double trueParameters[2] = { 2, -2 };
  for( unsigned int j = 0; j < 2; j++ )
    {
    if( vnl_math_abs( finalPosition[j] - trueParameters[j] ) > 0.01 )
      pass = false;
    }

  // Exercise various member functions.
  std::cout << "Maximize: " << itkOptimizer->GetMaximize() << std::endl;
  std::cout << std::endl;
  std::cout << "MaximumIteration: " << itkOptimizer->GetMaximumIteration();
  std::cout << std::endl;

  itkOptimizer->Print( std::cout );

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

  }

  {
  // Exercise the methods that set the optimization mode
  std::cout << "Testing Polak Ribiere Mode" << std::endl;
  itkOptimizer->SetToPolakRibiere();

  itkOptimizer->SetInitialPosition( initialPosition );

  try
    {
    itkOptimizer->StartOptimization();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cout << "Exception thrown ! " << std::endl;
    std::cout << "An error ocurred during Optimization" << std::endl;
    std::cout << "Location    = " << e.GetLocation()    << std::endl;
    std::cout << "Description = " << e.GetDescription() << std::endl;
    return EXIT_FAILURE;
    }

  ParametersType finalPosition = itkOptimizer->GetCurrentPosition();
  std::cout << "Solution        = (";
  std::cout << finalPosition[0] << "," ;
  std::cout << finalPosition[1] << ")" << std::endl;

  //
  // check results to see if it is within range
  //
  bool pass = true;
  double trueParameters[2] = { 2, -2 };
  for( unsigned int j = 0; j < 2; j++ )
    {
    if( vnl_math_abs( finalPosition[j] - trueParameters[j] ) > 0.01 )
      pass = false;
    }

  // Exercise various member functions.
  std::cout << "Maximize: " << itkOptimizer->GetMaximize() << std::endl;
  std::cout << std::endl;
  std::cout << "MaximumIteration: " << itkOptimizer->GetMaximumIteration();
  std::cout << std::endl;

  itkOptimizer->Print( std::cout );

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

  }
}

<|endoftext|>


<commit_before>// Copyright 2020 Chia Network Inc

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//    http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SRC_BLSHKDF_HPP_
#define SRC_BLSHKDF_HPP_

#include <relic_conf.h>
#include <math.h>

#if defined GMP && ARITH == GMP
#include <gmp.h>
#endif

#include <cassert>
#include "util.hpp"

namespace bls {

class HKDF256 {
    /**
     * Implements HKDF as specified in RFC5869: https://tools.ietf.org/html/rfc5869,
     * with sha256 as the hash function.
     **/
 public:
    static const uint8_t HASH_LEN = 32;

    static void Extract(uint8_t* prk_output, const uint8_t* salt, const size_t saltLen, const uint8_t* ikm, const size_t ikm_len) {
        // assert(saltLen == 4);  // Used for EIP2333 key derivation
        // assert(ikm_len == 32);  // Used for EIP2333 key derivation
        // Hash256 used as the hash function (sha256)
        // PRK Output is 32 bytes (HashLen)
        md_hmac(prk_output, ikm, ikm_len, salt, saltLen);
    }

    static void Expand(uint8_t* okm, size_t L, const uint8_t* prk, const uint8_t* info, const size_t infoLen) {
        assert(L <= 255 * HASH_LEN); // L <= 255 * HashLen
        assert(infoLen >= 0);
        size_t N = (L + HASH_LEN - 1) / HASH_LEN; // Round up
        size_t bytesWritten = 0;

        uint8_t* T = Util::SecAlloc<uint8_t>(HASH_LEN);
        uint8_t* hmacInput1 = Util::SecAlloc<uint8_t>(infoLen + 1);
        uint8_t* hmacInput = Util::SecAlloc<uint8_t>(HASH_LEN + infoLen + 1);

        assert(N >= 1 && N <= 255);

        for (size_t i = 1; i <= N; i++) {
            if (i == 1) {
                memcpy(hmacInput1, info, infoLen);
                hmacInput1[infoLen] = i;
                md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN);
            } else {
                memcpy(hmacInput, T, HASH_LEN);
                memcpy(hmacInput + HASH_LEN, info, infoLen);
                hmacInput[HASH_LEN + infoLen] = i;
                md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN);
            }
            size_t to_write = L - bytesWritten;
            if (to_write > HASH_LEN) {
                to_write = HASH_LEN;
            }
            assert (to_write > 0 && to_write <= HASH_LEN);
            memcpy(okm + bytesWritten, T, to_write);
            bytesWritten += to_write;
        }
        Util::SecFree(T);
        Util::SecFree(hmacInput1);
        Util::SecFree(hmacInput);
        assert(bytesWritten == L);
    }

    static void ExtractExpand(uint8_t* output, size_t outputLen,
                              const uint8_t* key, size_t keyLen,
                              const uint8_t* salt, size_t saltLen,
                              const uint8_t* info, size_t infoLen) {
        uint8_t* prk = Util::SecAlloc<uint8_t>(HASH_LEN);
        HKDF256::Extract(prk, salt, saltLen, key, keyLen);
        HKDF256::Expand(output, outputLen, prk, info, infoLen);
        Util::SecFree(prk);
    }
};
} // end namespace bls
#endif  // SRC_BLSHKDF_HPP_
<commit_msg>remove assert which is never false<commit_after>// Copyright 2020 Chia Network Inc

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//    http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SRC_BLSHKDF_HPP_
#define SRC_BLSHKDF_HPP_

#include <relic_conf.h>
#include <math.h>

#if defined GMP && ARITH == GMP
#include <gmp.h>
#endif

#include <cassert>
#include "util.hpp"

namespace bls {

class HKDF256 {
    /**
     * Implements HKDF as specified in RFC5869: https://tools.ietf.org/html/rfc5869,
     * with sha256 as the hash function.
     **/
 public:
    static const uint8_t HASH_LEN = 32;

    static void Extract(uint8_t* prk_output, const uint8_t* salt, const size_t saltLen, const uint8_t* ikm, const size_t ikm_len) {
        // assert(saltLen == 4);  // Used for EIP2333 key derivation
        // assert(ikm_len == 32);  // Used for EIP2333 key derivation
        // Hash256 used as the hash function (sha256)
        // PRK Output is 32 bytes (HashLen)
        md_hmac(prk_output, ikm, ikm_len, salt, saltLen);
    }

    static void Expand(uint8_t* okm, size_t L, const uint8_t* prk, const uint8_t* info, const size_t infoLen) {
        assert(L <= 255 * HASH_LEN); // L <= 255 * HashLen
        size_t N = (L + HASH_LEN - 1) / HASH_LEN; // Round up
        size_t bytesWritten = 0;

        uint8_t* T = Util::SecAlloc<uint8_t>(HASH_LEN);
        uint8_t* hmacInput1 = Util::SecAlloc<uint8_t>(infoLen + 1);
        uint8_t* hmacInput = Util::SecAlloc<uint8_t>(HASH_LEN + infoLen + 1);

        assert(N >= 1 && N <= 255);

        for (size_t i = 1; i <= N; i++) {
            if (i == 1) {
                memcpy(hmacInput1, info, infoLen);
                hmacInput1[infoLen] = i;
                md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN);
            } else {
                memcpy(hmacInput, T, HASH_LEN);
                memcpy(hmacInput + HASH_LEN, info, infoLen);
                hmacInput[HASH_LEN + infoLen] = i;
                md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN);
            }
            size_t to_write = L - bytesWritten;
            if (to_write > HASH_LEN) {
                to_write = HASH_LEN;
            }
            assert (to_write > 0 && to_write <= HASH_LEN);
            memcpy(okm + bytesWritten, T, to_write);
            bytesWritten += to_write;
        }
        Util::SecFree(T);
        Util::SecFree(hmacInput1);
        Util::SecFree(hmacInput);
        assert(bytesWritten == L);
    }

    static void ExtractExpand(uint8_t* output, size_t outputLen,
                              const uint8_t* key, size_t keyLen,
                              const uint8_t* salt, size_t saltLen,
                              const uint8_t* info, size_t infoLen) {
        uint8_t* prk = Util::SecAlloc<uint8_t>(HASH_LEN);
        HKDF256::Extract(prk, salt, saltLen, key, keyLen);
        HKDF256::Expand(output, outputLen, prk, info, infoLen);
        Util::SecFree(prk);
    }
};
} // end namespace bls
#endif  // SRC_BLSHKDF_HPP_
<|endoftext|>


<commit_before>namespace Bull
{
    template <typename T>
    Quaternion<T> Quaternion<T>::conjugate(const Quaternion<T>& left, const Quaternion<T>& right)
    {
        Quaternion<T> copy = left;

        return left.conjugate(right);
    }

    template <typename T>
    Quaternion<T>::Quaternion()
    {
        set(0, 0, 0, 0);
    }

    template <typename T>
    Quaternion<T>::Quaternion(const EulerAngles<T>& angles)
    {
        set(angles);
    }

    template <typename T>
    Quaternion<T>::Quaternion(T w, T x, T y, T z)
    {
        set(w, x, y, z);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::set(const EulerAngles<T>& angles)
    {
        return (*this);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::set(T w, T x, T y, T z)
    {
        this->w = w;
        this->x = x;
        this->y = y;
        this->z = z;

        return (*this);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::set(const Quaternion& quaternion)
    {
        return set(quaternion.w, quaternion.x, quaternion.y, quaternion.z);
    }

    template <typename T>
    float Quaternion<T>::getLength() const
    {
        return std::pow(w, 2) + std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2);
    }

    template <typename T>
    float Quaternion<T>::getSquareRootLength() const
    {
        return std::sqrt(getLength());
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::normalize()
    {
        T n = static_cast<T>(this->getSquareRootLenght()); /// We use this here to prevent GCC warning

        w /= n;
        x /= n;
        y /= n;
        z /= n;

        return (*this);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::conjugate(const Quaternion<T>& quaternion)
    {
        w =  quaternion.w;
        x = -quaternion.x;
        y = -quaternion.y;
        z = -quaternion.z;

        return (*this);
    }

    template <typename T>
    EulerAngles<T> Quaternion<T>::toEulerAngles() const
    {
        return EulerAngles<T>((*this));
    }

    template <typename T>
    bool Quaternion<T>::operator==(const Quaternion<T>& right) const
    {
        return w == right.w &&
               x == right.x &&
               y == right.y &&
               z == right.z;
    }

    template <typename T>
    bool Quaternion<T>::operator!=(const Quaternion<T>& right) const
    {
        return !((*this) == right);
    }
}<commit_msg>Math/Quaternion Cleanup<commit_after>namespace Bull
{
    template <typename T>
    Quaternion<T> Quaternion<T>::conjugate(const Quaternion<T>& left, const Quaternion<T>& right)
    {
        return Quaternion<T>(left).conjugate(right);
    }

    template <typename T>
    Quaternion<T>::Quaternion()
    {
        set(0, 0, 0, 0);
    }

    template <typename T>
    Quaternion<T>::Quaternion(const EulerAngles<T>& angles)
    {
        set(angles);
    }

    template <typename T>
    Quaternion<T>::Quaternion(T w, T x, T y, T z)
    {
        set(w, x, y, z);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::set(const EulerAngles<T>& angles)
    {
        T cy = std::cos(static_cast<T>(angles.yaw.asRadian())   * 0.5);
        T sy = std::sin(static_cast<T>(angles.yaw.asRadian())   * 0.5);
        T cr = std::cos(static_cast<T>(angles.roll.asRadian())  * 0.5);
        T sr = std::sin(static_cast<T>(angles.roll.asRadian())  * 0.5);
        T cp = std::cos(static_cast<T>(angles.pitch.asRadian()) * 0.5);
        T sp = std::sin(static_cast<T>(angles.pitch.asRadian()) * 0.5);

        w = cy * cr * cp + sy * sr * sp;
        x = cy * sr * cp - sy * cr * sp;
        y = cy * cr * sp + sy * sr * cp;
        z = sy * cr * cp - cy * sr * sp;

        return (*this);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::set(T w, T x, T y, T z)
    {
        this->w = w;
        this->x = x;
        this->y = y;
        this->z = z;

        return (*this);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::set(const Quaternion& quaternion)
    {
        return set(quaternion.w, quaternion.x, quaternion.y, quaternion.z);
    }

    template <typename T>
    float Quaternion<T>::getLength() const
    {
        return std::pow(w, 2) + std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2);
    }

    template <typename T>
    float Quaternion<T>::getSquareRootLength() const
    {
        return std::sqrt(getLength());
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::normalize()
    {
        T n = static_cast<T>(this->getSquareRootLenght()); /// We use this here to prevent GCC warning

        w /= n;
        x /= n;
        y /= n;
        z /= n;

        return (*this);
    }

    template <typename T>
    Quaternion<T>& Quaternion<T>::conjugate(const Quaternion<T>& quaternion)
    {
        w =  quaternion.w;
        x = -quaternion.x;
        y = -quaternion.y;
        z = -quaternion.z;

        return (*this);
    }

    template <typename T>
    bool Quaternion<T>::operator==(const Quaternion<T>& right) const
    {
        return w == right.w &&
               x == right.x &&
               y == right.y &&
               z == right.z;
    }

    template <typename T>
    bool Quaternion<T>::operator!=(const Quaternion<T>& right) const
    {
        return !((*this) == right);
    }
}<|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		08/2010
*/

#include "Precompiled.h"
#include "MyGUI_Precompiled.h"
#include "MyGUI_FilterNoneSkin.h"
#include "MyGUI_RenderItem.h"
#include "MyGUI_LayerManager.h"
#include "MyGUI_CommonStateInfo.h"

#ifdef MYGUI_OGRE_PLATFORM
#include <MyGUI_OgreRenderManager.h>
#include <MyGUI_OgreTexture.h>
#include <MyGUI_OgreVertexBuffer.h>
#elif MYGUI_OPENGL_PLATFORM
#include <MyGUI_OpenGlRenderManager.h>
#elif MYGUI_DIRECTX_PLATFORM
#include <MyGUI_DirectXRenderManager.h>
#elif MYGUI_DIRECTX11_PLATFORM
#include <MyGUI_DirectX11RenderManager.h>
#endif

namespace MyGUI
{

	FilterNone::FilterNone() :
		SubSkin()
	{
		mSeparate = true;
	}

	FilterNone::~FilterNone()
	{
	}

	void FilterNone::_setAlign(const IntSize& _oldsize)
	{
		mCurrentCoord.set(0, 0, mCroppedParent->getWidth(), mCroppedParent->getHeight());
		mAlign = Align::Stretch;

		Base::_setAlign(_oldsize);
	}

	void FilterNone::doManualRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
	{
#ifdef MYGUI_OGRE_PLATFORM
		if (OgreRenderManager::getInstancePtr()->getManualRender())
			OgreRenderManager::getInstancePtr()->begin();

		OgreRenderManager::getInstancePtr()->setManualRender(true);

		if (_texture)
		{
			OgreTexture* texture = static_cast<OgreTexture*>(_texture);
			Ogre::TexturePtr texture_ptr = texture->getOgreTexture();
			if (!texture_ptr.isNull())
			{
				OgreRenderManager::getInstancePtr()->getRenderSystem()->_setTexture(0, true, texture_ptr);
				OgreRenderManager::getInstancePtr()->getRenderSystem()->_setTextureUnitFiltering(0, Ogre::FO_NONE, Ogre::FO_NONE, Ogre::FO_NONE);
			}
		}

		OgreVertexBuffer* buffer = static_cast<OgreVertexBuffer*>(_buffer);
		Ogre::RenderOperation* operation = buffer->getRenderOperation();
		operation->vertexData->vertexCount = _count;

		OgreRenderManager::getInstancePtr()->getRenderSystem()->_render(*operation);
#elif MYGUI_OPENGL_PLATFORM
		OpenGLRenderManager::getInstancePtr()->doRender(_buffer, _texture, _count);
#elif MYGUI_DIRECTX_PLATFORM
		DirectXRenderManager::getInstancePtr()->doRender(_buffer, _texture, _count);
#elif MYGUI_DIRECTX11_PLATFORM
		DirectX11RenderManager::getInstancePtr()->doRender(_buffer, _texture, _count);
#endif
	}

}
<commit_msg>fast fix<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		08/2010
*/

#include "Precompiled.h"
#include "MyGUI_Precompiled.h"
#include "MyGUI_FilterNoneSkin.h"
#include "MyGUI_RenderItem.h"
#include "MyGUI_LayerManager.h"
#include "MyGUI_CommonStateInfo.h"

#ifdef MYGUI_OGRE_PLATFORM
#include <MyGUI_OgreRenderManager.h>
#include <MyGUI_OgreTexture.h>
#include <MyGUI_OgreVertexBuffer.h>
#elif MYGUI_OPENGL_PLATFORM
#include <MyGUI_OpenGlRenderManager.h>
#elif MYGUI_DIRECTX_PLATFORM
#include <MyGUI_DirectXRenderManager.h>
#elif MYGUI_DIRECTX11_PLATFORM
#include <MyGUI_DirectX11RenderManager.h>
#endif

namespace MyGUI
{

	FilterNone::FilterNone() :
		SubSkin()
	{
#ifdef MYGUI_OGRE_PLATFORM
		mSeparate = true;
#endif
	}

	FilterNone::~FilterNone()
	{
	}

	void FilterNone::_setAlign(const IntSize& _oldsize)
	{
		mCurrentCoord.set(0, 0, mCroppedParent->getWidth(), mCroppedParent->getHeight());
		mAlign = Align::Stretch;

		Base::_setAlign(_oldsize);
	}

	void FilterNone::doManualRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
	{
#ifdef MYGUI_OGRE_PLATFORM
		if (OgreRenderManager::getInstancePtr()->getManualRender())
			OgreRenderManager::getInstancePtr()->begin();

		OgreRenderManager::getInstancePtr()->setManualRender(true);

		if (_texture)
		{
			OgreTexture* texture = static_cast<OgreTexture*>(_texture);
			Ogre::TexturePtr texture_ptr = texture->getOgreTexture();
			if (!texture_ptr.isNull())
			{
				OgreRenderManager::getInstancePtr()->getRenderSystem()->_setTexture(0, true, texture_ptr);
				OgreRenderManager::getInstancePtr()->getRenderSystem()->_setTextureUnitFiltering(0, Ogre::FO_NONE, Ogre::FO_NONE, Ogre::FO_NONE);
			}
		}

		OgreVertexBuffer* buffer = static_cast<OgreVertexBuffer*>(_buffer);
		Ogre::RenderOperation* operation = buffer->getRenderOperation();
		operation->vertexData->vertexCount = _count;

		OgreRenderManager::getInstancePtr()->getRenderSystem()->_render(*operation);
#elif MYGUI_OPENGL_PLATFORM
		OpenGLRenderManager::getInstancePtr()->doRender(_buffer, _texture, _count);
#elif MYGUI_DIRECTX_PLATFORM
		DirectXRenderManager::getInstancePtr()->doRender(_buffer, _texture, _count);
#elif MYGUI_DIRECTX11_PLATFORM
		DirectX11RenderManager::getInstancePtr()->doRender(_buffer, _texture, _count);
#endif
	}

}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_ENUMS_NETWORK_HPP
#define NAZARA_ENUMS_NETWORK_HPP

namespace Nz
{
	enum NetCode : UInt16
	{
		NetCode_Acknowledge           = 0x9A4E,
		NetCode_AcknowledgeConnection = 0xC108,
		NetCode_Ping                  = 0x96AC,
		NetCode_Pong                  = 0x974C,
		NetCode_RequestConnection     = 0xF27D,

		NetCode_Invalid = 0x0000
	};

	enum NetProtocol
	{
		NetProtocol_Any,
		NetProtocol_IPv4,
		NetProtocol_IPv6,
		NetProtocol_Unknown,

		NetProtocol_Max = NetProtocol_Unknown
	};

	enum PacketPriority
	{
		PacketPriority_High      = 1, //< High-priority packet, will be sent quickly
		PacketPriority_Immediate = 0, //< Immediate priority, will be sent immediately
		PacketPriority_Medium    = 2, //< Medium-priority packet, will be sent as regular
		PacketPriority_Low       = 3, //< Low-priority packet, may take some time to be sent

		PacketPriority_Lowest  = PacketPriority_Low,
		PacketPriority_Highest = PacketPriority_Immediate,
		PacketPriority_Max     = PacketPriority_Low
	};

	enum PacketReliability
	{
		PacketReliability_Reliable,        //< Packet will be resent if lost
		PacketReliability_ReliableOrdered, //< Packet will be resent if lost and will only arrive in order
		PacketReliability_Unreliable,      //< Packet won't be resent if lost

		PacketReliability_Max = PacketReliability_Unreliable
	};

	enum ResolveError
	{
		ResolveError_NoError,

		ResolveError_Internal,             //< An internal error occurred
		ResolveError_ResourceError,        //< The operating system lacks the resources to proceed (insufficient memory)
		ResolveError_NonRecoverable,       //< An nonrecoverable error occurred
		ResolveError_NotFound,             //< No such host is known
		ResolveError_NotInitialized,       //< Nazara network has not been initialized
		ResolveError_ProtocolNotSupported, //< A specified protocol is not supported by the server
		ResolveError_TemporaryFailure,     //< A temporary failure occurred, try again
		ResolveError_Unknown,              //< The last operation failed with an unlisted error code

		ResolveError_Max = ResolveError_Unknown
	};

	enum SocketError
	{
		SocketError_NoError,

		SocketError_AddressNotAvailable, //< The address is already in use (when binding/listening)
		SocketError_ConnectionClosed,    //< The connection has been closed
		SocketError_ConnectionRefused,   //< The connection attempt was refused
		SocketError_DatagramSize,        //< The datagram size is over the system limit
		SocketError_Internal,            //< The error is coming from the engine
		SocketError_Packet,              //< The packet encoding/decoding failed, probably because of corrupted data
		SocketError_NetworkError,        //< The network system has failed (maybe network is down)
		SocketError_NotInitialized,      //< Nazara network has not been initialized
		SocketError_NotSupported,        //< The operation is not supported (e.g. creating a bluetooth socket on a system without any bluetooth adapter)
		SocketError_ResolveError,        //< The hostname couldn't be resolved (more information in ResolveError code)
		SocketError_ResourceError,       //< The operating system lacks the resources to proceed (e.g. memory/socket descriptor)
		SocketError_TimedOut,            //< The operation timed out
		SocketError_Unknown,             //< The last operation failed with an unlisted error code
		SocketError_UnreachableHost,     //< The host is not reachable

		SocketError_Max = SocketError_UnreachableHost
	};

	enum SocketState
	{
		SocketState_Bound,        //< The socket is currently bound
		SocketState_Connecting,   //< The socket is currently connecting
		SocketState_Connected,    //< The socket is currently connected
		SocketState_NotConnected, //< The socket is not connected (or has been disconnected)
		SocketState_Resolving,    //< The socket is currently resolving a host name

		SocketState_Max = SocketState_NotConnected
	};

	enum SocketType
	{
		SocketType_Raw,
		SocketType_TCP,
		SocketType_UDP,
		SocketType_Unknown,

		SocketType_Max = SocketType_Unknown
	};
}

#endif // NAZARA_ENUMS_NETWORK_HPP
<commit_msg>Network/Enums: Fix SocketState_Max<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_ENUMS_NETWORK_HPP
#define NAZARA_ENUMS_NETWORK_HPP

namespace Nz
{
	enum NetCode : UInt16
	{
		NetCode_Acknowledge           = 0x9A4E,
		NetCode_AcknowledgeConnection = 0xC108,
		NetCode_Ping                  = 0x96AC,
		NetCode_Pong                  = 0x974C,
		NetCode_RequestConnection     = 0xF27D,

		NetCode_Invalid = 0x0000
	};

	enum NetProtocol
	{
		NetProtocol_Any,
		NetProtocol_IPv4,
		NetProtocol_IPv6,
		NetProtocol_Unknown,

		NetProtocol_Max = NetProtocol_Unknown
	};

	enum PacketPriority
	{
		PacketPriority_High      = 1, //< High-priority packet, will be sent quickly
		PacketPriority_Immediate = 0, //< Immediate priority, will be sent immediately
		PacketPriority_Medium    = 2, //< Medium-priority packet, will be sent as regular
		PacketPriority_Low       = 3, //< Low-priority packet, may take some time to be sent

		PacketPriority_Lowest  = PacketPriority_Low,
		PacketPriority_Highest = PacketPriority_Immediate,
		PacketPriority_Max     = PacketPriority_Low
	};

	enum PacketReliability
	{
		PacketReliability_Reliable,        //< Packet will be resent if lost
		PacketReliability_ReliableOrdered, //< Packet will be resent if lost and will only arrive in order
		PacketReliability_Unreliable,      //< Packet won't be resent if lost

		PacketReliability_Max = PacketReliability_Unreliable
	};

	enum ResolveError
	{
		ResolveError_NoError,

		ResolveError_Internal,             //< An internal error occurred
		ResolveError_ResourceError,        //< The operating system lacks the resources to proceed (insufficient memory)
		ResolveError_NonRecoverable,       //< An nonrecoverable error occurred
		ResolveError_NotFound,             //< No such host is known
		ResolveError_NotInitialized,       //< Nazara network has not been initialized
		ResolveError_ProtocolNotSupported, //< A specified protocol is not supported by the server
		ResolveError_TemporaryFailure,     //< A temporary failure occurred, try again
		ResolveError_Unknown,              //< The last operation failed with an unlisted error code

		ResolveError_Max = ResolveError_Unknown
	};

	enum SocketError
	{
		SocketError_NoError,

		SocketError_AddressNotAvailable, //< The address is already in use (when binding/listening)
		SocketError_ConnectionClosed,    //< The connection has been closed
		SocketError_ConnectionRefused,   //< The connection attempt was refused
		SocketError_DatagramSize,        //< The datagram size is over the system limit
		SocketError_Internal,            //< The error is coming from the engine
		SocketError_Packet,              //< The packet encoding/decoding failed, probably because of corrupted data
		SocketError_NetworkError,        //< The network system has failed (maybe network is down)
		SocketError_NotInitialized,      //< Nazara network has not been initialized
		SocketError_NotSupported,        //< The operation is not supported (e.g. creating a bluetooth socket on a system without any bluetooth adapter)
		SocketError_ResolveError,        //< The hostname couldn't be resolved (more information in ResolveError code)
		SocketError_ResourceError,       //< The operating system lacks the resources to proceed (e.g. memory/socket descriptor)
		SocketError_TimedOut,            //< The operation timed out
		SocketError_Unknown,             //< The last operation failed with an unlisted error code
		SocketError_UnreachableHost,     //< The host is not reachable

		SocketError_Max = SocketError_UnreachableHost
	};

	enum SocketState
	{
		SocketState_Bound,        //< The socket is currently bound
		SocketState_Connecting,   //< The socket is currently connecting
		SocketState_Connected,    //< The socket is currently connected
		SocketState_NotConnected, //< The socket is not connected (or has been disconnected)
		SocketState_Resolving,    //< The socket is currently resolving a host name

		SocketState_Max = SocketState_Resolving
	};

	enum SocketType
	{
		SocketType_Raw,
		SocketType_TCP,
		SocketType_UDP,
		SocketType_Unknown,

		SocketType_Max = SocketType_Unknown
	};
}

#endif // NAZARA_ENUMS_NETWORK_HPP
<|endoftext|>


<commit_before>#include "pd_view.h"
#include "pd_view.h"
#include "pd_backend.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <vector>

#if defined(_WIN32)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif

#ifdef __clang__
#pragma clang diagnostic ignored "-Wformat-nonliteral" //error: format string is not a string literal [-Werror,-Wformat-nonliteral]

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct ConsoleData
{
	ConsoleData() : historyPos(0), scrollToBottom(0)
	{
		memset(inputBuffer, 0, sizeof(inputBuffer));
	}

    char inputBuffer[256];
    std::vector<char*> items;
    std::vector<char*> commands;
    std::vector<char*> history;
    std::vector<char*> scripts; // TODO: Temp, for testing
    int historyPos; // -1: New Line, 0...history.size()-1 Browsing History
    bool scrollToBottom;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void clearLog(ConsoleData* consoleData)
{
    for (size_t i = 0; i < consoleData->items.size(); ++i)
        free(consoleData->items[i]);
    consoleData->items.clear();
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void addLog(ConsoleData* consoleData, const char* fmt, ...)
{
    char buffer[1024];
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buffer, 1024, fmt, args);
    (void)w;
    buffer[1024 - 1] = 0;
    va_end(args);
    consoleData->items.push_back(strdup(buffer));
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void execCommand(ConsoleData* consoleData, const char* commandLine)
{
    // TODO: Hook up as PD event

    addLog(consoleData, "# %s\n", commandLine);

    // Insert history. First find match and delete it, so it can be pushed to the back.
    consoleData->historyPos = -1;
    for (int i = int(consoleData->history.size()) - 1; i >= 0; --i)
    {
        if (strcasecmp(consoleData->history[(size_t)i], commandLine) == 0)
        {
            free(consoleData->history[(size_t)i]);
            consoleData->history.erase(consoleData->history.begin() + i);
            break;
        }
    }

    consoleData->history.push_back(strdup(commandLine));

    // Process the command

    if (strcasecmp(commandLine, "clear") == 0)
    {
        clearLog(consoleData);
    }
    else if (strcasecmp(commandLine, "help") == 0)
    {
        addLog(consoleData, "Commands:");
        for (size_t i = 0; i < consoleData->commands.size(); i++)
            addLog(consoleData, "- %s", consoleData->commands[i]);
    }
    else if (strcasecmp(commandLine, "history") == 0)
    {
        for (size_t i = consoleData->history.size() >= 10 ? consoleData->history.size() - 10 : 0; i < consoleData->history.size(); i++)
            addLog(consoleData, "%3d: %s\n", i, consoleData->history[i]);
    }
    else if (strcasecmp(commandLine, "testText") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "Some text\nSome more text\nDisplay very important message here!\n");
    }
    else if (strcasecmp(commandLine, "testError") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "[Error] Something went wrong!\n");
    }
    else if (strcasecmp(commandLine, "testScript") == 0) // TODO: Temp for testing
    {
        consoleData->scripts.push_back((char*)"print(\"Hello ProDBG Lua World!\")");
    }
    else
    {
        addLog(consoleData, "Unknown command: '%s'\n", commandLine);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void textEditCallbackStub(PDInputTextCallbackData* data)
{
    ConsoleData* consoleData = (ConsoleData*)data->userData;

    //addLog(consoleData, "Cursor: %d, EventKey: %d, Selection: %d-%d", data->cursorPos, data->eventKey, data->selectionStart, data->selectionEnd);

    std::vector<const char*> candidates;
    const char* wordEnd   = nullptr;
    const char* wordStart = nullptr;
    switch (data->eventKey)
    {
        default:
            break;

        // Tab Completion
        case PDKEY_TAB:
		{
            // Locate beginning of current word
            wordEnd   = data->buffer + data->cursorPos;
            wordStart = wordEnd;
            while (wordStart > data->buffer)
            {
                const char c = wordStart[-1];
                if (c == ' ' || c == '\t' || c == ',' || c == ';')
                    break;
                wordStart--;
            }

            // Build a list of candidates

            for (size_t i = 0; i < consoleData->commands.size(); ++i)
                if (strncasecmp(consoleData->commands[i], wordStart, (size_t)(int(wordEnd - wordStart))) == 0)
                    candidates.push_back(consoleData->commands[i]);

            if (candidates.size() == 0)
            {
                // No match
                addLog(consoleData, "No match for \"%.*s\"!\n", wordEnd - wordStart, wordStart);
            }
            else if (candidates.size() == 1)
            {
                // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing

                data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                data->insertChars(data, data->cursorPos, candidates[0], 0);
                data->insertChars(data, data->cursorPos, " ", 0);
            }
            else
            {
                // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
                int matchLen = int(wordEnd - wordStart);
                while (true)
                {
                    int c = 0;
                    bool allCandidatesMatches = true;
                    for (size_t i = 0; i < candidates.size() && allCandidatesMatches; i++)
                    {
                        if (i == 0)
                            c = toupper(candidates[i][matchLen]);
                        else if (c != toupper(candidates[i][matchLen]))
                            allCandidatesMatches = false;
                    }

                    if (!allCandidatesMatches)
                        break;

                    matchLen++;
                }

                if (matchLen > 0)
                {
                    data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                    data->insertChars(data, data->cursorPos, candidates[0], candidates[0] + matchLen);
                }

                // List matches
                addLog(consoleData, "Possible matches:\n");
                for (size_t i = 0; i < candidates.size(); i++)
                    addLog(consoleData, "- %s\n", candidates[i]);
            }

            break;
        }

        // Command History
        case PDKEY_UP:
        case PDKEY_DOWN:
		{
            const int prevHistoryPos = consoleData->historyPos;
            if (data->eventKey == PDKEY_UP)
            {
                if (consoleData->historyPos == -1)
                    consoleData->historyPos = int(consoleData->history.size()) - 1;
                else if (consoleData->historyPos > 0)
                    consoleData->historyPos--;
            }
            else if (data->eventKey == PDKEY_DOWN)
            {
                if (consoleData->historyPos != -1)
                {
                    if (++consoleData->historyPos >= int(consoleData->history.size()))
                        consoleData->historyPos = -1;
                }
            }

            // TODO: A better implementation would preserve the data on the current input line along with cursor position
            if (prevHistoryPos != consoleData->historyPos)
            {
                strcpy(data->buffer, (consoleData->historyPos >= 0) ? consoleData->history[(size_t)consoleData->historyPos] : "");
                data->bufferDirty = true;
                data->cursorPos = data->selectionStart = data->selectionEnd = int(strlen(data->buffer));
            }

            break;
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void* createInstance(PDUI* uiFuncs, ServiceFunc* serviceFunc)
{
    (void)serviceFunc;
    (void)uiFuncs;

    ConsoleData* consoleData = new ConsoleData;
    clearLog(consoleData);

    consoleData->historyPos = -1;
    consoleData->commands.push_back((char*)"HELP");
    consoleData->commands.push_back((char*)"HISTORY");
    consoleData->commands.push_back((char*)"CLEAR");
    consoleData->commands.push_back((char*)"CLASSIFY");   // TODO: "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
    consoleData->commands.push_back((char*)"TESTTEXT");   // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTERROR");  // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTSCRIPT"); // TODO: Temp, for testing

    return consoleData;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void destroyInstance(void* userData)
{
    ConsoleData* consoleData = (ConsoleData*)userData;
    clearLog(consoleData);
    free(consoleData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void showInUI(ConsoleData* consoleData, PDReader* reader, PDUI* uiFuncs)
{
    (void)consoleData;
    (void)reader;

    uiFuncs->textWrapped("ProDBG Scripting Console");
    uiFuncs->textWrapped("Enter 'HELP' for help. Press TAB to use text completion.");

    // TODO: display from bottom
    // TODO: clip manually

    if (PDUI_buttonSmall(uiFuncs, "Clear"))
        clearLog(consoleData);

    uiFuncs->sameLine(0, -1);
    uiFuncs->separator();

    PDVec2 pad = { 0.0f, 0.0f };

    uiFuncs->pushStyleVarV(PDStyleVar_FramePadding, pad);

    //static ImGuiTextFilter filter;
    //filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover

    uiFuncs->popStyleVar(1);

    uiFuncs->separator();

    PDVec2 spacing = { 0, -uiFuncs->getTextLineSpacing() * 2 };
    PDVec2 itemSpacing = { 4.0f, 1.0f };

    uiFuncs->beginChild("ScrollingRegion", spacing, false, PDWindowFlags(0));
    uiFuncs->pushStyleVarV(PDStyleVar_ItemSpacing, itemSpacing); // Tighten spacing

    for (size_t i = 0; i < consoleData->items.size(); i++)
    {
        const char* item = consoleData->items[i];
        //if (!filter.PassFilter(item))
        //    continue;
        PDVec4 col = { 1.0f, 1.0f, 1.0f, 1.0f }; // A better implementation may store a type per-item. For now let's just parse the text.
        if (strstr(item, "[Error]"))
            col = { 1.0f, 0.4f, 0.4f, 1.0f };
        else if (strncmp(item, "# ", 2) == 0)
            col = { 1.0f, 0.8f, 0.6f, 1.0f };
        uiFuncs->textColored(col, item);
    }

    if (consoleData->scrollToBottom)
        uiFuncs->setScrollHere();

    consoleData->scrollToBottom = false;

    uiFuncs->popStyleVar(1);
    uiFuncs->endChild();
    uiFuncs->separator();

    // Command Line

    if (uiFuncs->inputText("Input", consoleData->inputBuffer, sizeof(consoleData->inputBuffer), PDInputTextFlags_EnterReturnsTrue | PDInputTextFlags_CallbackCompletion | PDInputTextFlags_CallbackHistory, &textEditCallbackStub, (void*)consoleData))
    {
        char* inputEnd = consoleData->inputBuffer + strlen(consoleData->inputBuffer);

        while (inputEnd > consoleData->inputBuffer && inputEnd[-1] == ' ')
            inputEnd--;

        *inputEnd = 0;

        if (consoleData->inputBuffer[0])
            execCommand(consoleData, consoleData->inputBuffer);

        strcpy(consoleData->inputBuffer, "");
    }

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* outEvents)
{
    ConsoleData* consoleData = (ConsoleData*)userData;

    uint32_t event = 0;
    (void)event;

    // dummy

    /*while ((event = PDRead_getEvent(inEvents)) != 0)
       {
        switch (event)
        {
            case PDEventType_setConsole:
            {
                //showInUI((ConsoleData*)userData, inEvents, uiFuncs);
                break;
            }
        }
       }*/

    showInUI(consoleData, inEvents, uiFuncs);

    for (size_t i = 0; i < consoleData->scripts.size(); ++i)
    {
        PDWrite_eventBegin(outEvents, PDEventType_executeConsole);
        PDWrite_string(outEvents, "command", consoleData->scripts[i]);   // TODO: Remove me
        PDWrite_eventEnd(outEvents);
        //free(consoleData->scripts[i]);
    }

    consoleData->scripts.clear();

    // Request console data

    PDWrite_eventBegin(outEvents, PDEventType_getConsole);
    PDWrite_u8(outEvents, "dummy_remove", 0);   // TODO: Remove me
    PDWrite_eventEnd(outEvents);

    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static PDViewPlugin plugin =
{
    "Console",
    createInstance,
    destroyInstance,
    update,
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern "C"
{

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

PD_EXPORT void InitPlugin(RegisterPlugin* registerPlugin, void* privateData)
{
	registerPlugin(PD_VIEW_API_VERSION, &plugin, privateData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}

<commit_msg>Monkey test<commit_after>#include "pd_view.h"
#include "pd_view.h"
#include "pd_backend.h"
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <vector>

#if defined(_WIN32)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif

#ifdef __clang__
#pragma clang diagnostic ignored "-Wformat-nonliteral" //error: format string is not a string literal [-Werror,-Wformat-nonliteral]

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct ConsoleData
{
	ConsoleData() : historyPos(0), scrollToBottom(0)
	{
		memset(inputBuffer, 0, sizeof(inputBuffer));
	}

    char inputBuffer[256];
    std::vector<char*> items;
    std::vector<char*> commands;
    std::vector<char*> history;
    std::vector<char*> scripts; // TODO: Temp, for testing
    int historyPos; // -1: New Line, 0...history.size()-1 Browsing History
    bool scrollToBottom;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void clearLog(ConsoleData* consoleData)
{
    for (size_t i = 0; i < consoleData->items.size(); ++i)
        free(consoleData->items[i]);
    consoleData->items.clear();
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void addLog(ConsoleData* consoleData, const char* fmt, ...)
{
    char buffer[1024];
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buffer, 1024, fmt, args);
    (void)w;
    buffer[1024 - 1] = 0;
    va_end(args);
    consoleData->items.push_back(strdup(buffer));
    consoleData->scrollToBottom = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void execCommand(ConsoleData* consoleData, const char* commandLine)
{
    // TODO: Hook up as PD event

    addLog(consoleData, "# %s\n", commandLine);

    // Insert history. First find match and delete it, so it can be pushed to the back.
    consoleData->historyPos = -1;
    for (int i = int(consoleData->history.size()) - 1; i >= 0; --i)
    {
        if (strcasecmp(consoleData->history[(size_t)i], commandLine) == 0)
        {
            free(consoleData->history[(size_t)i]);
            consoleData->history.erase(consoleData->history.begin() + i);
            break;
        }
    }

    consoleData->history.push_back(strdup(commandLine));

    // Process the command

    if (strcasecmp(commandLine, "clear") == 0)
    {
        clearLog(consoleData);
    }
    else if (strcasecmp(commandLine, "help") == 0)
    {
        addLog(consoleData, "Commands:");
        for (size_t i = 0; i < consoleData->commands.size(); i++)
            addLog(consoleData, "- %s", consoleData->commands[i]);
    }
    else if (strcasecmp(commandLine, "history") == 0)
    {
        for (size_t i = consoleData->history.size() >= 10 ? consoleData->history.size() - 10 : 0; i < consoleData->history.size(); i++)
            addLog(consoleData, "%3d: %s\n", i, consoleData->history[i]);
    }
    else if (strcasecmp(commandLine, "testText") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "Some text\nSome more text\nDisplay very important message here!\n");
    }
    else if (strcasecmp(commandLine, "testError") == 0) // TODO: Temp for testing
    {
        addLog(consoleData, "[Error] Something went wrong!\n");
    }
    else if (strcasecmp(commandLine, "testScript") == 0) // TODO: Temp for testing
    {
        consoleData->scripts.push_back((char*)"print(\"Hello ProDBG Lua World!\")");
    }
    else
    {
        addLog(consoleData, "Unknown command: '%s'\n", commandLine);
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void textEditCallbackStub(PDInputTextCallbackData* data)
{
    ConsoleData* consoleData = (ConsoleData*)data->userData;

    //addLog(consoleData, "Cursor: %d, EventKey: %d, Selection: %d-%d", data->cursorPos, data->eventKey, data->selectionStart, data->selectionEnd);

    std::vector<const char*> candidates;
    const char* wordEnd   = nullptr;
    const char* wordStart = nullptr;
    switch (data->eventKey)
    {
        default:
            break;

        // Tab Completion
        case PDKEY_TAB:
		{
            // Locate beginning of current word
            wordEnd   = data->buffer + data->cursorPos;
            wordStart = wordEnd;
            while (wordStart > data->buffer)
            {
                const char c = wordStart[-1];
                if (c == ' ' || c == '\t' || c == ',' || c == ';')
                    break;
                wordStart--;
            }

            // Build a list of candidates

            for (size_t i = 0; i < consoleData->commands.size(); ++i)
                if (strncasecmp(consoleData->commands[i], wordStart, (size_t)(int(wordEnd - wordStart))) == 0)
                    candidates.push_back(consoleData->commands[i]);

            if (candidates.size() == 0)
            {
                // No match
                addLog(consoleData, "No match for \"%.*s\"!\n", wordEnd - wordStart, wordStart);
            }
            else if (candidates.size() == 1)
            {
                // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing

                data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                data->insertChars(data, data->cursorPos, candidates[0], 0);
                data->insertChars(data, data->cursorPos, " ", 0);
            }
            else
            {
                // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
                int matchLen = int(wordEnd - wordStart);
                while (true)
                {
                    int c = 0;
                    bool allCandidatesMatches = true;
                    for (size_t i = 0; i < candidates.size() && allCandidatesMatches; i++)
                    {
                        if (i == 0)
                            c = toupper(candidates[i][matchLen]);
                        else if (c != toupper(candidates[i][matchLen]))
                            allCandidatesMatches = false;
                    }

                    if (!allCandidatesMatches)
                        break;

                    matchLen++;
                }

                if (matchLen > 0)
                {
                    data->deleteChars(data, int(wordStart - data->buffer), int(wordEnd - wordStart));
                    data->insertChars(data, data->cursorPos, candidates[0], candidates[0] + matchLen);
                }

                // List matches
                addLog(consoleData, "Possible matches:\n");
                for (size_t i = 0; i < candidates.size(); i++)
                    addLog(consoleData, "- %s\n", candidates[i]);
            }

            break;
        }

        // Command History
        case PDKEY_UP:
        case PDKEY_DOWN:
		{
            const int prevHistoryPos = consoleData->historyPos;
            if (data->eventKey == PDKEY_UP)
            {
                if (consoleData->historyPos == -1)
                    consoleData->historyPos = int(consoleData->history.size()) - 1;
                else if (consoleData->historyPos > 0)
                    consoleData->historyPos--;
            }
            else if (data->eventKey == PDKEY_DOWN)
            {
                if (consoleData->historyPos != -1)
                {
                    if (++consoleData->historyPos >= int(consoleData->history.size()))
                        consoleData->historyPos = -1;
                }
            }

            // TODO: A better implementation would preserve the data on the current input line along with cursor position
            if (prevHistoryPos != consoleData->historyPos)
            {
                strcpy(data->buffer, (consoleData->historyPos >= 0) ? consoleData->history[(size_t)consoleData->historyPos] : "");
                data->bufferDirty = true;
                data->cursorPos = data->selectionStart = data->selectionEnd = int(strlen(data->buffer));
            }

            break;
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void* createInstance(PDUI* uiFuncs, ServiceFunc* serviceFunc)
{
    (void)serviceFunc;
    (void)uiFuncs;

    ConsoleData* consoleData = new ConsoleData;
    clearLog(consoleData);

    consoleData->historyPos = -1;
    consoleData->commands.push_back((char*)"HELP");
    consoleData->commands.push_back((char*)"HISTORY");
    consoleData->commands.push_back((char*)"CLEAR");
    consoleData->commands.push_back((char*)"CLASSIFY");   // TODO: "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
    consoleData->commands.push_back((char*)"TESTTEXT");   // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTERROR");  // TODO: Temp, for testing
    consoleData->commands.push_back((char*)"TESTSCRIPT"); // TODO: Temp, for testing

    return consoleData;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void destroyInstance(void* userData)
{
    ConsoleData* consoleData = (ConsoleData*)userData;
    clearLog(consoleData);
    free(consoleData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static void showInUI(ConsoleData* consoleData, PDReader* reader, PDUI* uiFuncs)
{
    (void)consoleData;
    (void)reader;

    uiFuncs->textWrapped("ProDBG Scripting Console");
    uiFuncs->textWrapped("Enter 'HELP' for help. Press TAB to use text completion.");

    // TODO: display from bottom
    // TODO: clip manually

    if (PDUI_buttonSmall(uiFuncs, "Clear"))
        clearLog(consoleData);

    uiFuncs->sameLine(0, -1);
    uiFuncs->separator();

    PDVec2 pad = { 0.0f, 0.0f };

    uiFuncs->pushStyleVarV(PDStyleVar_FramePadding, pad);

    //static ImGuiTextFilter filter;
    //filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover

    uiFuncs->popStyleVar(1);

    uiFuncs->separator();

    PDVec2 spacing = { 0, -uiFuncs->getTextLineSpacing() * 2 };
    PDVec2 itemSpacing = { 4.0f, 1.0f };

    uiFuncs->beginChild("ScrollingRegion", spacing, false, PDWindowFlags(0));
    uiFuncs->pushStyleVarV(PDStyleVar_ItemSpacing, itemSpacing); // Tighten spacing

    for (size_t i = 0; i < consoleData->items.size(); i++)
    {
        const char* item = consoleData->items[i];
        //if (!filter.PassFilter(item))
        //    continue;
        PDVec4 col = { 1.0f, 1.0f, 1.0f, 1.0f }; // A better implementation may store a type per-item. For now let's just parse the text.
        if (strstr(item, "[Error]"))
            col = { 1.0f, 0.4f, 0.4f, 1.0f };
        else if (strncmp(item, "# ", 2) == 0)
            col = { 1.0f, 0.8f, 0.6f, 1.0f };
        uiFuncs->textColored(col, item);
    }

    if (consoleData->scrollToBottom)
        uiFuncs->setScrollHere();

    consoleData->scrollToBottom = false;

    uiFuncs->popStyleVar(1);
    uiFuncs->endChild();
    uiFuncs->separator();

    // Command Line

    if (uiFuncs->inputText("Input", consoleData->inputBuffer, sizeof(consoleData->inputBuffer), PDInputTextFlags_EnterReturnsTrue | PDInputTextFlags_CallbackCompletion | PDInputTextFlags_CallbackHistory, &textEditCallbackStub, (void*)consoleData))
    {
        char* inputEnd = consoleData->inputBuffer + strlen(consoleData->inputBuffer);

        while (inputEnd > consoleData->inputBuffer && inputEnd[-1] == ' ')
            inputEnd--;

        *inputEnd = 0;

        if (consoleData->inputBuffer[0])
            execCommand(consoleData, consoleData->inputBuffer);

        strcpy(consoleData->inputBuffer, "");
    }

    if (uiFuncs->isItemHovered())
        uiFuncs->setKeyboardFocusHere(-1); // Auto focus on hover
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static int update(void* userData, PDUI* uiFuncs, PDReader* inEvents, PDWriter* outEvents)
{
    ConsoleData* consoleData = (ConsoleData*)userData;

    uint32_t event = 0;
    (void)event;

    // dummy
    // sotehusoeth

    /*while ((event = PDRead_getEvent(inEvents)) != 0)
       {
        switch (event)
        {
            case PDEventType_setConsole:
            {
                //showInUI((ConsoleData*)userData, inEvents, uiFuncs);
                break;
            }
        }
       }*/

    showInUI(consoleData, inEvents, uiFuncs);

    for (size_t i = 0; i < consoleData->scripts.size(); ++i)
    {
        PDWrite_eventBegin(outEvents, PDEventType_executeConsole);
        PDWrite_string(outEvents, "command", consoleData->scripts[i]);   // TODO: Remove me
        PDWrite_eventEnd(outEvents);
        //free(consoleData->scripts[i]);
    }

    consoleData->scripts.clear();

    // Request console data

    PDWrite_eventBegin(outEvents, PDEventType_getConsole);
    PDWrite_u8(outEvents, "dummy_remove", 0);   // TODO: Remove me
    PDWrite_eventEnd(outEvents);

    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static PDViewPlugin plugin =
{
    "Console",
    createInstance,
    destroyInstance,
    update,
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern "C"
{

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

PD_EXPORT void InitPlugin(RegisterPlugin* registerPlugin, void* privateData)
{
	registerPlugin(PD_VIEW_API_VERSION, &plugin, privateData);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}

<|endoftext|>