<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * 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.
 *
 ************************************************************************/

#include <comphelper/namedvaluecollection.hxx>

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/beans/PropertyState.hpp>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/instance.hxx>
#include <osl/diagnose.h>

#include <boost/unordered_map.hpp>
#include <functional>
#include <algorithm>

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

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::uno::Type;
    using ::com::sun::star::uno::cpp_acquire;
    using ::com::sun::star::uno::cpp_release;
    using ::com::sun::star::uno::cpp_queryInterface;
    using ::com::sun::star::lang::IllegalArgumentException;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
    /** === end UNO using === **/

    //====================================================================
    //= NamedValueCollection_Impl
    //====================================================================
    typedef ::boost::unordered_map< ::rtl::OUString, Any, ::rtl::OUStringHash >    NamedValueRepository;

    struct NamedValueCollection_Impl
    {
        NamedValueRepository    aValues;
    };

    //====================================================================
    //= NamedValueCollection
    //====================================================================
    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection()
        :m_pImpl( new NamedValueCollection_Impl )
    {
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const NamedValueCollection& _rCopySource )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        *this = _rCopySource;
    }

    //--------------------------------------------------------------------
    NamedValueCollection& NamedValueCollection::operator=( const NamedValueCollection& i_rCopySource )
    {
        m_pImpl->aValues = i_rCopySource.m_pImpl->aValues;
        return *this;
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Any& _rElements )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rElements );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< NamedValue >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::~NamedValueCollection()
    {
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::canExtractFrom( ::com::sun::star::uno::Any const & i_value )
    {
        Type const & aValueType = i_value.getValueType();
        if  (   aValueType.equals( ::cppu::UnoType< PropertyValue >::get() )
            ||  aValueType.equals( ::cppu::UnoType< NamedValue >::get() )
            ||  aValueType.equals( ::cppu::UnoType< Sequence< PropertyValue > >::get() )
            ||  aValueType.equals( ::cppu::UnoType< Sequence< NamedValue > >::get() )
            )
            return true;
        return false;
    }

   //--------------------------------------------------------------------
    NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting )
    {
        for (   NamedValueRepository::const_iterator namedValue = _rAdditionalValues.m_pImpl->aValues.begin();
                namedValue != _rAdditionalValues.m_pImpl->aValues.end();
                ++namedValue
            )
        {
            if ( _bOverwriteExisting || !impl_has( namedValue->first ) )
                impl_put( namedValue->first, namedValue->second );
        }

        return *this;
    }

    //--------------------------------------------------------------------
    size_t NamedValueCollection::size() const
    {
        return m_pImpl->aValues.size();
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::empty() const
    {
        return m_pImpl->aValues.empty();
    }

    //--------------------------------------------------------------------
    ::std::vector< ::rtl::OUString > NamedValueCollection::getNames() const
    {
        ::std::vector< ::rtl::OUString > aNames;
        for ( NamedValueRepository::const_iterator it = m_pImpl->aValues.begin(), end = m_pImpl->aValues.end(); it != end; ++it )
        {
            aNames.push_back( it->first );
        }
        return aNames;
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Any& i_rWrappedElements )
    {
        Sequence< NamedValue > aNamedValues;
        Sequence< PropertyValue > aPropertyValues;
        NamedValue aNamedValue;
        PropertyValue aPropertyValue;

        if ( i_rWrappedElements >>= aNamedValues )
            impl_assign( aNamedValues );
        else if ( i_rWrappedElements >>= aPropertyValues )
            impl_assign( aPropertyValues );
        else if ( i_rWrappedElements >>= aNamedValue )
            impl_assign( Sequence< NamedValue >( &aNamedValue, 1 ) );
        else if ( i_rWrappedElements >>= aPropertyValue )
            impl_assign( Sequence< PropertyValue >( &aPropertyValue, 1 ) );
        else
            OSL_ENSURE( !i_rWrappedElements.hasValue(), "NamedValueCollection::impl_assign(Any): unsupported type!" );
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments )
    {
        {
            NamedValueRepository aEmpty;
            m_pImpl->aValues.swap( aEmpty );
        }

        PropertyValue aPropertyValue;
        NamedValue aNamedValue;

        const Any* pArgument = _rArguments.getConstArray();
        const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
        {
            if ( *pArgument >>= aPropertyValue )
                m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value;
            else if ( *pArgument >>= aNamedValue )
                m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value;
#if OSL_DEBUG_LEVEL > 0
            else if ( pArgument->hasValue() )
            {
                ::rtl::OStringBuffer message;
                message.append( "NamedValueCollection::impl_assign: encountered a value type which I cannot handle:\n" );
                message.append( ::rtl::OUStringToOString( pArgument->getValueTypeName(), RTL_TEXTENCODING_ASCII_US ) );
                OSL_FAIL( message.getStr() );
            }
#endif
        }
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments )
    {
        {
            NamedValueRepository aEmpty;
            m_pImpl->aValues.swap( aEmpty );
        }

        const PropertyValue* pArgument = _rArguments.getConstArray();
        const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
            m_pImpl->aValues[ pArgument->Name ] = pArgument->Value;
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments )
    {
        {
            NamedValueRepository aEmpty;
            m_pImpl->aValues.swap( aEmpty );
        }

        const NamedValue* pArgument = _rArguments.getConstArray();
        const NamedValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
            m_pImpl->aValues[ pArgument->Name ] = pArgument->Value;
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::get_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
        {
            if ( uno_type_assignData(
                    _pValueLocation, _rExpectedValueType.getTypeLibType(),
                    const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(),
                    reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
                    reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
                    reinterpret_cast< uno_ReleaseFunc >( cpp_release )
                ) )
                // argument exists, and could be extracted
                return true;

            // argument exists, but is of wrong type
            ::rtl::OUStringBuffer aBuffer;
            aBuffer.appendAscii( "Invalid value type for '" );
            aBuffer.append     ( _rValueName );
            aBuffer.appendAscii( "'.\nExpected: " );
            aBuffer.append     ( _rExpectedValueType.getTypeName() );
            aBuffer.appendAscii( "\nFound: " );
            aBuffer.append     ( pos->second.getValueType().getTypeName() );
            throw IllegalArgumentException( aBuffer.makeStringAndClear(), NULL, 0 );
        }

        // argument does not exist
        return false;
    }

    namespace
    {
        class theEmptyDefault : public rtl::Static<Any, theEmptyDefault> {};
    }

    //--------------------------------------------------------------------
    const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
            return pos->second;

        return theEmptyDefault::get();
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::impl_has( const ::rtl::OUString& _rValueName ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        return ( pos != m_pImpl->aValues.end() );
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::impl_put( const ::rtl::OUString& _rValueName, const Any& _rValue )
    {
        bool bHas = impl_has( _rValueName );
        m_pImpl->aValues[ _rValueName ] = _rValue;
        return bHas;
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::impl_remove( const ::rtl::OUString& _rValueName )
    {
        NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos == m_pImpl->aValues.end() )
            return false;
        m_pImpl->aValues.erase( pos );
        return true;
    }

    //--------------------------------------------------------------------
    namespace
    {
        struct Value2PropertyValue : public ::std::unary_function< NamedValueRepository::value_type, PropertyValue >
        {
            PropertyValue operator()( const NamedValueRepository::value_type& _rValue )
            {
                return PropertyValue(
                    _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE );
            }
        };

        struct Value2NamedValue : public ::std::unary_function< NamedValueRepository::value_type, NamedValue >
        {
            NamedValue operator()( const NamedValueRepository::value_type& _rValue )
            {
                return NamedValue( _rValue.first, _rValue.second );
            }
        };
    }

    //--------------------------------------------------------------------
    sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const
    {
        _out_rValues.realloc( m_pImpl->aValues.size() );
        ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2PropertyValue() );
        return _out_rValues.getLength();
    }

    //--------------------------------------------------------------------
    sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const
    {
        _out_rValues.realloc( m_pImpl->aValues.size() );
        ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2NamedValue() );
        return _out_rValues.getLength();
    }

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

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>comphelper: convert OSL_* to SAL_* in namedvaluecollection<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * 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.
 *
 ************************************************************************/

#include <comphelper/namedvaluecollection.hxx>

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/beans/PropertyState.hpp>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/instance.hxx>
#include <osl/diagnose.h>

#include <boost/unordered_map.hpp>
#include <functional>
#include <algorithm>

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

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::beans::PropertyValue;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::uno::Type;
    using ::com::sun::star::uno::cpp_acquire;
    using ::com::sun::star::uno::cpp_release;
    using ::com::sun::star::uno::cpp_queryInterface;
    using ::com::sun::star::lang::IllegalArgumentException;
    using ::com::sun::star::beans::NamedValue;
    using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
    /** === end UNO using === **/

    //====================================================================
    //= NamedValueCollection_Impl
    //====================================================================
    typedef ::boost::unordered_map< ::rtl::OUString, Any, ::rtl::OUStringHash >    NamedValueRepository;

    struct NamedValueCollection_Impl
    {
        NamedValueRepository    aValues;
    };

    //====================================================================
    //= NamedValueCollection
    //====================================================================
    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection()
        :m_pImpl( new NamedValueCollection_Impl )
    {
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const NamedValueCollection& _rCopySource )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        *this = _rCopySource;
    }

    //--------------------------------------------------------------------
    NamedValueCollection& NamedValueCollection::operator=( const NamedValueCollection& i_rCopySource )
    {
        m_pImpl->aValues = i_rCopySource.m_pImpl->aValues;
        return *this;
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Any& _rElements )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rElements );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::NamedValueCollection( const Sequence< NamedValue >& _rArguments )
        :m_pImpl( new NamedValueCollection_Impl )
    {
        impl_assign( _rArguments );
    }

    //--------------------------------------------------------------------
    NamedValueCollection::~NamedValueCollection()
    {
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::canExtractFrom( ::com::sun::star::uno::Any const & i_value )
    {
        Type const & aValueType = i_value.getValueType();
        if  (   aValueType.equals( ::cppu::UnoType< PropertyValue >::get() )
            ||  aValueType.equals( ::cppu::UnoType< NamedValue >::get() )
            ||  aValueType.equals( ::cppu::UnoType< Sequence< PropertyValue > >::get() )
            ||  aValueType.equals( ::cppu::UnoType< Sequence< NamedValue > >::get() )
            )
            return true;
        return false;
    }

   //--------------------------------------------------------------------
    NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting )
    {
        for (   NamedValueRepository::const_iterator namedValue = _rAdditionalValues.m_pImpl->aValues.begin();
                namedValue != _rAdditionalValues.m_pImpl->aValues.end();
                ++namedValue
            )
        {
            if ( _bOverwriteExisting || !impl_has( namedValue->first ) )
                impl_put( namedValue->first, namedValue->second );
        }

        return *this;
    }

    //--------------------------------------------------------------------
    size_t NamedValueCollection::size() const
    {
        return m_pImpl->aValues.size();
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::empty() const
    {
        return m_pImpl->aValues.empty();
    }

    //--------------------------------------------------------------------
    ::std::vector< ::rtl::OUString > NamedValueCollection::getNames() const
    {
        ::std::vector< ::rtl::OUString > aNames;
        for ( NamedValueRepository::const_iterator it = m_pImpl->aValues.begin(), end = m_pImpl->aValues.end(); it != end; ++it )
        {
            aNames.push_back( it->first );
        }
        return aNames;
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Any& i_rWrappedElements )
    {
        Sequence< NamedValue > aNamedValues;
        Sequence< PropertyValue > aPropertyValues;
        NamedValue aNamedValue;
        PropertyValue aPropertyValue;

        if ( i_rWrappedElements >>= aNamedValues )
            impl_assign( aNamedValues );
        else if ( i_rWrappedElements >>= aPropertyValues )
            impl_assign( aPropertyValues );
        else if ( i_rWrappedElements >>= aNamedValue )
            impl_assign( Sequence< NamedValue >( &aNamedValue, 1 ) );
        else if ( i_rWrappedElements >>= aPropertyValue )
            impl_assign( Sequence< PropertyValue >( &aPropertyValue, 1 ) );
        else
            SAL_WARN_IF( i_rWrappedElements.hasValue(), "comphelper", "NamedValueCollection::impl_assign(Any): unsupported type!" );
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments )
    {
        {
            NamedValueRepository aEmpty;
            m_pImpl->aValues.swap( aEmpty );
        }

        PropertyValue aPropertyValue;
        NamedValue aNamedValue;

        const Any* pArgument = _rArguments.getConstArray();
        const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
        {
            if ( *pArgument >>= aPropertyValue )
                m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value;
            else if ( *pArgument >>= aNamedValue )
                m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value;
#if OSL_DEBUG_LEVEL > 0
            else if ( pArgument->hasValue() )
            {
                ::rtl::OStringBuffer message;
                message.append( "NamedValueCollection::impl_assign: encountered a value type which I cannot handle:\n" );
                message.append( ::rtl::OUStringToOString( pArgument->getValueTypeName(), RTL_TEXTENCODING_ASCII_US ) );
                // Once this is rare, this could be turned into a warning.
                SAL_INFO( "comphelper", message.getStr() );
            }
#endif
        }
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments )
    {
        {
            NamedValueRepository aEmpty;
            m_pImpl->aValues.swap( aEmpty );
        }

        const PropertyValue* pArgument = _rArguments.getConstArray();
        const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
            m_pImpl->aValues[ pArgument->Name ] = pArgument->Value;
    }

    //--------------------------------------------------------------------
    void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments )
    {
        {
            NamedValueRepository aEmpty;
            m_pImpl->aValues.swap( aEmpty );
        }

        const NamedValue* pArgument = _rArguments.getConstArray();
        const NamedValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength();
        for ( ; pArgument != pArgumentEnd; ++pArgument )
            m_pImpl->aValues[ pArgument->Name ] = pArgument->Value;
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::get_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
        {
            if ( uno_type_assignData(
                    _pValueLocation, _rExpectedValueType.getTypeLibType(),
                    const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(),
                    reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
                    reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
                    reinterpret_cast< uno_ReleaseFunc >( cpp_release )
                ) )
                // argument exists, and could be extracted
                return true;

            // argument exists, but is of wrong type
            ::rtl::OUStringBuffer aBuffer;
            aBuffer.appendAscii( "Invalid value type for '" );
            aBuffer.append     ( _rValueName );
            aBuffer.appendAscii( "'.\nExpected: " );
            aBuffer.append     ( _rExpectedValueType.getTypeName() );
            aBuffer.appendAscii( "\nFound: " );
            aBuffer.append     ( pos->second.getValueType().getTypeName() );
            throw IllegalArgumentException( aBuffer.makeStringAndClear(), NULL, 0 );
        }

        // argument does not exist
        return false;
    }

    namespace
    {
        class theEmptyDefault : public rtl::Static<Any, theEmptyDefault> {};
    }

    //--------------------------------------------------------------------
    const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos != m_pImpl->aValues.end() )
            return pos->second;

        return theEmptyDefault::get();
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::impl_has( const ::rtl::OUString& _rValueName ) const
    {
        NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
        return ( pos != m_pImpl->aValues.end() );
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::impl_put( const ::rtl::OUString& _rValueName, const Any& _rValue )
    {
        bool bHas = impl_has( _rValueName );
        m_pImpl->aValues[ _rValueName ] = _rValue;
        return bHas;
    }

    //--------------------------------------------------------------------
    bool NamedValueCollection::impl_remove( const ::rtl::OUString& _rValueName )
    {
        NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName );
        if ( pos == m_pImpl->aValues.end() )
            return false;
        m_pImpl->aValues.erase( pos );
        return true;
    }

    //--------------------------------------------------------------------
    namespace
    {
        struct Value2PropertyValue : public ::std::unary_function< NamedValueRepository::value_type, PropertyValue >
        {
            PropertyValue operator()( const NamedValueRepository::value_type& _rValue )
            {
                return PropertyValue(
                    _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE );
            }
        };

        struct Value2NamedValue : public ::std::unary_function< NamedValueRepository::value_type, NamedValue >
        {
            NamedValue operator()( const NamedValueRepository::value_type& _rValue )
            {
                return NamedValue( _rValue.first, _rValue.second );
            }
        };
    }

    //--------------------------------------------------------------------
    sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const
    {
        _out_rValues.realloc( m_pImpl->aValues.size() );
        ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2PropertyValue() );
        return _out_rValues.getLength();
    }

    //--------------------------------------------------------------------
    sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const
    {
        _out_rValues.realloc( m_pImpl->aValues.size() );
        ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2NamedValue() );
        return _out_rValues.getLength();
    }

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

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// $Id$
/**
 * @file makeGlobalHistoConfigObject.C
 * @brief Creation of Global Histo component configuration objects in OCDB
 *
 *

 * Usage:
 *
 * aliroot -b -q $ALICE_ROOT/HLT/TPCLib/macros/makeTPCFastTransformOCDBObject.C'("uri", runmin, runmax)'
 *
 *

 *
 * Create an OCDB entry

 * Parameters:

 * - uri   (opt)    the OCDB URI, default $ALICE_ROOT/OCDB
 * - runmin (opt)   default 0
 * - runmax (opt)   default 999999999

 * @author sergey gorbunov
 * @ingroup alihlt_tutorial
 */

/*
aliroot -b -q $ALICE_ROOT/HLT/TPCLib/macros/makeTPCFastTransformOCDBObject.C'("local:///cvmfs/alice.gsi.de/alice/data/2010/OCDB/", 127941)'
//130704 )'

aliroot -q -b "$ALICE_ROOT/HLT/global/physics/macros/testconfigCalib.C"'("GLOBAL-flat-esd-converter","WriteAnalysisToFile=0 TPCcalibConfigString=TPCCalib:CalibTimeDrift EnableDebug=1 -pushback-period=1000")' $ALICE_ROOT/HLT/exa/recraw-local.C'("/hera/alice/local/filtered/alice/data/2010/LHC10e/000130704/raw/merged_highpt_12.root","local:///cvmfs/alice.gsi.de/alice/data/2010/OCDB/",'1', '1', "HLT", "chains=TPC-compression ignore

 */

void makeTPCFastTransformOCDBObject( const Char_t* cdbUri=NULL,
				     Int_t runMin=0, Int_t runMax=AliCDBRunRange::Infinity()) {

  // --------------------------------------
  // -- Setup CDB
  // --------------------------------------

  AliCDBManager* man = AliCDBManager::Instance();
  if (!man) {
    cerr << "Error : Can not get AliCDBManager" << end;
    exit;
  }

  TString storage;
  if (!man->IsDefaultStorageSet()) {
    if ( cdbUri ) {
      storage = cdbUri;
      if ( storage.Contains("://") == 0 ) {
	storage = "local://";
	storage += cdbUri;
      }
    }
    else {
      storage="local://$ALICE_ROOT/OCDB";
    }
    man->SetDefaultStorage(storage);
  }
  else {
    storage = man->GetDefaultStorage()->GetURI();
  }

  man->SetRun( runMin );
  AliGRPManager grp;
  grp.ReadGRPEntry();
  grp.SetMagField();

  const AliGRPObject *grpObj = grp.GetGRPData();

  if( !grpObj ){
    Error("No GRP object found!!");
  }

  if(!AliGeomManager::GetGeometry()){
    AliGeomManager::LoadGeometry();
  }

  AliTPCcalibDB *calib=AliTPCcalibDB::Instance();
  if(!calib){
    Error("AliTPCcalibDB does not exist");
    return -ENOENT;
  }

  Double_t bz = AliTracker::GetBz();

  cout<<"\n\nBz field is set to "<<bz<<", time stamp is set to "<<grpObj->GetTimeEnd()<<endl<<endl;

  calib->SetExBField(bz);
  calib->SetRun( runMin );
  calib->UpdateRunInformations( runMin );

  AliHLTTPCClusterTransformation hltTransform;

  TStopwatch timer;
  timer.Start();
  //int err = hltTransform.Init( GetBz(), GetTimeStamp() );
  int err = hltTransform.Init( bz, grpObj->GetTimeEnd() );
  timer.Stop();
  cout<<"\n\n Initialisation: "<<timer.CpuTime()<<" / "<<timer.RealTime()<<" sec.\n\n"<<endl;
  if( err!=0 ){
    cerr << Form("Cannot retrieve offline transform from AliTPCcalibDB, AliHLTTPCClusterTransformation returns %d",err).Data()<<endl;
    return -1;
  }

  TString path("HLT/ConfigTPC/TPCFastTransform");

  // --------------------------------------
  // -- Create Config Object
  // --------------------------------------

  // here is the actual content of the configuration object

  const AliHLTTPCFastTransform &fastTransform = hltTransform.GetFastTransform();

  AliHLTTPCFastTransformObject configObj;

  Int_t err = fastTransform.WriteToObject( configObj );

  if( err ){
    Error("Can not create transformation object, error code %d",err);
  }

  // --------------------------------------
  // -- Fill Object
  // --------------------------------------

  AliCDBPath cdbPath(path);
  AliCDBId   cdbId(cdbPath, runMin, runMax);
  AliCDBMetaData cdbMetaData;

  printf("Adding %s type OCDB object to %s [%d,%d] in %s \n",
	 configObj.ClassName(),
	 path.Data(),
	 runMin, runMax, storage.Data());

  if(1){ // for test proposes only
    storage="local://$ALICE_ROOT/OCDB";
    man->SetDefaultStorage(storage);
  }

  man->Put( (TObject*)&configObj, cdbId, &cdbMetaData);

}

<commit_msg>Fix usage of correct magnetic field for initialization of ExB map for fast transform object<commit_after>// $Id$
/**
 * @file makeGlobalHistoConfigObject.C
 * @brief Creation of Global Histo component configuration objects in OCDB
 *
 *

 * Usage:
 *
 * aliroot -b -q $ALICE_ROOT/HLT/TPCLib/macros/makeTPCFastTransformOCDBObject.C'("uri", runmin, runmax)'
 *
 *

 *
 * Create an OCDB entry

 * Parameters:

 * - uri   (opt)    the OCDB URI, default $ALICE_ROOT/OCDB
 * - runmin (opt)   default 0
 * - runmax (opt)   default 999999999

 * @author sergey gorbunov
 * @ingroup alihlt_tutorial
 */

/*
aliroot -b -q $ALICE_ROOT/HLT/TPCLib/macros/makeTPCFastTransformOCDBObject.C'("local:///cvmfs/alice.gsi.de/alice/data/2010/OCDB/", 127941)'
//130704 )'

aliroot -q -b "$ALICE_ROOT/HLT/global/physics/macros/testconfigCalib.C"'("GLOBAL-flat-esd-converter","WriteAnalysisToFile=0 TPCcalibConfigString=TPCCalib:CalibTimeDrift EnableDebug=1 -pushback-period=1000")' $ALICE_ROOT/HLT/exa/recraw-local.C'("/hera/alice/local/filtered/alice/data/2010/LHC10e/000130704/raw/merged_highpt_12.root","local:///cvmfs/alice.gsi.de/alice/data/2010/OCDB/",'1', '1', "HLT", "chains=TPC-compression ignore

 */

void makeTPCFastTransformOCDBObject( const Char_t* cdbUri=NULL,
				     Int_t runMin=0, Int_t runMax=AliCDBRunRange::Infinity()) {

  // --------------------------------------
  // -- Setup CDB
  // --------------------------------------

  AliCDBManager* man = AliCDBManager::Instance();
  if (!man) {
    cerr << "Error : Can not get AliCDBManager" << end;
    exit;
  }

  TString storage;
  if (!man->IsDefaultStorageSet()) {
    if ( cdbUri ) {
      storage = cdbUri;
      if ( storage.Contains("://") == 0 ) {
	storage = "local://";
	storage += cdbUri;
      }
    }
    else {
      storage="local://$ALICE_ROOT/OCDB";
    }
    man->SetDefaultStorage(storage);
  }
  else {
    storage = man->GetDefaultStorage()->GetURI();
  }

  man->SetRun( runMin );
  AliGRPManager grp;
  grp.ReadGRPEntry();
  grp.SetMagField();

  const AliGRPObject *grpObj = grp.GetGRPData();

  if( !grpObj ){
    Error("No GRP object found!!");
  }

  if(!AliGeomManager::GetGeometry()){
    AliGeomManager::LoadGeometry();
  }

  AliTPCcalibDB *calib=AliTPCcalibDB::Instance();
  if(!calib){
    Error("AliTPCcalibDB does not exist");
    return -ENOENT;
  }

  Double_t bz = AliTracker::GetBz();

  cout<<"\n\nBz field is set to "<<bz<<", time stamp is set to "<<grpObj->GetTimeEnd()<<endl<<endl;

  const AliMagF * field = (AliMagF*) TGeoGlobalMagField::Instance()->GetField();
  calib->SetExBField(field);
  calib->SetRun( runMin );
  calib->UpdateRunInformations( runMin );

  AliHLTTPCClusterTransformation hltTransform;

  TStopwatch timer;
  timer.Start();
  //int err = hltTransform.Init( GetBz(), GetTimeStamp() );
  int err = hltTransform.Init( bz, grpObj->GetTimeEnd() );
  timer.Stop();
  cout<<"\n\n Initialisation: "<<timer.CpuTime()<<" / "<<timer.RealTime()<<" sec.\n\n"<<endl;
  if( err!=0 ){
    cerr << Form("Cannot retrieve offline transform from AliTPCcalibDB, AliHLTTPCClusterTransformation returns %d",err).Data()<<endl;
    return -1;
  }

  TString path("HLT/ConfigTPC/TPCFastTransform");

  // --------------------------------------
  // -- Create Config Object
  // --------------------------------------

  // here is the actual content of the configuration object

  const AliHLTTPCFastTransform &fastTransform = hltTransform.GetFastTransform();

  AliHLTTPCFastTransformObject configObj;

  Int_t err = fastTransform.WriteToObject( configObj );

  if( err ){
    Error("Can not create transformation object, error code %d",err);
  }

  // --------------------------------------
  // -- Fill Object
  // --------------------------------------

  AliCDBPath cdbPath(path);
  AliCDBId   cdbId(cdbPath, runMin, runMax);
  AliCDBMetaData cdbMetaData;

  printf("Adding %s type OCDB object to %s [%d,%d] in %s \n",
	 configObj.ClassName(),
	 path.Data(),
	 runMin, runMax, storage.Data());

  if(1){ // for test proposes only
    storage="local://$ALICE_ROOT/OCDB";
    man->SetDefaultStorage(storage);
  }

  man->Put( (TObject*)&configObj, cdbId, &cdbMetaData);

}

<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingConnection>

#include "TelepathyQt4/_gen/pending-connection.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/ConnectionManager>
#include <TelepathyQt4/Connection>

#include <QDBusObjectPath>
#include <QDBusPendingCallWatcher>
#include <QDBusPendingReply>

/**
 * \addtogroup clientsideproxies Client-side proxies
 *
 * Proxy objects representing remote service objects accessed via D-Bus.
 *
 * In addition to providing direct access to methods, signals and properties
 * exported by the remote objects, some of these proxies offer features like
 * automatic inspection of remote object capabilities, property tracking,
 * backwards compatibility helpers for older services and other utilities.
 */

namespace Tp
{

struct TELEPATHY_QT4_NO_EXPORT PendingConnection::Private
{
    Private(const ConnectionManagerPtr &manager) :
        manager(manager)
    {
    }

    WeakPtr<ConnectionManager> manager;
    ConnectionPtr connection;
    QString busName;
    QDBusObjectPath objectPath;
};

/**
 * \class PendingConnection
 * \ingroup clientconnection
 * \headerfile <TelepathyQt4/pending-connection.h> <TelepathyQt4/PendingConnection>
 *
 * Class containing the parameters of and the reply to an asynchronous connection
 * request. Instances of this class cannot be constructed directly; the only
 * way to get one is via ConnectionManager.
 */

/**
 * Construct a PendingConnection object.
 *
 * \param manager ConnectionManager to use.
 * \param protocol Name of the protocol to create the connection for.
 * \param parameters Connection parameters.
 */
PendingConnection::PendingConnection(const ConnectionManagerPtr &manager,
        const QString &protocol, const QVariantMap &parameters)
    : PendingOperation(manager.data()),
      mPriv(new Private(manager))
{
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
            manager->baseInterface()->RequestConnection(protocol,
                parameters), this);
    connect(watcher,
            SIGNAL(finished(QDBusPendingCallWatcher *)),
            SLOT(onCallFinished(QDBusPendingCallWatcher *)));
}

/**
 * Class destructor.
 */
PendingConnection::~PendingConnection()
{
    delete mPriv;
}

/**
 * Return the ConnectionManager object through which the request was made.
 *
 * \return Connection Manager object.
 */
ConnectionManagerPtr PendingConnection::manager() const
{
    return ConnectionManagerPtr(mPriv->manager);
}

/**
 * Returns the newly created Connection object.
 *
 * \return Connection object.
 */
ConnectionPtr PendingConnection::connection() const
{
    if (!isFinished()) {
        warning() << "PendingConnection::connection called before finished, returning 0";
        return ConnectionPtr();
    } else if (!isValid()) {
        warning() << "PendingConnection::connection called when not valid, returning 0";
        return ConnectionPtr();
    }

    if (!mPriv->connection) {
        ConnectionManagerPtr manager(mPriv->manager);
        mPriv->connection = Connection::create(manager->dbusConnection(),
                mPriv->busName, mPriv->objectPath.path());
    }

    return mPriv->connection;
}

/**
 * Returns the connection's bus name ("service name"), or an empty string on
 * error.
 *
 * This method is useful for creating custom Connection objects: instead
 * of using PendingConnection::connection, one could construct a new custom
 * connection from the bus name and object path.
 *
 * \return Connection bus name
 * \sa objectPath()
 */
QString PendingConnection::busName() const
{
    if (!isFinished()) {
        warning() << "PendingConnection::busName called before finished";
    } else if (!isValid()) {
        warning() << "PendingConnection::busName called when not valid";
    }

    return mPriv->busName;
}

/**
 * Returns the connection's object path or an empty string on error.
 *
 * This method is useful for creating custom Connection objects: instead
 * of using PendingConnection::connection, one could construct a new custom
 * connection with the bus name and object path.
 *
 * \return Connection object path
 * \sa busName()
 */
QString PendingConnection::objectPath() const
{
    if (!isFinished()) {
        warning() << "PendingConnection::connection called before finished";
    } else if (!isValid()) {
        warning() << "PendingConnection::connection called when not valid";
    }

    return mPriv->objectPath.path();
}

void PendingConnection::onCallFinished(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QString, QDBusObjectPath> reply = *watcher;

    if (!reply.isError()) {
        mPriv->busName = reply.argumentAt<0>();
        mPriv->objectPath = reply.argumentAt<1>();
        debug() << "Got reply to ConnectionManager.CreateConnection - bus name:" <<
            mPriv->busName << "- object path:" << mPriv->objectPath.path();
        setFinished();
    } else {
        debug().nospace() <<
            "CreateConnection failed: " <<
            reply.error().name() << ": " << reply.error().message();
        setFinishedWithError(reply.error());
    }

    watcher->deleteLater();
}

} // Tp
<commit_msg>pending-connection: Improve documentation (bugfixes+additions)<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/PendingConnection>

#include "TelepathyQt4/_gen/pending-connection.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/ConnectionManager>
#include <TelepathyQt4/Connection>

#include <QDBusObjectPath>
#include <QDBusPendingCallWatcher>
#include <QDBusPendingReply>

namespace Tp
{

struct TELEPATHY_QT4_NO_EXPORT PendingConnection::Private
{
    Private(const ConnectionManagerPtr &manager) :
        manager(manager)
    {
    }

    WeakPtr<ConnectionManager> manager;
    ConnectionPtr connection;
    QString busName;
    QDBusObjectPath objectPath;
};

/**
 * \class PendingConnection
 * \ingroup clientconn
 * \headerfile TelepathyQt4/pending-connection.h <TelepathyQt4/PendingConnection>
 *
 * \brief Class containing the parameters of and the reply to an asynchronous
 * connection request. Instances of this class cannot be constructed directly;
 * the only way to get one is via ConnectionManager.
 */

/**
 * Construct a PendingConnection object.
 *
 * \param manager ConnectionManager to use.
 * \param protocol Name of the protocol to create the connection for.
 * \param parameters Connection parameters.
 */
PendingConnection::PendingConnection(const ConnectionManagerPtr &manager,
        const QString &protocol, const QVariantMap &parameters)
    : PendingOperation(manager.data()),
      mPriv(new Private(manager))
{
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
            manager->baseInterface()->RequestConnection(protocol,
                parameters), this);
    connect(watcher,
            SIGNAL(finished(QDBusPendingCallWatcher *)),
            SLOT(onCallFinished(QDBusPendingCallWatcher *)));
}

/**
 * Class destructor.
 */
PendingConnection::~PendingConnection()
{
    delete mPriv;
}

/**
 * Return the ConnectionManager object through which the request was made.
 *
 * \return Connection Manager object.
 */
ConnectionManagerPtr PendingConnection::manager() const
{
    return ConnectionManagerPtr(mPriv->manager);
}

/**
 * Returns the newly created Connection object.
 *
 * \return Connection object.
 */
ConnectionPtr PendingConnection::connection() const
{
    if (!isFinished()) {
        warning() << "PendingConnection::connection called before finished, returning 0";
        return ConnectionPtr();
    } else if (!isValid()) {
        warning() << "PendingConnection::connection called when not valid, returning 0";
        return ConnectionPtr();
    }

    if (!mPriv->connection) {
        ConnectionManagerPtr manager(mPriv->manager);
        mPriv->connection = Connection::create(manager->dbusConnection(),
                mPriv->busName, mPriv->objectPath.path());
    }

    return mPriv->connection;
}

/**
 * Returns the connection's bus name ("service name"), or an empty string on
 * error.
 *
 * This method is useful for creating custom Connection objects: instead
 * of using PendingConnection::connection, one could construct a new custom
 * connection from the bus name and object path.
 *
 * \return Connection bus name
 * \sa objectPath()
 */
QString PendingConnection::busName() const
{
    if (!isFinished()) {
        warning() << "PendingConnection::busName called before finished";
    } else if (!isValid()) {
        warning() << "PendingConnection::busName called when not valid";
    }

    return mPriv->busName;
}

/**
 * Returns the connection's object path or an empty string on error.
 *
 * This method is useful for creating custom Connection objects: instead
 * of using PendingConnection::connection, one could construct a new custom
 * connection with the bus name and object path.
 *
 * \return Connection object path
 * \sa busName()
 */
QString PendingConnection::objectPath() const
{
    if (!isFinished()) {
        warning() << "PendingConnection::connection called before finished";
    } else if (!isValid()) {
        warning() << "PendingConnection::connection called when not valid";
    }

    return mPriv->objectPath.path();
}

void PendingConnection::onCallFinished(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QString, QDBusObjectPath> reply = *watcher;

    if (!reply.isError()) {
        mPriv->busName = reply.argumentAt<0>();
        mPriv->objectPath = reply.argumentAt<1>();
        debug() << "Got reply to ConnectionManager.CreateConnection - bus name:" <<
            mPriv->busName << "- object path:" << mPriv->objectPath.path();
        setFinished();
    } else {
        debug().nospace() <<
            "CreateConnection failed: " <<
            reply.error().name() << ": " << reply.error().message();
        setFinishedWithError(reply.error());
    }

    watcher->deleteLater();
}

} // Tp
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include <gtest/gtest.h>

#include "OgreBitwise.h"
#include "OgreStringConverter.h"

using namespace Ogre;

//--------------------------------------------------------------------------
TEST(BitwiseTests,FixedPointConversion)
{
    EXPECT_EQ(Bitwise::fixedToFixed(0x0,  1,8), (unsigned int)0x00);
    EXPECT_EQ(Bitwise::fixedToFixed(0x1,  1,8), (unsigned int)0xFF);
    EXPECT_EQ(Bitwise::fixedToFixed(0x2,  2,8), (unsigned int)0xAA);     // 10101010
    EXPECT_EQ(Bitwise::fixedToFixed(0x1,  2,8), (unsigned int)0x55);     // 01010101
    EXPECT_EQ(Bitwise::fixedToFixed(0x2,  2,9), (unsigned int)0x155);    // 1 01010101
    EXPECT_EQ(Bitwise::fixedToFixed(0x1,  2,9), (unsigned int)0x0AA);    // 0 10101010
    EXPECT_EQ(Bitwise::fixedToFixed(0xFE, 8,3), (unsigned int)0x7);      // 111
    EXPECT_EQ(Bitwise::fixedToFixed(0xFE, 8,9), (unsigned int)0x1FD);    // 111111101

    EXPECT_EQ(Bitwise::fixedToFloat(0xFF, 8), 1.0f);
    EXPECT_EQ(Bitwise::fixedToFloat(0x00, 8), 0.0f);

    EXPECT_EQ(Bitwise::floatToFixed(1.0f, 8), (unsigned int)0xFF);
    EXPECT_EQ(Bitwise::floatToFixed(0.0f, 8), (unsigned int)0x00);

    // Test clamping
    EXPECT_EQ(Bitwise::floatToFixed(-1.0f,8), (unsigned int)0x00);
    EXPECT_EQ(Bitwise::floatToFixed(2.0f, 8), (unsigned int)0xFF);

    // Test circular conversion
    bool failed = false;
    for(unsigned int x = 0; x < 0x0010; x++)
        if(Bitwise::floatToFixed(Bitwise::fixedToFloat(x, 4), 4) != x)
            failed = true;
    EXPECT_TRUE(!failed) << "circular floatToFixed/fixedToFloat for 4 bit failed";

    failed = false;
    for(unsigned int x = 0; x < 0x0100; x++)
        if(Bitwise::floatToFixed(Bitwise::fixedToFloat(x, 8), 8) != x)
            failed = true;
    EXPECT_TRUE(!failed) << "circular floatToFixed/fixedToFloat for 8 bit failed";

    failed = false;
    for(unsigned int x = 0; x < 0xFFE; x++) // originally loop ran till 0x1000, but precision issues sometimes prevent that
        if(Bitwise::floatToFixed(Bitwise::fixedToFloat(x, 12), 12) != x)
            failed = true;
    EXPECT_TRUE(!failed) << "circular floatToFixed/fixedToFloat for 12 bit failed";
}
//--------------------------------------------------------------------------
TEST(BitwiseTests,IntReadWrite)
{
    // Test reading and writing integers
    uint32 testje = 0x12345678;
    EXPECT_TRUE(Bitwise::intRead(&testje, 4) == 0x12345678);
    uint16 testje2 = 0x1234;
    EXPECT_TRUE(Bitwise::intRead(&testje2, 2) == 0x1234);
    uint8 testje3 = 0xD3;
    EXPECT_TRUE(Bitwise::intRead(&testje3, 1) == 0xD3);
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
    uint8 testje4[] = {0x12, 0x34, 0x56};
#else
    uint8 testje4[] = {0x56, 0x34, 0x12};
#endif
    EXPECT_TRUE(Bitwise::intRead(&testje4, 3) == 0x123456);

    Bitwise::intWrite(&testje, 4, 0x87654321);
    EXPECT_TRUE(testje == 0x87654321);

    Bitwise::intWrite(&testje2, 2, 0x4321);
    EXPECT_TRUE(testje2 == 0x4321);

    Bitwise::intWrite(&testje3, 1, 0x12);
    EXPECT_TRUE(testje3 == 0x12);
}
//--------------------------------------------------------------------------
TEST(BitwiseTests,Half)
{
    /*
    for(int x=0; x<0x100; x++)
    {
        float f = (float)x/255.0f;
        uint32 fi = *reinterpret_cast<uint32*>(&f);
        uint16 g = Bitwise::floatToHalf(f);
        float h = Bitwise::halfToFloat(g);
        uint32 hi = *reinterpret_cast<uint32*>(&h);
        int i = h*256.0f;
        std::cerr << x << " " << fi << " " << std::hex << std::setw(4) << g << " " << hi << " " << i << std::endl;
    }
    */
}
//--------------------------------------------------------------------------
<commit_msg>Tests: implement BitwiseTests.Half<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include <gtest/gtest.h>

#include "OgreBitwise.h"
#include "OgreStringConverter.h"

using namespace Ogre;

//--------------------------------------------------------------------------
TEST(BitwiseTests,FixedPointConversion)
{
    EXPECT_EQ(Bitwise::fixedToFixed(0x0,  1,8), (unsigned int)0x00);
    EXPECT_EQ(Bitwise::fixedToFixed(0x1,  1,8), (unsigned int)0xFF);
    EXPECT_EQ(Bitwise::fixedToFixed(0x2,  2,8), (unsigned int)0xAA);     // 10101010
    EXPECT_EQ(Bitwise::fixedToFixed(0x1,  2,8), (unsigned int)0x55);     // 01010101
    EXPECT_EQ(Bitwise::fixedToFixed(0x2,  2,9), (unsigned int)0x155);    // 1 01010101
    EXPECT_EQ(Bitwise::fixedToFixed(0x1,  2,9), (unsigned int)0x0AA);    // 0 10101010
    EXPECT_EQ(Bitwise::fixedToFixed(0xFE, 8,3), (unsigned int)0x7);      // 111
    EXPECT_EQ(Bitwise::fixedToFixed(0xFE, 8,9), (unsigned int)0x1FD);    // 111111101

    EXPECT_EQ(Bitwise::fixedToFloat(0xFF, 8), 1.0f);
    EXPECT_EQ(Bitwise::fixedToFloat(0x00, 8), 0.0f);

    EXPECT_EQ(Bitwise::floatToFixed(1.0f, 8), (unsigned int)0xFF);
    EXPECT_EQ(Bitwise::floatToFixed(0.0f, 8), (unsigned int)0x00);

    // Test clamping
    EXPECT_EQ(Bitwise::floatToFixed(-1.0f,8), (unsigned int)0x00);
    EXPECT_EQ(Bitwise::floatToFixed(2.0f, 8), (unsigned int)0xFF);

    // Test circular conversion
    bool failed = false;
    for(unsigned int x = 0; x < 0x0010; x++)
        if(Bitwise::floatToFixed(Bitwise::fixedToFloat(x, 4), 4) != x)
            failed = true;
    EXPECT_TRUE(!failed) << "circular floatToFixed/fixedToFloat for 4 bit failed";

    failed = false;
    for(unsigned int x = 0; x < 0x0100; x++)
        if(Bitwise::floatToFixed(Bitwise::fixedToFloat(x, 8), 8) != x)
            failed = true;
    EXPECT_TRUE(!failed) << "circular floatToFixed/fixedToFloat for 8 bit failed";

    failed = false;
    for(unsigned int x = 0; x < 0xFFE; x++) // originally loop ran till 0x1000, but precision issues sometimes prevent that
        if(Bitwise::floatToFixed(Bitwise::fixedToFloat(x, 12), 12) != x)
            failed = true;
    EXPECT_TRUE(!failed) << "circular floatToFixed/fixedToFloat for 12 bit failed";
}
//--------------------------------------------------------------------------
TEST(BitwiseTests,IntReadWrite)
{
    // Test reading and writing integers
    uint32 testje = 0x12345678;
    EXPECT_TRUE(Bitwise::intRead(&testje, 4) == 0x12345678);
    uint16 testje2 = 0x1234;
    EXPECT_TRUE(Bitwise::intRead(&testje2, 2) == 0x1234);
    uint8 testje3 = 0xD3;
    EXPECT_TRUE(Bitwise::intRead(&testje3, 1) == 0xD3);
#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
    uint8 testje4[] = {0x12, 0x34, 0x56};
#else
    uint8 testje4[] = {0x56, 0x34, 0x12};
#endif
    EXPECT_TRUE(Bitwise::intRead(&testje4, 3) == 0x123456);

    Bitwise::intWrite(&testje, 4, 0x87654321);
    EXPECT_TRUE(testje == 0x87654321);

    Bitwise::intWrite(&testje2, 2, 0x4321);
    EXPECT_TRUE(testje2 == 0x4321);

    Bitwise::intWrite(&testje3, 1, 0x12);
    EXPECT_TRUE(testje3 == 0x12);
}
//--------------------------------------------------------------------------
TEST(BitwiseTests,Half)
{
    for(float f : {1.f, -1.f, INFINITY, 65504.f})
    {
        uint16 g = Bitwise::floatToHalf(f);
        float h = Bitwise::halfToFloat(g);
        EXPECT_EQ(f, h);
    }
}
//--------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "utility.hpp"

namespace ox {

template<typename T>
class UniquePtr {

	private:
		T *m_t;

	public:
		explicit constexpr UniquePtr(T *t = nullptr) noexcept: m_t(t) {
		}

		constexpr UniquePtr(const UniquePtr&) = delete;

		template<typename U>
		constexpr UniquePtr(UniquePtr<U> &&other) noexcept {
			m_t = other.release();
		}

		~UniquePtr() {
			delete m_t;
		}

		constexpr T *release() noexcept {
			auto t = m_t;
			m_t = nullptr;
			return t;
		}

		[[nodiscard]]
		constexpr T *get() const noexcept {
			return m_t;
		}

		constexpr void reset(UniquePtr &&other = UniquePtr()) {
			auto t = m_t;
			m_t = other.m_t;
			other.m_t = nullptr;
			delete t;
		}

		constexpr UniquePtr &operator=(UniquePtr &&other) {
			reset(ox::move(other));
			return *this;
		}

		constexpr T *operator->() const noexcept {
			return m_t;
		}

		constexpr T &operator*() const noexcept {
			return *m_t;
		}

		constexpr operator bool() const noexcept {
			return m_t;
		}

};

template<typename T>
constexpr bool operator==(const UniquePtr<T> p1, const UniquePtr<T> p2) noexcept {
	return p1.get() == p2.get();
}

template<typename T>
constexpr bool operator==(const UniquePtr<T> p1, std::nullptr_t) noexcept {
	return p1.get();
}

template<typename T>
constexpr bool operator==(std::nullptr_t, const UniquePtr<T> p2) noexcept {
	return p2.get();
}

template<typename T>
constexpr bool operator!=(const UniquePtr<T> p1, const UniquePtr<T> p2) noexcept {
	return p1.get() != p2.get();
}

template<typename T>
constexpr bool operator!=(const UniquePtr<T> p1, std::nullptr_t) noexcept {
	return !p1.get();
}

template<typename T>
constexpr bool operator!=(std::nullptr_t, const UniquePtr<T> p2) noexcept {
	return !p2.get();
}

template<typename T, typename ...Args>
[[nodiscard]]
constexpr auto make_unique(Args&&... args) noexcept {
	return UniquePtr(new T(args...));
}

}
<commit_msg>[ox/std] Make make_unique not noexcept<commit_after>/*
 * Copyright 2015 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "utility.hpp"

namespace ox {

template<typename T>
class UniquePtr {

	private:
		T *m_t;

	public:
		explicit constexpr UniquePtr(T *t = nullptr) noexcept: m_t(t) {
		}

		constexpr UniquePtr(const UniquePtr&) = delete;

		template<typename U>
		constexpr UniquePtr(UniquePtr<U> &&other) noexcept {
			m_t = other.release();
		}

		~UniquePtr() {
			delete m_t;
		}

		constexpr T *release() noexcept {
			auto t = m_t;
			m_t = nullptr;
			return t;
		}

		[[nodiscard]]
		constexpr T *get() const noexcept {
			return m_t;
		}

		constexpr void reset(UniquePtr &&other = UniquePtr()) {
			auto t = m_t;
			m_t = other.m_t;
			other.m_t = nullptr;
			delete t;
		}

		constexpr UniquePtr &operator=(UniquePtr &&other) {
			reset(ox::move(other));
			return *this;
		}

		constexpr T *operator->() const noexcept {
			return m_t;
		}

		constexpr T &operator*() const noexcept {
			return *m_t;
		}

		constexpr operator bool() const noexcept {
			return m_t;
		}

};

template<typename T>
constexpr bool operator==(const UniquePtr<T> p1, const UniquePtr<T> p2) noexcept {
	return p1.get() == p2.get();
}

template<typename T>
constexpr bool operator==(const UniquePtr<T> p1, std::nullptr_t) noexcept {
	return p1.get();
}

template<typename T>
constexpr bool operator==(std::nullptr_t, const UniquePtr<T> p2) noexcept {
	return p2.get();
}

template<typename T>
constexpr bool operator!=(const UniquePtr<T> p1, const UniquePtr<T> p2) noexcept {
	return p1.get() != p2.get();
}

template<typename T>
constexpr bool operator!=(const UniquePtr<T> p1, std::nullptr_t) noexcept {
	return !p1.get();
}

template<typename T>
constexpr bool operator!=(std::nullptr_t, const UniquePtr<T> p2) noexcept {
	return !p2.get();
}

template<typename T, typename ...Args>
[[nodiscard]]
constexpr auto make_unique(Args&&... args) {
	return UniquePtr(new T(args...));
}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "math.hpp"
#include "types.hpp"
#include "typetraits.hpp"

template<typename T1, typename T2>
constexpr char *ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
	for (std::size_t i = 0; i < maxLen && src[i]; i++) {
		dest[i] = src[i];
	}
	return dest;
}

[[nodiscard]] constexpr int ox_strnlen(const char *str1, int maxLen) noexcept {
	int len = 0;
	for (; len < maxLen && str1[len]; len++);
	return len;
}

template<typename T>
[[nodiscard]] constexpr int ox_strlen(T str1) noexcept {
	int len = 0;
	for (; str1[len]; len++);
	return len;
}

template<typename T1, typename T2>
[[nodiscard]] constexpr int ox_strcmp(T1 str1, T2 str2) noexcept {
	auto retval = 0;
	auto i = 0;
	while (str1[i] || str2[i]) {
		if (str1[i] < str2[i]) {
			retval = -1;
			break;
		} else if (str1[i] > str2[i]) {
			retval = 1;
			break;
		}
		i++;
	}
	return retval;
}

[[nodiscard]] constexpr int ox_strncmp(const char *str1, const char *str2, std::size_t len) noexcept {
	auto retval = 0;
	std::size_t i = 0;
	while (i < len && (str1[i] || str2[i])) {
		if (str1[i] < str2[i]) {
			retval = -1;
			break;
		} else if (str1[i] > str2[i]) {
			retval = 1;
			break;
		}
		i++;
	}
	return retval;
}

[[nodiscard]] constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
	for (std::size_t i = 0; i <= maxLen; i++) {
		if (str[i] == character) {
			return &str[i];
		} else if (str[i] == 0) {
			return nullptr;
		}
	}
	return nullptr;
}

[[nodiscard]] constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
	for (std::size_t i = 0; i < maxLen; i++) {
		if (str[i] == character) {
			return &str[i];
		} else if (str[i] == 0) {
			return nullptr;
		}
	}
	return nullptr;
}

[[nodiscard]] constexpr int ox_lastIndexOf(const char *str, int character, int maxLen = 0xFFFFFFFF) noexcept {
	int retval = -1;
	for (int i = 0; i < maxLen && str[i]; i++) {
		if (str[i] == character) {
			retval = i;
		}
	}
	return retval;
}

[[nodiscard]] constexpr int ox_lastIndexOf(char *str, int character, int maxLen = 0xFFFFFFFF) noexcept {
	int retval = -1;
	for (int i = 0; i < maxLen && str[i]; i++) {
		if (str[i] == character) {
			retval = i;
		}
	}
	return retval;
}

[[nodiscard]] constexpr int ox_atoi(const char *str) noexcept {
	int total = 0;
	int multiplier = 1;

	for (auto i = ox_strlen(str) - 1; i != -1; i--) {
		total += (str[i] - '0') * multiplier;
		multiplier *= 10;
	}

	return total;
}

template<typename T>
constexpr T ox_itoa(int64_t v, T str) noexcept {
	if (v) {
		auto mod = 1000000000000000000;
		constexpr auto base = 10;
		auto it = 0;
		if (v < 0) {
			str[it] = '-';
			it++;
		}
		while (mod) {
			auto digit = v / mod;
			v %= mod;
			mod /= base;
			if (it or digit) {
				int start = '0';
				if (digit >= 10) {
					start = 'a';
					digit -= 10;
				}
				str[it] = start + digit;
				it++;
			}
		}
		str[it] = 0;
	} else {
		// 0 is a special case
		str[0] = '0';
		str[1] = 0;
	}
	return str;
}
<commit_msg>[ox/std] Make ox_strlen return std::size<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "math.hpp"
#include "types.hpp"
#include "typetraits.hpp"

template<typename T1, typename T2>
constexpr char *ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
	for (std::size_t i = 0; i < maxLen && src[i]; i++) {
		dest[i] = src[i];
	}
	return dest;
}

[[nodiscard]] constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
	std::size_t len = 0;
	for (; len < maxLen && str1[len]; len++);
	return len;
}

template<typename T>
[[nodiscard]] constexpr auto ox_strlen(T str1) noexcept {
	std::size_t len = 0;
	for (; str1[len]; len++);
	return len;
}

template<typename T1, typename T2>
[[nodiscard]] constexpr int ox_strcmp(T1 str1, T2 str2) noexcept {
	auto retval = 0;
	auto i = 0;
	while (str1[i] || str2[i]) {
		if (str1[i] < str2[i]) {
			retval = -1;
			break;
		} else if (str1[i] > str2[i]) {
			retval = 1;
			break;
		}
		i++;
	}
	return retval;
}

[[nodiscard]] constexpr int ox_strncmp(const char *str1, const char *str2, std::size_t len) noexcept {
	auto retval = 0;
	std::size_t i = 0;
	while (i < len && (str1[i] || str2[i])) {
		if (str1[i] < str2[i]) {
			retval = -1;
			break;
		} else if (str1[i] > str2[i]) {
			retval = 1;
			break;
		}
		i++;
	}
	return retval;
}

[[nodiscard]] constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
	for (std::size_t i = 0; i <= maxLen; i++) {
		if (str[i] == character) {
			return &str[i];
		} else if (str[i] == 0) {
			return nullptr;
		}
	}
	return nullptr;
}

[[nodiscard]] constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
	for (std::size_t i = 0; i < maxLen; i++) {
		if (str[i] == character) {
			return &str[i];
		} else if (str[i] == 0) {
			return nullptr;
		}
	}
	return nullptr;
}

[[nodiscard]] constexpr int ox_lastIndexOf(const char *str, int character, int maxLen = 0xFFFFFFFF) noexcept {
	int retval = -1;
	for (int i = 0; i < maxLen && str[i]; i++) {
		if (str[i] == character) {
			retval = i;
		}
	}
	return retval;
}

[[nodiscard]] constexpr int ox_lastIndexOf(char *str, int character, int maxLen = 0xFFFFFFFF) noexcept {
	int retval = -1;
	for (int i = 0; i < maxLen && str[i]; i++) {
		if (str[i] == character) {
			retval = i;
		}
	}
	return retval;
}

[[nodiscard]] constexpr int ox_atoi(const char *str) noexcept {
	int total = 0;
	int multiplier = 1;

	for (auto i = static_cast<int64_t>(ox_strlen(str)) - 1; i != -1; i--) {
		total += (str[i] - '0') * multiplier;
		multiplier *= 10;
	}

	return total;
}

template<typename T>
constexpr T ox_itoa(int64_t v, T str) noexcept {
	if (v) {
		auto mod = 1000000000000000000;
		constexpr auto base = 10;
		auto it = 0;
		if (v < 0) {
			str[it] = '-';
			it++;
		}
		while (mod) {
			auto digit = v / mod;
			v %= mod;
			mod /= base;
			if (it or digit) {
				int start = '0';
				if (digit >= 10) {
					start = 'a';
					digit -= 10;
				}
				str[it] = start + digit;
				it++;
			}
		}
		str[it] = 0;
	} else {
		// 0 is a special case
		str[0] = '0';
		str[1] = 0;
	}
	return str;
}
<|endoftext|>


<commit_before>#include <iostream>

#include <basedefs.h>
#include <pluginmanager.h>
//#include <core_api_cpp.h>
//#include <core_frontend.h>
#include <networkmanager_frontend.h>
#include <networkmanager_api_cpp.h>
#include <unistd.h> // for Sleep
#include <string.h>

static pthread_mutex_t g_stateMutex;
static anp::uint32 g_state = 0;

void irc_onPrivMsg(void *network,
					const anp::int8 *sender,
					const anp::int8 *receiver,
					const anp::int8 *message)
{
	std::cout << "main.cpp: Received a PRIVMSG!" << std::endl;

	if ( 0 == strcmp(message, "die") )
	{
		// Write state
		pthread_mutex_lock(&g_stateMutex);
		g_state = 1; // QUIT
		pthread_mutex_unlock(&g_stateMutex);
	}
}

int main(int argc, char *argv[])
{
	using namespace anp;
	using namespace anp::firc;

	const int8 *pluginNames[] = {
		"./libpluginTest1.so"
	};

	pthread_mutex_init(&g_stateMutex, NULL);

//	ICoreFrontend *core = core_create(
//									sizeof(pluginNames)/sizeof(int8 *),
//									pluginNames);

//	std::cout << "Successfully created the firc core object!"
//		<< std::endl;

	PluginManager pluginManager;

	INetworkManagerFrontend *chatJunkies =
		networkmanager_create("irc.chatjunkies.org", "6667",
												&pluginManager);

	anp::uint32 state = 0;
	//core->addCallbackOnPrivMsg(irc_onPrivMsg);

	sleep(9);
	chatJunkies->sendMessage("JOIN #my-secret-botdev\r\n");
	chatJunkies->sendMessage("PRIVMSG #my-secret-botdev :Hello world!");
	sleep(20);

	// When the quit command has been received, state will equal 1.
	while ( 0 == state )
	{
		// Read state
		pthread_mutex_lock(&g_stateMutex);
		state = g_state;
		pthread_mutex_unlock(&g_stateMutex);
		sleep(1); // Just to conserve CPU..
	}

	// Quit
	//chatJunkies->setQuitMessage("Time to go! See you ChatJunkies!");
	networkmanager_destroy(chatJunkies);
	std::cout << "main.cpp: Successfully disconnected."	<< std::endl;

	pthread_mutex_destroy(&g_stateMutex);

	return 0;
}
<commit_msg>Made frontend load plugins.<commit_after>#include <iostream>

#include <basedefs.h>
#include <pluginmanager.h>
//#include <core_api_cpp.h>
//#include <core_frontend.h>
#include <networkmanager_frontend.h>
#include <networkmanager_api_cpp.h>
#include <unistd.h> // for Sleep
#include <string.h>

static pthread_mutex_t g_stateMutex;
static anp::uint32 g_state = 0;

void irc_onPrivMsg(void *network,
					const anp::int8 *sender,
					const anp::int8 *receiver,
					const anp::int8 *message)
{
	std::cout << "main.cpp: Received a PRIVMSG!" << std::endl;

	if ( 0 == strcmp(message, "die") )
	{
		// Write state
		pthread_mutex_lock(&g_stateMutex);
		g_state = 1; // QUIT
		pthread_mutex_unlock(&g_stateMutex);
	}
}

int main(int argc, char *argv[])
{
	using namespace anp;
	using namespace anp::firc;

	const int8 *pluginNames[] = {
		"./libpluginTest1.so"
	};

	pthread_mutex_init(&g_stateMutex, NULL);

//	ICoreFrontend *core = core_create(
//									sizeof(pluginNames)/sizeof(int8 *),
//									pluginNames);

//	std::cout << "Successfully created the firc core object!"
//		<< std::endl;

	PluginManager pluginManager;

	for ( uint32 i=0; i<sizeof(pluginNames)/sizeof(pluginNames[0]) )
	{
		pluginManager.loadPlugin(pluginNames[i]);
	}

	INetworkManagerFrontend *chatJunkies =
		networkmanager_create("irc.chatjunkies.org", "6667",
												&pluginManager);

	anp::uint32 state = 0;
	//core->addCallbackOnPrivMsg(irc_onPrivMsg);

	sleep(9);
	chatJunkies->sendMessage("JOIN #my-secret-botdev\r\n");
	chatJunkies->sendMessage("PRIVMSG #my-secret-botdev :Hello world!");
	sleep(20);

	// When the quit command has been received, state will equal 1.
	while ( 0 == state )
	{
		// Read state
		pthread_mutex_lock(&g_stateMutex);
		state = g_state;
		pthread_mutex_unlock(&g_stateMutex);
		sleep(1); // Just to conserve CPU..
	}

	// Quit
	//chatJunkies->setQuitMessage("Time to go! See you ChatJunkies!");
	networkmanager_destroy(chatJunkies);
	std::cout << "main.cpp: Successfully disconnected."	<< std::endl;

	pthread_mutex_destroy(&g_stateMutex);

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

int main()
{
	int *a,n,i,j,temp;
	cin>>n;
	a = new int[n];
	for(i=0;i<n;i++)
		cin>>a[i];

	for(i=0;i<n-1;i++)
	{
		for(j=0;j<n-i-1;j++)
		{
			if(a[j]>a[j+1])
			{
				temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
	}

	cout<<"Sorted array\n";
	for(i=0;i<n;i++)
		cout<<a[i]<<" ";
	cout<<endl;
}<commit_msg>Clarity + Documentation<commit_after>#include <iostream>
using namespace std;

int main()
{

	//i and j are used to iterate through the bubble sort
	int *arrayToSort,arraySize,i,j,temp;

	//Read in the desired aray size
	cin>>arraySize;

	//Define the size of the array to 'arrayToSort' and allow the user to populate said array.
	arrayToSort = new int[arraySize];
	for(i=0;i<arraySize;i++)
		cin>>arrayToSort[i];

	//Contains two loops || Note that in both average and worst-case scenarios, results in a big O notation of O(N^2)
	for(i=0;i<arraySize-1;i++)
	{
		for(j=0;j<arraySize-i-1;j++)
		{
			//Compares the values of all elements, swapping the lower figures for higher ones
			if(arrayToSort[j]>arrayToSort[j+1])
			{
				temp = arrayToSort[j];
				arrayToSort[j] = arrayToSort[j+1];
				arrayToSort[j+1] = temp;
			}
		}
	}

	cout<<"Sorted array\n";
	for(i=0;i<arraySize;i++)
		cout<<arrayToSort[i]<<" ";
	cout<<endl;
}
<|endoftext|>


<commit_before>
#include "../Header/mcs.h"
#include <set>

// TODO: The following optimization can be made via a note in the paper
// The procedure MCS can be implemented to run in O(|V | + |E|) time. To
// see that, notice that the first loop executes |V | iterations. In the
// second loop, for each vertex of G, all its neighbors are visited. After
// a vertex is evaluated, it is removed from the remaining graph. Therefore,
// the weight λ is increased exactly |E| times. By keeping vertices in an
// array of buckets indexed by λ, the vertex of highest weight can be found
// in O(1) time.

//Maximum Cardinal Search
map<string,int> GraphColoring::Mcs::color() {

	map<string,vector<string> > temp_graph = graph;
	map< string,int> weight;
	queue<string> ordering;

	// Initially set the weight of each node to 0
	for(map< string, vector<string> >::iterator i = temp_graph.begin(); i != temp_graph.end(); i++)
	{
		weight[(*i).first] = 0;
	}

	// Work through all the ndoes in the graph, choosing the node
	// with maximum weight, then add that node to the queue. Increase
	// the weight of the queued nodes neighbors by 1. Continue until
	// every node in the graph has been added to the queue
	for(int i = 0; i < graph.size(); i++)
	{
		int max_weight = -1;
		string max_vertex = "";

		// Out of the remaining nodes, find the node with the highest weight
		for(map< string, vector<string> >:: iterator j = temp_graph.begin(); j != temp_graph.end(); j++)
		{
			if(weight[(*j).first] > max_weight)
			{
				max_weight = weight[(*j).first];
				max_vertex = (*j).first;
			}
		}
		if(max_vertex == "")
		{
			cerr << "Error: Could not find a max weight node in the graph (reason unknown)" << endl;
			coloring.clear();
			return coloring;
		}

		// Add highest weight node to the queue and increment all of its
		// neighbors weights by 1
		ordering.push(max_vertex);
		for(unsigned j = 0; j<graph[max_vertex].size(); j++)
		{
			weight[temp_graph[max_vertex][j]] += 1;
		}

		// Remove the maximum weight node from the graph so that it won't
		// be accidentally added again
		temp_graph.erase(max_vertex);
	}

	// Work through the queue in order and color each node
	while(!ordering.empty())
	{
		int color = 0;

		// Find the lowest possible coloring for this node between
		// its neighbors
		string min = ordering.front();

		//Thanks to Michael Kochte @ Universitaet Stuttgart for the below speedup snippit

		//Collect color numbers of neighbors
		std::set<int> colorset;
		for(unsigned i = 0; i < graph[min].size(); i++) {
			int col = coloring[graph[min][i]];
			colorset.insert(col);
		}

		//Sort and uniquify
		vector<int> colorvec;
		std::copy(colorset.begin(), colorset.end(), std::back_inserter(colorvec));
		std::sort(colorvec.begin(), colorvec.end());

		//Pick the lowest color not contained
		int newcolor = 0;
		for(unsigned i = 0; i < colorvec.size(); i++) {
			if(colorvec[i] == newcolor) {
				newcolor++;
			}
		}
		color = newcolor;

		coloring[min] = color;
		ordering.pop();
	}
	return coloring;
}
<commit_msg>fixed sort mcs issue with travis<commit_after>#include "../Header/mcs.h"
#include <algorithm>
#include <set>

// TODO: The following optimization can be made via a note in the paper
// The procedure MCS can be implemented to run in O(|V | + |E|) time. To
// see that, notice that the first loop executes |V | iterations. In the
// second loop, for each vertex of G, all its neighbors are visited. After
// a vertex is evaluated, it is removed from the remaining graph. Therefore,
// the weight λ is increased exactly |E| times. By keeping vertices in an
// array of buckets indexed by λ, the vertex of highest weight can be found
// in O(1) time.

//Maximum Cardinal Search
map<string,int> GraphColoring::Mcs::color() {

	map<string,vector<string> > temp_graph = graph;
	map< string,int> weight;
	queue<string> ordering;

	// Initially set the weight of each node to 0
	for(map< string, vector<string> >::iterator i = temp_graph.begin(); i != temp_graph.end(); i++)
	{
		weight[(*i).first] = 0;
	}

	// Work through all the ndoes in the graph, choosing the node
	// with maximum weight, then add that node to the queue. Increase
	// the weight of the queued nodes neighbors by 1. Continue until
	// every node in the graph has been added to the queue
	for(int i = 0; i < graph.size(); i++)
	{
		int max_weight = -1;
		string max_vertex = "";

		// Out of the remaining nodes, find the node with the highest weight
		for(map< string, vector<string> >:: iterator j = temp_graph.begin(); j != temp_graph.end(); j++)
		{
			if(weight[(*j).first] > max_weight)
			{
				max_weight = weight[(*j).first];
				max_vertex = (*j).first;
			}
		}
		if(max_vertex == "")
		{
			cerr << "Error: Could not find a max weight node in the graph (reason unknown)" << endl;
			coloring.clear();
			return coloring;
		}

		// Add highest weight node to the queue and increment all of its
		// neighbors weights by 1
		ordering.push(max_vertex);
		for(unsigned j = 0; j<graph[max_vertex].size(); j++)
		{
			weight[temp_graph[max_vertex][j]] += 1;
		}

		// Remove the maximum weight node from the graph so that it won't
		// be accidentally added again
		temp_graph.erase(max_vertex);
	}

	// Work through the queue in order and color each node
	while(!ordering.empty())
	{
		int color = 0;

		// Find the lowest possible coloring for this node between
		// its neighbors
		string min = ordering.front();

		//Thanks to Michael Kochte @ Universitaet Stuttgart for the below speedup snippit

		//Collect color numbers of neighbors
		std::set<int> colorset;
		for(unsigned i = 0; i < graph[min].size(); i++) {
			int col = coloring[graph[min][i]];
			colorset.insert(col);
		}

		//Sort and uniquify
		vector<int> colorvec;
		std::copy(colorset.begin(), colorset.end(), std::back_inserter(colorvec));
		std::sort(colorvec.begin(), colorvec.end());

		//Pick the lowest color not contained
		int newcolor = 0;
		for(unsigned i = 0; i < colorvec.size(); i++) {
			if(colorvec[i] == newcolor) {
				newcolor++;
			}
		}
		color = newcolor;

		coloring[min] = color;
		ordering.pop();
	}
	return coloring;
}
<|endoftext|>


<commit_before>// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/web_resource/web_resource_service.h"

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/google/core/browser/google_util.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"

// No anonymous namespace, because const variables automatically get internal
// linkage.
const char kInvalidDataTypeError[] =
    "Data from web resource server is missing or not valid JSON.";

const char kUnexpectedJSONFormatError[] =
    "Data from web resource server does not have expected format.";

namespace web_resource {

WebResourceService::WebResourceService(
    PrefService* prefs,
    const GURL& web_resource_server,
    const std::string& application_locale,
    const char* last_update_time_pref_name,
    int start_fetch_delay_ms,
    int cache_update_delay_ms,
    net::URLRequestContextGetter* request_context,
    const char* disable_network_switch)
    : prefs_(prefs),
      resource_request_allowed_notifier_(prefs, disable_network_switch),
      in_fetch_(false),
      web_resource_server_(web_resource_server),
      application_locale_(application_locale),
      last_update_time_pref_name_(last_update_time_pref_name),
      start_fetch_delay_ms_(start_fetch_delay_ms),
      cache_update_delay_ms_(cache_update_delay_ms),
      request_context_(request_context),
      weak_ptr_factory_(this) {
  resource_request_allowed_notifier_.Init(this);
  DCHECK(prefs);
}

void WebResourceService::StartAfterDelay() {
  // If resource requests are not allowed, we'll get a callback when they are.
  if (resource_request_allowed_notifier_.ResourceRequestsAllowed())
    OnResourceRequestsAllowed();
}

WebResourceService::~WebResourceService() {
}

void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) {
  // Delete the URLFetcher when this function exits.
  scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release());

  if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
    std::string data;
    source->GetResponseAsString(&data);
    // Calls EndFetch() on completion.
    ParseJSON(data, base::Bind(&WebResourceService::OnUnpackFinished,
                               weak_ptr_factory_.GetWeakPtr()),
              base::Bind(&WebResourceService::OnUnpackError,
                         weak_ptr_factory_.GetWeakPtr()));
  } else {
    // Don't parse data if attempt to download was unsuccessful.
    // Stop loading new web resource data, and silently exit.
    // We do not call ParseJSON(), so we need to call EndFetch() ourselves.
    EndFetch();
  }
}

// Delay initial load of resource data into cache so as not to interfere
// with startup time.
void WebResourceService::ScheduleFetch(int64 delay_ms) {
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE, base::Bind(&WebResourceService::StartFetch,
                            weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromMilliseconds(delay_ms));
}

// Initializes the fetching of data from the resource server.  Data
// load calls OnURLFetchComplete.
void WebResourceService::StartFetch() {
  // First, put our next cache load on the MessageLoop.
  ScheduleFetch(cache_update_delay_ms_);

  // Set cache update time in preferences.
  prefs_->SetString(last_update_time_pref_name_,
                    base::DoubleToString(base::Time::Now().ToDoubleT()));

  // If we are still fetching data, exit.
  if (in_fetch_)
    return;
  in_fetch_ = true;

  GURL web_resource_server =
      application_locale_.empty()
          ? google_util::AppendGoogleLocaleParam(web_resource_server_,
                                                 application_locale_)
          : web_resource_server_;

  DVLOG(1) << "WebResourceService StartFetch " << web_resource_server;
  url_fetcher_.reset(
      net::URLFetcher::Create(web_resource_server, net::URLFetcher::GET, this));
  // Do not let url fetcher affect existing state in system context
  // (by setting cookies, for example).
  url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
                             net::LOAD_DO_NOT_SEND_COOKIES |
                             net::LOAD_DO_NOT_SAVE_COOKIES);
  url_fetcher_->SetRequestContext(request_context_.get());
  url_fetcher_->Start();
}

void WebResourceService::EndFetch() {
  in_fetch_ = false;
}

void WebResourceService::OnUnpackFinished(scoped_ptr<base::Value> value) {
  if (!value) {
    // Page information not properly read, or corrupted.
    OnUnpackError(kInvalidDataTypeError);
    return;
  }
  const base::DictionaryValue* dict = nullptr;
  if (!value->GetAsDictionary(&dict)) {
    OnUnpackError(kUnexpectedJSONFormatError);
    return;
  }
  Unpack(*dict);

  EndFetch();
}

void WebResourceService::OnUnpackError(const std::string& error_message) {
  LOG(ERROR) << error_message;
  EndFetch();
}

void WebResourceService::OnResourceRequestsAllowed() {
  int64 delay = start_fetch_delay_ms_;
  // Check whether we have ever put a value in the web resource cache;
  // if so, pull it out and see if it's time to update again.
  if (prefs_->HasPrefPath(last_update_time_pref_name_)) {
    std::string last_update_pref =
        prefs_->GetString(last_update_time_pref_name_);
    if (!last_update_pref.empty()) {
      double last_update_value;
      base::StringToDouble(last_update_pref, &last_update_value);
      int64 ms_until_update =
          cache_update_delay_ms_ -
          static_cast<int64>(
              (base::Time::Now() - base::Time::FromDoubleT(last_update_value))
                  .InMilliseconds());
      // Wait at least |start_fetch_delay_ms_|.
      if (ms_until_update > start_fetch_delay_ms_)
        delay = ms_until_update;
    }
  }
  // Start fetch and wait for UpdateResourceCache.
  ScheduleFetch(delay);
}

}  // namespace web_resource
<commit_msg>Add missing locale parameter to promo service.<commit_after>// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/web_resource/web_resource_service.h"

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/google/core/browser/google_util.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"

// No anonymous namespace, because const variables automatically get internal
// linkage.
const char kInvalidDataTypeError[] =
    "Data from web resource server is missing or not valid JSON.";

const char kUnexpectedJSONFormatError[] =
    "Data from web resource server does not have expected format.";

namespace web_resource {

WebResourceService::WebResourceService(
    PrefService* prefs,
    const GURL& web_resource_server,
    const std::string& application_locale,
    const char* last_update_time_pref_name,
    int start_fetch_delay_ms,
    int cache_update_delay_ms,
    net::URLRequestContextGetter* request_context,
    const char* disable_network_switch)
    : prefs_(prefs),
      resource_request_allowed_notifier_(prefs, disable_network_switch),
      in_fetch_(false),
      web_resource_server_(web_resource_server),
      application_locale_(application_locale),
      last_update_time_pref_name_(last_update_time_pref_name),
      start_fetch_delay_ms_(start_fetch_delay_ms),
      cache_update_delay_ms_(cache_update_delay_ms),
      request_context_(request_context),
      weak_ptr_factory_(this) {
  resource_request_allowed_notifier_.Init(this);
  DCHECK(prefs);
}

void WebResourceService::StartAfterDelay() {
  // If resource requests are not allowed, we'll get a callback when they are.
  if (resource_request_allowed_notifier_.ResourceRequestsAllowed())
    OnResourceRequestsAllowed();
}

WebResourceService::~WebResourceService() {
}

void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) {
  // Delete the URLFetcher when this function exits.
  scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release());

  if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
    std::string data;
    source->GetResponseAsString(&data);
    // Calls EndFetch() on completion.
    ParseJSON(data, base::Bind(&WebResourceService::OnUnpackFinished,
                               weak_ptr_factory_.GetWeakPtr()),
              base::Bind(&WebResourceService::OnUnpackError,
                         weak_ptr_factory_.GetWeakPtr()));
  } else {
    // Don't parse data if attempt to download was unsuccessful.
    // Stop loading new web resource data, and silently exit.
    // We do not call ParseJSON(), so we need to call EndFetch() ourselves.
    EndFetch();
  }
}

// Delay initial load of resource data into cache so as not to interfere
// with startup time.
void WebResourceService::ScheduleFetch(int64 delay_ms) {
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE, base::Bind(&WebResourceService::StartFetch,
                            weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromMilliseconds(delay_ms));
}

// Initializes the fetching of data from the resource server.  Data
// load calls OnURLFetchComplete.
void WebResourceService::StartFetch() {
  // First, put our next cache load on the MessageLoop.
  ScheduleFetch(cache_update_delay_ms_);

  // Set cache update time in preferences.
  prefs_->SetString(last_update_time_pref_name_,
                    base::DoubleToString(base::Time::Now().ToDoubleT()));

  // If we are still fetching data, exit.
  if (in_fetch_)
    return;
  in_fetch_ = true;

  GURL web_resource_server =
      application_locale_.empty()
          ? web_resource_server_
          : google_util::AppendGoogleLocaleParam(web_resource_server_,
                                                 application_locale_);

  DVLOG(1) << "WebResourceService StartFetch " << web_resource_server;
  url_fetcher_.reset(
      net::URLFetcher::Create(web_resource_server, net::URLFetcher::GET, this));
  // Do not let url fetcher affect existing state in system context
  // (by setting cookies, for example).
  url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
                             net::LOAD_DO_NOT_SEND_COOKIES |
                             net::LOAD_DO_NOT_SAVE_COOKIES);
  url_fetcher_->SetRequestContext(request_context_.get());
  url_fetcher_->Start();
}

void WebResourceService::EndFetch() {
  in_fetch_ = false;
}

void WebResourceService::OnUnpackFinished(scoped_ptr<base::Value> value) {
  if (!value) {
    // Page information not properly read, or corrupted.
    OnUnpackError(kInvalidDataTypeError);
    return;
  }
  const base::DictionaryValue* dict = nullptr;
  if (!value->GetAsDictionary(&dict)) {
    OnUnpackError(kUnexpectedJSONFormatError);
    return;
  }
  Unpack(*dict);

  EndFetch();
}

void WebResourceService::OnUnpackError(const std::string& error_message) {
  LOG(ERROR) << error_message;
  EndFetch();
}

void WebResourceService::OnResourceRequestsAllowed() {
  int64 delay = start_fetch_delay_ms_;
  // Check whether we have ever put a value in the web resource cache;
  // if so, pull it out and see if it's time to update again.
  if (prefs_->HasPrefPath(last_update_time_pref_name_)) {
    std::string last_update_pref =
        prefs_->GetString(last_update_time_pref_name_);
    if (!last_update_pref.empty()) {
      double last_update_value;
      base::StringToDouble(last_update_pref, &last_update_value);
      int64 ms_until_update =
          cache_update_delay_ms_ -
          static_cast<int64>(
              (base::Time::Now() - base::Time::FromDoubleT(last_update_value))
                  .InMilliseconds());
      // Wait at least |start_fetch_delay_ms_|.
      if (ms_until_update > start_fetch_delay_ms_)
        delay = ms_until_update;
    }
  }
  // Start fetch and wait for UpdateResourceCache.
  ScheduleFetch(delay);
}

}  // namespace web_resource
<|endoftext|>