text:
/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

#ifndef COMPHELPER_LOGGING_HXX
#define COMPHELPER_LOGGING_HXX

#include <comphelper/comphelperdllapi.h>

/** === begin UNO includes === **/
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/logging/XLogHandler.hpp>
#include <com/sun/star/logging/LogLevel.hpp>
/** === end UNO includes === **/

#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>

//........................................................................
namespace comphelper
{
//........................................................................

	//====================================================================
	//= string conversions, employed by the templatized log* members of
    //= EventLogger
	//====================================================================

    namespace log { namespace convert
    {
        inline const ::rtl::OUString& convertLogArgToString( const ::rtl::OUString& _rValue )
        {
            return _rValue;
        }

        inline ::rtl::OUString convertLogArgToString( const sal_Char* _pAsciiValue )
        {
            return ::rtl::OUString::createFromAscii( _pAsciiValue );
        }

        inline ::rtl::OUString convertLogArgToString( double      _nValue ) { return ::rtl::OUString::valueOf( _nValue ); }
        inline ::rtl::OUString convertLogArgToString( float       _nValue ) { return ::rtl::OUString::valueOf( _nValue ); }
        inline ::rtl::OUString convertLogArgToString( sal_Int64   _nValue ) { return ::rtl::OUString::valueOf( _nValue ); }
        inline ::rtl::OUString convertLogArgToString( sal_Int32   _nValue ) { return ::rtl::OUString::valueOf( _nValue ); }
        inline ::rtl::OUString convertLogArgToString( sal_Int16   _nValue ) { return ::rtl::OUString::valueOf( (sal_Int32)_nValue ); }
        inline ::rtl::OUString convertLogArgToString( sal_Unicode _nValue ) { return ::rtl::OUString::valueOf( _nValue ); }
        inline ::rtl::OUString convertLogArgToString( sal_Bool    _nValue ) { return ::rtl::OUString::valueOf( _nValue ); }

    } } // namespace log::convert

	//====================================================================
	//= EventLogger
	//====================================================================
    class EventLogger_Impl;
    typedef ::boost::optional< ::rtl::OUString >    OptionalString;

    /** encapsulates an <type scope="com::sun::star::logging">XLogger</type>

        The class silences several (unlikely) errors which could potentially happen
        when working with a logger. Additionally, it provides some convenience methods
        for logging events.

        You can use this class as follows

    EventLogger aLogger( xContext, sLoggerName );
    ....
    aLogger.log( LogLevel::SEVERE, sSomeMessage );
    aLogger.logp( LogLevel::CONFIG, "MyClass", "MyMethod", sSomeMessage, SomeParameter1, SomeParameter2, SomeParameter3 );

        The log and logp calls support up to 6 parameters, which can be of
        arbitrary type. For every parameter, there must exist a function convertLogArgToString
        which takes an argument of the respective type, and returns a string.

        After a parameter has been converted to a string using the above mentioned
        convertLogArgToString function, a placeholder $1$ (resp. $2$ resp. $4$ ...)
        in the message will be replaced with this string, and the resulting message will be logged.
    */
	class COMPHELPER_DLLPUBLIC EventLogger
	{
    protected:
        ::boost::shared_ptr< EventLogger_Impl > m_pImpl;

    public:
        /** creates an EventLogger instance working with a css.logging.XLogger
            instance given by name.

            @param _rxContext
                the component context to create services
            @param _rLoggerName
                the name of the logger to create. If empty, the office-wide default logger will be used.
        */
        EventLogger(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
            const ::rtl::OUString& _rLoggerName = ::rtl::OUString()
        );

        /** creates an EventLogger instance working with a css.logging.XLogger
            instance given by ASCII name.

            @param _rxContext
                the component context to create services

            @param _rLoggerName
                the ASCII name of the logger to create.
        */
        EventLogger(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
            const sal_Char* _pAsciiLoggerName
        );

        ~EventLogger();

    public:
        /** returns the name of the logger
        */
        const ::rtl::OUString&  getName() const;

        /// returns the current log level threshold of the logger
        sal_Int32   getLogLevel() const;

        /// sets a new log level threshold of the logger
        void        setLogLevel( const sal_Int32 _nLogLevel ) const;

        /// determines whether an event with the given level would be logged
        bool        isLoggable( const sal_Int32 _nLogLevel ) const;

        /** adds the given log handler to the logger's set of handlers.

            Note that normally, you would not use this method: The logger implementations
            initialize themselves from the configuration, where usually, a default log handler
            is specified. In this case, the logger will create and use this handler.

            @return
                <TRUE/> if and only if the addition was successful (as far as this can be detected
                from outside the XLogger's implementation.
        */
        bool        addLogHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::logging::XLogHandler >& _rxLogHandler );

        /** removes the given log handler from the logger's set of handlers.

            @return
                <TRUE/> if and only if the addition was successful (as far as this can be detected
                from outside the XLogger's implementation.
        */
        bool        removeLogHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::logging::XLogHandler >& _rxLogHandler );

	    //----------------------------------------------------------------
        //- XLogger::log equivalents/wrappers
        //- string messages

        /// logs a given message, without any arguments, or source class/method names
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage );
            return false;
        }

        /** logs a given message, replacing a placeholder in the message with an argument

            The function takes, additionally to the log level and the message, an arbitrary
            argument. This argument is converted to a string using an overloaded function
            named convertLogArgToString. Then, a placeholder "$1$"
            is searched in the message string, and replaced with the argument string.
        */
        template< typename ARGTYPE1 >
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ) );
            return false;
        }

        /// logs a given message, replacing 2 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2 >
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ) );
            return false;
        }

        /// logs a given message, replacing 3 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3 >
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ) );
            return false;
        }

        /// logs a given message, replacing 4 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4 >
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ) );
            return false;
        }

        /// logs a given message, replacing 5 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5 >
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ) );
            return false;
        }

        /// logs a given message, replacing 6 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5, typename ARGTYPE6 >
        bool        log( const sal_Int32 _nLogLevel, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5, ARGTYPE6 _argument6 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument6 ) ) );
            return false;
        }

	    //----------------------------------------------------------------
        //- XLogger::log equivalents/wrappers
        //- ASCII messages

        /// logs a given message, without any arguments, or source class/method names
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ) );
            return false;
        }

        /** logs a given message, replacing a placeholder in the message with an argument

            The function takes, additionally to the log level and the message, an arbitrary
            argument. This argument is converted to a string using an overloaded function
            named convertLogArgToString. Then, a placeholder "$1$"
            is searched in the message string, and replaced with the argument string.
        */
        template< typename ARGTYPE1 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage, ARGTYPE1 _argument1 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ) );
            return false;
        }

        /// logs a given message, replacing 2 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ) );
            return false;
        }

        /// logs a given message, replacing 3 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ) );
            return false;
        }

        /// logs a given message, replacing 4 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ) );
            return false;
        }

        /// logs a given message, replacing 5 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ) );
            return false;
        }

        /// logs a given message, replacing 6 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5, typename ARGTYPE6 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Char* _pMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5, ARGTYPE6 _argument6 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, ::rtl::OUString::createFromAscii( _pMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument6 ) ) );
            return false;
        }

	    //----------------------------------------------------------------
        //- XLogger::logp equivalents/wrappers
        //- string messages

        /// logs a given message, without any arguments, or source class/method names
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage );
            return false;
        }

        /** logs a given message, replacing a placeholder in the message with an argument

            The function takes, additionally to the logp level and the message, an arbitrary
            argument. This argument is converted to a string using an overloaded function
            named convertLogArgToString. Then, a placeholder "$1$"
            is searched in the message string, and replaced with the argument string.
        */
        template< typename ARGTYPE1 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ) );
            return false;
        }

        /// logs a given message, replacing 2 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ) );
            return false;
        }

        /// logs a given message, replacing 3 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ) );
            return false;
        }

        /// logs a given message, replacing 4 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ) );
            return false;
        }

        /// logs a given message, replacing 5 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ) );
            return false;
        }

        /// logs a given message, replacing 6 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5, typename ARGTYPE6 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const ::rtl::OUString& _rMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5, ARGTYPE6 _argument6 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, _rMessage,
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument6 ) ) );
            return false;
        }

	    //----------------------------------------------------------------
        //- XLogger::logp equivalents/wrappers
        //- ASCII messages

        /// logs a given ASCII message, without any arguments, or source class/method names
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ) );
            return false;
        }

        /** logs a given ASCII message, replacing a placeholder in the message with an argument

            The function takes, additionally to the logp level and the message, an arbitrary
            argument. This argument is converted to a string using an overloaded function
            named convertLogArgToString. Then, a placeholder "$1$"
            is searched in the message string, and replaced with the argument string.
        */
        template< typename ARGTYPE1 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage, ARGTYPE1 _argument1 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 2 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 3 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 4 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 5 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 6 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5, typename ARGTYPE6 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Char* _pAsciiMessage, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5, ARGTYPE6 _argument6 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, ::rtl::OUString::createFromAscii( _pAsciiMessage ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument6 ) ) );
            return false;
        }

    protected:
        bool        impl_log(
                        const sal_Int32 _nLogLevel,
                        const sal_Char* _pSourceClass,
                        const sal_Char* _pSourceMethod,
                        const ::rtl::OUString& _rMessage,
                        const OptionalString& _rArgument1 = OptionalString(),
                        const OptionalString& _rArgument2 = OptionalString(),
                        const OptionalString& _rArgument3 = OptionalString(),
                        const OptionalString& _rArgument4 = OptionalString(),
                        const OptionalString& _rArgument5 = OptionalString(),
                        const OptionalString& _rArgument6 = OptionalString()
                    ) const;
	};

	//====================================================================
	//= ResourceBasedEventLogger
	//====================================================================
    struct ResourceBasedEventLogger_Data;
    /** extends the EventLogger class with functionality to load log messages from
        a resource bundle.
    */
    class COMPHELPER_DLLPUBLIC ResourceBasedEventLogger : public EventLogger
    {
    private:
        ::boost::shared_ptr< ResourceBasedEventLogger_Data >    m_pData;

    public:
        /** creates a resource based event logger
            @param _rxContext
                the component context for creating new components
            @param _rResourceBundleBaseName
                the base name of the resource bundle to use. Will be used
                in conjunction with XResourceBundleLoader::loadResource.
            @param _rLoggerName
                the name of the logger to work with. If empty, the office-wide
                default logger will be used.

        */
        ResourceBasedEventLogger(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
            const ::rtl::OUString& _rResourceBundleBaseName,
            const ::rtl::OUString& _rLoggerName = ::rtl::OUString()
        );

        /** creates a resource based event logger
            @param _rxContext
                the component context for creating new components
            @param _pResourceBundleBaseName
                the ASCII base name of the resource bundle to use. Will be used
                in conjunction with XResourceBundleLoader::loadResource.
            @param _pAsciiLoggerName
                the ASCII name of the logger to work with. If NULL, the office-wide
                default logger will be used.

        */
        ResourceBasedEventLogger(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
            const sal_Char* _pResourceBundleBaseName,
            const sal_Char* _pAsciiLoggerName = NULL
        );

	    //----------------------------------------------------------------
        //- XLogger::log equivalents/wrappers
        //- resource IDs

        /// logs a given message, without any arguments, or source class/method names
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ) );
            return false;
        }

        /** logs a given message, replacing a placeholder in the message with an argument

            The function takes, additionally to the log level and the message, an arbitrary
            argument. This argument is converted to a string using an overloaded function
            named convertLogArgToString. Then, a placeholder "$1$"
            is searched in the message string, and replaced with the argument string.
        */
        template< typename ARGTYPE1 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ) );
            return false;
        }

        /// logs a given message, replacing 2 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ) );
            return false;
        }

        /// logs a given message, replacing 3 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ) );
            return false;
        }

        /// logs a given message, replacing 4 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ) );
            return false;
        }

        /// logs a given message, replacing 5 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ) );
            return false;
        }

        /// logs a given message, replacing 6 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5, typename ARGTYPE6 >
        bool        log( const sal_Int32 _nLogLevel, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5, ARGTYPE6 _argument6 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, NULL, NULL, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument6 ) ) );
            return false;
        }

	    //----------------------------------------------------------------
        //- XLogger::logp equivalents/wrappers
        //- resource IDs

        /// logs a given ASCII message, without any arguments, or source class/method names
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ) );
            return false;
        }

        /** logs a given ASCII message, replacing a placeholder in the message with an argument
        */
        template< typename ARGTYPE1 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 2 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 3 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 4 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 5 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ) );
            return false;
        }

        /// logs a given ASCII message, replacing 6 placeholders in the message with respective values
        template< typename ARGTYPE1, typename ARGTYPE2, typename ARGTYPE3, typename ARGTYPE4, typename ARGTYPE5, typename ARGTYPE6 >
        bool        logp( const sal_Int32 _nLogLevel, const sal_Char* _pSourceClass, const sal_Char* _pSourceMethod, const sal_Int32 _nMessageResID, ARGTYPE1 _argument1, ARGTYPE2 _argument2, ARGTYPE3 _argument3, ARGTYPE4 _argument4, ARGTYPE5 _argument5, ARGTYPE6 _argument6 ) const
        {
            if ( isLoggable( _nLogLevel ) )
                return impl_log( _nLogLevel, _pSourceClass, _pSourceMethod, impl_loadStringMessage_nothrow( _nMessageResID ),
                    OptionalString( log::convert::convertLogArgToString( _argument1 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument2 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument3 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument4 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument5 ) ),
                    OptionalString( log::convert::convertLogArgToString( _argument6 ) ) );
            return false;
        }

    private:
        ::rtl::OUString impl_loadStringMessage_nothrow( const sal_Int32 _nMessageResID ) const;
    };

//........................................................................
} // namespace comphelper
//........................................................................

#endif // COMPHELPER_LOGGING_HXX

ext: hxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice


text:
/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2021 INRIA.
 *
 * 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 "Topology.hpp"
#include "SiconosException.hpp"
#include "NonSmoothLaw.hpp"
#include "NonSmoothDynamicalSystem.hpp"
#include "Interaction.hpp"
#include "EqualityConditionNSL.hpp"
#include "OneStepIntegrator.hpp"

#if (__cplusplus >= 201103L) && !defined(USE_BOOST_FOR_CXX11)
#include <functional>
#else
#include <boost/bind.hpp>
#endif

#include <algorithm>
#include <limits>

//#define DEBUG_STDOUT
//#define DEBUG_MESSAGES 1
#include "siconos_debug.h"

#define MAX_RELATIVE_DEGREE 999

// --- CONSTRUCTORS/DESTRUCTOR ---

// default
Topology::Topology()
{
  _IG.resize(1);
  _DSG.resize(1);

  _IG[0].reset(new InteractionsGraph());
  _DSG[0].reset(new DynamicalSystemsGraph());

  _IG[0]->update_vertices_indices();
  _IG[0]->update_edges_indices();
}

// destructor
Topology::~Topology()
{
  clear();
}

std::pair<DynamicalSystemsGraph::EDescriptor, InteractionsGraph::VDescriptor>
Topology::__addInteractionInIndexSet0(SP::Interaction inter, SP::DynamicalSystem ds1, SP::DynamicalSystem ds2)
{
  // !! Private function !!
  //
  // This function must
  // - insert interaction and ds into IG/DSG
  // - update graph properties related to modeling (DSlink ...)
  //
  // Expected result : all interaction methods can be safely called after a call
  // to this function (whatever the simulation is, if it exists or not).

  // Update total number of constraints
  _numberOfConstraints += inter->nonSmoothLaw()->size();

  SP::DynamicalSystem ds2_ = ds2;
  // _DSG is the hyper forest : (vertices : dynamical systems, edges :
  // Interactions)
  //
  // _IG is the hyper graph : (vertices : Interactions, edges :
  // dynamical systems)
  assert(_DSG[0]->edges_number() == _IG[0]->size());

  // _IG = L(_DSG),  L is the line graph transformation
  // vector of the Interaction
  DynamicalSystemsGraph::VDescriptor dsgv1, dsgv2;
  dsgv1 = _DSG[0]->add_vertex(ds1);

  if(ds2)
  {
    dsgv2 = _DSG[0]->add_vertex(ds2);
  }
  else
  {
    dsgv2 = dsgv1;
    ds2_ = ds1;
  }

  // this may be a multi edges graph
  assert(!_DSG[0]->is_edge(dsgv1, dsgv2, inter));
  assert(!_IG[0]->is_vertex(inter));
  InteractionsGraph::VDescriptor ig_new_ve;
  DynamicalSystemsGraph::EDescriptor new_ed;
  std::tie(new_ed, ig_new_ve) = _DSG[0]->add_edge(dsgv1, dsgv2, inter, *_IG[0]);

  inter->initializeLinkToDsVariables(*ds1, *ds2_);

  // add self branches in vertex properties
  // note : boost graph SEGFAULT on self branch removal
  // see https://svn.boost.org/trac/boost/ticket/4622
  _IG[0]->properties(ig_new_ve).source = ds1;
  _IG[0]->properties(ig_new_ve).source_pos = 0;

  if(!ds2) // self loop in ds graph, source=target in interaction graph
  {
    _IG[0]->properties(ig_new_ve).target = ds1;
    _IG[0]->properties(ig_new_ve).target_pos = 0;
  }
  else
  {
    _IG[0]->properties(ig_new_ve).target = ds2;
    _IG[0]->properties(ig_new_ve).target_pos = ds1->dimension();
  }

  assert(_IG[0]->bundle(ig_new_ve) == inter);
  assert(_IG[0]->is_vertex(inter));
  assert(_DSG[0]->is_edge(dsgv1, dsgv2, inter));
  assert(_DSG[0]->edges_number() == _IG[0]->size());

  return std::pair<DynamicalSystemsGraph::EDescriptor, InteractionsGraph::VDescriptor>(new_ed, ig_new_ve);
}

/* an edge is removed from _DSG graph if the corresponding vertex is
   removed from the adjoint graph (_IG)
*/
struct VertexIsRemoved
{
  VertexIsRemoved(SP::Interaction I,
                  SP::DynamicalSystemsGraph sg, SP::InteractionsGraph asg) :
    _I(I), __DSG(sg), __IG(asg) {};
  bool operator()(DynamicalSystemsGraph::EDescriptor ed)
  {

    if(__IG->is_vertex(__DSG->bundle(ed)))
    {
      InteractionsGraph::VDescriptor ivd = __IG->descriptor(__DSG->bundle(ed));

      if(__IG->bundle(ivd) == _I)
      {
        __IG->remove_vertex(__DSG->bundle(ed));

        assert(__IG->size() == __DSG->edges_number() - 1);

        return true;
      }
      else
      {
        return false;
      }
    }
    else
    {
      return true;
    }
  }
  SP::Interaction _I;
  SP::DynamicalSystemsGraph __DSG;
  SP::InteractionsGraph __IG;
};

/* an edge is removed from _DSG graph if the corresponding vertex is
   removed from the adjoint graph (_IG)
*/
struct VertexIsRemovedDS
{
  VertexIsRemovedDS(SP::DynamicalSystem ds,
                    SP::DynamicalSystemsGraph sg, SP::InteractionsGraph asg) :
    _ds(ds), __DSG(sg), __IG(asg) {};
  bool operator()(DynamicalSystemsGraph::EDescriptor ed)
  {
    if(__IG->is_vertex(__DSG->bundle(ed)))
    {
      InteractionsGraph::VDescriptor ivd = __IG->descriptor(__DSG->bundle(ed));

      if(__IG->properties(ivd).source == _ds
          || __IG->properties(ivd).target == _ds)
      {
        __IG->remove_vertex(__DSG->bundle(ed));

        assert(__IG->size() == __DSG->edges_number() - 1);

        return true;
      }
      else
      {
        return false;
      }
    }
    else
    {
      return true;
    }
  }
  SP::DynamicalSystem _ds;
  SP::DynamicalSystemsGraph __DSG;
  SP::InteractionsGraph __IG;
};

/* remove an interaction : remove edges (Interaction) from _DSG if
   corresponding vertices are removed from _IG */
void Topology::__removeInteractionFromIndexSet(SP::Interaction inter)
{

  SP::DynamicalSystem ds1 = _IG[0]->properties(_IG[0]->descriptor(inter)).source;
  SP::DynamicalSystem ds2 = _IG[0]->properties(_IG[0]->descriptor(inter)).target;
  _DSG[0]->remove_out_edge_if(_DSG[0]->descriptor(ds1), VertexIsRemoved(inter, _DSG[0], _IG[0]));
  if(ds1 != ds2)
    _DSG[0]->remove_out_edge_if(_DSG[0]->descriptor(ds2), VertexIsRemoved(inter, _DSG[0], _IG[0]));
}

void Topology::insertDynamicalSystem(SP::DynamicalSystem ds)
{
  _DSG[0]->add_vertex(ds);
  setHasChanged(true);
}

/* remove a dynamical system : remove edges (DynamicalSystem) from _IG if
   corresponding vertices are removed from _DSG */
void Topology::__removeDynamicalSystemFromIndexSet(SP::DynamicalSystem ds)
{
  _DSG[0]->remove_edge_if(_DSG[0]->descriptor(ds),
                          VertexIsRemovedDS(ds, _DSG[0], _IG[0]));

  // note: remove_vertex also calls clear_vertex and removes all in/out edges
  _DSG[0]->remove_vertex(ds);
}

void Topology::setName(SP::DynamicalSystem ds, const std::string& name)
{
  DynamicalSystemsGraph::VDescriptor dsgv = _DSG[0]->descriptor(ds);
  _DSG[0]->name.insert(dsgv, name);
}

std::string Topology::name(SP::DynamicalSystem ds)
{
  DynamicalSystemsGraph::VDescriptor dsgv = _DSG[0]->descriptor(ds);
  if(dsgv)
    return _DSG[0]->name.at(dsgv);
  else
    return "";
}

void Topology::setName(SP::Interaction inter, const std::string& name)
{
  InteractionsGraph::VDescriptor igv = _IG[0]->descriptor(inter);
  _IG[0]->name.insert(igv, name);
}

std::string Topology::name(SP::Interaction inter)
{
  InteractionsGraph::VDescriptor igv = _IG[0]->descriptor(inter);
  if(igv)
    return _IG[0]->name.at(igv);
  else
    return "";
}

void Topology::setOSI(SP::DynamicalSystem ds, SP::OneStepIntegrator OSI)
{
  _DSG[0]->properties(_DSG[0]->descriptor(ds)).osi = OSI;
}

void Topology::setControlProperty(SP::Interaction inter,
                                  const bool isControlInteraction)
{
  InteractionsGraph::VDescriptor ivd = _IG[0]->descriptor(inter);
  DynamicalSystemsGraph::VDescriptor dvd = _DSG[0]->descriptor(_IG[0]->properties(ivd).target);
  SP::Interaction interG;
  DynamicalSystemsGraph::OEIterator oei, oeiend;
  for(std::tie(oei, oeiend) = _DSG[0]->out_edges(dvd); oei != oeiend; ++oei)
  {
    interG = _DSG[0]->bundle(*oei);
    if(inter == interG)
    {
      _DSG[0]->properties(*oei).forControl = isControlInteraction;
      break;
    }
  }
  _IG[0]->properties(ivd).forControl = isControlInteraction;
}

SP::InteractionsGraph Topology::indexSet(unsigned int num) const
{
  if(num >= _IG.size())
  {
    THROW_EXCEPTION("Topology::indexSet: indexSet does not exist");
  }
  assert(num < _IG.size()) ;
  return _IG[num];
};

void Topology::removeInteraction(SP::Interaction inter)
{
  DEBUG_PRINTF("removeInteraction : %p\n", &*inter);

  assert(_DSG[0]->edges_number() == _IG[0]->size());
  __removeInteractionFromIndexSet(inter);
  assert(_DSG[0]->edges_number() == _IG[0]->size());
  setHasChanged(true);
}

void Topology::removeDynamicalSystem(SP::DynamicalSystem ds)
{
  DEBUG_PRINTF("removeDynamicalSystem : %p\n", &*ds);

  assert(_DSG[0]->edges_number() == _IG[0]->size() && "1");
  __removeDynamicalSystemFromIndexSet(ds);
  assert(_DSG[0]->edges_number() == _IG[0]->size() && "2");
  setHasChanged(true);
}

std::pair<DynamicalSystemsGraph::EDescriptor, InteractionsGraph::VDescriptor>
Topology::link(SP::Interaction inter, SP::DynamicalSystem ds, SP::DynamicalSystem ds2)
{
  DEBUG_PRINTF("Topology::link : inter %p, ds1 %p, ds2 %p\n", &*inter, &*ds,
               &*ds2);

  // If the interaction is already in the graph remove it
  if(indexSet0()->is_vertex(inter))
  {
    __removeInteractionFromIndexSet(inter);
  }

  // Compute interaction dimension (sum of involved dynamical systems sizes)
  unsigned int sumOfDSSizes = 0;
  sumOfDSSizes += ds->dimension();
  if(ds2)
  {
    sumOfDSSizes += ds2->dimension();
    inter->setHas2Bodies(true);
  }
  inter->setDSSizes(sumOfDSSizes);

  return __addInteractionInIndexSet0(inter, ds, ds2);
}

bool Topology::hasInteraction(SP::Interaction inter) const
{
  return indexSet0()->is_vertex(inter);
}

bool Topology::hasDynamicalSystem(SP::DynamicalSystem ds) const
{
  return _DSG[0]->is_vertex(ds);
}

void Topology::setProperties()
{
  _IG[0]->update_vertices_indices();
  _IG[0]->update_edges_indices();

  for(unsigned int i = 1; i < _IG.size(); ++i)
  {
    // .. global properties may be defined here with
    // InteractionsSubGraphProperties(), see SiconosProperties.hpp
    // VertexSubProperties or EdgeSubProperties and the macros
    // INSTALL_GRAPH_PROPERTIES

    _IG[i]->properties().symmetric = _symmetric;

    _IG[i]->update_vertices_indices();
    _IG[i]->update_edges_indices();
  }

  _DSG[0]->properties().symmetric = _symmetric;

  _DSG[0]->update_vertices_indices();
  _DSG[0]->update_edges_indices();

}

void Topology::clear()
{
  _IG.clear();
  _DSG.clear();
}

SP::DynamicalSystem Topology::getDynamicalSystem(unsigned int requiredNumber) const
{
  DynamicalSystemsGraph::VIterator vi, vdend;
  SP::DynamicalSystem ds;
  unsigned int currentNumber;
  for(std::tie(vi, vdend) = _DSG[0]->vertices(); vi != vdend; ++vi)
  {
    ds = _DSG[0]->bundle(*vi);
    currentNumber = ds->number();
    if(currentNumber == requiredNumber)
      return ds;
  }

  THROW_EXCEPTION("Topology::getDynamicalSystem(n) ds not found.");

  return ds;
}

void Topology::displayDynamicalSystems() const
{
  DynamicalSystemsGraph::VIterator vi, vdend;
  SP::DynamicalSystem ds;
  unsigned int currentNumber;
  for(std::tie(vi, vdend) = _DSG[0]->vertices(); vi != vdend; ++vi)
  {
    ds = _DSG[0]->bundle(*vi);
    currentNumber = ds->number();
    std::cout << "Dynamical system number : " << currentNumber << std::endl;
    ds->display();
  }
}

SP::DynamicalSystem Topology::getDynamicalSystem(std::string name) const
{
  DynamicalSystemsGraph::VIterator vi, vdend;
  for(std::tie(vi, vdend) = _DSG[0]->vertices(); vi != vdend; ++vi)
  {
    if(name == _DSG[0]->name.at(*vi))
      return _DSG[0]->bundle(*vi);
  }

  THROW_EXCEPTION("Topology::getDynamicalSystem() ds not found.");

  return SP::DynamicalSystem();
}

unsigned int Topology::numberOfInvolvedDS(unsigned int inumber)
{
  if(inumber >= _IG.size())
  {
    THROW_EXCEPTION("Topology::numberOfInvolvedDS :: index number must be smaller than the number of indexSets");
  }

  /* on an adjoint graph a dynamical system may be on several edges */
  std::map<SP::DynamicalSystem, bool> flag;

  unsigned int return_value = 0;

  SP::InteractionsGraph indexSet = _IG[inumber];

  InteractionsGraph::VIterator vi, viend;
  for(std::tie(vi, viend) = indexSet->vertices();
      vi != viend; ++vi)
  {
    if(indexSet->properties(*vi).source)
    {
      if(flag.find(indexSet->properties(*vi).source) == flag.end())
      {
        flag[indexSet->properties(*vi).source] = true;
        return_value++;
      }
    }
    if(indexSet->properties(*vi).target)
    {
      if(flag.find(indexSet->properties(*vi).target) == flag.end())
      {
        flag[indexSet->properties(*vi).target] = true;
        return_value++;
      }
    }
  }

  InteractionsGraph::EIterator ei, eiend;

  for(std::tie(ei, eiend) = indexSet->edges();
      ei != eiend; ++ei)
  {
    if(flag.find(indexSet->bundle(*ei)) == flag.end())
    {
      flag[indexSet->bundle(*ei)] = true;
      return_value++;
    }
  }

  return return_value;
}

SP::Interaction Topology::getInteraction(unsigned int requiredNumber) const
{
  InteractionsGraph::VIterator vi, vdend;
  SP::Interaction inter;
  unsigned int currentNumber;
  for(std::tie(vi, vdend) = _IG[0]->vertices(); vi != vdend; ++vi)
  {
    inter = _IG[0]->bundle(*vi);
    currentNumber = inter->number();
    if(currentNumber == requiredNumber)
      return inter;
  }

  return inter;
}

SP::Interaction Topology::getInteraction(std::string name) const
{
  DynamicalSystemsGraph::VIterator vi, vdend;
  for(std::tie(vi, vdend) = _IG[0]->vertices(); vi != vdend; ++vi)
  {
    if(name == _IG[0]->name.at(*vi))
      return _IG[0]->bundle(*vi);
  }

  return SP::Interaction();
}

std::vector<SP::Interaction> Topology::interactionsForDS(
  SP::DynamicalSystem ds) const
{
  InteractionsGraph::VIterator ui, uiend;
  SP::Interaction inter;
  std::vector<SP::Interaction> result;
  if(!ds) return result;
  for(std::tie(ui, uiend) = _IG[0]->vertices(); ui != uiend; ++ui)
  {
    inter = _IG[0]->bundle(*ui);
    SP::DynamicalSystem ds1 = _IG[0]->properties(_IG[0]->descriptor(inter)).source;
    SP::DynamicalSystem ds2 = _IG[0]->properties(_IG[0]->descriptor(inter)).target;
    if(ds == ds1 || ds == ds2)
      result.push_back(inter);
  }
  return result;
}

std::vector<SP::Interaction> Topology::interactionsForPairOfDS(
  SP::DynamicalSystem dsA,
  SP::DynamicalSystem dsB) const
{
  InteractionsGraph::VIterator ui, uiend;
  SP::Interaction inter;
  std::vector<SP::Interaction> result;
  if(!dsA && !dsB) return result;
  for(std::tie(ui, uiend) = _IG[0]->vertices(); ui != uiend; ++ui)
  {
    inter = _IG[0]->bundle(*ui);
    SP::DynamicalSystem ds1 = _IG[0]->properties(_IG[0]->descriptor(inter)).source;
    SP::DynamicalSystem ds2 = _IG[0]->properties(_IG[0]->descriptor(inter)).target;
    int found = 0;
    if(dsA == ds1)
      found = 1;
    else if(dsA == ds2)
      found = 2;
    if(found==2 && dsB != ds1)
      found = 0;
    else if(found==1 && dsB == ds2)
      found = 0;
    if(found)
      result.push_back(inter);
  }
  return result;
}

std::vector<SP::DynamicalSystem>
Topology::dynamicalSystemsForInteraction(
  SP::Interaction inter) const
{
  SP::DynamicalSystem ds1 = _IG[0]->properties(_IG[0]->descriptor(inter)).source;
  SP::DynamicalSystem ds2 = _IG[0]->properties(_IG[0]->descriptor(inter)).target;
  std::vector<SP::DynamicalSystem> result;
  if(ds1) result.push_back(ds1);
  if(ds2 && ds1 != ds2) result.push_back(ds2);
  return result;
}

ext: cpp

max_stars_repo_name: BuildJet/siconos

max_issues_repo_name: BuildJet/siconos

max_forks_repo_name: BuildJet/siconos


text:
#include <boost/test/unit_test.hpp>

#include <boost/format.hpp>

#include <set>
#include <iostream>

using std::ostream;
using boost::format;
using namespace crave;

enum color_enum { RED, GREEN, BLUE };
CRAVE_ENUM(color_enum, (RED)(GREEN)(BLUE));

enum football_enum {
  GK,   // Goalkeeper
  SW,   // Sweeper
  LWB,  // Left-Wing-Back
  LB,   // Left-Back
  LCB,  // Left-Centre-Back
  RCB,  // Right-Centre-Back
  RB,   // Right-Back
  RWB,  // Right-Wing-Back
  DM,   // Defensive Midfielder
  LM,   // Left Wide Midfielder
  CM,   // Centre Midfielder
  RM,   // Right Wide Midfielder
  AM,   // Attacking Midfielder
  LW,   // Left Winger (Striker)
  SS,   // Secondary Striker
  RW,   // Right Winger
  CF    // Centre Striker
};
CRAVE_ENUM(football_enum, (GK)(SW)(LWB)(LB)(LCB)(RCB)(RB)(RWB)(DM)(LM)(CM)(RM)(AM)(LW)(SS)(RW)(CF));

BOOST_FIXTURE_TEST_SUITE(Random_Object_t, Context_Fixture)

class my_rand_obj : public rand_obj {
 public:
  randv<color_enum> color;
  randv<int> x;

  my_rand_obj(rand_obj* parent = 0) : rand_obj(parent), color(this), x(this) { constraint(color() == x()); }
};

BOOST_AUTO_TEST_CASE(t_rand_enum) {
  my_rand_obj obj(0);
  for (int i = 0; i < 20; i++) {
    BOOST_REQUIRE(obj.next());
    std::cout << obj.color << " " << obj.x << std::endl;
    BOOST_REQUIRE(obj.color == RED || obj.color == GREEN || obj.color == BLUE);
    BOOST_REQUIRE(obj.color == obj.x);
  }
}

BOOST_AUTO_TEST_CASE(t_rand_enum_standalone) {
  BOOST_REQUIRE_THROW(new randv<color_enum>(0), std::runtime_error);
}

class tall_rand_enum_obj : public rand_obj {
 public:
  randv<football_enum> player;

  tall_rand_enum_obj(rand_obj* parent = 0) : rand_obj(parent), player(this) {
    constraint(player() == GK && player() != CF);
  }
};

class tall_rand_enum_obj_gt : public rand_obj {
 public:
  randv<football_enum> player;

  tall_rand_enum_obj_gt(rand_obj* parent = 0) : rand_obj(parent), player(this) { constraint(player() > AM); }
};

BOOST_AUTO_TEST_CASE(enum_no_overflow) {
  tall_rand_enum_obj obj(0);
  BOOST_REQUIRE(obj.next());

  BOOST_REQUIRE_EQUAL(obj.player, GK);
}

BOOST_AUTO_TEST_CASE(enum_gt) {
  tall_rand_enum_obj_gt obj(0);

  for (int i = 0; i < 100; ++i) {
    BOOST_REQUIRE(obj.next());
    BOOST_REQUIRE_GT(obj.player, AM);
    BOOST_REQUIRE(obj.player == LW || obj.player == SS || obj.player == RW || obj.player == CF);
  }
}

class item : public rand_obj {
 public:
  item(rand_obj* parent) : rand_obj(parent), a(this), b(this), c(this) { constraint(a() + b() == c()); }

 public:
  randv<int> a;
  randv<int> b;
  randv<int> c;
};

class item1 : public item {
 public:
  item1(rand_obj* parent) : item(parent) {
    constraint(10 <= a() && a() <= 20);
    constraint(a() + b() + c() <= 200);
  }
};

class item2 : public item1 {
 public:
  item2(rand_obj* parent) : item1(parent), d(this) { constraint(a() + b() + c() == 100); }
  randv<int> d;
};

BOOST_AUTO_TEST_CASE(t2) {
  item it(0);
  BOOST_REQUIRE(it.next());
  std::cout << it.a << " " << it.b << " " << it.c << std::endl;
  BOOST_REQUIRE(it.a + it.b == it.c);
}

BOOST_AUTO_TEST_CASE(t3) {
  item1 it(0);
  BOOST_REQUIRE(it.next());
  std::cout << it.a << " " << it.b << " " << it.c << std::endl;
  BOOST_REQUIRE(it.a + it.b == it.c);
  BOOST_REQUIRE(10 <= it.a && it.a <= 20);
  BOOST_REQUIRE(it.a + it.b + it.c <= 200);
}

BOOST_AUTO_TEST_CASE(t4) {
  item2 it(0);
  BOOST_REQUIRE(it.next());
  std::cout << it.a << " " << it.b << " " << it.c << std::endl;
  BOOST_REQUIRE(it.a + it.b == it.c);
  BOOST_REQUIRE(10 <= it.a && it.a <= 20);
  BOOST_REQUIRE(it.a + it.b + it.c == 100);
}

class obj : public rand_obj {
 public:
  obj(rand_obj* parent) : rand_obj(parent), a(this), b(this), c(this), d(this), e(this), f(this) {
    constraint(dist(a(), distribution<int>::simple_range(-20, -10)));
    constraint(dist(b(), distribution<unsigned int>::simple_range(10, 20)));
    constraint(dist(c(), distribution<short>::simple_range(-20, -10)));
    constraint(dist(d(), distribution<unsigned short>::simple_range(10, 20)));
    constraint("e", dist(e(), distribution<char>::simple_range('a', 'z')));
    constraint("f", dist(f(), distribution<unsigned char>::simple_range('A', 'Z')));
  }
  randv<int> a;
  randv<unsigned int> b;
  randv<short> c;
  randv<unsigned short> d;
  randv<char> e;
  randv<unsigned char> f;

  friend ostream& operator<<(ostream& os, const obj& o) {
    os << "(" << o.a << " " << o.b << " " << o.c << " " << o.d << " " << o.e << " " << o.f << ")";
    return os;
  }
};

class obj1 : public obj {
 public:
  obj1(rand_obj* parent) : obj(parent) {
    disable_constraint("e");
    disable_constraint("f");
    constraint(dist(e(), distribution<char>::simple_range('A', 'Z')));
    constraint(dist(f(), distribution<unsigned char>::simple_range('a', 'z')));
  }
};

class obj2 : public rand_obj {
 public:
  obj2(rand_obj* parent) : rand_obj(parent), g(this), h(this), i(this), j(this), k(this), l(this) {
    constraint(dist(g(), distribution<long>::simple_range(-20, -10)));
    constraint(dist(h(), distribution<unsigned long>::simple_range(10, 20)));
    constraint(dist(i(), distribution<long long>::simple_range(-20, -10)));
    constraint(dist(j(), distribution<unsigned long long>::simple_range(10, 20)));
  }
  randv<long> g;
  randv<unsigned long> h;
  randv<long long> i;
  randv<unsigned long long> j;
  randv<bool> k;
  obj1 l;

  friend ostream& operator<<(ostream& os, const obj2& o1) {
    os << o1.l << " " << o1.g << " " << o1.h << " " << o1.i << " " << o1.j << " " << o1.k;
    return os;
  }
};

BOOST_AUTO_TEST_CASE(t5) {
  obj it(0);
  for (int i = 0; i < 20; i++) {
    BOOST_REQUIRE(it.next());
    BOOST_REQUIRE(-20 <= it.a && it.a <= -10);
    BOOST_REQUIRE(10 <= it.b && it.b <= 20);
    BOOST_REQUIRE(-20 <= it.c && it.c <= -10);
    BOOST_REQUIRE(10 <= it.d && it.d <= 20);
    BOOST_REQUIRE('a' <= it.e && it.e <= 'z');
    BOOST_REQUIRE('A' <= it.f && it.f <= 'Z');
  }

  obj1 it1(0);
  for (int i = 0; i < 20; i++) {
    BOOST_REQUIRE(it1.next());
    BOOST_REQUIRE(-20 <= it1.a && it1.a <= -10);
    BOOST_REQUIRE(10 <= it1.b && it1.b <= 20);
    BOOST_REQUIRE(-20 <= it1.c && it1.c <= -10);
    BOOST_REQUIRE(10 <= it1.d && it1.d <= 20);
    BOOST_REQUIRE('a' <= it1.f && it1.f <= 'z');
    BOOST_REQUIRE('A' <= it1.e && it1.e <= 'Z');
  }

  obj2 it2(0);
  for (int i = 0; i < 20; i++) {
    BOOST_REQUIRE(it2.next());
    BOOST_REQUIRE(-20 <= it2.g && it2.g <= -10);
    BOOST_REQUIRE(10 <= it2.h && it2.h <= 20);
    BOOST_REQUIRE(-20 <= it2.i && it2.i <= -10);
    BOOST_REQUIRE(10 <= it2.j && it2.j <= 20);
    BOOST_REQUIRE(-20 <= it2.l.a && it2.l.a <= -10);
    BOOST_REQUIRE(10 <= it2.l.b && it2.l.b <= 20);
    BOOST_REQUIRE(-20 <= it2.l.c && it2.l.c <= -10);
    BOOST_REQUIRE(10 <= it2.l.d && it2.l.d <= 20);
    BOOST_REQUIRE('a' <= it2.l.f && it2.l.f <= 'z');
    BOOST_REQUIRE('A' <= it2.l.e && it2.l.e <= 'Z');
  }
}

struct Item1 : public rand_obj {
  Item1() : x(this), pivot(0) {
    constraint("c1", x() * x() >= 24);
    constraint("c2", x() <= reference(pivot));
  }

  bool next() {
    int lower = 0;
    int upper = 100;
    while (lower < upper) {
      std::cout << lower << " " << upper << std::endl;
      pivot = (upper + lower) / 2;
      if (constraint.next())
        upper = x;
      else
        lower = pivot + 1;
    }
    x = upper;
    return true;
  }

  randv<unsigned> x;
  int pivot;
};

BOOST_AUTO_TEST_CASE(binary_search_test) {
  VariableDefaultSolver::bypass_constraint_analysis = true;

  Item1 it;
  BOOST_REQUIRE(it.next());
  BOOST_REQUIRE_EQUAL(it.x, 5);

  VariableDefaultSolver::bypass_constraint_analysis = false;
}

struct Item2 : public rand_obj {
  Item2() : i(), address(this), data(this) {
    constraint(address() % 4 == 0);
    constraint(address() <= 1000u);
    constraint(data().size() == 4);
    constraint(foreach (data(), -50 <= data()[i] && data()[i] <= 50));
    constraint(foreach (data(), data()[i - 1] <= data()[i]));
  }

  placeholder i;
  randv<unsigned> address;
  rand_vec<int> data;
};

BOOST_AUTO_TEST_CASE(item_with_vector) {
  Item2 it;
  for (int i = 0; i < 20; i++) {
    BOOST_REQUIRE(it.next());
    BOOST_REQUIRE_EQUAL(it.data.size(), 4);
    std::cout << "@" << it.address << ": " << it.data[0] << " " << it.data[1] << " " << it.data[2] << " " << it.data[3]
              << std::endl;
    BOOST_REQUIRE_EQUAL(it.address % 4, 0);
    BOOST_REQUIRE_LE(it.address, 1000);
    for (unsigned i = 0; i < it.data.size(); i++) {
      BOOST_REQUIRE_LE(-50, it.data[i]);
      BOOST_REQUIRE_LE(it.data[i], 50);
      if (i > 0) BOOST_REQUIRE_LE(it.data[i - 1], it.data[i]);
    }
  }
}

class Constraint_base : public Generator {
 public:
  Constraint_base() : Generator(), constraint(*this) {}

 protected:
  Generator& constraint;
};

class Constraint1 : public Constraint_base {
 public:
  Variable<unsigned> x;

  Constraint1() : Constraint_base() { constraint(x < 10); }
};

class Constraint2 : public Constraint1 {
 public:
  Constraint2() : Constraint1() { constraint(x > 6); }
};

BOOST_AUTO_TEST_CASE(t1) {
  Constraint2 c2;

  c2();
  unsigned r = c2[c2.x];
  BOOST_REQUIRE_LT(r, 10);
  BOOST_REQUIRE_GT(r, 6);

  c2(c2.x != r)();
  r = c2[c2.x];
  BOOST_REQUIRE_LT(r, 10);
  BOOST_REQUIRE_GT(r, 6);

  c2(c2.x != r)();
  r = c2[c2.x];
  BOOST_REQUIRE_LT(r, 10);
  BOOST_REQUIRE_GT(r, 6);

  c2(c2.x != r);
  BOOST_REQUIRE(!c2.next());
}

BOOST_AUTO_TEST_SUITE_END()  // Context

//  vim: ft=cpp:ts=2:sw=2:expandtab

max_stars_repo_name: quadric-io/crave

max_issues_repo_name: quadric-io/crave

max_forks_repo_name: quadric-io/crave


text:
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
#include <sys/time.h>
#include "GameState.h"
#include "Player.h"
#include "Config.h"
#include "DoTurn.h"
#include "Log.h"

#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH

#ifdef DEBUG
std::ofstream LOG_FILE;
std::ofstream LOG_ERROR_FILE;
std::string PROG_NAME;
#endif

// This is a utility class that parses strings.
class StringUtil {
    public:
        // Tokenizes a string s into tokens. Tokens are delimited by any of the
        // characters in delimiters. Blank tokens are omitted.
        static void Tokenize(const std::string& s,
                const std::string& delimiters,
                std::vector<std::string>& tokens);

        // A more convenient way of calling the Tokenize() method.
        static std::vector<std::string> Tokenize(
                const std::string& s,
                const std::string& delimiters = std::string(" "));
};

void StringUtil::Tokenize(const std::string& s,
        const std::string& delimiters,
        std::vector<std::string>& tokens) {
    std::string::size_type lastPos = s.find_first_not_of(delimiters, 0);
    std::string::size_type pos = s.find_first_of(delimiters, lastPos);
    while (std::string::npos != pos || std::string::npos != lastPos) {
        tokens.push_back(s.substr(lastPos, pos - lastPos));
        lastPos = s.find_first_not_of(delimiters, pos);
        pos = s.find_first_of(delimiters, lastPos);
    }
}

std::vector<std::string> StringUtil::Tokenize(const std::string& s,
        const std::string& delimiters) {
    std::vector<std::string> tokens;
    Tokenize(s, delimiters, tokens);
    return tokens;
}

const int PLANET_X = 1;
const int PLANET_Y = 2;
const int PLANET_OWNER = 3;
const int PLANET_SHIPS = 4;
const int PLANET_GROWTH = 5;

const int FLEET_OWNER = 1;
const int FLEET_SHIPS = 2;
const int FLEET_SOURCE = 3;
const int FLEET_DEST = 4;
const int FLEET_LENGTH = 5;
const int FLEET_REMAINING = 6;

// convert player id from external representation to internal representation
Player ConvertPlayerID(int raw_player_id) {
    switch (raw_player_id) {
        case 1:
            return ME;
        case 2:
            return ENEMY;
        case 0:
            return NEUTRAL;
        default:
            // TODO: log an error?
            return NEUTRAL;
    }
}

GameState ParseGameState(const std::string& game_state) {
    static int turn = 0;
    std::vector<PlanetPtr> planets;
    std::vector<Fleet> fleets;
    std::vector<std::string> lines = StringUtil::Tokenize(game_state, "\n");
    int planet_id = 0;

    for (unsigned int i = 0; i < lines.size(); ++i) {
        std::string& line = lines[i];
        size_t comment_begin = line.find_first_of('#');
        if (comment_begin != std::string::npos) {
            line = line.substr(0, comment_begin);
        }
        std::vector<std::string> tokens = StringUtil::Tokenize(line);
        if (tokens.size() == 0) {
            continue;
        }
        if (tokens[0] == "P") {
            if (tokens.size() != 6) {
                throw "Invalid planet";
            }
            PlanetPtr p( new Planet(
                planet_id++, // The ID of this planet
                ConvertPlayerID(atoi(tokens[PLANET_OWNER].c_str())),
                atoi(tokens[PLANET_SHIPS].c_str())
            ));
            planets.push_back(p);
        } else if (tokens[0] == "F") {
            if (tokens.size() != 7) {
                throw "Invalid fleet";
            }
            fleets.push_back(Fleet(
                ConvertPlayerID(atoi(tokens[FLEET_OWNER].c_str())),
                atoi(tokens[FLEET_SOURCE].c_str()),
                atoi(tokens[FLEET_DEST].c_str()),
                atoi(tokens[FLEET_SHIPS].c_str()),
                atoi(tokens[FLEET_REMAINING].c_str()) - atoi(tokens[FLEET_LENGTH].c_str())
            ));
        } else {
            throw "Invalid object";
        }
    }

    turn += 1;

    // TODO: make this less coypying around
    GameState state(turn, planets);

    // inform planets about fleets
    foreach ( const Fleet& f, fleets ) {
        state.AddFleet(f);
    }

    return state;
}

void ParseMap(const std::string& game_state) {
    std::vector<std::string> lines = StringUtil::Tokenize(game_state, "\n");
    for (unsigned int i = 0; i < lines.size(); ++i) {
        std::string& line = lines[i];
        size_t comment_begin = line.find_first_of('#');
        if (comment_begin != std::string::npos) {
            line = line.substr(0, comment_begin);
        }
        std::vector<std::string> tokens = StringUtil::Tokenize(line);
        if (tokens.size() == 0) {
            continue;
        }
        if (tokens[0] == "P") {
            if (tokens.size() != 6) {
                throw "Invalid planet";
            }
            Map::AddPlanet(
                atoi(tokens[PLANET_GROWTH].c_str()),
                atof(tokens[PLANET_X].c_str()),
                atof(tokens[PLANET_Y].c_str())
            );
        } else if (tokens[0] != "F") {
            throw "Invalid object";
        }
    }

    Map::Init();
}

void FinishTurn(const GameState& state, const std::vector<Fleet>& orders) {
    int num_ships = 0;

    // issue all the orders
    foreach ( const Fleet& o, orders ) {
        if ( o.source == o.dest
                || o.ships <= 0
                || o.ships > state.Planet(o.source)->Ships()
                || state.Planet(o.source)->Owner() != ME
        ) {
            // ensure the order is not to the same planet
            // and that the number of ships is positive
            // and that the source has enough ships
            // and that we own the planet
            continue;
        }

        std::cout << o.source << " "
            << o.dest << " "
            << o.ships << std::endl;
        std::cout.flush();

        num_ships += o.ships;
    }

    // finish up
    std::cout << "go" << std::endl;
    std::cout.flush();

    // Log AFTER we have sent the command (wastes less time)
    LOG( orders.size() << " Orders (" << num_ships << " ships):" );

    foreach ( const Fleet& o, orders ) {
        // TODO: seperate out and have different log message for each condition
        if ( o.source == o.dest
                || o.ships <= 0
                || o.ships > state.Planet(o.source)->Ships()
                || state.Planet(o.source)->Owner() != ME
        ) {
            LOG_ERROR( "Invalid order: " << o.source << "->" << o.dest << " (" << o.ships << " ships)" );
        }
        else {
            LOG( o.source << "->" << o.dest << " (" << o.ships << " ships)" );
        }
    }
}

// This is just the main game loop that takes care of communicating with the
// game engine for you. You don't have to understand or change the code below.
int main(int argc, char *argv[]) {
    std::string current_line;
    std::string map_data;
    bool map_parsed = false;

    Config::Init(argc, argv);

    LOG_INIT(argv[0], Config::Value<std::string>("log_file"));

    // log the command used to run this program
    for ( int i=0; i < argc; ++i ) { LOG_( argv[i] << " " ); } LOG(""); LOG("");

    // log the config options
    LOG("== OPTIONS ==");
    LOG_(Config::String());

    while (true) {
        int c = std::cin.get();
        current_line += (char)c;
        if (c == '\n') {
            if (current_line.length() >= 2 && current_line.substr(0, 2) == "go") {
                timeval init;
                timeval finish;

                // TODO: Start counting from time when we receive first line of next command
                gettimeofday(&init,NULL);

                if ( ! map_parsed ) {
                    // On the first turn we calculate the global map data
                    ParseMap(map_data);
                    map_parsed = true;
                }

                const GameState state = ParseGameState(map_data);

                LOG("");
                LOG( "== Turn " << state.Turn() << " ==" );

                LOG( "ME:    " << state.Ships(ME) << "/" << state.Production(ME) );
                LOG( "ENEMY: " << state.Ships(ENEMY) << "/" << state.Production(ENEMY) );

                std::vector<Fleet> orders;
                DoTurn(state, orders);
                FinishTurn(state, orders);
                map_data = "";

                gettimeofday(&finish,NULL);
                LOG( "Time: " <<  ( finish.tv_usec - init.tv_usec ) );
                LOG_FLUSH();
            } else {
                map_data += current_line;
            }
            current_line = "";
        }
    }

    LOG_CLOSE();

    return 0;
}

ext: cc

max_stars_repo_name: sigh/Planet-Wars

max_issues_repo_name: sigh/Planet-Wars

max_forks_repo_name: sigh/Planet-Wars


text:
#include "encoding.hpp"
#include "WordXMLNode.h"
#include "WordXMLNodeList.h"
#include "WordXMLDocument.h"
#include "WordXMLFunctions.h"
#include <boost/algorithm/string.hpp>

NAMESPACE_BEGIN(libword)

    // Split text into paragraphs
    std::vector<enc::ucs::string_t> splitParagraphs(const enc::ucs::char_t* str)
    {
        // Découpage de la string en paragraphe
        std::vector<enc::ucs::string_t> texts;
        enc::ucs::string_t sentence = str;
        typedef std::vector< boost::iterator_range<enc::ucs::string_t::iterator> > find_vector_type;
        find_vector_type separators;

        boost::ifind_all( separators, sentence, UCS("\r\n") );
        enc::ucs::string_t::iterator start = sentence.begin();
        for (find_vector_type::const_iterator i = separators.begin();
             i != separators.end();
             ++i)
        {
            texts.push_back(enc::ucs::string_t(start, i->begin()));
            start = i->end();
        }
        texts.push_back(enc::ucs::string_t(start, sentence.end()));
        return texts;
    }

    // Get text position
    void getTextPosition(const WordXMLNode& node, WordXMLNode& paragraph, WordXMLNode& revision, WordXMLNode& run, bool reverse)
    {
        // Recherche du paragraphe de départ
        if(node.getParent(WordXMLNode::PARAGRAPH_TAG).isValid())
        {
            // Fixe le paragraphe de départ
            paragraph = node.getParent(WordXMLNode::PARAGRAPH_TAG);
            // Recherche de la révision de départ
            if (node.getTagName() == WordXMLNode::REVISION_TAG)
            {
                revision = node;
            }
            else if (node.getParent(WordXMLNode::REVISION_TAG).isValid())
            {
                revision = node.getParent(WordXMLNode::REVISION_TAG);
            }
            // Recherche du run de départ
            if (node.getTagName() == WordXMLNode::RUN_TAG)
            {
                run = node;
            }
            else if (node.getParent(WordXMLNode::RUN_TAG).isValid())
            {
                run = node.getParent(WordXMLNode::RUN_TAG);
            }
            else if (revision.isValid())
            {
                WordXMLNodeList child = revision.getNodes(WordXMLNode::RUN_TAG);
                if (child.length() != 0)
                {
                    size_t i = 0;
                    if (reverse)
                    {
                        i = child.length()-1;
                    }
                    run = child.item(i);
                }
            }
            else
            {
                WordXMLNodeList child = paragraph.getNodes(WordXMLNode::RUN_TAG);
                if (child.length() != 0)
                {
                    size_t i = 0;
                    if (reverse)
                    {
                        i = child.length()-1;
                    }
                    run = child.item(i);
                }
            }
        }
        else
        {
            // Recherche du paragraphe de départ
            if (node.getTagName() == WordXMLNode::PARAGRAPH_TAG)
            {
                paragraph = node;
            }
            else
            {
                WordXMLNodeList child = node.getNodes(WordXMLNode::PARAGRAPH_TAG);
                if (child.length() != 0)
                {
                    size_t i = 0;
                    if (reverse)
                    {
                        i = child.length()-1;
                    }
                    paragraph = child.item(i);
                }
            }
            if (paragraph.isValid())
            {
                // Recherche du run de départ
                WordXMLNodeList child = paragraph.getNodes(WordXMLNode::RUN_TAG);
                if (child.length() != 0)
                {
                    size_t i = 0;
                    if (reverse)
                    {
                        i = child.length()-1;
                    }
                    run = child.item(i);
                }
                // Fixe la révision de départ
                if (run.isValid())
                {
                    revision = run.getParent(WordXMLNode::REVISION_TAG);
                }
            }
        }
    }

    // Advance position
    void advancePosition(WordXMLNode& paragraph, WordXMLNode& revision, WordXMLNode& run, size_t distance)
    {
        int pPos = distance;
        // Parcours des noeuds jusqu'à avoir pPos < 0
        WordXMLNode tmpNode;
        while ((run.isValid() && (pPos -= run.getString().length()) >= 0) ||
               (!run.isValid() && paragraph.isValid() && (pPos -= 2) >= 0))
        {
            if (run.isValid())
            {
                tmpNode = run.getNextNode();
                if (!tmpNode.isValid() && revision.isValid())
                {
                    tmpNode = revision.getNextNode();
                    revision = WordXMLNode();
                }
                if (tmpNode.isValid() && tmpNode.getTagName() == WordXMLNode::REVISION_TAG)
                {
                    revision = tmpNode;
                    tmpNode = revision.getNodes(WordXMLNode::RUN_TAG).item(0);
                }
                run = tmpNode;
            }
            else if (paragraph.isValid())
            {
                paragraph = paragraph.getNextNode();
                if (paragraph.isValid() && paragraph.getTagName() == WordXMLNode::PARAGRAPH_TAG)
                {
                    run = paragraph.getNodes(WordXMLNode::RUN_TAG).item(0);
                    if (run.isValid())
                    {
                        revision = run.getParent(WordXMLNode::REVISION_TAG);
                    }
                }
                else
                {
                    // Le noeud suivant n'est pas un paragraphe, on s'arrête.
                    paragraph = WordXMLNode();
                }
            }
        }
        // Recherche si le point d'insertion se trouve à l'intérieur d'un run
        if (pPos < 0 && run.isValid() && -((int)run.getString().length()) < pPos)
        {
            WordXMLDocument* document = run.getDocument();
            enc::ucs::string_t str = run.getString();
            size_t separation = str.length() + pPos;
            enc::ucs::string_t before = str.substr(0, separation);
            enc::ucs::string_t after = str.substr(separation);
            WordXMLNode previousRun = run.cloneNode(true);
            // Scission du run
            WordXMLNode text1 = document->createTextNode(before.c_str());
            previousRun.replace(text1, previousRun.getNodes(UCS("w:t")).item(0));
            WordXMLNode text2 = document->createTextNode(after.c_str());
            run.replace(text2, run.getNodes(UCS("w:t")).item(0));
            if (revision.isValid())
            {
                // Scission de la révision
                revision.insertBefore(previousRun, run);
                divideRevisionNode(revision, run);
            }
            else
            {
                paragraph.insertBefore(previousRun, run);
            }
        }
    }

    // Move nodes to destination parent node
    void moveNodes(WordXMLNode& parent, WordXMLNode& node)
    {
        WordXMLNode tmpNode;
        while (node.isValid())
        {
            parent.append(node.cloneNode(true));
            tmpNode = node.getNextNode();
            node.erase();
            node = tmpNode;
        }
    }

    // Divide revision node in two parts
    WordXMLNode divideRevisionNode(const WordXMLNode& revision, WordXMLNode& firstNewNode)
    {
        WordXMLDocument* document  = revision.getDocument();
        WordXMLNode parent         = revision.getParent();
        WordXMLNode nextAnnotation = document->createNode(UCS("aml:content"));
        WordXMLNode nextRevision   = revision.cloneNode(false);
        nextRevision.append(nextAnnotation);
        parent.insertBefore(nextRevision, revision.getNextNode());
        moveNodes(nextAnnotation, firstNewNode);
        return nextRevision;
    }

    // Create revision node
    WordXMLNode createRevisionNode(WordXMLNode& parent, const WordXMLNode& refNode, const enc::ucs::char_t* type, WordXMLNode& content)
    {
        WordXMLDocument* document = parent.getDocument();
        WordXMLNode annotation    = document->createNode(WordXMLNode::REVISION_TAG);
        annotation.setAttribute(UCS("w:type"), type);
        parent.insertBefore(annotation, refNode);
        content = document->createNode(UCS("aml:content"));
        annotation.append(content);
        return annotation;
    }

    // Set paragraph revision property
    WordXMLNode setParagraphRevisionProperty(WordXMLNode& paragraph, const enc::ucs::char_t* type)
    {
        WordXMLDocument* document       = paragraph.getDocument();
        WordXMLNode paragraphProperties = document->createNode(UCS("w:pPr"));
        WordXMLNode runProperties       = document->createNode(UCS("w:rPr"));
        WordXMLNode paragraphAnnotation = document->createNode(WordXMLNode::REVISION_TAG);
        paragraphAnnotation.setAttribute(UCS("w:type"), type);
        runProperties.append(paragraphAnnotation);
        paragraphProperties.append(runProperties);
        paragraph.setPropertiesNode(paragraphProperties);
        return paragraphAnnotation;
    }

NAMESPACE_END


text:
#ifndef H_SHAREBUY_SHOP
#define H_SHAREBUY_SHOP

#include <string>
using std::string;
#include <memory>
#include <set>
using std::shared_ptr;
#include <boost/property_tree/ptree.hpp>
namespace bpt=boost::property_tree;
#include <boost/regex.hpp>

#include "BasketAddTemplate.hpp"

class Shop
{
public:
	explicit Shop(bpt::ptree &pt);
	const string name;
	const shared_ptr<const BasketAddTemplate> basketAdd;
	const boost::regex inputURLRegex;
	boost::format imageTemplate;
	const boost::regex pageRegex;
};

typedef shared_ptr<std::map<string, shared_ptr<Shop> > > ShopList;
ShopList loadShops(string shopConfigFolder);

class ShopLoaderException : public std::exception
{
public:
	explicit ShopLoaderException(string text);
	virtual const char* what() const noexcept;
private:
	string text;
};

#endif // H_SHAREBUY_SHOP

ext: hpp

max_stars_repo_name: hephaisto/sharebuy

max_issues_repo_name: hephaisto/sharebuy

max_forks_repo_name: hephaisto/sharebuy