<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: apitreeimplobj.hxx,v $
 *
 *  $Revision: 1.26 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-23 14:04:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef CONFIGMGR_API_TREEIMPLOBJECTS_HXX_
#define CONFIGMGR_API_TREEIMPLOBJECTS_HXX_

#ifndef CONFIGMGR_CONFIGNODE_HXX_
#include "noderef.hxx"
#endif
#ifndef CONFIGMGR_CONFIGSET_HXX_
#include "configset.hxx"
#endif
#ifndef CONFIGMGR_CONFIG_DEFAULTPROVIDER_HXX_
#include "configdefaultprovider.hxx"
#endif
#ifndef CONFIGMGR_API_EVENTS_HXX_
#include "confevents.hxx"
#endif
#ifndef CONFIGMGR_MISC_OPTIONS_HXX_
#include "options.hxx"
#endif
#ifndef CONFIGMGR_UTILITY_HXX_
#include "utility.hxx"
#endif

#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _RTL_REF_HXX_
#include <rtl/ref.hxx>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef INCLUDED_MEMORY
#include <memory>
#define INCLUDED_MEMORY
#endif

#ifndef _COM_SUN_STAR_LANG_XEVENTLISTENER_HPP_
#include <com/sun/star/lang/XEventListener.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

namespace com { namespace sun { namespace star {
    namespace script { class XTypeConverter; }
} } }

namespace configmgr
{
//-----------------------------------------------------------------------------
    class OProviderImpl;
//-----------------------------------------------------------------------------
    namespace configapi
    {
//-----------------------------------------------------------------------------
        class Factory;
        class Notifier;
        class NotifierImpl;
        typedef vos::ORef<NotifierImpl> NotifierImplHolder;
//-----------------------------------------------------------------------------
        class ObjectRegistry;
        typedef rtl::Reference<ObjectRegistry> ObjectRegistryHolder;

        typedef uno::XInterface UnoInterface;
        typedef uno::Reference<UnoInterface> UnoInterfaceRef;
        typedef uno::Reference<com::sun::star::script::XTypeConverter>  UnoTypeConverter;

        typedef vos::ORef< OOptions > TreeOptions;
//-----------------------------------------------------------------------------
// API object implementation wrappers
//-------------------------------------------------------------------------
        class ApiProvider : Noncopyable
        {
            Factory&                    m_rFactory;
            OProviderImpl&              m_rProviderImpl;
        public:
            ApiProvider(Factory& rFactory, OProviderImpl& rProviderImpl );

            ~ApiProvider()
            {}

            UnoTypeConverter            getTypeConverter() const;
            Factory&                    getFactory()        { return m_rFactory; }
            OProviderImpl&              getProviderImpl()   { return m_rProviderImpl; }
        };

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

    //-------------------------------------------------------------------------
        class ApiTreeImpl : Noncopyable
        {
            class ComponentAdapter;
            typedef uno::Reference<ComponentAdapter> ComponentRef;
            typedef uno::Reference<com::sun::star::lang::XComponent> UnoComponent;

            typedef configuration::TreeRef TreeRef;
            typedef configuration::DefaultProvider DefaultProvider;

            TreeRef             m_aTree;
            NotifierImplHolder  m_aNotifier;
            DefaultProvider     m_aDefaultProvider;
            ComponentRef        m_xProvider;
            ApiProvider&        m_rProvider;
            ApiTreeImpl*        m_pParentTree;
            UnoInterface*       m_pInstance;

        public:
            explicit ApiTreeImpl(UnoInterface* pInstance, configuration::TreeRef const& aTree, ApiTreeImpl& rParentTree);
            explicit ApiTreeImpl(UnoInterface* pInstance, ApiProvider& rProvider, configuration::TreeRef const& aTree, ApiTreeImpl* pParentTree);
            explicit ApiTreeImpl(UnoInterface* _pInstance, ApiProvider& _rProvider, configuration::TreeRef const& _aTree, DefaultProvider const & _aDefaultProvider);
            ~ApiTreeImpl();

        // initialization
            void setNodeInstance(configuration::NodeRef const& aNode, UnoInterface* pInstance);

        // model access
            TreeRef getTree() const { return m_aTree; }

        // self-locked methods for dispose handling
            bool isAlive()  const;
            void checkAlive()   const;
            bool disposeTree(bool bForce);
            bool disposeTreeNow();
            void disposeNode(configuration::NodeRef const& aNode, UnoInterface* pInstance);

        // api object handling
            Factory&                    getFactory()    const   { return m_rProvider.getFactory(); }
            Notifier                    getNotifier()   const;
            DefaultProvider             getDefaultProvider()    const { return m_aDefaultProvider; }

        // needs external locking
            ApiTreeImpl const*          getRootTreeImpl() const;

            uno::XInterface*            getUnoInstance() const  { return m_pInstance; }
            ApiProvider&                getProvider()           { return m_rProvider; }
            UnoInterfaceRef             getUnoProviderInstance() const; //  { return m_xProvider; }

            /// wire this to a new parent tree
            void                        haveNewParent(ApiTreeImpl* pNewParent);
        private:
            void init(ApiTreeImpl*  pParentTree);
            void setParentTree(ApiTreeImpl* pNewParentTree);
            void deinit();

            bool implDisposeTree();
            void implDisposeNode(configuration::NodeRef const& aNode, UnoInterface* pInstance);

            friend class ComponentAdapter;
            void disposing(com::sun::star::lang::EventObject const& rEvt) throw();
            UnoComponent getProviderComponent();
            UnoComponent getParentComponent();

        };

    //-----------------------------------------------------------------------------
        class ApiRootTreeImpl
        {
            typedef configuration::AbsolutePath AbsolutePath;
            typedef configuration::DefaultProvider DefaultProvider;

        public:
            explicit ApiRootTreeImpl(UnoInterface* pInstance, ApiProvider& rProvider, configuration::Tree const& aTree, TreeOptions const& _xOptions);
            ~ApiRootTreeImpl();

            ApiTreeImpl& getApiTree() { return m_aTreeImpl; }
            ApiTreeImpl const& getApiTree() const { return m_aTreeImpl; }

            AbsolutePath const & getLocation() const { return m_aLocationPath; }
            TreeOptions getOptions() const { return m_xOptions; }

        // self-locked methods for dispose handling
            bool disposeTree();

            /// toggle whether this object relays notifications from the base provider
            bool enableNotification(bool bEnable);
        private:
            IConfigBroadcaster* implSetNotificationSource(IConfigBroadcaster* pNew);
            void implSetLocation(configuration::Tree const& _aTree);
            void releaseData();

        private:
            class NodeListener;
            friend class NodeListener;
            //IConfigBroadcaster*   m_pNotificationSource;

        // IConfigListener
            void disposing(IConfigBroadcaster* pSource) ;
        //INodeListener : IConfigListener
            void nodeChanged(Change const& aChange, AbsolutePath const& aPath, IConfigBroadcaster* pSource);
            void nodeDeleted(AbsolutePath const& aPath, IConfigBroadcaster* pSource);

        private:
            ApiTreeImpl                 m_aTreeImpl;
            AbsolutePath                m_aLocationPath;
            rtl::Reference<NodeListener> m_pNotificationListener;
            TreeOptions m_xOptions;
        };
//-----------------------------------------------------------------------------
    }
}

#endif // CONFIGMGR_API_TREEIMPLOBJECTS_HXX_
<commit_msg>INTEGRATION: CWS changefileheader (1.26.16); FILE MERGED 2008/04/01 15:06:31 thb 1.26.16.3: #i85898# Stripping all external header guards 2008/04/01 12:27:10 thb 1.26.16.2: #i85898# Stripping all external header guards 2008/03/31 12:22:36 rt 1.26.16.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: apitreeimplobj.hxx,v $
 * $Revision: 1.27 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef CONFIGMGR_API_TREEIMPLOBJECTS_HXX_
#define CONFIGMGR_API_TREEIMPLOBJECTS_HXX_

#include "noderef.hxx"
#include "configset.hxx"
#include "configdefaultprovider.hxx"
#include "confevents.hxx"
#include "options.hxx"
#include "utility.hxx"
#include <vos/ref.hxx>
#include <rtl/ref.hxx>
#include <osl/mutex.hxx>

#ifndef INCLUDED_MEMORY
#include <memory>
#define INCLUDED_MEMORY
#endif
#include <com/sun/star/lang/XEventListener.hpp>
#include <com/sun/star/lang/XComponent.hpp>

namespace com { namespace sun { namespace star {
    namespace script { class XTypeConverter; }
} } }

namespace configmgr
{
//-----------------------------------------------------------------------------
    class OProviderImpl;
//-----------------------------------------------------------------------------
    namespace configapi
    {
//-----------------------------------------------------------------------------
        class Factory;
        class Notifier;
        class NotifierImpl;
        typedef vos::ORef<NotifierImpl> NotifierImplHolder;
//-----------------------------------------------------------------------------
        class ObjectRegistry;
        typedef rtl::Reference<ObjectRegistry> ObjectRegistryHolder;

        typedef uno::XInterface UnoInterface;
        typedef uno::Reference<UnoInterface> UnoInterfaceRef;
        typedef uno::Reference<com::sun::star::script::XTypeConverter>  UnoTypeConverter;

        typedef vos::ORef< OOptions > TreeOptions;
//-----------------------------------------------------------------------------
// API object implementation wrappers
//-------------------------------------------------------------------------
        class ApiProvider : Noncopyable
        {
            Factory&                    m_rFactory;
            OProviderImpl&              m_rProviderImpl;
        public:
            ApiProvider(Factory& rFactory, OProviderImpl& rProviderImpl );

            ~ApiProvider()
            {}

            UnoTypeConverter            getTypeConverter() const;
            Factory&                    getFactory()        { return m_rFactory; }
            OProviderImpl&              getProviderImpl()   { return m_rProviderImpl; }
        };

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

    //-------------------------------------------------------------------------
        class ApiTreeImpl : Noncopyable
        {
            class ComponentAdapter;
            typedef uno::Reference<ComponentAdapter> ComponentRef;
            typedef uno::Reference<com::sun::star::lang::XComponent> UnoComponent;

            typedef configuration::TreeRef TreeRef;
            typedef configuration::DefaultProvider DefaultProvider;

            TreeRef             m_aTree;
            NotifierImplHolder  m_aNotifier;
            DefaultProvider     m_aDefaultProvider;
            ComponentRef        m_xProvider;
            ApiProvider&        m_rProvider;
            ApiTreeImpl*        m_pParentTree;
            UnoInterface*       m_pInstance;

        public:
            explicit ApiTreeImpl(UnoInterface* pInstance, configuration::TreeRef const& aTree, ApiTreeImpl& rParentTree);
            explicit ApiTreeImpl(UnoInterface* pInstance, ApiProvider& rProvider, configuration::TreeRef const& aTree, ApiTreeImpl* pParentTree);
            explicit ApiTreeImpl(UnoInterface* _pInstance, ApiProvider& _rProvider, configuration::TreeRef const& _aTree, DefaultProvider const & _aDefaultProvider);
            ~ApiTreeImpl();

        // initialization
            void setNodeInstance(configuration::NodeRef const& aNode, UnoInterface* pInstance);

        // model access
            TreeRef getTree() const { return m_aTree; }

        // self-locked methods for dispose handling
            bool isAlive()  const;
            void checkAlive()   const;
            bool disposeTree(bool bForce);
            bool disposeTreeNow();
            void disposeNode(configuration::NodeRef const& aNode, UnoInterface* pInstance);

        // api object handling
            Factory&                    getFactory()    const   { return m_rProvider.getFactory(); }
            Notifier                    getNotifier()   const;
            DefaultProvider             getDefaultProvider()    const { return m_aDefaultProvider; }

        // needs external locking
            ApiTreeImpl const*          getRootTreeImpl() const;

            uno::XInterface*            getUnoInstance() const  { return m_pInstance; }
            ApiProvider&                getProvider()           { return m_rProvider; }
            UnoInterfaceRef             getUnoProviderInstance() const; //  { return m_xProvider; }

            /// wire this to a new parent tree
            void                        haveNewParent(ApiTreeImpl* pNewParent);
        private:
            void init(ApiTreeImpl*  pParentTree);
            void setParentTree(ApiTreeImpl* pNewParentTree);
            void deinit();

            bool implDisposeTree();
            void implDisposeNode(configuration::NodeRef const& aNode, UnoInterface* pInstance);

            friend class ComponentAdapter;
            void disposing(com::sun::star::lang::EventObject const& rEvt) throw();
            UnoComponent getProviderComponent();
            UnoComponent getParentComponent();

        };

    //-----------------------------------------------------------------------------
        class ApiRootTreeImpl
        {
            typedef configuration::AbsolutePath AbsolutePath;
            typedef configuration::DefaultProvider DefaultProvider;

        public:
            explicit ApiRootTreeImpl(UnoInterface* pInstance, ApiProvider& rProvider, configuration::Tree const& aTree, TreeOptions const& _xOptions);
            ~ApiRootTreeImpl();

            ApiTreeImpl& getApiTree() { return m_aTreeImpl; }
            ApiTreeImpl const& getApiTree() const { return m_aTreeImpl; }

            AbsolutePath const & getLocation() const { return m_aLocationPath; }
            TreeOptions getOptions() const { return m_xOptions; }

        // self-locked methods for dispose handling
            bool disposeTree();

            /// toggle whether this object relays notifications from the base provider
            bool enableNotification(bool bEnable);
        private:
            IConfigBroadcaster* implSetNotificationSource(IConfigBroadcaster* pNew);
            void implSetLocation(configuration::Tree const& _aTree);
            void releaseData();

        private:
            class NodeListener;
            friend class NodeListener;
            //IConfigBroadcaster*   m_pNotificationSource;

        // IConfigListener
            void disposing(IConfigBroadcaster* pSource) ;
        //INodeListener : IConfigListener
            void nodeChanged(Change const& aChange, AbsolutePath const& aPath, IConfigBroadcaster* pSource);
            void nodeDeleted(AbsolutePath const& aPath, IConfigBroadcaster* pSource);

        private:
            ApiTreeImpl                 m_aTreeImpl;
            AbsolutePath                m_aLocationPath;
            rtl::Reference<NodeListener> m_pNotificationListener;
            TreeOptions m_xOptions;
        };
//-----------------------------------------------------------------------------
    }
}

#endif // CONFIGMGR_API_TREEIMPLOBJECTS_HXX_
<|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2010-2011 Matthias Kretz <kretz@kde.org>

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

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "unittest.h"
#include <limits>
#include <algorithm>

using namespace Vc;

template<typename V1, typename V2> void testNumber(double n)
{
    typedef typename V1::EntryType T1;
    typedef typename V2::EntryType T2;

    // compare casts from T1 -> T2 with casts from V1 -> V2

    const T1 n1 = static_cast<T1>(n);
    //std::cerr << "n1 = " << n1 << ", static_cast<T2>(n1) = " << static_cast<T2>(n1) << std::endl;
    COMPARE(static_cast<V2>(V1(n1)), V2(static_cast<T2>(n1))) << "\n       n1: " << n1;
}

template<typename T> double maxHelper()
{
    return static_cast<double>(std::numeric_limits<T>::max());
}

template<> double maxHelper<int>()
{
    const int intDigits = std::numeric_limits<int>::digits;
    const int floatDigits = std::numeric_limits<float>::digits;
    return static_cast<double>(((int(1) << floatDigits) - 1) << (intDigits - floatDigits));
}

template<> double maxHelper<unsigned int>()
{
    const int intDigits = std::numeric_limits<unsigned int>::digits;
    const int floatDigits = std::numeric_limits<float>::digits;
    return static_cast<double>(((unsigned(1) << floatDigits) - 1) << (intDigits - floatDigits));
}

template<typename V1, typename V2> void testCast2()
{
    typedef typename V1::EntryType T1;
    typedef typename V2::EntryType T2;

    const double max = std::min(maxHelper<T1>(), maxHelper<T2>());
    const double min = std::max(
            std::numeric_limits<T1>::is_integer ?
                static_cast<double>(std::numeric_limits<T1>::min()) :
                static_cast<double>(-std::numeric_limits<T1>::max()),
            std::numeric_limits<T2>::is_integer ?
                static_cast<double>(std::numeric_limits<T2>::min()) :
                static_cast<double>(-std::numeric_limits<T2>::max())
                );

    testNumber<V1, V2>(0.);
    testNumber<V1, V2>(1.);
    testNumber<V1, V2>(2.);
    testNumber<V1, V2>(max);
    testNumber<V1, V2>(max / 4 + max / 2);
    testNumber<V1, V2>(max / 2);
    testNumber<V1, V2>(max / 4);
    testNumber<V1, V2>(min);
}

template<typename T> void testCast()
{
    testCast2<typename T::V1, typename T::V2>();
}

#define _CONCAT(A, B) A ## _ ## B
#define CONCAT(A, B) _CONCAT(A, B)
template<typename T1, typename T2>
struct T2Helper
{
    typedef T1 V1;
    typedef T2 V2;
};

void testmain()
{
#define TEST(v1, v2) \
    typedef T2Helper<v1, v2> CONCAT(v1, v2); \
    runTest(testCast<CONCAT(v1, v2)>)

    TEST(float_v, float_v);
    TEST(float_v, int_v);
    TEST(float_v, uint_v);
    // needs special handling for different Size:
    //TEST(float_v, double_v);
    //TEST(float_v, short_v);
    //TEST(float_v, ushort_v);

    TEST(int_v, float_v);
    TEST(int_v, int_v);
    TEST(int_v, uint_v);

    TEST(uint_v, float_v);
    TEST(uint_v, int_v);
    TEST(uint_v, uint_v);

    TEST(ushort_v, short_v);
    TEST(ushort_v, ushort_v);

    TEST(short_v, short_v);
    TEST(short_v, ushort_v);
#undef TEST
}
<commit_msg>use a different macro name<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2010-2011 Matthias Kretz <kretz@kde.org>

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

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "unittest.h"
#include <limits>
#include <algorithm>

using namespace Vc;

template<typename V1, typename V2> void testNumber(double n)
{
    typedef typename V1::EntryType T1;
    typedef typename V2::EntryType T2;

    // compare casts from T1 -> T2 with casts from V1 -> V2

    const T1 n1 = static_cast<T1>(n);
    //std::cerr << "n1 = " << n1 << ", static_cast<T2>(n1) = " << static_cast<T2>(n1) << std::endl;
    COMPARE(static_cast<V2>(V1(n1)), V2(static_cast<T2>(n1))) << "\n       n1: " << n1;
}

template<typename T> double maxHelper()
{
    return static_cast<double>(std::numeric_limits<T>::max());
}

template<> double maxHelper<int>()
{
    const int intDigits = std::numeric_limits<int>::digits;
    const int floatDigits = std::numeric_limits<float>::digits;
    return static_cast<double>(((int(1) << floatDigits) - 1) << (intDigits - floatDigits));
}

template<> double maxHelper<unsigned int>()
{
    const int intDigits = std::numeric_limits<unsigned int>::digits;
    const int floatDigits = std::numeric_limits<float>::digits;
    return static_cast<double>(((unsigned(1) << floatDigits) - 1) << (intDigits - floatDigits));
}

template<typename V1, typename V2> void testCast2()
{
    typedef typename V1::EntryType T1;
    typedef typename V2::EntryType T2;

    const double max = std::min(maxHelper<T1>(), maxHelper<T2>());
    const double min = std::max(
            std::numeric_limits<T1>::is_integer ?
                static_cast<double>(std::numeric_limits<T1>::min()) :
                static_cast<double>(-std::numeric_limits<T1>::max()),
            std::numeric_limits<T2>::is_integer ?
                static_cast<double>(std::numeric_limits<T2>::min()) :
                static_cast<double>(-std::numeric_limits<T2>::max())
                );

    testNumber<V1, V2>(0.);
    testNumber<V1, V2>(1.);
    testNumber<V1, V2>(2.);
    testNumber<V1, V2>(max);
    testNumber<V1, V2>(max / 4 + max / 2);
    testNumber<V1, V2>(max / 2);
    testNumber<V1, V2>(max / 4);
    testNumber<V1, V2>(min);
}

template<typename T> void testCast()
{
    testCast2<typename T::V1, typename T::V2>();
}

#define _CONCAT(A, B) A ## _ ## B
#define CONCAT(A, B) _CONCAT(A, B)
template<typename T1, typename T2>
struct T2Helper
{
    typedef T1 V1;
    typedef T2 V2;
};

void testmain()
{
#define TEST_CAST(v1, v2) \
    typedef T2Helper<v1, v2> CONCAT(v1, v2); \
    runTest(testCast<CONCAT(v1, v2)>)

    TEST_CAST(float_v, float_v);
    TEST_CAST(float_v, int_v);
    TEST_CAST(float_v, uint_v);
    // needs special handling for different Size:
    //TEST_CAST(float_v, double_v);
    //TEST_CAST(float_v, short_v);
    //TEST_CAST(float_v, ushort_v);

    TEST_CAST(int_v, float_v);
    TEST_CAST(int_v, int_v);
    TEST_CAST(int_v, uint_v);

    TEST_CAST(uint_v, float_v);
    TEST_CAST(uint_v, int_v);
    TEST_CAST(uint_v, uint_v);

    TEST_CAST(ushort_v, short_v);
    TEST_CAST(ushort_v, ushort_v);

    TEST_CAST(short_v, short_v);
    TEST_CAST(short_v, ushort_v);
#undef TEST_CAST
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cmath>

using namespace std;

int n, m;
int st[1000010][21], pow2[21];

inline int max(int x, int y)
{
	return x > y ? x : y;
}

inline int _log2(int x)
{
	int res = 0;
	while (x > 1)
	{
		x >>= 1;
		res++;
	}
	return res;
}

void init_pow2()
{
	pow2[0] = 1;
	for (int i = 1; i <= 20; i++)
	{
		pow2[i] = pow2[i - 1] * 2;
	}
}

void build_st()
{
	init_pow2();
	for (int i = 1; i <= 20; i++)
	{
		for (int j = 0; j < n; j++)
		{
			st[j][i] = max(st[j][i - 1], st[j + pow2[i - 1]][i - 1]);
		}
	}
}

int get_max(int l, int r)
{
	int x = _log2(r - l + 1);
	return max(st[l][x], st[r - pow2[x] + 1][x]);
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &st[i][0]);
	}
	build_st();
	for (int i = 0; i < m; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		printf("%d\n", get_max(a - 1, b - 1));
	}

	return 0;
}
<commit_msg>删除未引用的头文件<commit_after>#include <cstdio>

using namespace std;

int n, m;
int st[1000010][21], pow2[21];

inline int max(int x, int y)
{
	return x > y ? x : y;
}

inline int _log2(int x)
{
	int res = 0;
	while (x > 1)
	{
		x >>= 1;
		res++;
	}
	return res;
}

void init_pow2()
{
	pow2[0] = 1;
	for (int i = 1; i <= 20; i++)
	{
		pow2[i] = pow2[i - 1] * 2;
	}
}

void build_st()
{
	init_pow2();
	for (int i = 1; i <= 20; i++)
	{
		for (int j = 0; j < n; j++)
		{
			st[j][i] = max(st[j][i - 1], st[j + pow2[i - 1]][i - 1]);
		}
	}
}

int get_max(int l, int r)
{
	int x = _log2(r - l + 1);
	return max(st[l][x], st[r - pow2[x] + 1][x]);
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &st[i][0]);
	}
	build_st();
	for (int i = 0; i < m; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		printf("%d\n", get_max(a - 1, b - 1));
	}

	return 0;
}
<|endoftext|>


<commit_before>//test program for opencv kalman filters

#include "KalmanFilter.hpp"

#include "opencv/cv.h"

#include <iostream>

using std::cout;
using std::endl;

int main (){
  cout << "Testing opencv" << endl;

  //creating a KalmanFilter
  KalmanFilter k(KalmanFilter::R_P);
  k.printState();

  //create a starting measurement matrix
  float z[] = {0.5, 0.5, 0.1};
  CvMat * meas =  cvCreateMat(3, 1, CV_32FC1);
  memcpy(meas->data.fl, z, sizeof(z));

  cout << "====== Single Measurement =====" << endl;

  for (unsigned int i = 0; i<5; ++i){

    //run predict
    cout << "Predicting..." << endl;
    k.predict();
    //k.printState();

    //run correct
    cout << "Correcting..." << endl;
    k.correct(meas);
    k.printState();
  }

  cout << "====== Moving Measurement =====" << endl;
  float zm[3] = {0.5, 0.5, 0.1};

  for (unsigned int i = 0; i<5; ++i){

    //adjust measurement
    zm[0] = zm[0]+0.2;
    zm[1] = zm[1]+0.2;
    zm[2] = zm[2]+0.1;

    CvMat * meas =  cvCreateMat(3, 1, CV_32FC1);
    memcpy(meas->data.fl, zm, sizeof(zm));

    //run predict
    cout << "Predicting..." << endl;
    k.predict();
    //k.printState();

    //run correct
    cout << "Correcting..." << endl;
    k.correct(meas);
    k.printState();
  }

  cout << "Test complete" << endl;

  return 0;
}
<commit_msg>removed extraneous old tests from modeling<commit_after><|endoftext|>


<commit_before>// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
/*
 *  HybridBinarizer.cpp
 *  zxing
 *
 *  Copyright 2010 ZXing authors All rights reserved.
 *
 * 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.
 */

#include <zxing/common/HybridBinarizer.h>

#include <zxing/common/IllegalArgumentException.h>

using namespace std;
using namespace zxing;

namespace {
  const int BLOCK_SIZE_POWER = 3;
  const int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER;
  const int BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
  const int MINIMUM_DIMENSION = BLOCK_SIZE * 5;
}

HybridBinarizer::HybridBinarizer(Ref<LuminanceSource> source) :
  GlobalHistogramBinarizer(source), matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
}

HybridBinarizer::~HybridBinarizer() {
}

Ref<Binarizer>
HybridBinarizer::createBinarizer(Ref<LuminanceSource> source) {
  return Ref<Binarizer> (new HybridBinarizer(source));
}

Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
  // Calculates the final BitMatrix once for all requests. This could
  // be called once from the constructor instead, but there are some
  // advantages to doing it lazily, such as making profiling easier,
  // and not doing heavy lifting when callers don't expect it.
  if (matrix_) {
    return matrix_;
  }
  LuminanceSource& source = *getLuminanceSource();
  if (source.getWidth() >= MINIMUM_DIMENSION &&
      source.getHeight() >= MINIMUM_DIMENSION) {
    unsigned char* luminances = source.getMatrix();
    int width = source.getWidth();
    int height = source.getHeight();
    int subWidth = width >> BLOCK_SIZE_POWER;
    if ((width & BLOCK_SIZE_MASK) != 0) {
      subWidth++;
    }
    int subHeight = height >> BLOCK_SIZE_POWER;
    if ((height & BLOCK_SIZE_MASK) != 0) {
      subHeight++;
    }
    int* blackPoints =
      calculateBlackPoints(luminances, subWidth, subHeight, width, height);

    Ref<BitMatrix> newMatrix (new BitMatrix(width, height));
    calculateThresholdForBlock(luminances,
                               subWidth,
                               subHeight,
                               width,
                               height,
                               blackPoints,
                               newMatrix);
    matrix_ = newMatrix;

    // N.B.: these deletes are inadequate if anything between the new
    // and this point can throw.  As of this writing, it doesn't look
    // like they do.

    delete [] blackPoints;
    delete [] luminances;
  } else {
    // If the image is too small, fall back to the global histogram approach.
    matrix_ = GlobalHistogramBinarizer::getBlackMatrix();
  }
  return matrix_;
}

void
HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances,
                                            int subWidth,
                                            int subHeight,
                                            int width,
                                            int height,
                                            int blackPoints[],
                                            Ref<BitMatrix> const& matrix) {
  for (int y = 0; y < subHeight; y++) {
    int yoffset = y << BLOCK_SIZE_POWER;
    if (yoffset + BLOCK_SIZE >= height) {
      yoffset = height - BLOCK_SIZE;
    }
    for (int x = 0; x < subWidth; x++) {
      int xoffset = x << BLOCK_SIZE_POWER;
      if (xoffset + BLOCK_SIZE >= width) {
        xoffset = width - BLOCK_SIZE;
      }
      int left = (x > 1) ? x : 2;
      left = (left < subWidth - 2) ? left : subWidth - 3;
      int top = (y > 1) ? y : 2;
      top = (top < subHeight - 2) ? top : subHeight - 3;
      int sum = 0;
      for (int z = -2; z <= 2; z++) {
        int *blackRow = &blackPoints[(top + z) * subWidth];
        sum += blackRow[left - 2];
        sum += blackRow[left - 1];
        sum += blackRow[left];
        sum += blackRow[left + 1];
        sum += blackRow[left + 2];
      }
      int average = sum / 25;
      threshold8x8Block(luminances, xoffset, yoffset, average, width, matrix);
    }
  }
}

void HybridBinarizer::threshold8x8Block(unsigned char* luminances,
                                        int xoffset,
                                        int yoffset,
                                        int threshold,
                                        int stride,
                                        Ref<BitMatrix> const& matrix) {
  for (int y = 0, offset = yoffset * stride + xoffset;
       y < BLOCK_SIZE;
       y++,  offset += stride) {
    for (int x = 0; x < BLOCK_SIZE; x++) {
      int pixel = luminances[offset + x] & 0xff;
      if (pixel <= threshold) {
        matrix->set(xoffset + x, yoffset + y);
      }
    }
  }
}

namespace {
  inline int getBlackPointFromNeighbors(int* blackPoints, int subWidth, int x, int y) {
    return (blackPoints[(y-1)*subWidth+x] +
            2*blackPoints[y*subWidth+x-1] +
            blackPoints[(y-1)*subWidth+x-1]) >> 2;
  }
}

int* HybridBinarizer::calculateBlackPoints(unsigned char* luminances, int subWidth, int subHeight,
    int width, int height) {
  int *blackPoints = new int[subHeight * subWidth];
  for (int y = 0; y < subHeight; y++) {
    int yoffset = y << BLOCK_SIZE_POWER;
    if (yoffset + BLOCK_SIZE >= height) {
      yoffset = height - BLOCK_SIZE;
    }
    for (int x = 0; x < subWidth; x++) {
      int xoffset = x << BLOCK_SIZE_POWER;
      if (xoffset + BLOCK_SIZE >= width) {
        xoffset = width - BLOCK_SIZE;
      }
      int sum = 0;
      int min = 0xFF;
      int max = 0;
      for (int yy = 0, offset = yoffset * width + xoffset;
           yy < BLOCK_SIZE;
           yy++, offset += width) {
        for (int xx = 0; xx < BLOCK_SIZE; xx++) {
          int pixel = luminances[offset + xx] & 0xFF;
          sum += pixel;
          if (pixel < min) {
            min = pixel;
          }
          if (pixel > max) {
            max = pixel;
          }
        }
      }

      // See
      // http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
      int average = sum >> 6;
      if (max - min <= 24) {
        average = min >> 1;
        if (y > 0 && x > 0) {
          int bp = getBlackPointFromNeighbors(blackPoints, subWidth, x, y);
          if (min < bp) {
            average = bp;
          }
        }
      }
      blackPoints[y * subWidth + x] = average;
    }
  }
  return blackPoints;
}

<commit_msg>Decent speed improvement for HybridBinarizer::calculateBlackPoints().  The approach is to stop testing for min/max values once the dynamic range condition is satisfied.<commit_after>// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
/*
 *  HybridBinarizer.cpp
 *  zxing
 *
 *  Copyright 2010 ZXing authors All rights reserved.
 *
 * 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.
 */

#include <zxing/common/HybridBinarizer.h>

#include <zxing/common/IllegalArgumentException.h>

using namespace std;
using namespace zxing;

namespace {
  const int BLOCK_SIZE_POWER = 3;
  const int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER;
  const int BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
  const int MINIMUM_DIMENSION = BLOCK_SIZE * 5;
}

HybridBinarizer::HybridBinarizer(Ref<LuminanceSource> source) :
  GlobalHistogramBinarizer(source), matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
}

HybridBinarizer::~HybridBinarizer() {
}

Ref<Binarizer>
HybridBinarizer::createBinarizer(Ref<LuminanceSource> source) {
  return Ref<Binarizer> (new HybridBinarizer(source));
}

Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
  // Calculates the final BitMatrix once for all requests. This could
  // be called once from the constructor instead, but there are some
  // advantages to doing it lazily, such as making profiling easier,
  // and not doing heavy lifting when callers don't expect it.
  if (matrix_) {
    return matrix_;
  }
  LuminanceSource& source = *getLuminanceSource();
  if (source.getWidth() >= MINIMUM_DIMENSION &&
      source.getHeight() >= MINIMUM_DIMENSION) {
    unsigned char* luminances = source.getMatrix();
    int width = source.getWidth();
    int height = source.getHeight();
    int subWidth = width >> BLOCK_SIZE_POWER;
    if ((width & BLOCK_SIZE_MASK) != 0) {
      subWidth++;
    }
    int subHeight = height >> BLOCK_SIZE_POWER;
    if ((height & BLOCK_SIZE_MASK) != 0) {
      subHeight++;
    }
    int* blackPoints =
      calculateBlackPoints(luminances, subWidth, subHeight, width, height);

    Ref<BitMatrix> newMatrix (new BitMatrix(width, height));
    calculateThresholdForBlock(luminances,
                               subWidth,
                               subHeight,
                               width,
                               height,
                               blackPoints,
                               newMatrix);
    matrix_ = newMatrix;

    // N.B.: these deletes are inadequate if anything between the new
    // and this point can throw.  As of this writing, it doesn't look
    // like they do.

    delete [] blackPoints;
    delete [] luminances;
  } else {
    // If the image is too small, fall back to the global histogram approach.
    matrix_ = GlobalHistogramBinarizer::getBlackMatrix();
  }
  return matrix_;
}

void
HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances,
                                            int subWidth,
                                            int subHeight,
                                            int width,
                                            int height,
                                            int blackPoints[],
                                            Ref<BitMatrix> const& matrix) {
  for (int y = 0; y < subHeight; y++) {
    int yoffset = y << BLOCK_SIZE_POWER;
    if (yoffset + BLOCK_SIZE >= height) {
      yoffset = height - BLOCK_SIZE;
    }
    for (int x = 0; x < subWidth; x++) {
      int xoffset = x << BLOCK_SIZE_POWER;
      if (xoffset + BLOCK_SIZE >= width) {
        xoffset = width - BLOCK_SIZE;
      }
      int left = (x > 1) ? x : 2;
      left = (left < subWidth - 2) ? left : subWidth - 3;
      int top = (y > 1) ? y : 2;
      top = (top < subHeight - 2) ? top : subHeight - 3;
      int sum = 0;
      for (int z = -2; z <= 2; z++) {
        int *blackRow = &blackPoints[(top + z) * subWidth];
        sum += blackRow[left - 2];
        sum += blackRow[left - 1];
        sum += blackRow[left];
        sum += blackRow[left + 1];
        sum += blackRow[left + 2];
      }
      int average = sum / 25;
      threshold8x8Block(luminances, xoffset, yoffset, average, width, matrix);
    }
  }
}

void HybridBinarizer::threshold8x8Block(unsigned char* luminances,
                                        int xoffset,
                                        int yoffset,
                                        int threshold,
                                        int stride,
                                        Ref<BitMatrix> const& matrix) {
  for (int y = 0, offset = yoffset * stride + xoffset;
       y < BLOCK_SIZE;
       y++,  offset += stride) {
    for (int x = 0; x < BLOCK_SIZE; x++) {
      int pixel = luminances[offset + x] & 0xff;
      if (pixel <= threshold) {
        matrix->set(xoffset + x, yoffset + y);
      }
    }
  }
}

namespace {
  inline int getBlackPointFromNeighbors(int* blackPoints, int subWidth, int x, int y) {
    return (blackPoints[(y-1)*subWidth+x] +
            2*blackPoints[y*subWidth+x-1] +
            blackPoints[(y-1)*subWidth+x-1]) >> 2;
  }
}

int* HybridBinarizer::calculateBlackPoints(unsigned char* luminances, int subWidth, int subHeight,
    int width, int height) {
  const int minDynamicRange = 24;

  int *blackPoints = new int[subHeight * subWidth];
  for (int y = 0; y < subHeight; y++) {
    int yoffset = y << BLOCK_SIZE_POWER;
    if (yoffset + BLOCK_SIZE >= height) {
      yoffset = height - BLOCK_SIZE;
    }
    for (int x = 0; x < subWidth; x++) {
      int xoffset = x << BLOCK_SIZE_POWER;
      if (xoffset + BLOCK_SIZE >= width) {
        xoffset = width - BLOCK_SIZE;
      }
      int sum = 0;
      int min = 0xFF;
      int max = 0;
      for (int yy = 0, offset = yoffset * width + xoffset;
           yy < BLOCK_SIZE;
           yy++, offset += width) {
        for (int xx = 0; xx < BLOCK_SIZE; xx++) {
          int pixel = luminances[offset + xx] & 0xFF;
          sum += pixel;
          // still looking for good contrast
          if (pixel < min) {
            min = pixel;
          }
          if (pixel > max) {
            max = pixel;
          }
        }

        // short-circuit min/max tests once dynamic range is met
        if (max - min > minDynamicRange) {
          // finish the rest of the rows quickly
          for (yy++, offset += width; yy < BLOCK_SIZE; yy++, offset += width) {
            for (int xx = 0; xx < BLOCK_SIZE; xx += 2) {
              sum += luminances[offset + xx] & 0xFF;
              sum += luminances[offset + xx + 1] & 0xFF;
            }
          }
        }
      }
      // See
      // http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
      int average = sum >> (BLOCK_SIZE_POWER * 2);
      if (max - min <= minDynamicRange) {
        average = min >> 1;
        if (y > 0 && x > 0) {
          int bp = getBlackPointFromNeighbors(blackPoints, subWidth, x, y);
          if (min < bp) {
            average = bp;
          }
        }
      }
      blackPoints[y * subWidth + x] = average;
    }
  }
  return blackPoints;
}

<|endoftext|>


<commit_before>/**
 * Created by Jian Chen
 * @since  2016.05.06
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#include <chen/base/utf8.hpp>

using namespace chen;

// -----------------------------------------------------------------------------
// utf8
std::size_t utf8::count(const std::string &text)
{
    auto ptr = text.data();
    auto len = text.size();

    std::size_t num  = 0;
    std::size_t pos  = utf8::bom(text) ? 3 : 0;
    std::size_t step = 0;

    while (pos < len)
    {
        if ((ptr[pos] & 0x80) == 0x00)       // 1Bytes
            step = 1;
        else if ((ptr[pos] & 0xE0) == 0xC0)  // 2Bytes
            step = 2;
        else if ((ptr[pos] & 0xF0) == 0xE0)  // 3Bytes
            step = 3;
        else if ((ptr[pos] & 0xF8) == 0xF0)  // 4Bytes
            step = 4;
        else if ((ptr[pos] & 0xFC) == 0xF8)  // 5Bytes
            step = 5;
        else if ((ptr[pos] & 0xFE) == 0xFC)  // 6Bytes
            step = 6;
        else
            break;

        ++num;
        pos += step;
    }

    return num;
}

std::string utf8::substr(const std::string &text, std::size_t start, std::size_t count)
{
    if (!count)
        return "";

    auto ptr = text.data();
    auto len = text.size();

    std::string ret;

    std::size_t num  = 0;
    std::size_t pos  = utf8::bom(text) ? 3 : 0;
    std::size_t step = 0;

    while ((pos < len) && count)
    {
        if ((ptr[pos] & 0x80) == 0x00)       // 1Bytes
            step = 1;
        else if ((ptr[pos] & 0xE0) == 0xC0)  // 2Bytes
            step = 2;
        else if ((ptr[pos] & 0xF0) == 0xE0)  // 3Bytes
            step = 3;
        else if ((ptr[pos] & 0xF8) == 0xF0)  // 4Bytes
            step = 4;
        else if ((ptr[pos] & 0xFC) == 0xF8)  // 5Bytes
            step = 5;
        else if ((ptr[pos] & 0xFE) == 0xFC)  // 6Bytes
            step = 6;
        else
            return ret;

        if (num >= start)
        {
            ret.append(ptr + pos, step);
            count--;
        }

        ++num;
        pos += step;
    }

    return ret;
}

bool utf8::bom(const std::string &text)
{
    return (text.size() >= 3) &&
           (static_cast<unsigned char>(text[0]) == 0xEF) &&
           (static_cast<unsigned char>(text[1]) == 0xBB) &&
           (static_cast<unsigned char>(text[2]) == 0xBF);
}

std::string utf8::convert(std::uint32_t ch)
{
    // I want to use C++11's codecvt to do the convert
    // but unfortunately the cocos2d-x didn't support it on Android now
    // I don't like to import any third-party library to do the simple convert
    // so I bought from http://stackoverflow.com/questions/4607413/c-library-to-convert-unicode-code-points-to-utf8
    // thanks to its author
    std::string ret;

    if (ch < 0x80)
    {
        ret += ch;
    }
    else if (ch < 0x800)
    {
        ret += 192 + ch / 64;
        ret += 128 + ch % 64;
    }
    else if (ch - 0xd800u < 0x800)
    {
        // error
        throw std::runtime_error("utf8: invalid unicode char");
    }
    else if (ch < 0x10000)
    {
        ret += 224 + ch / 4096;
        ret += 128 + ch / 64 % 64;
        ret += 128 + ch % 64;
    }
    else if (ch < 0x110000)
    {
        ret += 240 + ch / 262144;
        ret += 128 + ch / 4096 % 64;
        ret += 128 + ch / 64 % 64;
        ret += 128 + ch % 64;
    }
    else
    {
        // error
        throw std::runtime_error("utf8: invalid unicode char");
    }

    return ret;
}<commit_msg>utf8: add header file for exception<commit_after>/**
 * Created by Jian Chen
 * @since  2016.05.06
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#include <chen/base/utf8.hpp>
#include <stdexcept>

using namespace chen;

// -----------------------------------------------------------------------------
// utf8
std::size_t utf8::count(const std::string &text)
{
    auto ptr = text.data();
    auto len = text.size();

    std::size_t num  = 0;
    std::size_t pos  = utf8::bom(text) ? 3 : 0;
    std::size_t step = 0;

    while (pos < len)
    {
        if ((ptr[pos] & 0x80) == 0x00)       // 1Bytes
            step = 1;
        else if ((ptr[pos] & 0xE0) == 0xC0)  // 2Bytes
            step = 2;
        else if ((ptr[pos] & 0xF0) == 0xE0)  // 3Bytes
            step = 3;
        else if ((ptr[pos] & 0xF8) == 0xF0)  // 4Bytes
            step = 4;
        else if ((ptr[pos] & 0xFC) == 0xF8)  // 5Bytes
            step = 5;
        else if ((ptr[pos] & 0xFE) == 0xFC)  // 6Bytes
            step = 6;
        else
            break;

        ++num;
        pos += step;
    }

    return num;
}

std::string utf8::substr(const std::string &text, std::size_t start, std::size_t count)
{
    if (!count)
        return "";

    auto ptr = text.data();
    auto len = text.size();

    std::string ret;

    std::size_t num  = 0;
    std::size_t pos  = utf8::bom(text) ? 3 : 0;
    std::size_t step = 0;

    while ((pos < len) && count)
    {
        if ((ptr[pos] & 0x80) == 0x00)       // 1Bytes
            step = 1;
        else if ((ptr[pos] & 0xE0) == 0xC0)  // 2Bytes
            step = 2;
        else if ((ptr[pos] & 0xF0) == 0xE0)  // 3Bytes
            step = 3;
        else if ((ptr[pos] & 0xF8) == 0xF0)  // 4Bytes
            step = 4;
        else if ((ptr[pos] & 0xFC) == 0xF8)  // 5Bytes
            step = 5;
        else if ((ptr[pos] & 0xFE) == 0xFC)  // 6Bytes
            step = 6;
        else
            return ret;

        if (num >= start)
        {
            ret.append(ptr + pos, step);
            count--;
        }

        ++num;
        pos += step;
    }

    return ret;
}

bool utf8::bom(const std::string &text)
{
    return (text.size() >= 3) &&
           (static_cast<unsigned char>(text[0]) == 0xEF) &&
           (static_cast<unsigned char>(text[1]) == 0xBB) &&
           (static_cast<unsigned char>(text[2]) == 0xBF);
}

std::string utf8::convert(std::uint32_t ch)
{
    // I want to use C++11's codecvt to do the convert
    // but unfortunately the cocos2d-x didn't support it on Android now
    // I don't like to import any third-party library to do the simple convert
    // so I bought from http://stackoverflow.com/questions/4607413/c-library-to-convert-unicode-code-points-to-utf8
    // thanks to its author
    std::string ret;

    if (ch < 0x80)
    {
        ret += ch;
    }
    else if (ch < 0x800)
    {
        ret += 192 + ch / 64;
        ret += 128 + ch % 64;
    }
    else if (ch - 0xd800u < 0x800)
    {
        // error
        throw std::runtime_error("utf8: invalid unicode char");
    }
    else if (ch < 0x10000)
    {
        ret += 224 + ch / 4096;
        ret += 128 + ch / 64 % 64;
        ret += 128 + ch % 64;
    }
    else if (ch < 0x110000)
    {
        ret += 240 + ch / 262144;
        ret += 128 + ch / 4096 % 64;
        ret += 128 + ch / 64 % 64;
        ret += 128 + ch % 64;
    }
    else
    {
        // error
        throw std::runtime_error("utf8: invalid unicode char");
    }

    return ret;
}<|endoftext|>


<commit_before>/* Copyright (c) 2008-2009, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "bootimage.h"
#include "heapwalk.h"
#include "common.h"
#include "machine.h"
#include "util.h"
#include "assembler.h"

// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }

using namespace vm;

namespace {

bool
endsWith(const char* suffix, const char* s, unsigned length)
{
  unsigned suffixLength = strlen(suffix);
  return length >= suffixLength
    and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}

object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
              uintptr_t* codeMap, const char* className,
              const char* methodName, const char* methodSpec)
{
  object constants = 0;
  PROTECT(t, constants);

  object calls = 0;
  PROTECT(t, calls);

  DelayedPromise* addresses = 0;

  for (Finder::Iterator it(t->m->finder); it.hasMore();) {
    unsigned nameSize = 0;
    const char* name = it.next(&nameSize);

    if (endsWith(".class", name, nameSize)
        and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
    {
//       fprintf(stderr, "%.*s\n", nameSize - 6, name);
      object c = resolveSystemClass
        (t, makeByteArray(t, "%.*s", nameSize - 6, name));

      if (t->exception) return 0;

      PROTECT(t, c);

      if (classMethodTable(t, c)) {
        for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
          object method = arrayBody(t, classMethodTable(t, c), i);
          if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
              and ((methodName == 0
                    or ::strcmp
                    (reinterpret_cast<char*>
                     (&byteArrayBody
                      (t, vm::methodName(t, method), 0)), methodName) == 0)
                   and (methodSpec == 0
                        or ::strcmp
                        (reinterpret_cast<char*>
                         (&byteArrayBody
                          (t, vm::methodSpec(t, method), 0)), methodSpec)
                        == 0)))
          {
            t->m->processor->compileMethod
              (t, zone, &constants, &calls, &addresses, method);
          }
        }
      }
    }
  }

  for (; calls; calls = tripleThird(t, calls)) {
    object method = tripleFirst(t, calls);
    uintptr_t address;
    if (methodFlags(t, method) & ACC_NATIVE) {
      address = reinterpret_cast<uintptr_t>(code + image->nativeThunk);
    } else {
      address = methodCompiled(t, method);
    }

    static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
      ->listener->resolve(address, 0);
  }

  for (; addresses; addresses = addresses->next) {
    uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
    assert(t, value >= code);

    void* location;
    bool flat = addresses->listener->resolve(0, &location);
    uintptr_t offset = value - code;
    if (flat) {
      offset |= BootFlatConstant;
    }
    memcpy(location, &offset, BytesPerWord);

    assert(t, reinterpret_cast<intptr_t>(location)
           >= reinterpret_cast<intptr_t>(code));

    markBit(codeMap, reinterpret_cast<intptr_t>(location)
            - reinterpret_cast<intptr_t>(code));
  }

  return constants;
}

unsigned
objectSize(Thread* t, object o)
{
  assert(t, not objectExtended(t, o));

  return baseSize(t, o, objectClass(t, o));
}

void
visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{
  Machine* m = t->m;

  for (HashMapIterator it(t, m->classMap); it.hasMore();) {
    w->visitRoot(tripleSecond(t, it.next()));
  }

  image->loader = w->visitRoot(m->loader);
  image->types = w->visitRoot(m->types);

  m->processor->visitRoots(w);

  for (; constants; constants = tripleThird(t, constants)) {
    w->visitRoot(tripleFirst(t, constants));
  }
}

HeapWalker*
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
              unsigned capacity, object constants)
{
  class Visitor: public HeapVisitor {
   public:
    Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
      t(t), currentObject(0), currentNumber(0), currentOffset(0), heap(heap),
      map(map), position(0), capacity(capacity)
    { }

    void visit(unsigned number) {
      if (currentObject) {
        unsigned offset = currentNumber - 1 + currentOffset;
        unsigned mark = heap[offset] & (~PointerMask);
        unsigned value = number | (mark << BootShift);

        if (value) markBit(map, offset);

        heap[offset] = value;
      }
    }

    virtual void root() {
      currentObject = 0;
    }

    virtual unsigned visitNew(object p) {
      if (p) {
        unsigned size = objectSize(t, p);

        unsigned number;
        if (currentObject
            and (currentOffset * BytesPerWord) == ClassStaticTable)
        {
          FixedAllocator allocator
            (t->m->system, reinterpret_cast<uint8_t*>(heap + position),
             (capacity - position) * BytesPerWord);

          unsigned totalInBytes;
          uintptr_t* dst = static_cast<uintptr_t*>
            (t->m->heap->allocateImmortalFixed
             (&allocator, size, true, &totalInBytes));

          memcpy(dst, p, size * BytesPerWord);

          dst[0] |= FixedMark;

          number = (dst - heap) + 1;
          position += ceiling(totalInBytes, BytesPerWord);
        } else {
          assert(t, position + size < capacity);
          memcpy(heap + position, p, size * BytesPerWord);

          number = position + 1;
          position += size;
        }

        visit(number);

        return number;
      } else {
        return 0;
      }
    }

    virtual void visitOld(object, unsigned number) {
      visit(number);
    }

    virtual void push(object object, unsigned number, unsigned offset) {
      currentObject = object;
      currentNumber = number;
      currentOffset = offset;
    }

    virtual void pop() {
      currentObject = 0;
    }

    Thread* t;
    object currentObject;
    unsigned currentNumber;
    unsigned currentOffset;
    uintptr_t* heap;
    uintptr_t* map;
    unsigned position;
    unsigned capacity;
  } visitor(t, heap, map, capacity / BytesPerWord);

  HeapWalker* w = makeHeapWalker(t, &visitor);
  visitRoots(t, image, w, constants);

  image->heapSize = visitor.position * BytesPerWord;

  return w;
}

void
updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
                HeapMap* heapTable)
{
  for (; constants; constants = tripleThird(t, constants)) {
    unsigned target = heapTable->find(tripleFirst(t, constants));
    assert(t, target > 0);

    for (Promise::Listener* pl = static_cast<ListenPromise*>
           (pointerValue(t, tripleSecond(t, constants)))->listener;
         pl; pl = pl->next)
    {
      void* location;
      bool flat = pl->resolve(0, &location);
      uintptr_t offset = target | BootHeapOffset;
      if (flat) {
        offset |= BootFlatConstant;
      }
      memcpy(location, &offset, BytesPerWord);

      assert(t, reinterpret_cast<intptr_t>(location)
             >= reinterpret_cast<intptr_t>(code));

      markBit(codeMap, reinterpret_cast<intptr_t>(location)
              - reinterpret_cast<intptr_t>(code));
    }
  }
}

unsigned
offset(object a, uintptr_t* b)
{
  return reinterpret_cast<uintptr_t>(b) - reinterpret_cast<uintptr_t>(a);
}

void
writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
               unsigned codeCapacity, const char* className,
               const char* methodName, const char* methodSpec)
{
  Zone zone(t->m->system, t->m->heap, 64 * 1024);

  uintptr_t* codeMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(codeMapSize(codeCapacity)));
  memset(codeMap, 0, codeMapSize(codeCapacity));

  object constants = makeCodeImage
    (t, &zone, image, code, codeMap, className, methodName, methodSpec);

  if (t->exception) return;

  PROTECT(t, constants);

  const unsigned HeapCapacity = 32 * 1024 * 1024;
  uintptr_t* heap = static_cast<uintptr_t*>
    (t->m->heap->allocate(HeapCapacity));
  uintptr_t* heapMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(heapMapSize(HeapCapacity)));
  memset(heapMap, 0, heapMapSize(HeapCapacity));

  // this map will not be used when the bootimage is loaded, so
  // there's no need to preserve it:
  t->m->byteArrayMap = makeWeakHashMap(t, 0, 0);

  collect(t, Heap::MajorCollection);

  HeapWalker* heapWalker = makeHeapImage
    (t, image, heap, heapMap, HeapCapacity, constants);

  updateConstants(t, constants, code, codeMap, heapWalker->map());

  image->classCount = hashMapSize(t, t->m->classMap);
  unsigned* classTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->classCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
      classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
    }
  }

  image->stringCount = hashMapSize(t, t->m->stringMap);
  unsigned* stringTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->stringCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
      stringTable[i++] = heapWalker->map()->find
        (jreferenceTarget(t, tripleFirst(t, it.next())));
    }
  }

  unsigned* callTable = t->m->processor->makeCallTable(t, heapWalker);

  heapWalker->dispose();

  image->magic = BootImage::Magic;
  image->codeBase = reinterpret_cast<uintptr_t>(code);

  fprintf(stderr, "class count %d string count %d call count %d\n"
          "heap size %d code size %d\n",
          image->classCount, image->stringCount, image->callCount,
          image->heapSize, image->codeSize);

  if (true) {
    fwrite(image, sizeof(BootImage), 1, out);

    fwrite(classTable, image->classCount * sizeof(unsigned), 1, out);
    fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, out);
    fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, out);

    unsigned offset = (image->classCount * sizeof(unsigned))
      + (image->stringCount * sizeof(unsigned))
      + (image->callCount * sizeof(unsigned) * 2);

    while (offset % BytesPerWord) {
      uint8_t c = 0;
      fwrite(&c, 1, 1, out);
      ++ offset;
    }

    fwrite(heapMap, pad(heapMapSize(image->heapSize)), 1, out);
    fwrite(heap, pad(image->heapSize), 1, out);

    fwrite(codeMap, pad(codeMapSize(image->codeSize)), 1, out);
    fwrite(code, pad(image->codeSize), 1, out);
  }
}

} // namespace

int
main(int ac, const char** av)
{
  if (ac < 3 or ac > 6) {
    fprintf(stderr, "usage: %s <classpath> <output file> "
            "[<class name> [<method name> [<method spec>]]]\n", av[0]);
    return -1;
  }

  System* s = makeSystem(0);
  Heap* h = makeHeap(s, 128 * 1024 * 1024);
  Finder* f = makeFinder(s, av[1], 0);
  Processor* p = makeProcessor(s, h, false);

  BootImage image;
  const unsigned CodeCapacity = 32 * 1024 * 1024;
  uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity));
  p->initialize(&image, code, CodeCapacity);

  Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
  Thread* t = p->makeThread(m, 0, 0);

  enter(t, Thread::ActiveState);
  enter(t, Thread::IdleState);

  FILE* output = vm::fopen(av[2], "wb");
  if (output == 0) {
    fprintf(stderr, "unable to open %s\n", av[2]);
    return -1;
  }

  writeBootImage
    (t, output, &image, code, CodeCapacity,
     (ac > 3 ? av[3] : 0), (ac > 4 ? av[4] : 0), (ac > 5 ? av[5] : 0));

  fclose(output);

  if (t->exception) {
    printTrace(t, t->exception);
  }

  return 0;
}
<commit_msg>update bootimage.cpp to reflect BootImage restructuring<commit_after>/* Copyright (c) 2008-2009, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "bootimage.h"
#include "heapwalk.h"
#include "common.h"
#include "machine.h"
#include "util.h"
#include "assembler.h"

// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }

using namespace vm;

namespace {

bool
endsWith(const char* suffix, const char* s, unsigned length)
{
  unsigned suffixLength = strlen(suffix);
  return length >= suffixLength
    and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}

object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
              uintptr_t* codeMap, const char* className,
              const char* methodName, const char* methodSpec)
{
  object constants = 0;
  PROTECT(t, constants);

  object calls = 0;
  PROTECT(t, calls);

  DelayedPromise* addresses = 0;

  for (Finder::Iterator it(t->m->finder); it.hasMore();) {
    unsigned nameSize = 0;
    const char* name = it.next(&nameSize);

    if (endsWith(".class", name, nameSize)
        and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
    {
//       fprintf(stderr, "%.*s\n", nameSize - 6, name);
      object c = resolveSystemClass
        (t, makeByteArray(t, "%.*s", nameSize - 6, name));

      if (t->exception) return 0;

      PROTECT(t, c);

      if (classMethodTable(t, c)) {
        for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
          object method = arrayBody(t, classMethodTable(t, c), i);
          if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
              and ((methodName == 0
                    or ::strcmp
                    (reinterpret_cast<char*>
                     (&byteArrayBody
                      (t, vm::methodName(t, method), 0)), methodName) == 0)
                   and (methodSpec == 0
                        or ::strcmp
                        (reinterpret_cast<char*>
                         (&byteArrayBody
                          (t, vm::methodSpec(t, method), 0)), methodSpec)
                        == 0)))
          {
            t->m->processor->compileMethod
              (t, zone, &constants, &calls, &addresses, method);
          }
        }
      }
    }
  }

  for (; calls; calls = tripleThird(t, calls)) {
    object method = tripleFirst(t, calls);
    uintptr_t address;
    if (methodFlags(t, method) & ACC_NATIVE) {
      address = reinterpret_cast<uintptr_t>(code + image->thunks.native.start);
    } else {
      address = methodCompiled(t, method);
    }

    static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
      ->listener->resolve(address, 0);
  }

  for (; addresses; addresses = addresses->next) {
    uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
    assert(t, value >= code);

    void* location;
    bool flat = addresses->listener->resolve(0, &location);
    uintptr_t offset = value - code;
    if (flat) {
      offset |= BootFlatConstant;
    }
    memcpy(location, &offset, BytesPerWord);

    assert(t, reinterpret_cast<intptr_t>(location)
           >= reinterpret_cast<intptr_t>(code));

    markBit(codeMap, reinterpret_cast<intptr_t>(location)
            - reinterpret_cast<intptr_t>(code));
  }

  return constants;
}

unsigned
objectSize(Thread* t, object o)
{
  assert(t, not objectExtended(t, o));

  return baseSize(t, o, objectClass(t, o));
}

void
visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{
  Machine* m = t->m;

  for (HashMapIterator it(t, m->classMap); it.hasMore();) {
    w->visitRoot(tripleSecond(t, it.next()));
  }

  image->loader = w->visitRoot(m->loader);
  image->types = w->visitRoot(m->types);

  m->processor->visitRoots(w);

  for (; constants; constants = tripleThird(t, constants)) {
    w->visitRoot(tripleFirst(t, constants));
  }
}

HeapWalker*
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
              unsigned capacity, object constants)
{
  class Visitor: public HeapVisitor {
   public:
    Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
      t(t), currentObject(0), currentNumber(0), currentOffset(0), heap(heap),
      map(map), position(0), capacity(capacity)
    { }

    void visit(unsigned number) {
      if (currentObject) {
        unsigned offset = currentNumber - 1 + currentOffset;
        unsigned mark = heap[offset] & (~PointerMask);
        unsigned value = number | (mark << BootShift);

        if (value) markBit(map, offset);

        heap[offset] = value;
      }
    }

    virtual void root() {
      currentObject = 0;
    }

    virtual unsigned visitNew(object p) {
      if (p) {
        unsigned size = objectSize(t, p);

        unsigned number;
        if (currentObject
            and (currentOffset * BytesPerWord) == ClassStaticTable)
        {
          FixedAllocator allocator
            (t->m->system, reinterpret_cast<uint8_t*>(heap + position),
             (capacity - position) * BytesPerWord);

          unsigned totalInBytes;
          uintptr_t* dst = static_cast<uintptr_t*>
            (t->m->heap->allocateImmortalFixed
             (&allocator, size, true, &totalInBytes));

          memcpy(dst, p, size * BytesPerWord);

          dst[0] |= FixedMark;

          number = (dst - heap) + 1;
          position += ceiling(totalInBytes, BytesPerWord);
        } else {
          assert(t, position + size < capacity);
          memcpy(heap + position, p, size * BytesPerWord);

          number = position + 1;
          position += size;
        }

        visit(number);

        return number;
      } else {
        return 0;
      }
    }

    virtual void visitOld(object, unsigned number) {
      visit(number);
    }

    virtual void push(object object, unsigned number, unsigned offset) {
      currentObject = object;
      currentNumber = number;
      currentOffset = offset;
    }

    virtual void pop() {
      currentObject = 0;
    }

    Thread* t;
    object currentObject;
    unsigned currentNumber;
    unsigned currentOffset;
    uintptr_t* heap;
    uintptr_t* map;
    unsigned position;
    unsigned capacity;
  } visitor(t, heap, map, capacity / BytesPerWord);

  HeapWalker* w = makeHeapWalker(t, &visitor);
  visitRoots(t, image, w, constants);

  image->heapSize = visitor.position * BytesPerWord;

  return w;
}

void
updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
                HeapMap* heapTable)
{
  for (; constants; constants = tripleThird(t, constants)) {
    unsigned target = heapTable->find(tripleFirst(t, constants));
    assert(t, target > 0);

    for (Promise::Listener* pl = static_cast<ListenPromise*>
           (pointerValue(t, tripleSecond(t, constants)))->listener;
         pl; pl = pl->next)
    {
      void* location;
      bool flat = pl->resolve(0, &location);
      uintptr_t offset = target | BootHeapOffset;
      if (flat) {
        offset |= BootFlatConstant;
      }
      memcpy(location, &offset, BytesPerWord);

      assert(t, reinterpret_cast<intptr_t>(location)
             >= reinterpret_cast<intptr_t>(code));

      markBit(codeMap, reinterpret_cast<intptr_t>(location)
              - reinterpret_cast<intptr_t>(code));
    }
  }
}

unsigned
offset(object a, uintptr_t* b)
{
  return reinterpret_cast<uintptr_t>(b) - reinterpret_cast<uintptr_t>(a);
}

void
writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
               unsigned codeCapacity, const char* className,
               const char* methodName, const char* methodSpec)
{
  Zone zone(t->m->system, t->m->heap, 64 * 1024);

  uintptr_t* codeMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(codeMapSize(codeCapacity)));
  memset(codeMap, 0, codeMapSize(codeCapacity));

  object constants = makeCodeImage
    (t, &zone, image, code, codeMap, className, methodName, methodSpec);

  if (t->exception) return;

  PROTECT(t, constants);

  const unsigned HeapCapacity = 32 * 1024 * 1024;
  uintptr_t* heap = static_cast<uintptr_t*>
    (t->m->heap->allocate(HeapCapacity));
  uintptr_t* heapMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(heapMapSize(HeapCapacity)));
  memset(heapMap, 0, heapMapSize(HeapCapacity));

  // this map will not be used when the bootimage is loaded, so
  // there's no need to preserve it:
  t->m->byteArrayMap = makeWeakHashMap(t, 0, 0);

  collect(t, Heap::MajorCollection);

  HeapWalker* heapWalker = makeHeapImage
    (t, image, heap, heapMap, HeapCapacity, constants);

  updateConstants(t, constants, code, codeMap, heapWalker->map());

  image->classCount = hashMapSize(t, t->m->classMap);
  unsigned* classTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->classCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
      classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
    }
  }

  image->stringCount = hashMapSize(t, t->m->stringMap);
  unsigned* stringTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->stringCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
      stringTable[i++] = heapWalker->map()->find
        (jreferenceTarget(t, tripleFirst(t, it.next())));
    }
  }

  unsigned* callTable = t->m->processor->makeCallTable(t, heapWalker);

  heapWalker->dispose();

  image->magic = BootImage::Magic;
  image->codeBase = reinterpret_cast<uintptr_t>(code);

  fprintf(stderr, "class count %d string count %d call count %d\n"
          "heap size %d code size %d\n",
          image->classCount, image->stringCount, image->callCount,
          image->heapSize, image->codeSize);

  if (true) {
    fwrite(image, sizeof(BootImage), 1, out);

    fwrite(classTable, image->classCount * sizeof(unsigned), 1, out);
    fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, out);
    fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, out);

    unsigned offset = (image->classCount * sizeof(unsigned))
      + (image->stringCount * sizeof(unsigned))
      + (image->callCount * sizeof(unsigned) * 2);

    while (offset % BytesPerWord) {
      uint8_t c = 0;
      fwrite(&c, 1, 1, out);
      ++ offset;
    }

    fwrite(heapMap, pad(heapMapSize(image->heapSize)), 1, out);
    fwrite(heap, pad(image->heapSize), 1, out);

    fwrite(codeMap, pad(codeMapSize(image->codeSize)), 1, out);
    fwrite(code, pad(image->codeSize), 1, out);
  }
}

} // namespace

int
main(int ac, const char** av)
{
  if (ac < 3 or ac > 6) {
    fprintf(stderr, "usage: %s <classpath> <output file> "
            "[<class name> [<method name> [<method spec>]]]\n", av[0]);
    return -1;
  }

  System* s = makeSystem(0);
  Heap* h = makeHeap(s, 128 * 1024 * 1024);
  Finder* f = makeFinder(s, av[1], 0);
  Processor* p = makeProcessor(s, h, false);

  BootImage image;
  const unsigned CodeCapacity = 32 * 1024 * 1024;
  uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity));
  p->initialize(&image, code, CodeCapacity);

  Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
  Thread* t = p->makeThread(m, 0, 0);

  enter(t, Thread::ActiveState);
  enter(t, Thread::IdleState);

  FILE* output = vm::fopen(av[2], "wb");
  if (output == 0) {
    fprintf(stderr, "unable to open %s\n", av[2]);
    return -1;
  }

  writeBootImage
    (t, output, &image, code, CodeCapacity,
     (ac > 3 ? av[3] : 0), (ac > 4 ? av[4] : 0), (ac > 5 ? av[5] : 0));

  fclose(output);

  if (t->exception) {
    printTrace(t, t->exception);
  }

  return 0;
}
<|endoftext|>


<commit_before>
#include <commonOptions/commonOptions.h>
#include "commands/commands.h"

namespace {
	auto cmdBuild      = commonOptions::make_command("build",     "", "builds a specific project");
	auto cmdBuildMode  = commonOptions::make_command("buildMode", "", "Changes current buildmode to release or debug");
	auto cmdClang      = commonOptions::make_command("clang",         "Generates a .clang_complete file");
	auto cmdClean      = commonOptions::make_command("clean",         "Cleans current build and .busy directory");
	auto cmdCleanAll   = commonOptions::make_command("cleanall",      "deletes all build files");
	auto cmdDocu       = commonOptions::make_command("docu",          "Generates html docu");
	auto cmdEclipse    = commonOptions::make_command("eclipse",       "Generate Eclipse .project and .cproject file");
	auto cmdGit        = commonOptions::make_command("git", std::vector<std::string>{}, "executes given options on every repository (including root package)");
	auto cmdInstall    = commonOptions::make_command("install",       "Installs the script to the current target");
	auto cmdLsFiles    = commonOptions::make_command("ls-files",      "Print all files of these repositories");
	auto cmdPull       = commonOptions::make_command("pull",          "Execute pull on all git repositories");
	auto cmdPush       = commonOptions::make_command("push",          "Execute push on all git repositories");
	auto cmdQF         = commonOptions::make_command("qf",            "Quickfixes busy.yaml");
	auto cmdQuickFix   = commonOptions::make_command("quickfix",      "Quickfixes busy.yaml");
	auto cmdRelPath    = commonOptions::make_command("showRelPath",   "Show the relative path to the root busy.yaml file");
	auto cmdShowDep    = commonOptions::make_command("showDep","",    "Show projects that depends directory on the given project");
	auto cmdStatus     = commonOptions::make_command("status",        "Shows current status of git repositories");
	auto cmdTest       = commonOptions::make_command("test",          "Run all unittests");
	auto cmdToolchain  = commonOptions::make_command("toolchain", "", "Changes current toolchain");
	auto cmdToolchains = commonOptions::make_command("toolchains",    "Shows available toolchain");

	auto swtHelp       = commonOptions::make_switch("help",        "Shows some inforamation about this program");
	auto swtNoConsole  = commonOptions::make_switch("noterminal",  "Doesn't use pretty output to display current progress");
	auto swtVerbose    = commonOptions::make_switch("verbose",     "Shows more information while running");

	auto optFlavor     = commonOptions::make_option("flavor", "",   "builds and sets given flavor for future builds (toolchain + buildMode)");
	auto optJobCt      = commonOptions::make_option("j",       10, "changes the amount of jobs");
}
using namespace busy;

using Action = std::function<void()>;

/**
 * check current working dir, and changes, if this is very likely to be
 * the wrong one. idea is to always endup in the cwd where busy.yaml is
 * located
 */
std::string checkCwd() {
	std::string relPath = ".";
	auto cwd = utils::cwd();
	while (cwd != "/" and not utils::fileExists("busy.yaml")) {
		utils::cwd("..");
		relPath = relPath + "/..";
		cwd = utils::cwd();
		if (cwd == "/") {
			throw std::runtime_error("this is not a busy repository/workspace");
		}
	}
	auto dirs = utils::explode(cwd, "/");
	if (dirs.size() > 1) {
		if (dirs[dirs.size()-2] == "extRepositories"
		    and utils::fileExists("../../busy.yaml")) {
			utils::cwd("../..");
			relPath = relPath + "/../..";
		}
	}
	return relPath;
}

int main(int argc, char** argv) {
	try {

		if (not commonOptions::parse(argc, argv)) {
			commonOptions::print();
			return 0;
		} else if (*swtHelp) {
			commonOptions::print();
			return 0;
		}
		std::string relPath = ".";
		if (not *cmdLsFiles) {
			relPath = checkCwd();
		}

		if (*optFlavor != "") {
			Workspace ws(".");
			ws.accessConfigFile().setLastFlavor(*optFlavor);
			ws.save();
		}

		if (*cmdDocu) {
			commands::docu();
		} else if (*cmdTest) {
			commands::test();
		} else if (*cmdClean) {
			commands::clean();
		} else if (*cmdCleanAll) {
			commands::cleanAll();
		} else if (cmdGit->size() > 0) {
			commands::git(*cmdGit);
		} else if (*cmdEclipse) {
			commands::eclipse();
		} else if (*cmdPull) {
			commands::pull();
		} else if (*cmdPush) {
			commands::push();
		} else if (*cmdRelPath) {
			std::cout<<relPath<<std::endl;
		} else if (*cmdInstall) {
			commands::install();
		} else if (*cmdQuickFix or *cmdQF) {
			commands::quickFix();
		} else if (*cmdStatus) {
			commands::status();
		} else if (*cmdBuildMode != "") {
			commands::status(*cmdBuildMode);
		} else if (*cmdLsFiles) {
			int exitCode = commands::listFiles(relPath + "/");
			exit(exitCode);
			return exitCode;
		} else if (*cmdToolchains) {
			commands::toolchains();
		} else if (*cmdToolchain != "") {
			commands::toolchain(*cmdToolchain);
		} else if (*cmdClang) {
			commands::clang();
		} else if (*cmdShowDep != "") {
			commands::showDep(*cmdShowDep);
		} else {
			auto success = commands::build(*cmdBuild, *swtVerbose, *swtNoConsole, *optJobCt);
			if (not success) return EXIT_FAILURE;
		}
	} catch(std::runtime_error e) {
		std::cerr<<"exception(runtime_error): " << e.what() << std::endl;
		return EXIT_FAILURE;
	} catch(std::exception const& e) {
		std::cerr << "exception(exception): " << e.what() << std::endl;
		return EXIT_FAILURE;
	} catch(std::string const& s) {
		std::cerr << "exception(string): " << s << std::endl;
		return EXIT_FAILURE;
	} catch(char const* s) {
		std::cerr << "exception(char): " << s << std::endl;
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}
<commit_msg>exception should be catched by reference<commit_after>
#include <commonOptions/commonOptions.h>
#include "commands/commands.h"

namespace {
	auto cmdBuild      = commonOptions::make_command("build",     "", "builds a specific project");
	auto cmdBuildMode  = commonOptions::make_command("buildMode", "", "Changes current buildmode to release or debug");
	auto cmdClang      = commonOptions::make_command("clang",         "Generates a .clang_complete file");
	auto cmdClean      = commonOptions::make_command("clean",         "Cleans current build and .busy directory");
	auto cmdCleanAll   = commonOptions::make_command("cleanall",      "deletes all build files");
	auto cmdDocu       = commonOptions::make_command("docu",          "Generates html docu");
	auto cmdEclipse    = commonOptions::make_command("eclipse",       "Generate Eclipse .project and .cproject file");
	auto cmdGit        = commonOptions::make_command("git", std::vector<std::string>{}, "executes given options on every repository (including root package)");
	auto cmdInstall    = commonOptions::make_command("install",       "Installs the script to the current target");
	auto cmdLsFiles    = commonOptions::make_command("ls-files",      "Print all files of these repositories");
	auto cmdPull       = commonOptions::make_command("pull",          "Execute pull on all git repositories");
	auto cmdPush       = commonOptions::make_command("push",          "Execute push on all git repositories");
	auto cmdQF         = commonOptions::make_command("qf",            "Quickfixes busy.yaml");
	auto cmdQuickFix   = commonOptions::make_command("quickfix",      "Quickfixes busy.yaml");
	auto cmdRelPath    = commonOptions::make_command("showRelPath",   "Show the relative path to the root busy.yaml file");
	auto cmdShowDep    = commonOptions::make_command("showDep","",    "Show projects that depends directory on the given project");
	auto cmdStatus     = commonOptions::make_command("status",        "Shows current status of git repositories");
	auto cmdTest       = commonOptions::make_command("test",          "Run all unittests");
	auto cmdToolchain  = commonOptions::make_command("toolchain", "", "Changes current toolchain");
	auto cmdToolchains = commonOptions::make_command("toolchains",    "Shows available toolchain");

	auto swtHelp       = commonOptions::make_switch("help",        "Shows some inforamation about this program");
	auto swtNoConsole  = commonOptions::make_switch("noterminal",  "Doesn't use pretty output to display current progress");
	auto swtVerbose    = commonOptions::make_switch("verbose",     "Shows more information while running");

	auto optFlavor     = commonOptions::make_option("flavor", "",   "builds and sets given flavor for future builds (toolchain + buildMode)");
	auto optJobCt      = commonOptions::make_option("j",       10, "changes the amount of jobs");
}
using namespace busy;

using Action = std::function<void()>;

/**
 * check current working dir, and changes, if this is very likely to be
 * the wrong one. idea is to always endup in the cwd where busy.yaml is
 * located
 */
std::string checkCwd() {
	std::string relPath = ".";
	auto cwd = utils::cwd();
	while (cwd != "/" and not utils::fileExists("busy.yaml")) {
		utils::cwd("..");
		relPath = relPath + "/..";
		cwd = utils::cwd();
		if (cwd == "/") {
			throw std::runtime_error("this is not a busy repository/workspace");
		}
	}
	auto dirs = utils::explode(cwd, "/");
	if (dirs.size() > 1) {
		if (dirs[dirs.size()-2] == "extRepositories"
		    and utils::fileExists("../../busy.yaml")) {
			utils::cwd("../..");
			relPath = relPath + "/../..";
		}
	}
	return relPath;
}

int main(int argc, char** argv) {
	try {

		if (not commonOptions::parse(argc, argv)) {
			commonOptions::print();
			return 0;
		} else if (*swtHelp) {
			commonOptions::print();
			return 0;
		}
		std::string relPath = ".";
		if (not *cmdLsFiles) {
			relPath = checkCwd();
		}

		if (*optFlavor != "") {
			Workspace ws(".");
			ws.accessConfigFile().setLastFlavor(*optFlavor);
			ws.save();
		}

		if (*cmdDocu) {
			commands::docu();
		} else if (*cmdTest) {
			commands::test();
		} else if (*cmdClean) {
			commands::clean();
		} else if (*cmdCleanAll) {
			commands::cleanAll();
		} else if (cmdGit->size() > 0) {
			commands::git(*cmdGit);
		} else if (*cmdEclipse) {
			commands::eclipse();
		} else if (*cmdPull) {
			commands::pull();
		} else if (*cmdPush) {
			commands::push();
		} else if (*cmdRelPath) {
			std::cout<<relPath<<std::endl;
		} else if (*cmdInstall) {
			commands::install();
		} else if (*cmdQuickFix or *cmdQF) {
			commands::quickFix();
		} else if (*cmdStatus) {
			commands::status();
		} else if (*cmdBuildMode != "") {
			commands::status(*cmdBuildMode);
		} else if (*cmdLsFiles) {
			int exitCode = commands::listFiles(relPath + "/");
			exit(exitCode);
			return exitCode;
		} else if (*cmdToolchains) {
			commands::toolchains();
		} else if (*cmdToolchain != "") {
			commands::toolchain(*cmdToolchain);
		} else if (*cmdClang) {
			commands::clang();
		} else if (*cmdShowDep != "") {
			commands::showDep(*cmdShowDep);
		} else {
			auto success = commands::build(*cmdBuild, *swtVerbose, *swtNoConsole, *optJobCt);
			if (not success) return EXIT_FAILURE;
		}
	} catch(std::runtime_error const& e) {
		std::cerr<<"exception(runtime_error): " << e.what() << std::endl;
		return EXIT_FAILURE;
	} catch(std::exception const& e) {
		std::cerr << "exception(exception): " << e.what() << std::endl;
		return EXIT_FAILURE;
	} catch(std::string const& s) {
		std::cerr << "exception(string): " << s << std::endl;
		return EXIT_FAILURE;
	} catch(char const* s) {
		std::cerr << "exception(char): " << s << std::endl;
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*

  FMD DA for online calibration of conditions

  Contact:                 canute@nbi.dk
  Link:                    fmd.nbi.dk/fmd/offline
  Run Type:                PHYSICS
  DA Type:                 LDC
  Number of events needed: depending on the run, being run-level
  Input Files:             raw data
  Output Files:            conditions.csv
  Trigger types used:      PHYSICS_EVENT
*/
#include <TSystem.h>
#include <TString.h>
#include <AliFMDParameters.h>
#include <AliRawReader.h>
#include <TStopwatch.h>
#include <AliFMDBaseDA.h>
#include <AliRawReaderDate.h>
#include <AliRawReaderRoot.h>
#include "daqDA.h"
#include "TROOT.h"
#include "TPluginManager.h"

int main(int argc, char **argv)
{

#if 0
  /* magic line from Rene - for future reference! */
  gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
					"*",
					"TStreamerInfo",
					"RIO",
					"TStreamerInfo()");
#endif

  Char_t* fileName = argv[1];

  Bool_t old = kTRUE;

  AliFMDParameters::Instance()->Init(kFALSE,0);
  AliFMDParameters::Instance()->UseCompleteHeader(!old);

  AliRawReader *reader = 0;
  TString fileNam(fileName);
  if (fileNam.EndsWith(".root")) reader = new AliRawReaderRoot(fileName);
  else reader = new AliRawReaderDate(fileName);
  if (!reader) {
    std::cerr << "Don't know how to make reader for " << fileNam
	      << std::endl;
    return -2;
  }

  TStopwatch timer;
  timer.Start();
  AliFMDBaseDA baseDA;

  baseDA.Run(reader);

  timer.Stop();
  timer.Print();

  Int_t  retval = daqDA_FES_storeFile("conditions.csv", AliFMDParameters::Instance()->GetConditionsShuttleID());
  if (retval != 0) std::cerr << "Base DA failed" << std::endl;

  return retval;
}
<commit_msg>Base DA changed to be a monitoring DA and to pick up only the SOD event<commit_after>/*

  FMD DA for online calibration of conditions

  Contact:                 canute@nbi.dk
  Link:                    fmd.nbi.dk/fmd/offline
  Run Type:                PHYSICS
  DA Type:                 MON
  Number of events needed: depending on the run, being run-level
  Input Files:             raw data
  Output Files:            conditions.csv
  Trigger types used:      PHYSICS_EVENT
*/
#include "monitor.h"
#include <TSystem.h>
#include <TString.h>
#include <AliFMDParameters.h>
#include <AliRawReader.h>
#include <TStopwatch.h>
#include <AliFMDBaseDA.h>
#include <AliRawReaderDate.h>
#include <AliRawReaderRoot.h>
#include "daqDA.h"
#include "TROOT.h"
#include "TPluginManager.h"

int main(int argc, char **argv)
{

#if 0
  /* magic line from Rene - for future reference! */
  gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
					"*",
					"TStreamerInfo",
					"RIO",
					"TStreamerInfo()");
#endif

  Char_t* tableSOD[]  = {"SOD","all",NULL};
  Char_t* tablePHYS[] = {"PHY","no",NULL};

  monitorDeclareTable(tableSOD);
  monitorDeclareTable(tablePHYS);

  Char_t* fileName = argv[1];

  Bool_t old = kTRUE;

  AliFMDParameters::Instance()->Init(kFALSE,0);
  AliFMDParameters::Instance()->UseCompleteHeader(!old);

  AliRawReader *reader = 0;
  TString fileNam(fileName);
  if (fileNam.EndsWith(".root")) reader = new AliRawReaderRoot(fileName);
  else reader = new AliRawReaderDate(fileName);
  if (!reader) {
    std::cerr << "Don't know how to make reader for " << fileNam
	      << std::endl;
    return -2;
  }

  TStopwatch timer;
  timer.Start();
  AliFMDBaseDA baseDA;

  baseDA.Run(reader);

  timer.Stop();
  timer.Print();

  Int_t  retval = daqDA_FES_storeFile("conditions.csv", AliFMDParameters::Instance()->GetConditionsShuttleID());
  if (retval != 0) std::cerr << "Base DA failed" << std::endl;

  return retval;
}
<|endoftext|>


<commit_before>#include "StateMachine.h"
#include <algorithm>

bool DriveInstruction::aimTarget(const ObjectPosition &target, Speed &speed, double errorMargin){
	double heading = target.getHeading();
	if (fabs(heading) > errorMargin){
		speed.rotation = -sign0(heading) * std::min(40.0, std::max(fabs(heading), 5.0));
		return false;
	}
	else return fabs(heading) < errorMargin;
}
bool DriveInstruction::catchTarget(const ObjectPosition &target, Speed &speed){
	if (m_pCom->BallInTribbler()) return true;
	double heading = target.getHeading();
	double dist = target.getDistance();
	speed.velocity = 60;
	speed.heading = 0;
	return false;
}

bool DriveInstruction::driveToTarget(const ObjectPosition &target, Speed &speed, double maxDistance){
	double dist = target.getDistance();
	if (dist > maxDistance){
		speed.velocity = std::max(20.0, dist);
		return false;
	}
	else{
		speed.velocity = 20;
		return true;
	}
}

bool DriveInstruction::driveToTargetWithAngle(const ObjectPosition &target, Speed &speed, double maxDistance, double errorMargin){
	double heading = target.getHeading();
	double dist = target.getDistance();
	double velocity = 0;
	double direction = 0;
	double angularSpeed = 0;
	bool onPoint = false;
	if (fabs(heading) > errorMargin){
		if (dist > maxDistance){
			velocity = std::max(30.0, dist); //max speed is limited to 190 in wheelController.cpp
			direction = heading; //drive towards target
			angularSpeed = sign0(heading) * 20; //meanwhile rotate slowly to face the target
		}
		else{ //at location but facing wrong way
			angularSpeed = sign0(heading) * std::max(fabs(heading) * 0.5, 10.0); //rotate
		}
	}
	else{
		if (dist > maxDistance){
			velocity = std::max(30.0, dist);
			direction = heading; //drive towards target
		}
		else onPoint = true;
	}
	speed.velocity = velocity;
	speed.heading = direction;
	speed.rotation = -angularSpeed;
	return onPoint;
}

const BallPosition &DriveInstruction::getClosestBall(bool includeHeading, bool reset){
	return  m_pFieldState->balls.getClosest();
}

StateMachine::StateMachine(ICommunicationModule *pComModule, FieldState *pState,
	const std::map<DriveMode, DriveInstruction*> &driveModes) :driveModes(driveModes), ThreadedClass("Autopilot/StateMachine")
{
	m_pComModule = pComModule;
	m_pFieldState = pState;
	for (auto driveMode : driveModes) driveMode.second->Init(pComModule, pState);
	curDriveMode = this->driveModes.find(DRIVEMODE_IDLE);
}

void StateMachine::setTestMode(DriveMode mode){ testDriveMode = mode; }

void StateMachine::enableTestMode(bool enable)
{
	setTestMode(DRIVEMODE_IDLE);
	testMode = enable;
	if (!testMode) m_pComModule->Drive(0, 0, 0);
}

void StateMachine::Run()
{
	boost::posix_time::ptime lastStep = boost::posix_time::microsec_clock::local_time();
	DriveMode newMode = curDriveMode->first;
	curDriveMode->second->onEnter();
	while (!stop_thread) {
		boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration::tick_type dt = (time - lastStep).total_milliseconds();
		newMode = testMode ? curDriveMode->second->step(double(dt)) : curDriveMode->second->step1(double(dt), newMode);
		auto old = curDriveMode;

		if (newMode != curDriveMode->first){
			boost::mutex::scoped_lock lock(mutex);
			std::cout << "state: " << curDriveMode->second->name;

			curDriveMode->second->onExit();
			if (testMode){
				if (testDriveMode != DRIVEMODE_IDLE && newMode == DRIVEMODE_IDLE) newMode = testDriveMode;
				else if (newMode != testDriveMode) {
					auto newDriveMode = driveModes.find(newMode);
					std::cout << "-> actual state: " << newDriveMode->second->name << std::endl;

					newMode = DRIVEMODE_IDLE;
					testDriveMode = DRIVEMODE_IDLE;
				}
			}
			curDriveMode = driveModes.find(newMode);
			if (curDriveMode == driveModes.end()){
				curDriveMode = driveModes.find(DRIVEMODE_IDLE);
				std::cout << "-> unknown state: " << newMode << std::endl;
			}
			std::cout << " -> " << curDriveMode->second->name << std::endl;

			curDriveMode->second->onEnter();
			std::this_thread::sleep_for(std::chrono::milliseconds(50)); // this seems to be neccecary
		}
	}
}

std::string StateMachine::GetDebugInfo(){
	std::ostringstream oss;
	boost::mutex::scoped_lock lock(mutex);
	oss << "[StateMachine] State: " << curDriveMode->second->name;
	return oss.str();
}

StateMachine::~StateMachine()
{
	WaitForStop();
	for (auto &mode : driveModes){ delete mode.second; }
}

DriveMode DriveInstruction::prevDriveMode = DRIVEMODE_IDLE;
DriveMode DriveInstruction::ACTIVE_DRIVE_TO_BALL_MODE = DRIVEMODE_IDLE;<commit_msg>restore working version<commit_after>#include "StateMachine.h"
#include <algorithm>

bool DriveInstruction::aimTarget(const ObjectPosition &target, Speed &speed, double errorMargin){
	double heading = target.getHeading();
	if (fabs(heading) > errorMargin){
		speed.rotation = -sign0(heading) * std::min(40.0, std::max(fabs(heading), 5.0));
		return false;
	}
	else return fabs(heading) < errorMargin;
}
bool DriveInstruction::catchTarget(const ObjectPosition &target, Speed &speed){
	if (m_pCom->BallInTribbler()) return true;
	double heading = target.getHeading();
	double dist = target.getDistance();
	speed.velocity = 60;
	speed.heading = 0;
	return false;
}

bool DriveInstruction::driveToTarget(const ObjectPosition &target, Speed &speed, double maxDistance){
	double dist = target.getDistance();
	if (dist > maxDistance){
		speed.velocity = std::max(20.0, dist);
		return false;
	}
	else{
		speed.velocity = 20;
		return true;
	}
}

bool DriveInstruction::driveToTargetWithAngle(const ObjectPosition &target, Speed &speed, double maxDistance, double errorMargin){
	double heading = target.getHeading();
	double dist = target.getDistance();
	double velocity = 0;
	double direction = 0;
	double angularSpeed = 0;
	bool onPoint = false;
	if (fabs(heading) > errorMargin){
		if (dist > maxDistance){
			velocity = std::max(30.0, dist); //max speed is limited to 190 in wheelController.cpp
			direction = heading; //drive towards target
			angularSpeed = sign0(heading) * 20; //meanwhile rotate slowly to face the target
		}
		else{ //at location but facing wrong way
			angularSpeed = sign0(heading) * std::max(fabs(heading) * 0.5, 10.0); //rotate
		}
	}
	else{
		if (dist > maxDistance){
			velocity = std::max(30.0, dist);
			direction = heading; //drive towards target
		}
		else onPoint = true;
	}
	speed.velocity = velocity;
	speed.heading = direction;
	speed.rotation = -angularSpeed;
	return onPoint;
}

const BallPosition &DriveInstruction::getClosestBall(bool includeHeading, bool reset){
	return  m_pFieldState->balls.getClosest();
}

StateMachine::StateMachine(ICommunicationModule *pComModule, FieldState *pState,
	const std::map<DriveMode, DriveInstruction*> &driveModes) :driveModes(driveModes), ThreadedClass("Autopilot/StateMachine")
{
	m_pComModule = pComModule;
	m_pFieldState = pState;
	for (auto driveMode : driveModes) driveMode.second->Init(pComModule, pState);
	curDriveMode = this->driveModes.find(DRIVEMODE_IDLE);
}

void StateMachine::setTestMode(DriveMode mode){ testDriveMode = mode; }

void StateMachine::enableTestMode(bool enable)
{
	setTestMode(DRIVEMODE_IDLE);
	testMode = enable;
	if (!testMode) m_pComModule->Drive(0, 0, 0);
}

void StateMachine::Run()
{
	boost::posix_time::ptime lastStep = boost::posix_time::microsec_clock::local_time();
	DriveMode newMode = curDriveMode->first;
	curDriveMode->second->onEnter();
	while (!stop_thread) {
		boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration::tick_type dt = (time - lastStep).total_milliseconds();
		newMode = testMode ? curDriveMode->second->step(double(dt)) : curDriveMode->second->step1(double(dt), newMode);
		auto old = curDriveMode;
		if (testMode){
			if (testDriveMode != DRIVEMODE_IDLE && newMode == DRIVEMODE_IDLE) newMode = testDriveMode;
			else if (newMode != testDriveMode) {
				newMode = DRIVEMODE_IDLE;
				testDriveMode = DRIVEMODE_IDLE;
			}
		}

		if (newMode != curDriveMode->first){
			boost::mutex::scoped_lock lock(mutex);
			std::cout << "state: " << curDriveMode->second->name;

			curDriveMode->second->onExit();
			curDriveMode = driveModes.find(newMode);
			if (curDriveMode == driveModes.end()){
				curDriveMode = driveModes.find(DRIVEMODE_IDLE);
				std::cout << "-> unknown state: " << newMode << std::endl;
			}
			std::cout << " -> " << curDriveMode->second->name << std::endl;

			curDriveMode->second->onEnter();
			std::this_thread::sleep_for(std::chrono::milliseconds(50)); // this seems to be neccecary
		}
	}
}

std::string StateMachine::GetDebugInfo(){
	std::ostringstream oss;
	boost::mutex::scoped_lock lock(mutex);
	oss << "[StateMachine] State: " << curDriveMode->second->name;
	return oss.str();
}

StateMachine::~StateMachine()
{
	WaitForStop();
	for (auto &mode : driveModes){ delete mode.second; }
}

DriveMode DriveInstruction::prevDriveMode = DRIVEMODE_IDLE;
DriveMode DriveInstruction::ACTIVE_DRIVE_TO_BALL_MODE = DRIVEMODE_IDLE;<|endoftext|>