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

#include "IECore/PointsPrimitive.h"
#include "IECore/Exception.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/MessageHandler.h"

#include "IECoreGL/ToGLPointsConverter.h"
#include "IECoreGL/PointsPrimitive.h"

using namespace IECoreGL;

ToGLPointsConverter::ToGLPointsConverter( IECore::ConstPointsPrimitivePtr toConvert )
	:	ToGLConverter( "Converts IECore::PointsPrimitive objects to IECoreGL::PointsPrimitive objects.", IECore::PointsPrimitiveTypeId )
{
	srcParameter()->setValue( IECore::constPointerCast<IECore::PointsPrimitive>( toConvert ) );
}

ToGLPointsConverter::~ToGLPointsConverter()
{
}

IECore::RunTimeTypedPtr ToGLPointsConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const
{
	IECore::PointsPrimitive::ConstPtr pointsPrim = IECore::staticPointerCast<const IECore::PointsPrimitive>( src ); // safe because the parameter validated it for us

	IECore::V3fVectorData::ConstPtr points = pointsPrim->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex );
	if( !points )
	{
		throw IECore::Exception( "Must specify primitive variable \"P\", of type V3fVectorData and interpolation type Vertex." );
	}

	// get type
	PointsPrimitive::Type type = PointsPrimitive::Disk;
	if( IECore::ConstStringDataPtr t = pointsPrim->variableData<IECore::StringData>( "type", IECore::PrimitiveVariable::Uniform ) )
	{
		if( t->readable()=="particle" || t->readable()=="disk" || t->readable()=="blobby" )
		{
			type = PointsPrimitive::Disk;
		}
		else if( t->readable()=="sphere" )
		{
			type = PointsPrimitive::Sphere;
		}
		else if( t->readable()=="patch" )
		{
			type = PointsPrimitive::Quad;
		}
		else if( t->readable()=="gl:point" )
		{
			type = PointsPrimitive::Point;
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter::doConversion", boost::format( "Unknown type \"%s\" - reverting to particle type." ) % t->readable() );
		}
	}

	PointsPrimitive::Ptr result = new PointsPrimitive( type );

	for ( IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.begin(); pIt != pointsPrim->variables.end(); ++pIt )
	{
		if ( pIt->first == "type" )
			continue;

		if ( pIt->second.data )
		{
			result->addPrimitiveVariable( pIt->first, pIt->second );
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter", boost::format( "No data given for primvar \"%s\"" ) % pIt->first );
		}
	}

	IECore::ConstFloatVectorDataPtr widths = pointsPrim->variableData<IECore::FloatVectorData>( "width" );
	IECore::ConstFloatDataPtr width = pointsPrim->variableData<IECore::FloatData>( "width", IECore::PrimitiveVariable::Constant );

	// use "constantwidth" as "width"
	if ( pointsPrim->variables.find( "width" ) == pointsPrim->variables.end() )
	{
		IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.find( "constantwidth" );
		if ( pIt != pointsPrim->variables.end() )
		{
			result->addPrimitiveVariable( "width", pIt->second );
			width = IECore::runTimeCast< const IECore::FloatData >(pIt->second.data);
		}
	}

	// compute heights
	IECore::ConstFloatDataPtr constantAspectData = pointsPrim->variableData<IECore::FloatData>( "patchaspectratio", IECore::PrimitiveVariable::Constant );
	IECore::ConstFloatVectorDataPtr aspectData = pointsPrim->variableData<IECore::FloatVectorData>( "patchaspectratio" );

	if( !constantAspectData && !aspectData )
	{
		// heights = width
		if ( widths )
		{
			result->addPrimitiveVariable( "height", pointsPrim->variables.find( "width" )->second );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() ) ) );
		}
	}
	else if( constantAspectData )
	{
		float aspect = constantAspectData->readable();
		if ( widths )
		{
			IECore::FloatVectorDataPtr h = widths->copy();
			std::vector<float> &hV = h->writable();
			for( unsigned int i=0; i<hV.size(); i++ )
			{
				hV[i] /= aspect;
			}
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("width")->second.interpolation, h ) );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() / aspect) ) );
		}
	}
	else
	{
		// we have varying aspect data
		IECore::FloatVectorDataPtr h = aspectData->copy();
		std::vector<float> &hV = h->writable();
		float defaultWidth = 1;
		const float *widthsP = &defaultWidth;
		unsigned int widthStride = 0;
		if( widths )
		{
			widthsP = &widths->readable()[0];
			if ( widths->readable().size() == aspectData->readable().size() )
				widthStride = 1;
		}
		else if ( width )
		{
			widthsP = &width->readable();
			widthStride = 0;
		}
		for( unsigned int i=0; i<hV.size(); i++ )
		{
			hV[i] = *widthsP / hV[i];
			widthsP += widthStride;
		}
		result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("patchaspectratio")->second.interpolation, h ) );
	}
	return result;
}
<commit_msg>Testing "type" primvar as Constant, and if it's not there, then test as Uniform. Should be Constant because if it's Uniform than arePrimitiveVariablesValid() returns False.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/PointsPrimitive.h"
#include "IECore/Exception.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/MessageHandler.h"

#include "IECoreGL/ToGLPointsConverter.h"
#include "IECoreGL/PointsPrimitive.h"

using namespace IECoreGL;

ToGLPointsConverter::ToGLPointsConverter( IECore::ConstPointsPrimitivePtr toConvert )
	:	ToGLConverter( "Converts IECore::PointsPrimitive objects to IECoreGL::PointsPrimitive objects.", IECore::PointsPrimitiveTypeId )
{
	srcParameter()->setValue( IECore::constPointerCast<IECore::PointsPrimitive>( toConvert ) );
}

ToGLPointsConverter::~ToGLPointsConverter()
{
}

IECore::RunTimeTypedPtr ToGLPointsConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const
{
	IECore::PointsPrimitive::ConstPtr pointsPrim = IECore::staticPointerCast<const IECore::PointsPrimitive>( src ); // safe because the parameter validated it for us

	IECore::V3fVectorData::ConstPtr points = pointsPrim->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex );
	if( !points )
	{
		throw IECore::Exception( "Must specify primitive variable \"P\", of type V3fVectorData and interpolation type Vertex." );
	}

	// get type
	PointsPrimitive::Type type = PointsPrimitive::Disk;
	IECore::ConstStringDataPtr t = pointsPrim->variableData<IECore::StringData>( "type", IECore::PrimitiveVariable::Constant );
	if ( !t )
	{
		t = pointsPrim->variableData<IECore::StringData>( "type", IECore::PrimitiveVariable::Uniform );
	}
	if( t )
	{
		if( t->readable()=="particle" || t->readable()=="disk" || t->readable()=="blobby" )
		{
			type = PointsPrimitive::Disk;
		}
		else if( t->readable()=="sphere" )
		{
			type = PointsPrimitive::Sphere;
		}
		else if( t->readable()=="patch" )
		{
			type = PointsPrimitive::Quad;
		}
		else if( t->readable()=="gl:point" )
		{
			type = PointsPrimitive::Point;
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter::doConversion", boost::format( "Unknown type \"%s\" - reverting to particle type." ) % t->readable() );
		}
	}

	PointsPrimitive::Ptr result = new PointsPrimitive( type );

	for ( IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.begin(); pIt != pointsPrim->variables.end(); ++pIt )
	{
		if ( pIt->first == "type" )
			continue;

		if ( pIt->second.data )
		{
			result->addPrimitiveVariable( pIt->first, pIt->second );
		}
		else
		{
			IECore::msg( IECore::Msg::Warning, "ToGLPointsConverter", boost::format( "No data given for primvar \"%s\"" ) % pIt->first );
		}
	}

	IECore::ConstFloatVectorDataPtr widths = pointsPrim->variableData<IECore::FloatVectorData>( "width" );
	IECore::ConstFloatDataPtr width = pointsPrim->variableData<IECore::FloatData>( "width", IECore::PrimitiveVariable::Constant );

	// use "constantwidth" as "width"
	if ( pointsPrim->variables.find( "width" ) == pointsPrim->variables.end() )
	{
		IECore::PrimitiveVariableMap::const_iterator pIt = pointsPrim->variables.find( "constantwidth" );
		if ( pIt != pointsPrim->variables.end() )
		{
			result->addPrimitiveVariable( "width", pIt->second );
			width = IECore::runTimeCast< const IECore::FloatData >(pIt->second.data);
		}
	}

	// compute heights
	IECore::ConstFloatDataPtr constantAspectData = pointsPrim->variableData<IECore::FloatData>( "patchaspectratio", IECore::PrimitiveVariable::Constant );
	IECore::ConstFloatVectorDataPtr aspectData = pointsPrim->variableData<IECore::FloatVectorData>( "patchaspectratio" );

	if( !constantAspectData && !aspectData )
	{
		// heights = width
		if ( widths )
		{
			result->addPrimitiveVariable( "height", pointsPrim->variables.find( "width" )->second );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() ) ) );
		}
	}
	else if( constantAspectData )
	{
		float aspect = constantAspectData->readable();
		if ( widths )
		{
			IECore::FloatVectorDataPtr h = widths->copy();
			std::vector<float> &hV = h->writable();
			for( unsigned int i=0; i<hV.size(); i++ )
			{
				hV[i] /= aspect;
			}
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("width")->second.interpolation, h ) );
		}
		else if ( width )
		{
			// constant width...
			result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new IECore::FloatData(width->readable() / aspect) ) );
		}
	}
	else
	{
		// we have varying aspect data
		IECore::FloatVectorDataPtr h = aspectData->copy();
		std::vector<float> &hV = h->writable();
		float defaultWidth = 1;
		const float *widthsP = &defaultWidth;
		unsigned int widthStride = 0;
		if( widths )
		{
			widthsP = &widths->readable()[0];
			if ( widths->readable().size() == aspectData->readable().size() )
				widthStride = 1;
		}
		else if ( width )
		{
			widthsP = &width->readable();
			widthStride = 0;
		}
		for( unsigned int i=0; i<hV.size(); i++ )
		{
			hV[i] = *widthsP / hV[i];
			widthsP += widthStride;
		}
		result->addPrimitiveVariable( "height", IECore::PrimitiveVariable( pointsPrim->variables.find("patchaspectratio")->second.interpolation, h ) );
	}
	return result;
}
<|endoftext|>


<commit_before>#ifndef DELEGATE_HPP
#define DELEGATE_HPP

#include <type_traits>
#include "variadic.hpp"

namespace ctl {
    template<typename T>
    struct delegate;

    namespace impl {
        template<typename R, typename T>
        struct is_valid_function_signature;

        template<typename R>
        struct is_valid_function_signature<R, std::nullptr_t> : std::false_type {};

        template<typename R, typename ... Args, typename T>
        struct is_valid_function_signature<R(Args...), T> : std::integral_constant<bool,
            std::is_convertible<ctl::return_type<T>, R>::value &&
            ctl::argument_count<T>::value == sizeof...(Args) &&
            ctl::are_convertible<ctl::function_arguments<T>, type_list<Args...>>::value> {};

        template<typename R, typename T>
        using is_valid_function_signature_t = typename is_valid_function_signature<
            R, typename std::decay<T>::type>::type;
    }

    /// Wrapper to store lambda functions.
    /** This structure is a simple wrapper that, much like std::bind(), stores the "this" pointer of
        member functions in order to use member functions like normal functions.
        The bound member function does not need to have the same signature as that of the delegate.
        The delegate parameters just need to be implicitly convertible to that of the member
        function, and the converse is true for the return value.

        Use case:

        \code{.cpp}
            std::vector<delegate<int(int)>> v;
            v.push_back([](int i) { return 1*i; });
            v.push_back([](int i) { return 2*i; });
            v.push_back([](int i) { return 3*i; });
            for (auto& d : v) {
                std::cout << d(12) << std::endl;
            }
        \endcode

        It shares similar features with std::function, except that it does not support free
        functions and custom allocators (not needed). On the other hand, it is tailored for use with
        lambda functions (or any other functor), and provides substantial performance improvements
        over std::function (about a factor 2 faster with clang & gcc in -O3).

        Based on "Impossibly fast C++ delegates".
        http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
    **/
    template<typename R, typename ... Args>
    struct delegate<R(Args...)> {
        /// Default constructor.
        /** When default constructed, a delegate is in "empty" state. See empty().
        **/
        delegate() = default;
        delegate(std::nullptr_t) : delegate() {}

        /// Construct a new delegate from a member function.
        /** \param obj The object on which the delegate acts. When the object is given as a
                       reference or a pointer, then only a pointer to this object is kept inside
                       the delegate, and the object is expected to outlive the delegate. On the
                       other hand, if the object is given as an r-value (either a temporary or an
                       r-value reference), a new instance is move constructed inside the delegate,
                       and its lifetime is bound to that of the delegate.
            \param fun The member function. It can be given either as a function pointer, or as an
                       std::integral_constant. The latter is usually faster because the function
                       pointer is a template argument, and can be more easily inlined by the
                       compiler, but it is also more tedious to write.
        **/
        template<typename T, typename M, typename enable = typename std::enable_if<
            impl::is_valid_function_signature_t<R(Args...), M>::value>::type>
        delegate(T&& obj, M&& fun) {
            init_obj_(std::forward<T>(obj));
            init_fun_<T>(std::forward<M>(fun));
        }

        /// Construct a new delegate from a functor or lambda.
        /** \param obj The functor or lambda. If the functor is given as a reference or a pointer,
                       then only a pointer to this object is kept inside the delegate, and the
                       object is expected to outlive the delegate. On the other hand, if the
                       object is given as an r-value (either a temporary or an r-value reference),
                       a new instance is move constructed inside the delegate, and its lifetime is
                       bound to that of the delegate.
        **/
        template<typename T, typename enable = typename std::enable_if<
            impl::is_valid_function_signature_t<R(Args...), T>::value>::type>
        delegate(T&& obj) {
            init_obj_(std::forward<T>(obj));
            using RT = typename std::remove_reference<T>::type;
            init_fun_<T>(std::integral_constant<decltype(&RT::operator()),&RT::operator()>());
        }

        delegate(const delegate&) = delete;
        delegate& operator= (const delegate&) = delete;

        /// Move constructor.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate(delegate&& d) :
            fun_(d.fun_), wfun_(d.wfun_), del_(d.del_), mov_(d.mov_) {
            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;
        }

        /// Destructor
        ~delegate() {
            if (del_) {
                (*del_)(obj_);
            }
        }

        /// Move assignment.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate& operator= (delegate&& d) {
            if (del_) {
                (*del_)(obj_);
            }

            del_ = d.del_;
            mov_ = d.mov_;
            fun_ = d.fun_;
            wfun_ = d.wfun_;

            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;

            return *this;
        }

        /// Assign a new functor or lambda to this delegate.
        /** \param obj The functor or lambda. If the functor is given as a reference or a pointer,
                       then only a pointer to this object is kept inside the delegate, and the
                       object is expected to outlive the delegate. On the other hand, if the
                       object is given as an r-value (either a temporary or an r-value reference),
                       a new instance is move constructed inside the delegate, and its lifetime is
                       bound to that of the delegate.
        **/
        // template<typename T, typename enable = typename std::enable_if<std::is_convertible<
        //     return_type<T>, R>::value>::type>
        // delegate& operator= (T&& obj) {
        //     clear();

        //     init_obj_(std::forward<T>(obj));
        //     using RT = typename std::remove_reference<T>::type;
        //     init_fun_<T>(std::integral_constant<decltype(&RT::operator()),&RT::operator()>());
        //     return *this;
        // }

        /// Put the delegate in "empty" state. See empty().
        delegate& operator= (const std::nullptr_t&) {
            clear();
            return *this;
        }

        /// Put the delegate in "empty" state. See empty().
        void clear() {
            if (del_) {
                (*del_)(obj_);
            }

            obj_ = nullptr;
            del_ = nullptr;
            mov_ = nullptr;
            fun_ = nullptr;
            wfun_ = nullptr;
        }

        /// Return 'true' if in "empty" state.
        /** When in "empty" state, a delegate has minimal memory usage.
            Trying to call an empty delegate will crash the program.
        **/
        bool empty() const {
            return obj_ == nullptr;
        }

        /// Check if the delegate is not in "empty" state.
        explicit operator bool () const {
            return !empty();
        }

        bool operator == (std::nullptr_t) const {
            return empty();
        }

        bool operator != (std::nullptr_t) const {
            return !empty();
        }

        /// Call the delegate.
        R operator() (Args ... args) const {
            return (*wfun_)(obj_, fun_, std::forward<Args>(args)...);
        }

    private :
        using wfun_t = R (*)(void*, void*, Args...);
        using dfun_t = void (*)(void*);
        using mfun_t = void (*)(delegate&&, delegate&);

        static const std::size_t max_small_object_size = 2*sizeof(std::size_t);

        void* obj_ = nullptr;
        char inplace_[max_small_object_size];

        void* fun_ = nullptr;
        wfun_t wfun_ = nullptr;

        dfun_t del_ = nullptr;
        mfun_t mov_ = nullptr;

        template<typename T>
        static void deleter_(void* obj) {
            delete static_cast<T*>(obj);
        }

        template<typename T>
        static void inplace_deleter_(void* obj) {
            static_cast<T*>(obj)->~T();
        }

        template<typename T>
        static void inplace_mover_(delegate&& from, delegate& to) {
            to.obj_ = new (static_cast<void*>(to.inplace_)) T(std::move(*static_cast<T*>(from.obj_)));
            inplace_deleter_<T>(from.obj_);
        }

        template<typename T, typename M>
        static R wrapper_(void* obj, void* fun, Args... args) {
            M cfun = nullptr;
            *reinterpret_cast<void**>(&cfun) = fun;
            return (static_cast<T*>(obj)->*cfun)(std::forward<Args>(args)...);
        }

        template<typename T, typename M, M m>
        static R template_wrapper_(void* obj, void*, Args... args) {
            return (static_cast<T*>(obj)->*m)(std::forward<Args>(args)...);
        }

        template<typename T>
        void init_obj_(T& obj) {
            obj_ = &obj;
        }

        template<typename T>
        void init_obj_(T* obj) {
            obj_ = obj;
        }

        template<typename T>
        void init_obj_(T&& obj, std::false_type) {
            obj_ = new T(std::forward<T>(obj));
            del_ = &deleter_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj, std::true_type) {
            // Small object optimization
            obj_ = new (static_cast<void*>(inplace_)) T(std::forward<T>(obj));
            del_ = &inplace_deleter_<T>;
            mov_ = &inplace_mover_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj) {
            init_obj_(std::forward<T>(obj),
                std::integral_constant<bool, sizeof(T) <= max_small_object_size>{});
        }

        template<typename T, typename FT, FT F>
        void init_fun_(std::integral_constant<FT,F>) {
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &template_wrapper_<RT, FT, F>;
        }

        template<typename T, typename M>
        void init_fun_(M fun) {
            fun_ = *reinterpret_cast<void**>(&fun);
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &wrapper_<RT, M>;
        }
    };
}

#define make_delegate(obj,func) ctl::delegate<ctl::get_signature<decltype(func)>>( \
    obj, std::integral_constant<decltype(func),func>{})

#endif
<commit_msg>Fixed ambiguous template instantiation found by gcc 7.4<commit_after>#ifndef DELEGATE_HPP
#define DELEGATE_HPP

#include <type_traits>
#include "variadic.hpp"

namespace ctl {
    template<typename T>
    struct delegate;

    namespace impl {
        template<typename R, typename T>
        struct is_valid_function_signature;

        template<typename R, typename ... Args>
        struct is_valid_function_signature<R(Args...), std::nullptr_t> : std::false_type {};

        template<typename R, typename ... Args, typename T>
        struct is_valid_function_signature<R(Args...), T> : std::integral_constant<bool,
            std::is_convertible<ctl::return_type<T>, R>::value &&
            ctl::argument_count<T>::value == sizeof...(Args) &&
            ctl::are_convertible<ctl::function_arguments<T>, type_list<Args...>>::value> {};

        template<typename R, typename T>
        using is_valid_function_signature_t = typename is_valid_function_signature<
            R, typename std::decay<T>::type>::type;
    }

    /// Wrapper to store lambda functions.
    /** This structure is a simple wrapper that, much like std::bind(), stores the "this" pointer of
        member functions in order to use member functions like normal functions.
        The bound member function does not need to have the same signature as that of the delegate.
        The delegate parameters just need to be implicitly convertible to that of the member
        function, and the converse is true for the return value.

        Use case:

        \code{.cpp}
            std::vector<delegate<int(int)>> v;
            v.push_back([](int i) { return 1*i; });
            v.push_back([](int i) { return 2*i; });
            v.push_back([](int i) { return 3*i; });
            for (auto& d : v) {
                std::cout << d(12) << std::endl;
            }
        \endcode

        It shares similar features with std::function, except that it does not support free
        functions and custom allocators (not needed). On the other hand, it is tailored for use with
        lambda functions (or any other functor), and provides substantial performance improvements
        over std::function (about a factor 2 faster with clang & gcc in -O3).

        Based on "Impossibly fast C++ delegates".
        http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
    **/
    template<typename R, typename ... Args>
    struct delegate<R(Args...)> {
        /// Default constructor.
        /** When default constructed, a delegate is in "empty" state. See empty().
        **/
        delegate() = default;
        delegate(std::nullptr_t) : delegate() {}

        /// Construct a new delegate from a member function.
        /** \param obj The object on which the delegate acts. When the object is given as a
                       reference or a pointer, then only a pointer to this object is kept inside
                       the delegate, and the object is expected to outlive the delegate. On the
                       other hand, if the object is given as an r-value (either a temporary or an
                       r-value reference), a new instance is move constructed inside the delegate,
                       and its lifetime is bound to that of the delegate.
            \param fun The member function. It can be given either as a function pointer, or as an
                       std::integral_constant. The latter is usually faster because the function
                       pointer is a template argument, and can be more easily inlined by the
                       compiler, but it is also more tedious to write.
        **/
        template<typename T, typename M, typename enable = typename std::enable_if<
            impl::is_valid_function_signature_t<R(Args...), M>::value>::type>
        delegate(T&& obj, M&& fun) {
            init_obj_(std::forward<T>(obj));
            init_fun_<T>(std::forward<M>(fun));
        }

        /// Construct a new delegate from a functor or lambda.
        /** \param obj The functor or lambda. If the functor is given as a reference or a pointer,
                       then only a pointer to this object is kept inside the delegate, and the
                       object is expected to outlive the delegate. On the other hand, if the
                       object is given as an r-value (either a temporary or an r-value reference),
                       a new instance is move constructed inside the delegate, and its lifetime is
                       bound to that of the delegate.
        **/
        template<typename T, typename enable = typename std::enable_if<
            impl::is_valid_function_signature_t<R(Args...), T>::value>::type>
        delegate(T&& obj) {
            init_obj_(std::forward<T>(obj));
            using RT = typename std::remove_reference<T>::type;
            init_fun_<T>(std::integral_constant<decltype(&RT::operator()),&RT::operator()>());
        }

        delegate(const delegate&) = delete;
        delegate& operator= (const delegate&) = delete;

        /// Move constructor.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate(delegate&& d) :
            fun_(d.fun_), wfun_(d.wfun_), del_(d.del_), mov_(d.mov_) {
            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;
        }

        /// Destructor
        ~delegate() {
            if (del_) {
                (*del_)(obj_);
            }
        }

        /// Move assignment.
        /** The delegate object that is moved into this one is left in empty state.
        **/
        delegate& operator= (delegate&& d) {
            if (del_) {
                (*del_)(obj_);
            }

            del_ = d.del_;
            mov_ = d.mov_;
            fun_ = d.fun_;
            wfun_ = d.wfun_;

            if (mov_) {
                (*mov_)(std::move(d), *this);
                d.mov_ = nullptr;
            } else {
                obj_ = d.obj_;
            }

            d.obj_ = nullptr;
            d.del_ = nullptr;
            d.fun_ = nullptr;
            d.wfun_ = nullptr;

            return *this;
        }

        /// Assign a new functor or lambda to this delegate.
        /** \param obj The functor or lambda. If the functor is given as a reference or a pointer,
                       then only a pointer to this object is kept inside the delegate, and the
                       object is expected to outlive the delegate. On the other hand, if the
                       object is given as an r-value (either a temporary or an r-value reference),
                       a new instance is move constructed inside the delegate, and its lifetime is
                       bound to that of the delegate.
        **/
        // template<typename T, typename enable = typename std::enable_if<std::is_convertible<
        //     return_type<T>, R>::value>::type>
        // delegate& operator= (T&& obj) {
        //     clear();

        //     init_obj_(std::forward<T>(obj));
        //     using RT = typename std::remove_reference<T>::type;
        //     init_fun_<T>(std::integral_constant<decltype(&RT::operator()),&RT::operator()>());
        //     return *this;
        // }

        /// Put the delegate in "empty" state. See empty().
        delegate& operator= (std::nullptr_t) {
            clear();
            return *this;
        }

        /// Put the delegate in "empty" state. See empty().
        void clear() {
            if (del_) {
                (*del_)(obj_);
            }

            obj_ = nullptr;
            del_ = nullptr;
            mov_ = nullptr;
            fun_ = nullptr;
            wfun_ = nullptr;
        }

        /// Return 'true' if in "empty" state.
        /** When in "empty" state, a delegate has minimal memory usage.
            Trying to call an empty delegate will crash the program.
        **/
        bool empty() const {
            return obj_ == nullptr;
        }

        /// Check if the delegate is not in "empty" state.
        explicit operator bool () const {
            return !empty();
        }

        bool operator == (std::nullptr_t) const {
            return empty();
        }

        bool operator != (std::nullptr_t) const {
            return !empty();
        }

        /// Call the delegate.
        R operator() (Args ... args) const {
            return (*wfun_)(obj_, fun_, std::forward<Args>(args)...);
        }

    private :
        using wfun_t = R (*)(void*, void*, Args...);
        using dfun_t = void (*)(void*);
        using mfun_t = void (*)(delegate&&, delegate&);

        static const std::size_t max_small_object_size = 2*sizeof(std::size_t);

        void* obj_ = nullptr;
        char inplace_[max_small_object_size];

        void* fun_ = nullptr;
        wfun_t wfun_ = nullptr;

        dfun_t del_ = nullptr;
        mfun_t mov_ = nullptr;

        template<typename T>
        static void deleter_(void* obj) {
            delete static_cast<T*>(obj);
        }

        template<typename T>
        static void inplace_deleter_(void* obj) {
            static_cast<T*>(obj)->~T();
        }

        template<typename T>
        static void inplace_mover_(delegate&& from, delegate& to) {
            to.obj_ = new (static_cast<void*>(to.inplace_)) T(std::move(*static_cast<T*>(from.obj_)));
            inplace_deleter_<T>(from.obj_);
        }

        template<typename T, typename M>
        static R wrapper_(void* obj, void* fun, Args... args) {
            M cfun = nullptr;
            *reinterpret_cast<void**>(&cfun) = fun;
            return (static_cast<T*>(obj)->*cfun)(std::forward<Args>(args)...);
        }

        template<typename T, typename M, M m>
        static R template_wrapper_(void* obj, void*, Args... args) {
            return (static_cast<T*>(obj)->*m)(std::forward<Args>(args)...);
        }

        template<typename T>
        void init_obj_(T& obj) {
            obj_ = &obj;
        }

        template<typename T>
        void init_obj_(T* obj) {
            obj_ = obj;
        }

        template<typename T>
        void init_obj_(T&& obj, std::false_type) {
            obj_ = new T(std::forward<T>(obj));
            del_ = &deleter_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj, std::true_type) {
            // Small object optimization
            obj_ = new (static_cast<void*>(inplace_)) T(std::forward<T>(obj));
            del_ = &inplace_deleter_<T>;
            mov_ = &inplace_mover_<T>;
        }

        template<typename T>
        void init_obj_(T&& obj) {
            init_obj_(std::forward<T>(obj),
                std::integral_constant<bool, sizeof(T) <= max_small_object_size>{});
        }

        template<typename T, typename FT, FT F>
        void init_fun_(std::integral_constant<FT,F>) {
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &template_wrapper_<RT, FT, F>;
        }

        template<typename T, typename M>
        void init_fun_(M fun) {
            fun_ = *reinterpret_cast<void**>(&fun);
            using RT = typename std::remove_reference<T>::type;
            wfun_ = &wrapper_<RT, M>;
        }
    };
}

#define make_delegate(obj,func) ctl::delegate<ctl::get_signature<decltype(func)>>( \
    obj, std::integral_constant<decltype(func),func>{})

#endif
<|endoftext|>


<commit_before>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2016 ZXing authors
* Copyright 2022 Axel Waggershauser
*/
// SPDX-License-Identifier: Apache-2.0

#include "HRI.h"

#include "ZXAlgorithms.h"

#include <sstream>

namespace ZXing {

struct AiInfo
{
	std::string_view aiPrefix;
	int _fieldSize;	// if negative, the length is variable and abs(length) give the max size

	bool isVariableLength() const noexcept { return _fieldSize < 0; }
	int fieldSize() const noexcept { return std::abs(_fieldSize); }
	int aiSize() const
	{
		if ((aiPrefix[0] == '3' && Contains("1234569", aiPrefix[1])) || aiPrefix == "703" || aiPrefix == "723")
			return 4;
		else
			return Size(aiPrefix);
	}
};

// GS1 General Specifications Release 22.0 (Jan 22, 2022)
static const AiInfo aiInfos[] = {
// TWO_DIGIT_DATA_LENGTH
	{ "00", 18 },
	{ "01", 14 },
	{ "02", 14 },

	{ "10", -20 },
	{ "11", 6 },
	{ "12", 6 },
	{ "13", 6 },
	{ "15", 6 },
	{ "16", 6 },
	{ "17", 6 },

	{ "20", 2 },
	{ "21", -20 },
	{ "22", -20 },

	{ "30", -8 },
	{ "37", -8 },

	//internal company codes
	{ "90", -30 },
	{ "91", -90 },
	{ "92", -90 },
	{ "93", -90 },
	{ "94", -90 },
	{ "95", -90 },
	{ "96", -90 },
	{ "97", -90 },
	{ "98", -90 },
	{ "99", -90 },

//THREE_DIGIT_DATA_LENGTH
	{ "235", -28 },
	{ "240", -30 },
	{ "241", -30 },
	{ "242", -6 },
	{ "243", -20 },
	{ "250", -30 },
	{ "251", -30 },
	{ "253", -30 },
	{ "254", -20 },
	{ "255", -25 },

	{ "400", -30 },
	{ "401", -30 },
	{ "402", 17 },
	{ "403", -30 },
	{ "410", 13 },
	{ "411", 13 },
	{ "412", 13 },
	{ "413", 13 },
	{ "414", 13 },
	{ "415", 13 },
	{ "416", 13 },
	{ "417", 13 },
	{ "420", -20 },
	{ "421", -12 },
	{ "422", 3 },
	{ "423", -15 },
	{ "424", 3 },
	{ "425", -15 },
	{ "426", 3 },
	{ "427", -3 },

	{ "710", -20 },
	{ "711", -20 },
	{ "712", -20 },
	{ "713", -20 },
	{ "714", -20 },
	{ "715", -20 },

//THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH
	{ "310", 6 },
	{ "311", 6 },
	{ "312", 6 },
	{ "313", 6 },
	{ "314", 6 },
	{ "315", 6 },
	{ "316", 6 },
	{ "320", 6 },
	{ "321", 6 },
	{ "322", 6 },
	{ "323", 6 },
	{ "324", 6 },
	{ "325", 6 },
	{ "326", 6 },
	{ "327", 6 },
	{ "328", 6 },
	{ "329", 6 },
	{ "330", 6 },
	{ "331", 6 },
	{ "332", 6 },
	{ "333", 6 },
	{ "334", 6 },
	{ "335", 6 },
	{ "336", 6 },
	{ "337", 6 },
	{ "340", 6 },
	{ "341", 6 },
	{ "342", 6 },
	{ "343", 6 },
	{ "344", 6 },
	{ "345", 6 },
	{ "346", 6 },
	{ "347", 6 },
	{ "348", 6 },
	{ "349", 6 },
	{ "350", 6 },
	{ "351", 6 },
	{ "352", 6 },
	{ "353", 6 },
	{ "354", 6 },
	{ "355", 6 },
	{ "356", 6 },
	{ "357", 6 },
	{ "360", 6 },
	{ "361", 6 },
	{ "362", 6 },
	{ "363", 6 },
	{ "364", 6 },
	{ "365", 6 },
	{ "366", 6 },
	{ "367", 6 },
	{ "368", 6 },
	{ "369", 6 },
	{ "390", -15 },
	{ "391", -18 },
	{ "392", -15 },
	{ "393", -18 },
	{ "394", 4 },
	{ "395", 6 },
	{ "703", -30 },
	{ "723", -30 },

//FOUR_DIGIT_DATA_LENGTH
	{ "4300", -35 },
	{ "4301", -35 },
	{ "4302", -70 },
	{ "4303", -70 },
	{ "4304", -70 },
	{ "4305", -70 },
	{ "4306", -70 },
	{ "4307", 2 },
	{ "4308", -30 },
	{ "4310", -35 },
	{ "4311", -35 },
	{ "4312", -70 },
	{ "4313", -70 },
	{ "4314", -70 },
	{ "4315", -70 },
	{ "4316", -70 },
	{ "4317", 2 },
	{ "4318", -20 },
	{ "4319", -30 },
	{ "4320", -35 },
	{ "4321", 1 },
	{ "4322", 1 },
	{ "4323", 1 },
	{ "4324", 10 },
	{ "4325", 10 },
	{ "4326", 6 },

	{ "7001", 13 },
	{ "7002", -30 },
	{ "7003", 10 },
	{ "7004", -4 },
	{ "7005", -12 },
	{ "7006", 6 },
	{ "7007", -12 },
	{ "7008", -3 },
	{ "7009", -10 },
	{ "7010", -2 },
	{ "7020", -20 },
	{ "7021", -20 },
	{ "7022", -20 },
	{ "7023", -30 },
	{ "7040", 4 },
	{ "7240", -20 },

	{ "8001", 14 },
	{ "8002", -20 },
	{ "8003", -30 },
	{ "8004", -30 },
	{ "8005", 6 },
	{ "8006", 18 },
	{ "8007", -34 },
	{ "8008", -12 },
	{ "8009", -50 },
	{ "8010", -30 },
	{ "8011", -12 },
	{ "8012", -20 },
	{ "8013", -25 },
	{ "8017", 18 },
	{ "8018", 18 },
	{ "8019", -10 },
	{ "8020", -25 },
	{ "8026", 18 },
	{ "8110", -70 },
	{ "8111", 4 },
	{ "8112", -70 },
	{ "8200", -70 },
};

std::string HRIFromGS1(std::string_view gs1)
{
	//TODO: c++20
	auto starts_with = [](std::string_view str, std::string_view pre) { return str.substr(0, pre.size()) == pre; };
	constexpr char GS = 29; // GS character (29 / 0x1D)

	std::string_view rem = gs1;
	std::string res;

	while (rem.size()) {
		const AiInfo* i = FindIf(aiInfos, [&](const AiInfo& i) { return starts_with(rem, i.aiPrefix); });
		if (i == std::end(aiInfos))
			return {};

		int aiSize = i->aiSize();
		if (Size(rem) < aiSize)
			return {};

		res += '(';
		res += rem.substr(0, aiSize);
		res += ')';
		rem.remove_prefix(aiSize);

		int fieldSize = i->fieldSize();
		if (i->isVariableLength()) {
			auto gsPos = rem.find(GS);
#if 1
			fieldSize = std::min(gsPos == std::string_view::npos ? Size(rem) : narrow_cast<int>(gsPos), fieldSize);
#else
			// TODO: ignore the 'max field size' part for now as it breaks rssexpanded-3/13.png?
			fieldSize = gsPos == std::string_view::npos ? Size(rem) : narrow_cast<int>(gsPos);
#endif
		}
		if (fieldSize == 0 || Size(rem) < fieldSize)
			return {};

		res += rem.substr(0, fieldSize);
		rem.remove_prefix(fieldSize);

		// See General Specification v22.0 Section 7.8.6.3: "...the processing routine SHALL tolerate a single separator character
		// immediately following any element string, whether necessary or not..."
		if (Size(rem) && rem.front() == GS)
			rem.remove_prefix(1);
	}

	return res;
}

#if __cplusplus > 201703L
std::ostream& operator<<(std::ostream& os, const char8_t* str)
{
	return os << reinterpret_cast<const char*>(str);
}
#endif

std::string HRIFromISO15434(std::string_view str)
{
	// Use available unicode symbols to simulate sub- and superscript letters as specified in
	// ISO/IEC 15434:2019(E) 6. Human readable representation

	std::ostringstream oss;

	for (char c : str) {
		switch (c) {
		case 4: oss << u8"\u1d31\u1d52\u209c"; break; // EOT
		case 28: oss << u8"\ua7f3\u209b"; break; // FS
		case 29: oss << u8"\u1d33\u209b"; break; // GS
		case 30: oss << u8"\u1d3f\u209b"; break; // RS
		case 31: oss << u8"\u1d41\u209b"; break; // US
		default: oss << c;
		}
	}

	return oss.str();
}

} // namespace ZXing
<commit_msg>HRI: use unicode "Control Pictures" for ASCII control characters<commit_after>/*
* Copyright 2016 Nu-book Inc.
* Copyright 2016 ZXing authors
* Copyright 2022 Axel Waggershauser
*/
// SPDX-License-Identifier: Apache-2.0

#include "HRI.h"

#include "ZXAlgorithms.h"

#include <sstream>

namespace ZXing {

struct AiInfo
{
	std::string_view aiPrefix;
	int _fieldSize;	// if negative, the length is variable and abs(length) give the max size

	bool isVariableLength() const noexcept { return _fieldSize < 0; }
	int fieldSize() const noexcept { return std::abs(_fieldSize); }
	int aiSize() const
	{
		if ((aiPrefix[0] == '3' && Contains("1234569", aiPrefix[1])) || aiPrefix == "703" || aiPrefix == "723")
			return 4;
		else
			return Size(aiPrefix);
	}
};

// GS1 General Specifications Release 22.0 (Jan 22, 2022)
static const AiInfo aiInfos[] = {
// TWO_DIGIT_DATA_LENGTH
	{ "00", 18 },
	{ "01", 14 },
	{ "02", 14 },

	{ "10", -20 },
	{ "11", 6 },
	{ "12", 6 },
	{ "13", 6 },
	{ "15", 6 },
	{ "16", 6 },
	{ "17", 6 },

	{ "20", 2 },
	{ "21", -20 },
	{ "22", -20 },

	{ "30", -8 },
	{ "37", -8 },

	//internal company codes
	{ "90", -30 },
	{ "91", -90 },
	{ "92", -90 },
	{ "93", -90 },
	{ "94", -90 },
	{ "95", -90 },
	{ "96", -90 },
	{ "97", -90 },
	{ "98", -90 },
	{ "99", -90 },

//THREE_DIGIT_DATA_LENGTH
	{ "235", -28 },
	{ "240", -30 },
	{ "241", -30 },
	{ "242", -6 },
	{ "243", -20 },
	{ "250", -30 },
	{ "251", -30 },
	{ "253", -30 },
	{ "254", -20 },
	{ "255", -25 },

	{ "400", -30 },
	{ "401", -30 },
	{ "402", 17 },
	{ "403", -30 },
	{ "410", 13 },
	{ "411", 13 },
	{ "412", 13 },
	{ "413", 13 },
	{ "414", 13 },
	{ "415", 13 },
	{ "416", 13 },
	{ "417", 13 },
	{ "420", -20 },
	{ "421", -12 },
	{ "422", 3 },
	{ "423", -15 },
	{ "424", 3 },
	{ "425", -15 },
	{ "426", 3 },
	{ "427", -3 },

	{ "710", -20 },
	{ "711", -20 },
	{ "712", -20 },
	{ "713", -20 },
	{ "714", -20 },
	{ "715", -20 },

//THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH
	{ "310", 6 },
	{ "311", 6 },
	{ "312", 6 },
	{ "313", 6 },
	{ "314", 6 },
	{ "315", 6 },
	{ "316", 6 },
	{ "320", 6 },
	{ "321", 6 },
	{ "322", 6 },
	{ "323", 6 },
	{ "324", 6 },
	{ "325", 6 },
	{ "326", 6 },
	{ "327", 6 },
	{ "328", 6 },
	{ "329", 6 },
	{ "330", 6 },
	{ "331", 6 },
	{ "332", 6 },
	{ "333", 6 },
	{ "334", 6 },
	{ "335", 6 },
	{ "336", 6 },
	{ "337", 6 },
	{ "340", 6 },
	{ "341", 6 },
	{ "342", 6 },
	{ "343", 6 },
	{ "344", 6 },
	{ "345", 6 },
	{ "346", 6 },
	{ "347", 6 },
	{ "348", 6 },
	{ "349", 6 },
	{ "350", 6 },
	{ "351", 6 },
	{ "352", 6 },
	{ "353", 6 },
	{ "354", 6 },
	{ "355", 6 },
	{ "356", 6 },
	{ "357", 6 },
	{ "360", 6 },
	{ "361", 6 },
	{ "362", 6 },
	{ "363", 6 },
	{ "364", 6 },
	{ "365", 6 },
	{ "366", 6 },
	{ "367", 6 },
	{ "368", 6 },
	{ "369", 6 },
	{ "390", -15 },
	{ "391", -18 },
	{ "392", -15 },
	{ "393", -18 },
	{ "394", 4 },
	{ "395", 6 },
	{ "703", -30 },
	{ "723", -30 },

//FOUR_DIGIT_DATA_LENGTH
	{ "4300", -35 },
	{ "4301", -35 },
	{ "4302", -70 },
	{ "4303", -70 },
	{ "4304", -70 },
	{ "4305", -70 },
	{ "4306", -70 },
	{ "4307", 2 },
	{ "4308", -30 },
	{ "4310", -35 },
	{ "4311", -35 },
	{ "4312", -70 },
	{ "4313", -70 },
	{ "4314", -70 },
	{ "4315", -70 },
	{ "4316", -70 },
	{ "4317", 2 },
	{ "4318", -20 },
	{ "4319", -30 },
	{ "4320", -35 },
	{ "4321", 1 },
	{ "4322", 1 },
	{ "4323", 1 },
	{ "4324", 10 },
	{ "4325", 10 },
	{ "4326", 6 },

	{ "7001", 13 },
	{ "7002", -30 },
	{ "7003", 10 },
	{ "7004", -4 },
	{ "7005", -12 },
	{ "7006", 6 },
	{ "7007", -12 },
	{ "7008", -3 },
	{ "7009", -10 },
	{ "7010", -2 },
	{ "7020", -20 },
	{ "7021", -20 },
	{ "7022", -20 },
	{ "7023", -30 },
	{ "7040", 4 },
	{ "7240", -20 },

	{ "8001", 14 },
	{ "8002", -20 },
	{ "8003", -30 },
	{ "8004", -30 },
	{ "8005", 6 },
	{ "8006", 18 },
	{ "8007", -34 },
	{ "8008", -12 },
	{ "8009", -50 },
	{ "8010", -30 },
	{ "8011", -12 },
	{ "8012", -20 },
	{ "8013", -25 },
	{ "8017", 18 },
	{ "8018", 18 },
	{ "8019", -10 },
	{ "8020", -25 },
	{ "8026", 18 },
	{ "8110", -70 },
	{ "8111", 4 },
	{ "8112", -70 },
	{ "8200", -70 },
};

std::string HRIFromGS1(std::string_view gs1)
{
	//TODO: c++20
	auto starts_with = [](std::string_view str, std::string_view pre) { return str.substr(0, pre.size()) == pre; };
	constexpr char GS = 29; // GS character (29 / 0x1D)

	std::string_view rem = gs1;
	std::string res;

	while (rem.size()) {
		const AiInfo* i = FindIf(aiInfos, [&](const AiInfo& i) { return starts_with(rem, i.aiPrefix); });
		if (i == std::end(aiInfos))
			return {};

		int aiSize = i->aiSize();
		if (Size(rem) < aiSize)
			return {};

		res += '(';
		res += rem.substr(0, aiSize);
		res += ')';
		rem.remove_prefix(aiSize);

		int fieldSize = i->fieldSize();
		if (i->isVariableLength()) {
			auto gsPos = rem.find(GS);
#if 1
			fieldSize = std::min(gsPos == std::string_view::npos ? Size(rem) : narrow_cast<int>(gsPos), fieldSize);
#else
			// TODO: ignore the 'max field size' part for now as it breaks rssexpanded-3/13.png?
			fieldSize = gsPos == std::string_view::npos ? Size(rem) : narrow_cast<int>(gsPos);
#endif
		}
		if (fieldSize == 0 || Size(rem) < fieldSize)
			return {};

		res += rem.substr(0, fieldSize);
		rem.remove_prefix(fieldSize);

		// See General Specification v22.0 Section 7.8.6.3: "...the processing routine SHALL tolerate a single separator character
		// immediately following any element string, whether necessary or not..."
		if (Size(rem) && rem.front() == GS)
			rem.remove_prefix(1);
	}

	return res;
}

#if __cplusplus > 201703L
std::ostream& operator<<(std::ostream& os, const char8_t* str)
{
	return os << reinterpret_cast<const char*>(str);
}
#endif

std::string HRIFromISO15434(std::string_view str)
{
	// Use available unicode symbols to simulate sub- and superscript letters as specified in
	// ISO/IEC 15434:2019(E) 6. Human readable representation

	std::ostringstream oss;

	for (char c : str) {
#if 1
		if (0 <= c && c <= 0x20)
			oss << "\xe2\x90" << char(0x80 + c); // Unicode Block “Control Pictures”: 0x2400
		else
			oss << c;
#else
		switch (c) {
		case 4: oss << u8"\u1d31\u1d52\u209c"; break; // EOT
		case 28: oss << u8"\ua7f3\u209b"; break; // FS
		case 29: oss << u8"\u1d33\u209b"; break; // GS
		case 30: oss << u8"\u1d3f\u209b"; break; // RS
		case 31: oss << u8"\u1d41\u209b"; break; // US
		default: oss << c;
		}
#endif
	}

	return oss.str();
}

} // namespace ZXing
<|endoftext|>


<commit_before>#include <system/System.h>

#ifdef HX_MACOS
#include <CoreFoundation/CoreFoundation.h>
#endif

#include <SDL_rwops.h>
#include <SDL_timer.h>

namespace lime {

	double System::GetTimer () {

		return SDL_GetTicks ();

	}

	FILE* FILE_HANDLE::getFile () {

		if (((SDL_RWops*)handle)->type == SDL_RWOPS_STDFILE) {

			return ((SDL_RWops*)handle)->hidden.stdio.fp;

		} else if (((SDL_RWops*)handle)->type == SDL_RWOPS_JNIFILE) {

			#ifdef ANDROID
			FILE* file = ::fdopen (((SDL_RWops*)handle)->hidden.androidio.fd, "rb");
			::fseek (file, ((SDL_RWops*)handle)->hidden.androidio.offset, 0);
			return file;
			#endif

		}

		return NULL;

	}

	int FILE_HANDLE::getLength () {

		return SDL_RWsize (((SDL_RWops*)handle));

	}

	bool FILE_HANDLE::isFile () {

		return ((SDL_RWops*)handle)->type == SDL_RWOPS_STDFILE;

	}

	int fclose (FILE_HANDLE *stream) {

		if (stream) {

			return SDL_RWclose ((SDL_RWops*)stream->handle);

		}

		return 0;

	}

	FILE_HANDLE *fdopen (int fd, const char *mode) {

		FILE* fp = ::fdopen (fd, mode);
		SDL_RWops *result = SDL_RWFromFP (fp, SDL_TRUE);

		if (result) {

			return new FILE_HANDLE (result);

		}

		return NULL;

	}

	FILE_HANDLE *fopen (const char *filename, const char *mode) {

		SDL_RWops *result;

		#ifdef HX_MACOS

		result = SDL_RWFromFile (filename, "rb");

		if (!result) {

			CFStringRef str = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
			CFURLRef path = CFBundleCopyResourceURL (CFBundleGetMainBundle (), str, NULL, NULL);
			CFRelease (str);

			if (path) {

				str = CFURLCopyPath (path);
				CFIndex maxSize = CFStringGetMaximumSizeForEncoding (CFStringGetLength (str), kCFStringEncodingUTF8);
				char *buffer = (char *)malloc (maxSize);

				if (CFStringGetCString (str, buffer, maxSize, kCFStringEncodingUTF8)) {

					result = SDL_RWFromFP (::fopen (buffer, "rb"), SDL_TRUE);
					free (buffer);

				}

				CFRelease (str);
				CFRelease (path);

			}

		}
		#else
		result = SDL_RWFromFile (filename, mode);
		#endif

		if (result) {

			return new FILE_HANDLE (result);

		}

		return NULL;

	}

	size_t fread (void *ptr, size_t size, size_t count, FILE_HANDLE *stream) {

		return SDL_RWread (stream ? (SDL_RWops*)stream->handle : NULL, ptr, size, count);

	}

	int fseek (FILE_HANDLE *stream, long int offset, int origin) {

		return SDL_RWseek (stream ? (SDL_RWops*)stream->handle : NULL, offset, origin);

	}

	long int ftell (FILE_HANDLE *stream) {

		return SDL_RWtell (stream ? (SDL_RWops*)stream->handle : NULL);

	}

	size_t fwrite (const void *ptr, size_t size, size_t count, FILE_HANDLE *stream) {

		return SDL_RWwrite (stream ? (SDL_RWops*)stream->handle : NULL, ptr, size, count);

	}

}<commit_msg>Fix Windows file I/O<commit_after>#include <system/System.h>

#ifdef HX_MACOS
#include <CoreFoundation/CoreFoundation.h>
#endif

#ifdef HX_WINDOWS
#include <stdio.h>
//#include <io.h>
//#include <fcntl.h>
#endif

#include <SDL_rwops.h>
#include <SDL_timer.h>

namespace lime {

	double System::GetTimer () {

		return SDL_GetTicks ();

	}

	FILE* FILE_HANDLE::getFile () {

		#ifndef HX_WINDOWS

		switch (((SDL_RWops*)handle)->type) {

			case SDL_RWOPS_STDFILE:

				return ((SDL_RWops*)handle)->hidden.stdio.fp;

			case SDL_RWOPS_JNIFILE:
			{
				#ifdef ANDROID
				FILE* file = ::fdopen (((SDL_RWops*)handle)->hidden.androidio.fd, "rb");
				::fseek (file, ((SDL_RWops*)handle)->hidden.androidio.offset, 0);
				return file;
				#endif
			}

			case SDL_RWOPS_WINFILE:
			{
				/*#ifdef HX_WINDOWS
				printf("SDKFLJDSLFKJ\n");
				int fd = _open_osfhandle ((intptr_t)((SDL_RWops*)handle)->hidden.windowsio.h, _O_RDONLY);

				if (fd != -1) {
					printf("SDKFLJDSLFKJ\n");
					return ::fdopen (fd, "rb");

				}
				#endif*/
			}

		}

		return NULL;

		#else

		return (FILE*)handle;

		#endif

	}

	int FILE_HANDLE::getLength () {

		#ifndef HX_WINDOWS

		return SDL_RWsize (((SDL_RWops*)handle));

		#else

		return 0;

		#endif

	}

	bool FILE_HANDLE::isFile () {

		#ifndef HX_WINDOWS

		return ((SDL_RWops*)handle)->type == SDL_RWOPS_STDFILE;

		#else

		return true;

		#endif

	}

	int fclose (FILE_HANDLE *stream) {

		#ifndef HX_WINDOWS

		if (stream) {

			return SDL_RWclose ((SDL_RWops*)stream->handle);

		}

		return 0;

		#else

		return ::fclose ((FILE*)stream->handle);

		#endif

	}

	FILE_HANDLE *fdopen (int fd, const char *mode) {

		#ifndef HX_WINDOWS

		FILE* fp = ::fdopen (fd, mode);
		SDL_RWops *result = SDL_RWFromFP (fp, SDL_TRUE);

		if (result) {

			return new FILE_HANDLE (result);

		}

		return NULL;

		#else

		FILE* result = ::fdopen (fd, mode);

		if (result) {

			return new FILE_HANDLE (result);

		}

		return NULL;

		#endif

	}

	FILE_HANDLE *fopen (const char *filename, const char *mode) {

		#ifndef HX_WINDOWS

		SDL_RWops *result;

		#ifdef HX_MACOS

		result = SDL_RWFromFile (filename, "rb");

		if (!result) {

			CFStringRef str = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
			CFURLRef path = CFBundleCopyResourceURL (CFBundleGetMainBundle (), str, NULL, NULL);
			CFRelease (str);

			if (path) {

				str = CFURLCopyPath (path);
				CFIndex maxSize = CFStringGetMaximumSizeForEncoding (CFStringGetLength (str), kCFStringEncodingUTF8);
				char *buffer = (char *)malloc (maxSize);

				if (CFStringGetCString (str, buffer, maxSize, kCFStringEncodingUTF8)) {

					result = SDL_RWFromFP (::fopen (buffer, "rb"), SDL_TRUE);
					free (buffer);

				}

				CFRelease (str);
				CFRelease (path);

			}

		}
		#else
		result = SDL_RWFromFile (filename, mode);
		#endif

		if (result) {

			return new FILE_HANDLE (result);

		}

		return NULL;

		#else

		FILE* result = ::fopen (filename, mode);

		if (result) {

			return new FILE_HANDLE (result);

		}

		return NULL;

		#endif

	}

	size_t fread (void *ptr, size_t size, size_t count, FILE_HANDLE *stream) {

		#ifndef HX_WINDOWS

		return SDL_RWread (stream ? (SDL_RWops*)stream->handle : NULL, ptr, size, count);

		#else

		return ::fread (ptr, size, count, (FILE*)stream->handle);

		#endif

	}

	int fseek (FILE_HANDLE *stream, long int offset, int origin) {

		#ifndef HX_WINDOWS

		return SDL_RWseek (stream ? (SDL_RWops*)stream->handle : NULL, offset, origin);

		#else

		return ::fseek ((FILE*)stream->handle, offset, origin);

		#endif

	}

	long int ftell (FILE_HANDLE *stream) {

		#ifndef HX_WINDOWS

		return SDL_RWtell (stream ? (SDL_RWops*)stream->handle : NULL);

		#else

		return ::ftell ((FILE*)stream->handle);

		#endif

	}

	size_t fwrite (const void *ptr, size_t size, size_t count, FILE_HANDLE *stream) {

		#ifndef HX_WINDOWS

		return SDL_RWwrite (stream ? (SDL_RWops*)stream->handle : NULL, ptr, size, count);

		#else

		return ::fwrite (ptr, size, count, (FILE*)stream->handle);

		#endif

	}

}<|endoftext|>


<commit_before>#include "c-enum.src.hpp"
#include "c-enum.gen.hpp"

#define CATCH_CONFIG_MAIN
#include "tests/catch.hpp"

using namespace reflang;
using namespace std;

TEST_CASE("iterate")
{
	for (const auto& it : Enum<CEnum>::Iterate())
	{
		REQUIRE(false);
	}
}

TEST_CASE("to string")
{
	REQUIRE(Enum<CEnum>::Translate(CEnum()) == "");
}

TEST_CASE("from string")
{
	CEnum e1;
	REQUIRE(!Enum<CEnum>::TryTranslate("", e1));
	REQUIRE(!Enum<CEnum>::TryTranslate("Hi", e1));
}
<commit_msg>Fix tests for C-style enums<commit_after>#include "c-enum.src.hpp"
#include "c-enum.gen.hpp"

#define CATCH_CONFIG_MAIN
#include "tests/catch.hpp"

using namespace reflang;
using namespace std;

TEST_CASE("iterate")
{
	int i = 0;
	for (const auto& it : Enum<CEnum>::Iterate())
	{
		switch (i)
		{
			case 0:
				REQUIRE(it == CEnum::Value0);
				break;
			case 1:
				REQUIRE(it == CEnum::Value1);
				break;
			default:
				REQUIRE(false);
				break;
		}
		++i;
	}
}

TEST_CASE("to string")
{
	REQUIRE(Enum<CEnum>::Translate(CEnum::Value0) == "Value0");
	REQUIRE(Enum<CEnum>::Translate(CEnum::Value1) == "Value1");
}

TEST_CASE("from string")
{
	auto FromString = [](const string& s)
	{
		CEnum e;
		REQUIRE(Enum<CEnum>::TryTranslate(s, e));
		return e;
	};
	REQUIRE(FromString("Value0") == CEnum::Value0);
	REQUIRE(FromString("Value1") == CEnum::Value1);

	CEnum e;
	REQUIRE(!Enum<CEnum>::TryTranslate("UnknownString", e));
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <algorithm>
#include <unistd.h>
#include <sstream>
#include <string>
using namespace std;

int auto_commit() {
    vector<string> cmds;
    cmds.push_back("echo `date \"+%Y-%m-%d %H:%M:%S\"` >>  exe_history");
    cmds.push_back("git add .");
    cmds.push_back("git commit -m \"impl ApnsPooledConnection.java\"");
    cmds.push_back("git push");

    vector<string>::iterator iter=cmds.begin();
    for(; iter!=cmds.end(); iter++) {
        string s=*iter;
        system(s.c_str());
    }
}

int main() {
    while(true) {
        auto_commit();

        /* gap 6 hours */
        for(int i=1; i<4320; ++i) {
            /* print keep-alive log */
            std::ostringstream ss;
            ss << i;
            string cmd="echo ";
            cmd+=ss.str();
            cmd+=" >>  keep_thread_alive.log";
            system(cmd.c_str());
            sleep(5);
        }
    }
    return 0;
}

<commit_msg>Create github.cpp<commit_after>#include <iostream>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <algorithm>
#include <unistd.h>
#include <sstream>
#include <string>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int auto_commit() {
    vector<string> cmds;
    cmds.push_back("echo `date \"+%Y-%m-%d %H:%M:%S\"` >>  exe_history");
    cmds.push_back("git add .");
    cmds.push_back("git commit -m \"impl ApnsPooledConnection.java\"");
    cmds.push_back("git push");

    vector<string>::iterator iter=cmds.begin();
    for(; iter!=cmds.end(); iter++) {
        string s=*iter;
        system(s.c_str());
    }
}

int main() {
    while(true) {
        srand((unsigned)time(NULL));
        int num=rand()%4;

        for(int i=0; i<num; ++i) {
            auto_commit();
        }

        /* gap 24 hours */
        for(int i=1; i<17280; ++i) {
            /* print keep-alive log */
            std::ostringstream ss;
            ss << i;
            string cmd="echo ";
            cmd+=ss.str();
            cmd+=" >>  keep_thread_alive.log";
            system(cmd.c_str());
            sleep(5);
        }
    }
    return 0;
}

// #include <iostream>
// #include <cstdlib>
// #include <vector>
// #include <iostream>
// #include <algorithm>
// #include <unistd.h>
// #include <sstream>
// #include <string>
// using namespace std;

// int auto_commit() {
//     vector<string> cmds;
//     cmds.push_back("echo `date \"+%Y-%m-%d %H:%M:%S\"` >>  exe_history");
//     cmds.push_back("git add .");
//     cmds.push_back("git commit -m \"impl ApnsPooledConnection.java\"");
//     cmds.push_back("git push");

//     vector<string>::iterator iter=cmds.begin();
//     for(; iter!=cmds.end(); iter++) {
//         string s=*iter;
//         system(s.c_str());
//     }
// }

// int main() {
//     while(true) {
//         auto_commit();

//         /* gap 6 hours */
//         for(int i=1; i<4320; ++i) {
//             /* print keep-alive log */
//             std::ostringstream ss;
//             ss << i;
//             string cmd="echo ";
//             cmd+=ss.str();
//             cmd+=" >>  keep_thread_alive.log";
//             system(cmd.c_str());
//             sleep(5);
//         }
//     }
//     return 0;
// }

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/eff_config/memory_size.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file memory_size.C
/// @brief Return the effective memory size behind a target
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#include <fapi2.H>
#include <lib/mss_attribute_accessors.H>

#include <lib/shared/mss_const.H>
#include <lib/eff_config/memory_size.H>

#include <lib/utils/find.H>

namespace mss
{

///
/// @brief Return the total memory size behind an MCA
/// @param[in] i_target the MCA target
/// @param[out] o_size the size of memory in GB behind the target
/// @return FAPI2_RC_SUCCESS if ok
///
template<>
fapi2::ReturnCode eff_memory_size( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint64_t& o_size )
{
    uint32_t l_sizes[MAX_DIMM_PER_PORT];
    o_size = 0;

    FAPI_TRY( mss::eff_dimm_size(i_target, &(l_sizes[0])) );

    for (size_t i = 0; i < MAX_DIMM_PER_PORT; ++i)
    {
        o_size += l_sizes[i];
    }

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Return the total memory size behind an MBIST
/// @param[in] i_target the MCBIST target
/// @param[out] o_size the size of memory in GB behind the target
/// @return FAPI2_RC_SUCCESS if ok
///
template<>
fapi2::ReturnCode eff_memory_size( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, uint64_t& o_size )
{
    o_size = 0;

    for (const auto& mcs : mss::find_targets<fapi2::TARGET_TYPE_MCS>(i_target))
    {
        uint32_t l_sizes[PORTS_PER_MCS][MAX_DIMM_PER_PORT];
        FAPI_TRY( mss::eff_dimm_size(mcs, &(l_sizes[0][0])) );

        for (size_t i = 0; i < PORTS_PER_MCS; ++i)
        {
            for (size_t j = 0; j < MAX_DIMM_PER_PORT; ++j)
            {
                o_size += l_sizes[i][j];
            }
        }
    }

fapi_try_exit:
    return fapi2::current_err;
}

}

<commit_msg>Change eff_memory_size to account for non-initialized attrs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/eff_config/memory_size.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file memory_size.C
/// @brief Return the effective memory size behind a target
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#include <fapi2.H>
#include <lib/mss_attribute_accessors.H>

#include <lib/shared/mss_const.H>
#include <lib/eff_config/memory_size.H>

#include <lib/utils/find.H>

namespace mss
{

///
/// @brief Return the total memory size behind an MCA
/// @param[in] i_target the MCA target
/// @param[out] o_size the size of memory in GB behind the target
/// @return FAPI2_RC_SUCCESS if ok
///
template<>
fapi2::ReturnCode eff_memory_size( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint64_t& o_size )
{
    // Don't try to get cute and read the attributes once and loop over the array.
    // Cronus honors initToZero which would work, but HB might not and so we might get
    // crap in some of the attributes (which we shouldn't access as there's no DIMM there)
    uint32_t l_sizes = 0;
    o_size = 0;

    for (const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
    {
        FAPI_TRY( mss::eff_dimm_size(d, l_sizes) );
        o_size += l_sizes;
    }

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Return the total memory size behind an MBIST
/// @param[in] i_target the MCBIST target
/// @param[out] o_size the size of memory in GB behind the target
/// @return FAPI2_RC_SUCCESS if ok
///
template<>
fapi2::ReturnCode eff_memory_size( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, uint64_t& o_size )
{
    o_size = 0;

    for (const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target))
    {
        uint64_t l_size = 0;
        FAPI_TRY( eff_memory_size(p, l_size) );
        o_size += l_size;
    }

fapi_try_exit:
    return fapi2::current_err;
}

}

<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /fs/turing/cvs/copasi_dev/cvs_admin/addHeader,v $
//   $Revision: 1.18 $
//   $Name: HEAD $
//   $Author: shoops $
//   $Date: 2012/03/07 20:49:51 $
// End CVS Header

// Copyright (C) 2012 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include "CPlotColors.h"

//static
std::string CPlotColors::getCopasiColorStr(size_t index)
{
  index = index % 6;

  switch (index)
    {
      case 0: return "#FF0000";
      case 1: return "#0000FF";
      case 2: return "#00E600";
      case 3: return "#00BEF0";
      case 4: return "#F000FF";
      case 5: return "#F0C800";

    }

  return "auto";
}

//static
size_t CPlotColors::getNumCopasiColors()
{
  return 6;
}

//QColor curveColours[6] = {QColor(255, 0, 0), QColor(0, 0, 255), QColor(0, 230, 0), QColor(0, 190, 240), QColor(240, 0, 255), QColor(240, 200, 0)} ; //TODO
<commit_msg>- issue 2877: new colors added<commit_after>// Copyright (C) 2019 - 2020 by Pedro Mendes, Rector and Visitors of the
// University of Virginia, University of Heidelberg, and University
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2017 - 2018 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and University of
// of Connecticut School of Medicine.
// All rights reserved.

// Copyright (C) 2012 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include "CPlotColors.h"

//static
std::string CPlotColors::getCopasiColorStr(size_t index)
{
  index = index % getNumCopasiColors();

  switch (index)
    {
      case 0:
        return "#FF0000"; //red

      case 1:
        return "#0000FF"; //blue

      case 2:
        return "#00E600"; //green

      case 3:
        return "#00BEF0"; //deep sky blue

      case 4:
        return "#F000FF"; //magenta

      case 5:
        return "#F0C800"; //supernova

      case 6:
        return "#000000"; // black

      case 7:
        return "#7051A7"; //purple

      case 8:
        return "#FD8D3C"; //orange

      case 9:
        return "#1B9E77"; //dark teal

    }

  return "auto";
}

//static
size_t CPlotColors::getNumCopasiColors()
{
  return 10;
}

//QColor curveColours[6] = {QColor(255, 0, 0), QColor(0, 0, 255), QColor(0, 230, 0), QColor(0, 190, 240), QColor(240, 0, 255), QColor(240, 200, 0)} ; //TODO
<|endoftext|>


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

#if defined (SSAG)

#include "camera.h"
#include "time.h"
#include "image_math.h"

#include <wx/stdpaths.h>
#include <wx/textfile.h>
//wxTextFile *qglogfile;

#include "cam_SSAG.h"
// QHY CMOS guide camera version
// Tom's driver

#include <Setupapi.h>

#define INITGUID
#include <devpkey.h>

extern int ushort_compare(const void * a, const void * b);

static bool GetDiPropStr(HDEVINFO h, SP_DEVINFO_DATA *data, const DEVPROPKEY& key, WCHAR *buf, DWORD size)
{
    DEVPROPTYPE proptype;
    return SetupDiGetDeviceProperty(h, data, &key, &proptype, (PBYTE)buf, size, &size, 0) &&
        proptype == DEVPROP_TYPE_STRING;
}

static unsigned int GetSSAGDriverVersion()
{
    // check to see if the SSAG driver is v2 ("1.2.0.0") or v4 ("3.0.0.0")

    unsigned int driverVersion = 2; // assume v2

    HDEVINFO h = SetupDiGetClassDevs(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
    if (h != INVALID_HANDLE_VALUE)
    {
        DWORD idx = 0;
        SP_DEVINFO_DATA data;
        memset(&data, 0, sizeof(data));
        data.cbSize = sizeof(data);

        while (SetupDiEnumDeviceInfo(h, idx, &data))
        {
            WCHAR buf[4096];

            if (GetDiPropStr(h, &data, DEVPKEY_Device_InstanceId, buf, sizeof(buf)) &&
                wcsncmp(buf, L"USB\\VID_1856&PID_0012\\", 22) == 0)
            {
                if (GetDiPropStr(h, &data, DEVPKEY_Device_DriverVersion, buf, sizeof(buf)))
                {
                    Debug.AddLine(wxString::Format("SSAG driver version is %s", wxString(buf)));
                    int v;
                    if (swscanf(buf, L"%d", &v) == 1 && v >= 3)
                    {
                        driverVersion = 4;
                    }
                }
                break;
            }

            ++idx;
        }

        SetupDiDestroyDeviceInfoList(h);
    }

    return driverVersion;
}

// declare function pointers for imported functions

#define F1(r,f,a1)             typedef r (_stdcall *f##_t)(a1);             static f##_t f;
#define F2(r,f,a1,a2)          typedef r (_stdcall *f##_t)(a1,a2);          static f##_t f;
#define F5(r,f,a1,a2,a3,a4,a5) typedef r (_stdcall *f##_t)(a1,a2,a3,a4,a5); static f##_t f;
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5

// initialize the function pointers

static bool InitProcs(HINSTANCE hinst)
{
    bool ok = false;

    try
    {

#define F(f,n) \
    if ((f = (f##_t) GetProcAddress(hinst, n)) == NULL) \
        throw ERROR_INFO("SSAGIF DLL missing " n);
#define F1(r,f,a1) F(f,#f)
#define F2(r,f,a1,a2) F(f,#f)
#define F5(r,f,a1,a2,a3,a4,a5) F(f,#f)
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5
#undef F

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
    }

    return ok;
}

static HINSTANCE s_dllinst;

//
// load the SSAGv2 or SSAGv4 DLL based on the SSAG driver version and load the addresses of the imported functions
//
static bool LoadSSAGIFDll()
{
    bool ok = false;

    try
    {
        unsigned int driverVersion = GetSSAGDriverVersion();

        LPCWSTR libname;
        if (driverVersion == 2)
            libname = _T("SSAGIFv2.dll");
        else if (driverVersion == 4)
            libname = _T("SSAGIFv4.dll");
        else
            throw ERROR_INFO("unexpected SSAG driver version!");

        wxASSERT(s_dllinst == NULL);
        s_dllinst = LoadLibrary(libname);
        if (s_dllinst == NULL)
            throw ERROR_INFO("SSAG LoadLibrary failed");

        if (!InitProcs(s_dllinst))
            throw ERROR_INFO("SSAG failed to load required symbols");

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
        if (s_dllinst != NULL)
        {
            FreeLibrary(s_dllinst);
            s_dllinst = NULL;
        }
    }

    return ok;
}

static void UnloadSSAGIFDll()
{
    if (s_dllinst != NULL)
    {
        FreeLibrary(s_dllinst);
        s_dllinst = NULL;
    }
}

Camera_SSAGClass::Camera_SSAGClass()
{
    Connected = false;
    Name = _T("StarShoot Autoguider");
    FullSize = wxSize(1280, 1024);
    m_hasGuideOutput = true;
    HasGainControl = true;
    PixelSize = 5.2;
}

bool Camera_SSAGClass::Connect()
{
    // returns true on error

    if (!LoadSSAGIFDll())
        return true;

    if (!_SSAG_openUSB())
    {
        UnloadSSAGIFDll();
        return true;
    }

    _SSAG_SETBUFFERMODE(0);
    Connected = true;

    //qglogfile = new wxTextFile(Debug.GetLogDir() + PATHSEPSTR + _T("PHD_QGuide_log.txt"));
    //qglogfile->AddLine(wxNow() + ": QGuide connected"); //qglogfile->Write();

    return false;
}

bool Camera_SSAGClass::ST4PulseGuideScope(int direction, int duration)
{
    int reg = 0;
    int dur = duration / 10;

    //qglogfile->AddLine(wxString::Format("Sending guide dur %d",dur)); //qglogfile->Write();

    if (dur >= 255) dur = 254; // Max guide pulse is 2.54s -- 255 keeps it on always

    // Output pins are NC, Com, RA+(W), Dec+(N), Dec-(S), RA-(E) ??  http://www.starlight-xpress.co.uk/faq.htm
    switch (direction) {
        case WEST: reg = 0x80; break;   // 0111 0000
        case NORTH: reg = 0x40; break;  // 1011 0000
        case SOUTH: reg = 0x20; break;  // 1101 0000
        case EAST: reg = 0x10;  break;  // 1110 0000
        default: return true; // bad direction passed in
    }
    _SSAG_GuideCommand(reg, dur);

    wxMilliSleep(duration + 10);

    //qglogfile->AddLine("Done"); //qglogfile->Write();

    return false;
}

void Camera_SSAGClass::ClearGuidePort()
{
}

void Camera_SSAGClass::InitCapture()
{
    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));
    _SSAG_SetNoiseReduction(0);
}

bool Camera_SSAGClass::Disconnect()
{
    _SSAG_closeUSB();
    UnloadSSAGIFDll();
    Connected = false;
    //qglogfile->AddLine(wxNow() + ": Disconnecting"); //qglogfile->Write(); //qglogfile->Close();
    return false;
}

bool Camera_SSAGClass::Capture(int duration, usImage& img, wxRect subframe, bool recon)
{
    // Only does full frames

    unsigned short *dptr;
    int xsize = FullSize.GetWidth();
    int ysize = FullSize.GetHeight();
    bool firstimg = true;

    //qglogfile->AddLine(wxString::Format("Capturing dur %d",duration)); //qglogfile->Write();

    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));

    if (img.NPixels != (xsize*ysize))
    {
        if (img.Init(xsize,ysize))
        {
            pFrame->Alert(_T("Memory allocation error during capture"));
            Disconnect();
            return true;
        }
    }

    _SSAG_ThreadedExposure(duration, NULL);

    //qglogfile->AddLine("Exposure programmed"); //qglogfile->Write();

    if (duration > 100) {
        wxMilliSleep(duration - 100);
        wxGetApp().Yield();
    }

    while (_SSAG_isExposing())
        wxMilliSleep(50);

    //qglogfile->AddLine("Exposure done"); //qglogfile->Write();

    dptr = img.ImageData;
    _SSAG_GETBUFFER(dptr, img.NPixels * 2);

    if (recon) SubtractDark(img);

    //qglogfile->AddLine("Image loaded"); //qglogfile->Write();

    // Do quick L recon to remove bayer array
//  QuickLRecon(img);
//  RemoveLines(img);

    return false;
}

void Camera_SSAGClass::RemoveLines(usImage& img)
{
    int i, j, val;
    unsigned short data[21];
    unsigned short *ptr1, *ptr2;
    unsigned short med[1024];
    int offset;
    double mean;
    int h = img.Size.GetHeight();
    int w = img.Size.GetWidth();
    size_t sz = sizeof(unsigned short);
    mean = 0.0;

    for (i=0; i<h; i++) {
        ptr1 = data;
        ptr2 = img.ImageData + i*w;
        for (j=0; j<21; j++, ptr1++, ptr2++)
            *ptr1 = *ptr2;
        qsort(data,21,sz,ushort_compare);
        med[i] = data[10];
        mean = mean + (double) (med[i]);
    }
    mean = mean / (double) h;
    for (i=0; i<h; i++) {
        offset = (int) mean - (int) med[i];
        ptr2 = img.ImageData + i*w;
        for (j=0; j<w; j++, ptr2++) {
            val = (int) *ptr2 + offset;
            if (val < 0) val = 0;
            else if (val > 65535) val = 65535;
            *ptr2 = (unsigned short) val;
        }

    }
}

#endif
<commit_msg>fix case in new SSAG driver detection code where some SSAG cameras were not being detected<commit_after>/*
 *  cam_SSAG.cpp
 *  PHD Guiding
 *
 *  Created by Craig Stark.
 *  Copyright (c) 2006, 2007, 2008, 2009, 2010 Craig Stark.
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *    Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *    Neither the name of Craig Stark, Stark Labs nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */
#include "phd.h"

#if defined (SSAG)

#include "camera.h"
#include "time.h"
#include "image_math.h"

#include <wx/stdpaths.h>
#include <wx/textfile.h>
//wxTextFile *qglogfile;

#include "cam_SSAG.h"
// QHY CMOS guide camera version
// Tom's driver

#include <Setupapi.h>

#define INITGUID
#include <devpkey.h>

extern int ushort_compare(const void * a, const void * b);

static bool GetDiPropStr(HDEVINFO h, SP_DEVINFO_DATA *data, const DEVPROPKEY& key, WCHAR *buf, DWORD size)
{
    DEVPROPTYPE proptype;
    return SetupDiGetDeviceProperty(h, data, &key, &proptype, (PBYTE)buf, size, &size, 0) &&
        proptype == DEVPROP_TYPE_STRING;
}

static unsigned int GetSSAGDriverVersion()
{
    // check to see if the SSAG driver is v2 ("1.2.0.0") or v4 ("3.0.0.0")

    Debug.AddLine("Checking SSAG driver version");

    bool found = false;
    unsigned int driverVersion = 2; // assume v2

    HDEVINFO h = SetupDiGetClassDevs(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
    if (h != INVALID_HANDLE_VALUE)
    {
        DWORD idx = 0;
        SP_DEVINFO_DATA data;
        memset(&data, 0, sizeof(data));
        data.cbSize = sizeof(data);

        while (SetupDiEnumDeviceInfo(h, idx, &data))
        {
            WCHAR buf[4096];

            if (GetDiPropStr(h, &data, DEVPKEY_Device_InstanceId, buf, sizeof(buf)) &&
                (wcsncmp(buf, L"USB\\VID_1856&PID_0012\\", 22) == 0) ||
                (wcsncmp(buf, L"USB\\VID_1856&PID_0011\\", 22) == 0))
            {
                Debug.AddLine(wxString::Format("Found SSAG device %s", buf));
                if (GetDiPropStr(h, &data, DEVPKEY_Device_DriverVersion, buf, sizeof(buf)))
                {
                    Debug.AddLine(wxString::Format("SSAG driver version is %s", wxString(buf)));
                    int v;
                    if (swscanf(buf, L"%d", &v) == 1 && v >= 3)
                    {
                        driverVersion = 4;
                    }
                }
                found = true;
                break;
            }

            ++idx;
        }

        SetupDiDestroyDeviceInfoList(h);
    }

    if (!found)
        Debug.AddLine("No SSAG device was found");

    return driverVersion;
}

// declare function pointers for imported functions

#define F1(r,f,a1)             typedef r (_stdcall *f##_t)(a1);             static f##_t f;
#define F2(r,f,a1,a2)          typedef r (_stdcall *f##_t)(a1,a2);          static f##_t f;
#define F5(r,f,a1,a2,a3,a4,a5) typedef r (_stdcall *f##_t)(a1,a2,a3,a4,a5); static f##_t f;
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5

// initialize the function pointers

static bool InitProcs(HINSTANCE hinst)
{
    bool ok = false;

    try
    {

#define F(f,n) \
    if ((f = (f##_t) GetProcAddress(hinst, n)) == NULL) \
        throw ERROR_INFO("SSAGIF DLL missing " n);
#define F1(r,f,a1) F(f,#f)
#define F2(r,f,a1,a2) F(f,#f)
#define F5(r,f,a1,a2,a3,a4,a5) F(f,#f)
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5
#undef F

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
    }

    return ok;
}

static HINSTANCE s_dllinst;

//
// load the SSAGv2 or SSAGv4 DLL based on the SSAG driver version and load the addresses of the imported functions
//
static bool LoadSSAGIFDll()
{
    bool ok = false;

    try
    {
        unsigned int driverVersion = GetSSAGDriverVersion();

        LPCWSTR libname;
        if (driverVersion == 2)
            libname = _T("SSAGIFv2.dll");
        else if (driverVersion == 4)
            libname = _T("SSAGIFv4.dll");
        else
            throw ERROR_INFO("unexpected SSAG driver version!");

        wxASSERT(s_dllinst == NULL);
        Debug.AddLine(wxString::Format("Loading SSAG dll %s", libname));
        s_dllinst = LoadLibrary(libname);
        if (s_dllinst == NULL)
            throw ERROR_INFO("SSAG LoadLibrary failed");

        if (!InitProcs(s_dllinst))
            throw ERROR_INFO("SSAG failed to load required symbols");

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
        if (s_dllinst != NULL)
        {
            FreeLibrary(s_dllinst);
            s_dllinst = NULL;
        }
    }

    return ok;
}

static void UnloadSSAGIFDll()
{
    if (s_dllinst != NULL)
    {
        Debug.AddLine("Unloading SSAG DLL");
        FreeLibrary(s_dllinst);
        s_dllinst = NULL;
    }
}

Camera_SSAGClass::Camera_SSAGClass()
{
    Connected = false;
    Name = _T("StarShoot Autoguider");
    FullSize = wxSize(1280, 1024);
    m_hasGuideOutput = true;
    HasGainControl = true;
    PixelSize = 5.2;
}

bool Camera_SSAGClass::Connect()
{
    // returns true on error

    if (!LoadSSAGIFDll())
        return true;

    if (!_SSAG_openUSB())
    {
        UnloadSSAGIFDll();
        return true;
    }

    _SSAG_SETBUFFERMODE(0);
    Connected = true;

    //qglogfile = new wxTextFile(Debug.GetLogDir() + PATHSEPSTR + _T("PHD_QGuide_log.txt"));
    //qglogfile->AddLine(wxNow() + ": QGuide connected"); //qglogfile->Write();

    return false;
}

bool Camera_SSAGClass::ST4PulseGuideScope(int direction, int duration)
{
    int reg = 0;
    int dur = duration / 10;

    //qglogfile->AddLine(wxString::Format("Sending guide dur %d",dur)); //qglogfile->Write();

    if (dur >= 255) dur = 254; // Max guide pulse is 2.54s -- 255 keeps it on always

    // Output pins are NC, Com, RA+(W), Dec+(N), Dec-(S), RA-(E) ??  http://www.starlight-xpress.co.uk/faq.htm
    switch (direction) {
        case WEST: reg = 0x80; break;   // 0111 0000
        case NORTH: reg = 0x40; break;  // 1011 0000
        case SOUTH: reg = 0x20; break;  // 1101 0000
        case EAST: reg = 0x10;  break;  // 1110 0000
        default: return true; // bad direction passed in
    }
    _SSAG_GuideCommand(reg, dur);

    wxMilliSleep(duration + 10);

    //qglogfile->AddLine("Done"); //qglogfile->Write();

    return false;
}

void Camera_SSAGClass::ClearGuidePort()
{
}

void Camera_SSAGClass::InitCapture()
{
    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));
    _SSAG_SetNoiseReduction(0);
}

bool Camera_SSAGClass::Disconnect()
{
    _SSAG_closeUSB();
    UnloadSSAGIFDll();
    Connected = false;
    //qglogfile->AddLine(wxNow() + ": Disconnecting"); //qglogfile->Write(); //qglogfile->Close();
    return false;
}

bool Camera_SSAGClass::Capture(int duration, usImage& img, wxRect subframe, bool recon)
{
    // Only does full frames

    unsigned short *dptr;
    int xsize = FullSize.GetWidth();
    int ysize = FullSize.GetHeight();
    bool firstimg = true;

    //qglogfile->AddLine(wxString::Format("Capturing dur %d",duration)); //qglogfile->Write();

    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));

    if (img.NPixels != (xsize*ysize))
    {
        if (img.Init(xsize,ysize))
        {
            pFrame->Alert(_T("Memory allocation error during capture"));
            Disconnect();
            return true;
        }
    }

    _SSAG_ThreadedExposure(duration, NULL);

    //qglogfile->AddLine("Exposure programmed"); //qglogfile->Write();

    if (duration > 100) {
        wxMilliSleep(duration - 100);
        wxGetApp().Yield();
    }

    while (_SSAG_isExposing())
        wxMilliSleep(50);

    //qglogfile->AddLine("Exposure done"); //qglogfile->Write();

    dptr = img.ImageData;
    _SSAG_GETBUFFER(dptr, img.NPixels * 2);

    if (recon) SubtractDark(img);

    //qglogfile->AddLine("Image loaded"); //qglogfile->Write();

    // Do quick L recon to remove bayer array
//  QuickLRecon(img);
//  RemoveLines(img);

    return false;
}

void Camera_SSAGClass::RemoveLines(usImage& img)
{
    int i, j, val;
    unsigned short data[21];
    unsigned short *ptr1, *ptr2;
    unsigned short med[1024];
    int offset;
    double mean;
    int h = img.Size.GetHeight();
    int w = img.Size.GetWidth();
    size_t sz = sizeof(unsigned short);
    mean = 0.0;

    for (i=0; i<h; i++) {
        ptr1 = data;
        ptr2 = img.ImageData + i*w;
        for (j=0; j<21; j++, ptr1++, ptr2++)
            *ptr1 = *ptr2;
        qsort(data,21,sz,ushort_compare);
        med[i] = data[10];
        mean = mean + (double) (med[i]);
    }
    mean = mean / (double) h;
    for (i=0; i<h; i++) {
        offset = (int) mean - (int) med[i];
        ptr2 = img.ImageData + i*w;
        for (j=0; j<w; j++, ptr2++) {
            val = (int) *ptr2 + offset;
            if (val < 0) val = 0;
            else if (val > 65535) val = 65535;
            *ptr2 = (unsigned short) val;
        }

    }
}

#endif
<|endoftext|>