<commit_before>/*************************************************************************
 *
 *  $RCSfile: splash.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-25 13:52:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "splash.hxx"

#ifndef _UTL_BOOTSTRAP_HXX
#include <unotools/bootstrap.hxx>
#endif
#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _URLOBJ_HXX
#include <tools/urlobj.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _SFX_HRC
#include <sfx2/sfx.hrc>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star::registry;

namespace desktop
{

SplashScreen::SplashScreen(const Reference< XMultiServiceFactory >& rSMgr)
        :
        IntroWindow()
    , _iProgress(0)
    , _iMax(100)
    , _bPaintBitmap(sal_True)
    , _bPaintProgress(sal_False)
    , _xoffset(12)
    , _yoffset(16)
    , _barheight(6)
    , _barspace(2)
{
    _rFactory = rSMgr;

    initBitmap();
    Size aSize = _aIntroBmp.GetSizePixel();
    SetOutputSizePixel( aSize );
    _height = aSize.Height();
    _width = aSize.Width();
    _tlx = _xoffset;              // top-left x
    _tly = _height - _yoffset; // top-left y
    _barwidth  = _width - (2*_yoffset);
    Application::AddEventListener(
        LINK( this, SplashScreen, AppEventListenerHdl ) );
}

SplashScreen::~SplashScreen()
{
    Application::RemoveEventListener(
        LINK( this, SplashScreen, AppEventListenerHdl ) );
    Hide();
}

void SAL_CALL SplashScreen::start(const OUString& aText, sal_Int32 nRange)
    throw (RuntimeException)
{
    _iMax = nRange;
    if (_bVisible) {
        ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
        Show();
        Paint(Rectangle());
    }
}
void SAL_CALL SplashScreen::end()
    throw (RuntimeException)
{
    _iProgress = _iMax;
    updateStatus();
    if (_bVisible) Hide();
}
void SAL_CALL SplashScreen::reset()
    throw (RuntimeException)
{
    _iProgress = 0;
    updateStatus();
}

void SAL_CALL SplashScreen::setText(const OUString& aText)
    throw (RuntimeException)
{
}

void SAL_CALL SplashScreen::setValue(sal_Int32 nValue)
    throw (RuntimeException)
{
    ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );

    if (nValue >= _iMax) _iProgress = _iMax;
    else _iProgress = nValue;
    updateStatus();
}

// XInitialize
void SAL_CALL
SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
    throw (RuntimeException)
{
    ::osl::ClearableMutexGuard  aGuard( _aMutex );
    if (aArguments.getLength() > 0)
        aArguments[0] >>= _bVisible;
}

void SplashScreen::updateStatus()
{
    if (!_bVisible) return;
    if (!_bPaintProgress) _bPaintProgress = sal_True;
    _bPaintBitmap=sal_False;
    Paint(Rectangle());
    _bPaintBitmap=sal_True;
}

// internal private methods
IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent )
{
    if ( inEvent != 0 )
    {
        switch ( inEvent->GetId() )
        {
            case VCLEVENT_WINDOW_HIDE:
                Paint( Rectangle() );
                break;
            default:
                break;
        }
    }
    return 0;
}

void SplashScreen::initBitmap()
{
    String aBmpFileName;
    OUString aIniPath;
    OUString aLogo( RTL_CONSTASCII_USTRINGPARAM( "1" ) );
    aLogo = ::utl::Bootstrap::getLogoData( aLogo );
    sal_Bool bLogo = (sal_Bool)aLogo.toInt32();
    if ( bLogo )
    {
        xub_StrLen nIndex = 0;
        aBmpFileName += String( DEFINE_CONST_UNICODE("intro.bmp") );
        // retrieve our current installation path
        OUString aExecutePath;
        ::vos::OStartupInfo().getExecutableFile( aExecutePath );
        sal_uInt32  lastIndex = aExecutePath.lastIndexOf('/');
        if ( lastIndex > 0 )
            aExecutePath = aExecutePath.copy( 0, lastIndex+1 );
        INetURLObject aObj( aExecutePath, INET_PROT_FILE );
        aObj.insertName( aBmpFileName );
        SvFileStream aStrm( aObj.PathToFileName(), STREAM_STD_READ );
        if ( !aStrm.GetError() )
        {
            // Default case, we load the intro bitmap from a seperate file
            // (e.g. staroffice_intro.bmp or starsuite_intro.bmp)
            aStrm >> _aIntroBmp;
        }
        else
        {
            // Save case:
            // Create resource manager for intro bitmap. Due to our problem that we don't have
            // any language specific information, we have to search for the correct resource
            // file. The bitmap resource is language independent.
            const USHORT nResId = RID_DEFAULTINTRO;
            LanguageType aLanguageType;
            String       aMgrName = String::CreateFromAscii( "iso" );
            aMgrName += String::CreateFromInt32(SUPD); // current build version
            ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLanguageType );
            ResId aIntroBmpRes( nResId, pLabelResMgr );
            _aIntroBmp = Bitmap( aIntroBmpRes );
            delete pLabelResMgr;
        }
    }
}

void SplashScreen::Paint( const Rectangle& )
{
    if(!_bVisible) return;
    // draw bitmap
    if (_bPaintBitmap)
        DrawBitmap( Point(), _aIntroBmp );

    if (_bPaintProgress) {
        // draw progress...
        long length = (_iProgress * _barwidth / _iMax) - (2 * _barspace);
        if (length < 0) length = 0;
        const Color cBlue(COL_BLUE);
        const Color cGray(COL_LIGHTGRAY);

        // border
        SetFillColor();
        SetLineColor(cGray);
        DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth,
            _tly+_barheight));

        // progress bar
        SetFillColor(cBlue);
        SetLineColor();
        DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace,
            _tlx+_barspace+length, _tly+_barheight-_barspace));
    }
    Flush();
}

// get service instance...
SplashScreen *SplashScreen::_pINSTANCE = NULL;
osl::Mutex SplashScreen::_aMutex;

Reference< XInterface > SplashScreen::getInstance(const Reference< XMultiServiceFactory >& rSMgr)
{
    if ( _pINSTANCE == 0 )
    {
        osl::MutexGuard guard(_aMutex);
        if (_pINSTANCE == 0)
            return (XComponent*)new SplashScreen(rSMgr);
    }

    return (XComponent*)0;
}

// static service info...
const sal_Char *SplashScreen::serviceName = "com.sun.star.office.SplashScreen";
const sal_Char *SplashScreen::implementationName = "com.sun.star.office.comp.SplashScreen";
const sal_Char *SplashScreen::supportedServiceNames[] = {"com.sun.star.office.SplashScreen", NULL};
OUString SplashScreen::impl_getImplementationName()
{
    return OUString::createFromAscii(implementationName);
}
Sequence<OUString> SplashScreen::impl_getSupportedServiceNames()
{
    Sequence<OUString> aSequence;
    for (int i=0; supportedServiceNames[i]!=NULL; i++) {
        aSequence.realloc(i+1);
        aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i]));
    }
    return aSequence;
}

}

// component management stuff...
// ----------------------------------------------------------------------------
extern "C"
{
using namespace desktop;

void SAL_CALL
component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **ppEnvironment)
{
    *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
}

sal_Bool SAL_CALL
component_writeInfo(void *pServiceManager, void *pRegistryKey)
{
    Reference< XMultiServiceFactory > xMan(reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
    Reference< XRegistryKey > xKey(reinterpret_cast< XRegistryKey* >(pRegistryKey));

    // register service
    ::rtl::OUString aTempStr;
    ::rtl::OUString aImpl(RTL_CONSTASCII_USTRINGPARAM("/"));
    aImpl += SplashScreen::impl_getImplementationName();
    aImpl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES"));
    Reference< XRegistryKey > xNewKey = xKey->createKey(aImpl);
    xNewKey->createKey(SplashScreen::impl_getSupportedServiceNames()[0]);

    return sal_True;
}

void * SAL_CALL
component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *pRegistryKey)
{
    void* pReturn = NULL ;
    if  ( pImplementationName && pServiceManager )
    {
        // Define variables which are used in following macros.
        Reference< XSingleServiceFactory > xFactory                                             ;
        Reference< XMultiServiceFactory >  xServiceManager(
            reinterpret_cast< XMultiServiceFactory* >(pServiceManager));

        if (desktop::SplashScreen::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL )
        {
            xFactory = Reference< XSingleServiceFactory >(
                cppu::createOneInstanceFactory(
                    xServiceManager, SplashScreen::impl_getImplementationName(),
                    SplashScreen::getInstance, SplashScreen::impl_getSupportedServiceNames()));
        }

        // Factory is valid - service was found.
        if ( xFactory.is() )
        {
            xFactory->acquire();
            pReturn = xFactory.get();
        }
    }

    // Return with result of this operation.
    return pReturn ;
}

} // extern "C"
<commit_msg>INTEGRATION: CWS os9 (1.2.18); FILE MERGED 2003/04/29 16:20:38 lo 1.2.18.1: typo<commit_after>/*************************************************************************
 *
 *  $RCSfile: splash.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2003-05-22 08:55:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "splash.hxx"

#ifndef _UTL_BOOTSTRAP_HXX
#include <unotools/bootstrap.hxx>
#endif
#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif
#ifndef _URLOBJ_HXX
#include <tools/urlobj.hxx>
#endif
#ifndef _STREAM_HXX
#include <tools/stream.hxx>
#endif
#ifndef _SFX_HRC
#include <sfx2/sfx.hrc>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star::registry;

namespace desktop
{

SplashScreen::SplashScreen(const Reference< XMultiServiceFactory >& rSMgr)
        :
        IntroWindow()
    , _iProgress(0)
    , _iMax(100)
    , _bPaintBitmap(sal_True)
    , _bPaintProgress(sal_False)
    , _xoffset(12)
    , _yoffset(16)
    , _barheight(6)
    , _barspace(2)
{
    _rFactory = rSMgr;

    initBitmap();
    Size aSize = _aIntroBmp.GetSizePixel();
    SetOutputSizePixel( aSize );
    _height = aSize.Height();
    _width = aSize.Width();
    _tlx = _xoffset;              // top-left x
    _tly = _height - _yoffset; // top-left y
    _barwidth  = _width - (2*_yoffset);
    Application::AddEventListener(
        LINK( this, SplashScreen, AppEventListenerHdl ) );
}

SplashScreen::~SplashScreen()
{
    Application::RemoveEventListener(
        LINK( this, SplashScreen, AppEventListenerHdl ) );
    Hide();
}

void SAL_CALL SplashScreen::start(const OUString& aText, sal_Int32 nRange)
    throw (RuntimeException)
{
    _iMax = nRange;
    if (_bVisible) {
        ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
        Show();
        Paint(Rectangle());
    }
}
void SAL_CALL SplashScreen::end()
    throw (RuntimeException)
{
    _iProgress = _iMax;
    updateStatus();
    if (_bVisible) Hide();
}
void SAL_CALL SplashScreen::reset()
    throw (RuntimeException)
{
    _iProgress = 0;
    updateStatus();
}

void SAL_CALL SplashScreen::setText(const OUString& aText)
    throw (RuntimeException)
{
}

void SAL_CALL SplashScreen::setValue(sal_Int32 nValue)
    throw (RuntimeException)
{
    ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );

    if (nValue >= _iMax) _iProgress = _iMax;
    else _iProgress = nValue;
    updateStatus();
}

// XInitialize
void SAL_CALL
SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
    throw (RuntimeException)
{
    ::osl::ClearableMutexGuard  aGuard( _aMutex );
    if (aArguments.getLength() > 0)
        aArguments[0] >>= _bVisible;
}

void SplashScreen::updateStatus()
{
    if (!_bVisible) return;
    if (!_bPaintProgress) _bPaintProgress = sal_True;
    _bPaintBitmap=sal_False;
    Paint(Rectangle());
    _bPaintBitmap=sal_True;
}

// internal private methods
IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent )
{
    if ( inEvent != 0 )
    {
        switch ( inEvent->GetId() )
        {
            case VCLEVENT_WINDOW_HIDE:
                Paint( Rectangle() );
                break;
            default:
                break;
        }
    }
    return 0;
}

void SplashScreen::initBitmap()
{
    String aBmpFileName;
    OUString aIniPath;
    OUString aLogo( RTL_CONSTASCII_USTRINGPARAM( "1" ) );
    aLogo = ::utl::Bootstrap::getLogoData( aLogo );
    sal_Bool bLogo = (sal_Bool)aLogo.toInt32();
    if ( bLogo )
    {
        xub_StrLen nIndex = 0;
        aBmpFileName += String( DEFINE_CONST_UNICODE("intro.bmp") );
        // retrieve our current installation path
        OUString aExecutePath;
        ::vos::OStartupInfo().getExecutableFile( aExecutePath );
        sal_uInt32  lastIndex = aExecutePath.lastIndexOf('/');
        if ( lastIndex > 0 )
            aExecutePath = aExecutePath.copy( 0, lastIndex+1 );
        INetURLObject aObj( aExecutePath, INET_PROT_FILE );
        aObj.insertName( aBmpFileName );
        SvFileStream aStrm( aObj.PathToFileName(), STREAM_STD_READ );
        if ( !aStrm.GetError() )
        {
            // Default case, we load the intro bitmap from a seperate file
            // (e.g. staroffice_intro.bmp or starsuite_intro.bmp)
            aStrm >> _aIntroBmp;
        }
        else
        {
            // Save case:
            // Create resource manager for intro bitmap. Due to our problem that we don't have
            // any language specific information, we have to search for the correct resource
            // file. The bitmap resource is language independent.
            const USHORT nResId = RID_DEFAULTINTRO;
            LanguageType aLanguageType;
            String       aMgrName = String::CreateFromAscii( "iso" );
            aMgrName += String::CreateFromInt32(SUPD); // current build version
            ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLanguageType );
            ResId aIntroBmpRes( nResId, pLabelResMgr );
            _aIntroBmp = Bitmap( aIntroBmpRes );
            delete pLabelResMgr;
        }
    }
}

void SplashScreen::Paint( const Rectangle& )
{
    if(!_bVisible) return;
    // draw bitmap
    if (_bPaintBitmap)
        DrawBitmap( Point(), _aIntroBmp );

    if (_bPaintProgress) {
        // draw progress...
        long length = (_iProgress * _barwidth / _iMax) - (2 * _barspace);
        if (length < 0) length = 0;
        const Color cBlue(COL_BLUE);
        const Color cGray(COL_LIGHTGRAY);

        // border
        SetFillColor();
        SetLineColor(cGray);
        DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth,
            _tly+_barheight));

        // progress bar
        SetFillColor(cBlue);
        SetLineColor();
        DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace,
            _tlx+_barspace+length, _tly+_barheight-_barspace));
    }
    Flush();
}

// get service instance...
SplashScreen *SplashScreen::_pINSTANCE = NULL;
osl::Mutex SplashScreen::_aMutex;

Reference< XInterface > SplashScreen::getInstance(const Reference< XMultiServiceFactory >& rSMgr)
{
    if ( _pINSTANCE == 0 )
    {
        osl::MutexGuard guard(_aMutex);
        if (_pINSTANCE == 0)
            return (XComponent*)new SplashScreen(rSMgr);
    }

    return (XComponent*)0;
}

// static service info...
const sal_Char *SplashScreen::serviceName = "com.sun.star.office.SplashScreen";
const sal_Char *SplashScreen::implementationName = "com.sun.star.office.comp.SplashScreen";
const sal_Char *SplashScreen::supportedServiceNames[] = {"com.sun.star.office.SplashScreen", NULL};
OUString SplashScreen::impl_getImplementationName()
{
    return OUString::createFromAscii(implementationName);
}
Sequence<OUString> SplashScreen::impl_getSupportedServiceNames()
{
    Sequence<OUString> aSequence;
    for (int i=0; supportedServiceNames[i]!=NULL; i++) {
        aSequence.realloc(i+1);
        aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i]));
    }
    return aSequence;
}

}

// component management stuff...
// ----------------------------------------------------------------------------
extern "C"
{
using namespace desktop;

void SAL_CALL
component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **ppEnvironment)
{
    *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
}

sal_Bool SAL_CALL
component_writeInfo(void *pServiceManager, void *pRegistryKey)
{
    Reference< XMultiServiceFactory > xMan(reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
    Reference< XRegistryKey > xKey(reinterpret_cast< XRegistryKey* >(pRegistryKey));

    // register service
    ::rtl::OUString aTempStr;
    ::rtl::OUString aImpl(RTL_CONSTASCII_USTRINGPARAM("/"));
    aImpl += SplashScreen::impl_getImplementationName();
    aImpl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES"));
    Reference< XRegistryKey > xNewKey = xKey->createKey(aImpl);
    xNewKey->createKey(SplashScreen::impl_getSupportedServiceNames()[0]);

    return sal_True;
}

void * SAL_CALL
component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *pRegistryKey)
{
    void* pReturn = NULL ;
    if  ( pImplementationName && pServiceManager )
    {
        // Define variables which are used in following macros.
        Reference< XSingleServiceFactory > xFactory;
        Reference< XMultiServiceFactory >  xServiceManager(
            reinterpret_cast< XMultiServiceFactory* >(pServiceManager));

        if (desktop::SplashScreen::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL )
        {
            xFactory = Reference< XSingleServiceFactory >(
                cppu::createOneInstanceFactory(
                    xServiceManager, SplashScreen::impl_getImplementationName(),
                    SplashScreen::getInstance, SplashScreen::impl_getSupportedServiceNames()));
        }

        // Factory is valid - service was found.
        if ( xFactory.is() )
        {
            xFactory->acquire();
            pReturn = xFactory.get();
        }
    }

    // Return with result of this operation.
    return pReturn ;
}

} // extern "C"
<|endoftext|>


<commit_before>#ifndef ITER_ZIP_HPP_
#define ITER_ZIP_HPP_

#include "internal/iterbase.hpp"

#include <iterator>
#include <tuple>
#include <utility>

namespace iter {
  namespace impl {
    template <typename... RestContainers>
    class Zipped;

    template <typename Container, typename... RestContainers>
    class Zipped<Container, RestContainers...>;

    template <>
    class Zipped<>;
  }

  template <typename... Containers>
  impl::Zipped<Containers...> zip(Containers&&...);
}

// specialization for at least 1 template argument
template <typename Container, typename... RestContainers>
class iter::impl::Zipped<Container, RestContainers...> {
  using ZipIterDeref =
      std::tuple<iterator_deref<Container>, iterator_deref<RestContainers>...>;

  friend Zipped iter::zip<Container, RestContainers...>(
      Container&&, RestContainers&&...);

  template <typename...>
  friend class Zipped;

 private:
  Container container;
  Zipped<RestContainers...> rest_zipped;
  Zipped(Container&& in_container, RestContainers&&... rest)
      : container(std::forward<Container>(in_container)),
        rest_zipped{std::forward<RestContainers>(rest)...} {}

 public:
  class Iterator : public std::iterator<std::input_iterator_tag, ZipIterDeref> {
   private:
    using RestIter = typename Zipped<RestContainers...>::Iterator;

    iterator_type<Container> iter;
    RestIter rest_iter;

   public:
    constexpr static const bool is_base_iter = false;
    Iterator(iterator_type<Container>&& it, RestIter&& rest)
        : iter{std::move(it)}, rest_iter{std::move(rest)} {}

    Iterator& operator++() {
      ++this->iter;
      ++this->rest_iter;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return this->iter != other.iter
             && (RestIter::is_base_iter || this->rest_iter != other.rest_iter);
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    auto operator*() -> decltype(std::tuple_cat(
        std::tuple<iterator_deref<Container>>{*this->iter}, *this->rest_iter)) {
      return std::tuple_cat(
          std::tuple<iterator_deref<Container>>{*this->iter}, *this->rest_iter);
    }

    auto operator -> () -> ArrowProxy<decltype(**this)> {
      return {**this};
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::begin(this->rest_zipped)};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->rest_zipped)};
  }
};

template <>
class iter::impl::Zipped<> {
 public:
  class Iterator : public std::iterator<std::input_iterator_tag, std::tuple<>> {
   public:
    constexpr static const bool is_base_iter = true;

    Iterator& operator++() {
      return *this;
    }

    Iterator operator++(int) {
      return *this;
    }

    // if this were to return true, there would be no need
    // for the is_base_iter static class attribute.
    // However, returning false causes an empty zip() call
    // to reach the "end" immediately. Returning true here
    // instead results in an infinite loop in the zip() case
    bool operator!=(const Iterator&) const {
      return false;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    std::tuple<> operator*() {
      return std::tuple<>{};
    }

    auto operator -> () -> ArrowProxy<decltype(**this)> {
      return {**this};
    }
  };

  Iterator begin() {
    return {};
  }

  Iterator end() {
    return {};
  }
};

template <typename... Containers>
iter::impl::Zipped<Containers...> iter::zip(Containers&&... containers) {
  return {std::forward<Containers>(containers)...};
}

#endif
<commit_msg>makes zip impl class move-only<commit_after>#ifndef ITER_ZIP_HPP_
#define ITER_ZIP_HPP_

#include "internal/iterbase.hpp"

#include <iterator>
#include <tuple>
#include <utility>

namespace iter {
  namespace impl {
    template <typename... RestContainers>
    class Zipped;

    template <typename Container, typename... RestContainers>
    class Zipped<Container, RestContainers...>;

    template <>
    class Zipped<>;
  }

  template <typename... Containers>
  impl::Zipped<Containers...> zip(Containers&&...);
}

// specialization for at least 1 template argument
template <typename Container, typename... RestContainers>
class iter::impl::Zipped<Container, RestContainers...> {
  using ZipIterDeref =
      std::tuple<iterator_deref<Container>, iterator_deref<RestContainers>...>;

  friend Zipped iter::zip<Container, RestContainers...>(
      Container&&, RestContainers&&...);

  template <typename...>
  friend class Zipped;

 private:
  Container container;
  Zipped<RestContainers...> rest_zipped;
  Zipped(Container&& in_container, RestContainers&&... rest)
      : container(std::forward<Container>(in_container)),
        rest_zipped{std::forward<RestContainers>(rest)...} {}

 public:
  Zipped(Zipped&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag, ZipIterDeref> {
   private:
    using RestIter = typename Zipped<RestContainers...>::Iterator;

    iterator_type<Container> iter;
    RestIter rest_iter;

   public:
    constexpr static const bool is_base_iter = false;
    Iterator(iterator_type<Container>&& it, RestIter&& rest)
        : iter{std::move(it)}, rest_iter{std::move(rest)} {}

    Iterator& operator++() {
      ++this->iter;
      ++this->rest_iter;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return this->iter != other.iter
             && (RestIter::is_base_iter || this->rest_iter != other.rest_iter);
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    auto operator*() -> decltype(std::tuple_cat(
        std::tuple<iterator_deref<Container>>{*this->iter}, *this->rest_iter)) {
      return std::tuple_cat(
          std::tuple<iterator_deref<Container>>{*this->iter}, *this->rest_iter);
    }

    auto operator -> () -> ArrowProxy<decltype(**this)> {
      return {**this};
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::begin(this->rest_zipped)};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->rest_zipped)};
  }
};

template <>
class iter::impl::Zipped<> {
 public:
  Zipped(Zipped&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag, std::tuple<>> {
   public:
    constexpr static const bool is_base_iter = true;

    Iterator& operator++() {
      return *this;
    }

    Iterator operator++(int) {
      return *this;
    }

    // if this were to return true, there would be no need
    // for the is_base_iter static class attribute.
    // However, returning false causes an empty zip() call
    // to reach the "end" immediately. Returning true here
    // instead results in an infinite loop in the zip() case
    bool operator!=(const Iterator&) const {
      return false;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    std::tuple<> operator*() {
      return std::tuple<>{};
    }

    auto operator -> () -> ArrowProxy<decltype(**this)> {
      return {**this};
    }
  };

  Iterator begin() {
    return {};
  }

  Iterator end() {
    return {};
  }
};

template <typename... Containers>
iter::impl::Zipped<Containers...> iter::zip(Containers&&... containers) {
  return {std::forward<Containers>(containers)...};
}

#endif
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/window_capturer.h"

#include <assert.h>
#include <windows.h>

#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"

namespace webrtc {

namespace {

typedef HRESULT (WINAPI *DwmIsCompositionEnabledFunc)(BOOL* enabled);

// Coverts a zero-terminated UTF-16 string to UTF-8. Returns an empty string if
// error occurs.
std::string Utf16ToUtf8(const WCHAR* str) {
  int len_utf8 = WideCharToMultiByte(CP_UTF8, 0, str, -1,
                                     NULL, 0, NULL, NULL);
  if (len_utf8 <= 0)
    return std::string();
  std::string result(len_utf8, '\0');
  int rv = WideCharToMultiByte(CP_UTF8, 0, str, -1,
                               &*(result.begin()), len_utf8, NULL, NULL);
  if (rv != len_utf8)
    assert(false);

  return result;
}

BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
  WindowCapturer::WindowList* list =
      reinterpret_cast<WindowCapturer::WindowList*>(param);

  // Skip windows that are invisible, minimized, have no title, or are owned,
  // unless they have the app window style set.
  int len = GetWindowTextLength(hwnd);
  HWND owner = GetWindow(hwnd, GW_OWNER);
  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
      (owner && !(exstyle & WS_EX_APPWINDOW))) {
    return TRUE;
  }

  // Skip the Program Manager window and the Start button.
  const size_t kClassLength = 256;
  WCHAR class_name[kClassLength];
  GetClassName(hwnd, class_name, kClassLength);
  // Skip Program Manager window and the Start button. This is the same logic
  // that's used in Win32WindowPicker in libjingle. Consider filtering other
  // windows as well (e.g. toolbars).
  if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0)
    return TRUE;

  WindowCapturer::Window window;
  window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);

  const size_t kTitleLength = 500;
  WCHAR window_title[kTitleLength];
  // Truncate the title if it's longer than kTitleLength.
  GetWindowText(hwnd, window_title, kTitleLength);
  window.title = Utf16ToUtf8(window_title);

  // Skip windows when we failed to convert the title or it is empty.
  if (window.title.empty())
    return TRUE;

  list->push_back(window);

  return TRUE;
}

class WindowCapturerWin : public WindowCapturer {
 public:
  WindowCapturerWin();
  virtual ~WindowCapturerWin();

  // WindowCapturer interface.
  virtual bool GetWindowList(WindowList* windows) OVERRIDE;
  virtual bool SelectWindow(WindowId id) OVERRIDE;

  // DesktopCapturer interface.
  virtual void Start(Callback* callback) OVERRIDE;
  virtual void Capture(const DesktopRegion& region) OVERRIDE;

 private:
  bool IsAeroEnabled();

  Callback* callback_;

  // HWND and HDC for the currently selected window or NULL if window is not
  // selected.
  HWND window_;
  HDC window_dc_;

  // dwmapi.dll is used to determine if desktop compositing is enabled.
  HMODULE dwmapi_library_;
  DwmIsCompositionEnabledFunc is_composition_enabled_func_;

  DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
};

WindowCapturerWin::WindowCapturerWin()
    : callback_(NULL),
      window_(NULL),
      window_dc_(NULL) {
  // Try to load dwmapi.dll dynamically since it is not available on XP.
  dwmapi_library_ = LoadLibrary(L"dwmapi.dll");
  if (dwmapi_library_) {
    is_composition_enabled_func_ =
        reinterpret_cast<DwmIsCompositionEnabledFunc>(
            GetProcAddress(dwmapi_library_, "DwmIsCompositionEnabled"));
    assert(is_composition_enabled_func_);
  } else {
    is_composition_enabled_func_ = NULL;
  }
}

WindowCapturerWin::~WindowCapturerWin() {
  if (dwmapi_library_)
    FreeLibrary(dwmapi_library_);
}

bool WindowCapturerWin::IsAeroEnabled() {
  BOOL result = FALSE;
  if (is_composition_enabled_func_)
    is_composition_enabled_func_(&result);
  return result != FALSE;
}

bool WindowCapturerWin::GetWindowList(WindowList* windows) {
  WindowList result;
  LPARAM param = reinterpret_cast<LPARAM>(&result);
  if (!EnumWindows(&WindowsEnumerationHandler, param))
    return false;
  windows->swap(result);
  return true;
}

bool WindowCapturerWin::SelectWindow(WindowId id) {
  if (window_dc_)
    ReleaseDC(window_, window_dc_);

  window_ = reinterpret_cast<HWND>(id);
  window_dc_ = GetWindowDC(window_);
  if (!window_dc_) {
    LOG(LS_WARNING) << "Failed to select window: " << GetLastError();
    window_ = NULL;
    return false;
  }

  return true;
}

void WindowCapturerWin::Start(Callback* callback) {
  assert(!callback_);
  assert(callback);

  callback_ = callback;
}

void WindowCapturerWin::Capture(const DesktopRegion& region) {
  if (!window_dc_) {
    LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  // Stop capturing if the window has been minimized or hidden.
  if (IsIconic(window_) || !IsWindowVisible(window_)) {
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  assert(window_);

  RECT rect;
  if (!GetWindowRect(window_, &rect)) {
    LOG(LS_WARNING) << "Failed to get window size: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  scoped_ptr<DesktopFrameWin> frame(DesktopFrameWin::Create(
      DesktopSize(rect.right - rect.left, rect.bottom - rect.top),
      NULL, window_dc_));
  if (!frame.get()) {
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC mem_dc = CreateCompatibleDC(window_dc_);
  SelectObject(mem_dc, frame->bitmap());
  BOOL result = FALSE;

  // When desktop composition (Aero) is enabled each window is rendered to a
  // private buffer allowing BitBlt() to get the window content even if the
  // window is occluded. PrintWindow() is slower but lets rendering the window
  // contents to an off-screen device context when Aero is not available.
  // PrintWindow() is not supported by some applications.

  // If Aero is enabled, we prefer BitBlt() because it's faster and avoids
  // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may
  // render occluding windows on top of the desired window.

  if (!IsAeroEnabled())
    result = PrintWindow(window_, mem_dc, 0);

  // Aero is enabled or PrintWindow() failed, use BitBlt.
  if (!result) {
    result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
                    window_dc_, 0, 0, SRCCOPY);
  }

  DeleteDC(mem_dc);

  if (!result) {
    LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
    frame.reset();
  }

  callback_->OnCaptureCompleted(frame.release());
}

}  // namespace

// static
WindowCapturer* WindowCapturer::Create() {
  return new WindowCapturerWin();
}

}  // namespace webrtc
<commit_msg>Fix window capturer not to leak HDC.<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/window_capturer.h"

#include <assert.h>
#include <windows.h>

#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"

namespace webrtc {

namespace {

typedef HRESULT (WINAPI *DwmIsCompositionEnabledFunc)(BOOL* enabled);

// Coverts a zero-terminated UTF-16 string to UTF-8. Returns an empty string if
// error occurs.
std::string Utf16ToUtf8(const WCHAR* str) {
  int len_utf8 = WideCharToMultiByte(CP_UTF8, 0, str, -1,
                                     NULL, 0, NULL, NULL);
  if (len_utf8 <= 0)
    return std::string();
  std::string result(len_utf8, '\0');
  int rv = WideCharToMultiByte(CP_UTF8, 0, str, -1,
                               &*(result.begin()), len_utf8, NULL, NULL);
  if (rv != len_utf8)
    assert(false);

  return result;
}

BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
  WindowCapturer::WindowList* list =
      reinterpret_cast<WindowCapturer::WindowList*>(param);

  // Skip windows that are invisible, minimized, have no title, or are owned,
  // unless they have the app window style set.
  int len = GetWindowTextLength(hwnd);
  HWND owner = GetWindow(hwnd, GW_OWNER);
  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
      (owner && !(exstyle & WS_EX_APPWINDOW))) {
    return TRUE;
  }

  // Skip the Program Manager window and the Start button.
  const size_t kClassLength = 256;
  WCHAR class_name[kClassLength];
  GetClassName(hwnd, class_name, kClassLength);
  // Skip Program Manager window and the Start button. This is the same logic
  // that's used in Win32WindowPicker in libjingle. Consider filtering other
  // windows as well (e.g. toolbars).
  if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0)
    return TRUE;

  WindowCapturer::Window window;
  window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);

  const size_t kTitleLength = 500;
  WCHAR window_title[kTitleLength];
  // Truncate the title if it's longer than kTitleLength.
  GetWindowText(hwnd, window_title, kTitleLength);
  window.title = Utf16ToUtf8(window_title);

  // Skip windows when we failed to convert the title or it is empty.
  if (window.title.empty())
    return TRUE;

  list->push_back(window);

  return TRUE;
}

class WindowCapturerWin : public WindowCapturer {
 public:
  WindowCapturerWin();
  virtual ~WindowCapturerWin();

  // WindowCapturer interface.
  virtual bool GetWindowList(WindowList* windows) OVERRIDE;
  virtual bool SelectWindow(WindowId id) OVERRIDE;

  // DesktopCapturer interface.
  virtual void Start(Callback* callback) OVERRIDE;
  virtual void Capture(const DesktopRegion& region) OVERRIDE;

 private:
  bool IsAeroEnabled();

  Callback* callback_;

  // HWND and HDC for the currently selected window or NULL if window is not
  // selected.
  HWND window_;

  // dwmapi.dll is used to determine if desktop compositing is enabled.
  HMODULE dwmapi_library_;
  DwmIsCompositionEnabledFunc is_composition_enabled_func_;

  DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
};

WindowCapturerWin::WindowCapturerWin()
    : callback_(NULL),
      window_(NULL) {
  // Try to load dwmapi.dll dynamically since it is not available on XP.
  dwmapi_library_ = LoadLibrary(L"dwmapi.dll");
  if (dwmapi_library_) {
    is_composition_enabled_func_ =
        reinterpret_cast<DwmIsCompositionEnabledFunc>(
            GetProcAddress(dwmapi_library_, "DwmIsCompositionEnabled"));
    assert(is_composition_enabled_func_);
  } else {
    is_composition_enabled_func_ = NULL;
  }
}

WindowCapturerWin::~WindowCapturerWin() {
  if (dwmapi_library_)
    FreeLibrary(dwmapi_library_);
}

bool WindowCapturerWin::IsAeroEnabled() {
  BOOL result = FALSE;
  if (is_composition_enabled_func_)
    is_composition_enabled_func_(&result);
  return result != FALSE;
}

bool WindowCapturerWin::GetWindowList(WindowList* windows) {
  WindowList result;
  LPARAM param = reinterpret_cast<LPARAM>(&result);
  if (!EnumWindows(&WindowsEnumerationHandler, param))
    return false;
  windows->swap(result);
  return true;
}

bool WindowCapturerWin::SelectWindow(WindowId id) {
  HWND window = reinterpret_cast<HWND>(id);
  if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
    return false;
  window_ = window;
  return true;
}

void WindowCapturerWin::Start(Callback* callback) {
  assert(!callback_);
  assert(callback);

  callback_ = callback;
}

void WindowCapturerWin::Capture(const DesktopRegion& region) {
  if (!window_) {
    LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  // Stop capturing if the window has been minimized or hidden.
  if (IsIconic(window_) || !IsWindowVisible(window_)) {
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  RECT rect;
  if (!GetWindowRect(window_, &rect)) {
    LOG(LS_WARNING) << "Failed to get window size: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC window_dc = GetWindowDC(window_);
  if (!window_dc) {
    LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError();
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  scoped_ptr<DesktopFrameWin> frame(DesktopFrameWin::Create(
      DesktopSize(rect.right - rect.left, rect.bottom - rect.top),
      NULL, window_dc));
  if (!frame.get()) {
    ReleaseDC(window_, window_dc);
    callback_->OnCaptureCompleted(NULL);
    return;
  }

  HDC mem_dc = CreateCompatibleDC(window_dc);
  SelectObject(mem_dc, frame->bitmap());
  BOOL result = FALSE;

  // When desktop composition (Aero) is enabled each window is rendered to a
  // private buffer allowing BitBlt() to get the window content even if the
  // window is occluded. PrintWindow() is slower but lets rendering the window
  // contents to an off-screen device context when Aero is not available.
  // PrintWindow() is not supported by some applications.

  // If Aero is enabled, we prefer BitBlt() because it's faster and avoids
  // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may
  // render occluding windows on top of the desired window.

  if (!IsAeroEnabled())
    result = PrintWindow(window_, mem_dc, 0);

  // Aero is enabled or PrintWindow() failed, use BitBlt.
  if (!result) {
    result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
                    window_dc, 0, 0, SRCCOPY);
  }

  if (!result) {
    LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
    frame.reset();
  }

  SelectObject(mem_dc, NULL);
  DeleteDC(mem_dc);
  ReleaseDC(window_, window_dc);

  callback_->OnCaptureCompleted(frame.release());
}

}  // namespace

// static
WindowCapturer* WindowCapturer::Create() {
  return new WindowCapturerWin();
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>
    Copyright (C) 2014 Daniel Vrátil <dvraitl@redhat.com>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "intervalcheck.h"
#include "storage/datastore.h"
#include "storage/itemretrievalmanager.h"

using namespace Akonadi::Server;

static int MINIMUM_AUTOSYNC_INTERVAL = 5; // minutes
static int MINIMUM_COLTREESYNC_INTERVAL = 5; // minutes

IntervalCheck::IntervalCheck( QObject *parent )
  : CollectionScheduler( parent )
{
}

IntervalCheck::~ IntervalCheck()
{
}

void IntervalCheck::requestCollectionSync( const Collection &collection )
{
  QMetaObject::invokeMethod( this, "collectionExpired",
                             Qt::QueuedConnection,
                             Q_ARG( Collection, collection ) );
}

int IntervalCheck::collectionScheduleInterval( const Collection &collection )
{
  return collection.cachePolicyCheckInterval();
}

bool IntervalCheck::hasChanged( const Collection &collection, const Collection &changed )
{
  return collection.cachePolicyCheckInterval() != changed.cachePolicyCheckInterval()
        || collection.subscribed() != changed.subscribed();
}

bool IntervalCheck::shouldScheduleCollection( const Collection &collection )
{
  return collection.cachePolicyCheckInterval() > 0
        && collection.subscribed();
}

void IntervalCheck::collectionExpired( const Collection &collection )
{
  const QDateTime now( QDateTime::currentDateTime() );

  if ( collection.parentId() == 0 ) {
    const QString resourceName = collection.resource().name();

    const int interval = qMax( MINIMUM_COLTREESYNC_INTERVAL, collection.cachePolicyCheckInterval() );

    const QDateTime lastExpectedCheck = now.addSecs( interval * -60 );
    if ( !mLastCollectionTreeSyncs.contains( resourceName ) || mLastCollectionTreeSyncs.value( resourceName ) < lastExpectedCheck ) {
      mLastCollectionTreeSyncs.insert( resourceName, now );
      QMetaObject::invokeMethod( ItemRetrievalManager::instance(), "triggerCollectionTreeSync",
                                 Qt::QueuedConnection,
                                 Q_ARG( QString, resourceName ) );
    }
  }

  // now on to the actual collection syncing
  const int interval = qMax( MINIMUM_AUTOSYNC_INTERVAL, collection.cachePolicyCheckInterval() );

  const QDateTime lastExpectedCheck = now.addSecs( interval * -60 );
  if ( mLastChecks.contains( collection.id() ) && mLastChecks.value( collection.id() ) > lastExpectedCheck ) {
    return;
  }
  mLastChecks.insert( collection.id(), now );
  QMetaObject::invokeMethod( ItemRetrievalManager::instance(), "triggerCollectionSync",
                             Qt::QueuedConnection,
                             Q_ARG( QString, collection.resource().name() ),
                             Q_ARG( qint64, collection.id() ) );
}
<commit_msg>Only schedule collections for sync that are enabled or have a corresponding preference.<commit_after>/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>
    Copyright (C) 2014 Daniel Vrátil <dvraitl@redhat.com>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "intervalcheck.h"
#include "storage/datastore.h"
#include "storage/itemretrievalmanager.h"
#include "storage/entity.h"

using namespace Akonadi::Server;

static int MINIMUM_AUTOSYNC_INTERVAL = 5; // minutes
static int MINIMUM_COLTREESYNC_INTERVAL = 5; // minutes

IntervalCheck::IntervalCheck( QObject *parent )
  : CollectionScheduler( parent )
{
}

IntervalCheck::~ IntervalCheck()
{
}

void IntervalCheck::requestCollectionSync( const Collection &collection )
{
  QMetaObject::invokeMethod( this, "collectionExpired",
                             Qt::QueuedConnection,
                             Q_ARG( Collection, collection ) );
}

int IntervalCheck::collectionScheduleInterval( const Collection &collection )
{
  return collection.cachePolicyCheckInterval();
}

bool IntervalCheck::hasChanged( const Collection &collection, const Collection &changed )
{
  return collection.cachePolicyCheckInterval() != changed.cachePolicyCheckInterval()
        || collection.subscribed() != changed.subscribed()
        || collection.enabled() != changed.enabled()
        || collection.syncPref() != changed.syncPref();
}

bool IntervalCheck::shouldScheduleCollection( const Collection &collection )
{
  return collection.cachePolicyCheckInterval() > 0
        && ( collection.subscribed() || ( collection.syncPref() == Tristate::True ) || ( ( collection.syncPref() == Tristate::Undefined ) && collection.enabled() ) );
}

void IntervalCheck::collectionExpired( const Collection &collection )
{
  const QDateTime now( QDateTime::currentDateTime() );

  if ( collection.parentId() == 0 ) {
    const QString resourceName = collection.resource().name();

    const int interval = qMax( MINIMUM_COLTREESYNC_INTERVAL, collection.cachePolicyCheckInterval() );

    const QDateTime lastExpectedCheck = now.addSecs( interval * -60 );
    if ( !mLastCollectionTreeSyncs.contains( resourceName ) || mLastCollectionTreeSyncs.value( resourceName ) < lastExpectedCheck ) {
      mLastCollectionTreeSyncs.insert( resourceName, now );
      QMetaObject::invokeMethod( ItemRetrievalManager::instance(), "triggerCollectionTreeSync",
                                 Qt::QueuedConnection,
                                 Q_ARG( QString, resourceName ) );
    }
  }

  // now on to the actual collection syncing
  const int interval = qMax( MINIMUM_AUTOSYNC_INTERVAL, collection.cachePolicyCheckInterval() );

  const QDateTime lastExpectedCheck = now.addSecs( interval * -60 );
  if ( mLastChecks.contains( collection.id() ) && mLastChecks.value( collection.id() ) > lastExpectedCheck ) {
    return;
  }
  mLastChecks.insert( collection.id(), now );
  QMetaObject::invokeMethod( ItemRetrievalManager::instance(), "triggerCollectionSync",
                             Qt::QueuedConnection,
                             Q_ARG( QString, collection.resource().name() ),
                             Q_ARG( qint64, collection.id() ) );
}
<|endoftext|>


<commit_before>#include <fstream>

#include "main.h"
#include "elf.h"
#include "package.h"
#include "db.h"

#include "pkgdepdb.h"

#include "capi_algorithm.h"

using namespace pkgdepdb;

extern "C" {

pkgdepdb_pkg* pkgdepdb_pkg_new(void) {
  return reinterpret_cast<pkgdepdb_pkg*>(new Package);
}

pkgdepdb_pkg* pkgdepdb_pkg_load(const char *filename, pkgdepdb_config *cfg_) {
  auto cfg = reinterpret_cast<Config*>(cfg_);
  auto pkg = Package::Open(filename, *cfg);
  return reinterpret_cast<pkgdepdb_pkg*>(pkg);
}

void pkgdepdb_pkg_delete(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  delete pkg;
}

const char* pkgdepdb_pkg_name(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkg->name_.c_str();
}

const char* pkgdepdb_pkg_version(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkg->version_.c_str();
}

void pkgdepdb_pkg_set_name(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  pkg->name_ = v;
}

void pkgdepdb_pkg_set_version(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  pkg->version_ = v;
}

static DependList Package::* const kDepMember[] = {
  &Package::depends_,
  &Package::optdepends_,
  &Package::makedepends_,
  &Package::provides_,
  &Package::conflicts_,
  &Package::replaces_,
};
static const size_t kDepMemberCount = sizeof(kDepMember)/sizeof(kDepMember[0]);

static inline
size_t pkg_dependlist_count(const Package& pkg, DependList Package::*member) {
  return (pkg.*member).size();
}

static inline
size_t pkg_dependlist_get(const Package& pkg, DependList Package::*member,
                          const char **on, const char **oc, size_t off,
                          size_t n)
{
  if (off >= (pkg.*member).size())
    return 0;
  auto i   = (pkg.*member).begin() + off;
  auto end = (pkg.*member).end();
  size_t got = 0;
  for (; i != end; ++i) {
    if (!n--)
      return got;
    on[got++] = std::get<0>(*i).c_str();
    oc[got++] = std::get<1>(*i).c_str();
  }
  return got;
}

static inline
int pkg_dependlist_add(Package& pkg, DependList Package::*member,
                       const char *name, const char *constraint)
{
  (pkg.*member).emplace_back(name, constraint ? constraint : "");
  return 1;
}

static inline
int pkg_dependlist_del_name(Package& pkg, DependList Package::*member,
                            const char *name)
{
  auto i = (pkg.*member).begin();
  auto end = (pkg.*member).end();
  for (; i != end; ++i) {
    if (std::get<0>(*i) == name) {
      (pkg.*member).erase(i);
      return 1;
    }
  }
  return 0;
}

static inline
int pkg_dependlist_del_full(Package& pkg, DependList Package::*member,
                            const char *name, const char *constraint)
{
  auto i = (pkg.*member).begin();
  auto end = (pkg.*member).end();
  for (; i != end; ++i) {
    if (std::get<0>(*i) == name && std::get<1>(*i) == constraint) {
      (pkg.*member).erase(i);
      return 1;
    }
  }
  return 0;
}

static inline
int pkg_dependlist_del_i(Package& pkg, DependList Package::*member, size_t i) {
  if (i >= (pkg.*member).size())
    return 0;
  (pkg.*member).erase((pkg.*member).begin() + i);
  return 1;
}

size_t pkgdepdb_pkg_dep_count(pkgdepdb_pkg *pkg_, unsigned int what) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_count(*pkg, kDepMember[what]);
}

size_t pkgdepdb_pkg_dep_get(pkgdepdb_pkg *pkg_, unsigned int what,
                            const char **on, const char **oc, size_t off,
                            size_t n)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_get(*pkg, kDepMember[what], on, oc, off, n);
}

int pkgdepdb_pkg_dep_add(pkgdepdb_pkg *pkg_, unsigned int what,
                         const char *name, const char *constraint)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_add(*pkg, kDepMember[what], name, constraint);
}

int pkgdepdb_pkg_dep_del_name(pkgdepdb_pkg *pkg_, unsigned int what,
                              const char *name)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_del_name(*pkg, kDepMember[what], name);
}

int pkgdepdb_pkg_dep_del_full(pkgdepdb_pkg *pkg_, unsigned int what,
                              const char *name, const char *constraint)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_del_full(*pkg, kDepMember[what], name, constraint);
}

int pkgdepdb_pkg_dep_del_i(pkgdepdb_pkg *pkg_, unsigned int what, size_t idx) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_del_i(*pkg, kDepMember[what], idx);
}

size_t pkgdepdb_pkg_groups_count(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_count(*pkg, &Package::groups_);
}

size_t pkgdepdb_pkg_groups_get(pkgdepdb_pkg *pkg_, const char **o, size_t n) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_get(*pkg, &Package::groups_, o, 0, n);
}

size_t pkgdepdb_pkg_groups_add(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_add_unique(*pkg, &Package::groups_, v);
}

size_t pkgdepdb_pkg_groups_del_s(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_s_all(*pkg, &Package::groups_, v);
}

size_t pkgdepdb_pkg_groups_del_i(pkgdepdb_pkg *pkg_, size_t index) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_i(*pkg, &Package::groups_, index);
}

size_t pkgdepdb_pkg_filelist_count(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_count(*pkg, &Package::filelist_);
}

size_t pkgdepdb_pkg_filelist_get(pkgdepdb_pkg *pkg_,
                                 const char **out, size_t off, size_t count)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_get(*pkg, &Package::filelist_, out, off, count);
}

size_t pkgdepdb_pkg_filelist_add(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_add_always(*pkg, &Package::filelist_, v);
}

size_t pkgdepdb_pkg_filelist_del_s(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_s_one(*pkg, &Package::filelist_, v);
}

size_t pkgdepdb_pkg_filelist_del_i(pkgdepdb_pkg *pkg_, size_t index) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_i(*pkg, &Package::filelist_, index);
}

void pkgdepdb_pkg_guess_version(pkgdepdb_pkg *pkg_, const char *filename) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  pkg->Guess(filename);
}

int pkgdepdb_pkg_conflict(pkgdepdb_pkg *subj_, pkgdepdb_pkg *obj_) {
  auto pkg = reinterpret_cast<Package*>(subj_);
  auto obj = reinterpret_cast<Package*>(obj_);
  return pkg->ConflictsWith(*obj);
}

int pkgdepdb_pkg_replaces(pkgdepdb_pkg *subj_, pkgdepdb_pkg *obj_) {
  auto pkg = reinterpret_cast<Package*>(subj_);
  auto obj = reinterpret_cast<Package*>(obj_);
  return pkg->Replaces(*obj);
}

} // extern "C"
<commit_msg>remove double increment<commit_after>#include <fstream>

#include "main.h"
#include "elf.h"
#include "package.h"
#include "db.h"

#include "pkgdepdb.h"

#include "capi_algorithm.h"

using namespace pkgdepdb;

extern "C" {

pkgdepdb_pkg* pkgdepdb_pkg_new(void) {
  return reinterpret_cast<pkgdepdb_pkg*>(new Package);
}

pkgdepdb_pkg* pkgdepdb_pkg_load(const char *filename, pkgdepdb_config *cfg_) {
  auto cfg = reinterpret_cast<Config*>(cfg_);
  auto pkg = Package::Open(filename, *cfg);
  return reinterpret_cast<pkgdepdb_pkg*>(pkg);
}

void pkgdepdb_pkg_delete(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  delete pkg;
}

const char* pkgdepdb_pkg_name(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkg->name_.c_str();
}

const char* pkgdepdb_pkg_version(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkg->version_.c_str();
}

void pkgdepdb_pkg_set_name(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  pkg->name_ = v;
}

void pkgdepdb_pkg_set_version(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  pkg->version_ = v;
}

static DependList Package::* const kDepMember[] = {
  &Package::depends_,
  &Package::optdepends_,
  &Package::makedepends_,
  &Package::provides_,
  &Package::conflicts_,
  &Package::replaces_,
};
static const size_t kDepMemberCount = sizeof(kDepMember)/sizeof(kDepMember[0]);

static inline
size_t pkg_dependlist_count(const Package& pkg, DependList Package::*member) {
  return (pkg.*member).size();
}

static inline
size_t pkg_dependlist_get(const Package& pkg, DependList Package::*member,
                          const char **on, const char **oc, size_t off,
                          size_t n)
{
  if (off >= (pkg.*member).size())
    return 0;
  auto i   = (pkg.*member).begin() + off;
  auto end = (pkg.*member).end();
  size_t got = 0;
  for (; i != end; ++i) {
    if (!n--)
      return got;
    on[got] = std::get<0>(*i).c_str();
    oc[got] = std::get<1>(*i).c_str();
    ++got;
  }
  return got;
}

static inline
int pkg_dependlist_add(Package& pkg, DependList Package::*member,
                       const char *name, const char *constraint)
{
  (pkg.*member).emplace_back(name, constraint ? constraint : "");
  return 1;
}

static inline
int pkg_dependlist_del_name(Package& pkg, DependList Package::*member,
                            const char *name)
{
  auto i = (pkg.*member).begin();
  auto end = (pkg.*member).end();
  for (; i != end; ++i) {
    if (std::get<0>(*i) == name) {
      (pkg.*member).erase(i);
      return 1;
    }
  }
  return 0;
}

static inline
int pkg_dependlist_del_full(Package& pkg, DependList Package::*member,
                            const char *name, const char *constraint)
{
  auto i = (pkg.*member).begin();
  auto end = (pkg.*member).end();
  for (; i != end; ++i) {
    if (std::get<0>(*i) == name && std::get<1>(*i) == constraint) {
      (pkg.*member).erase(i);
      return 1;
    }
  }
  return 0;
}

static inline
int pkg_dependlist_del_i(Package& pkg, DependList Package::*member, size_t i) {
  if (i >= (pkg.*member).size())
    return 0;
  (pkg.*member).erase((pkg.*member).begin() + i);
  return 1;
}

size_t pkgdepdb_pkg_dep_count(pkgdepdb_pkg *pkg_, unsigned int what) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_count(*pkg, kDepMember[what]);
}

size_t pkgdepdb_pkg_dep_get(pkgdepdb_pkg *pkg_, unsigned int what,
                            const char **on, const char **oc, size_t off,
                            size_t n)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_get(*pkg, kDepMember[what], on, oc, off, n);
}

int pkgdepdb_pkg_dep_add(pkgdepdb_pkg *pkg_, unsigned int what,
                         const char *name, const char *constraint)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_add(*pkg, kDepMember[what], name, constraint);
}

int pkgdepdb_pkg_dep_del_name(pkgdepdb_pkg *pkg_, unsigned int what,
                              const char *name)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_del_name(*pkg, kDepMember[what], name);
}

int pkgdepdb_pkg_dep_del_full(pkgdepdb_pkg *pkg_, unsigned int what,
                              const char *name, const char *constraint)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_del_full(*pkg, kDepMember[what], name, constraint);
}

int pkgdepdb_pkg_dep_del_i(pkgdepdb_pkg *pkg_, unsigned int what, size_t idx) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  if (what >= kDepMemberCount)
    return 0;
  return pkg_dependlist_del_i(*pkg, kDepMember[what], idx);
}

size_t pkgdepdb_pkg_groups_count(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_count(*pkg, &Package::groups_);
}

size_t pkgdepdb_pkg_groups_get(pkgdepdb_pkg *pkg_, const char **o, size_t n) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_get(*pkg, &Package::groups_, o, 0, n);
}

size_t pkgdepdb_pkg_groups_add(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_add_unique(*pkg, &Package::groups_, v);
}

size_t pkgdepdb_pkg_groups_del_s(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_s_all(*pkg, &Package::groups_, v);
}

size_t pkgdepdb_pkg_groups_del_i(pkgdepdb_pkg *pkg_, size_t index) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_i(*pkg, &Package::groups_, index);
}

size_t pkgdepdb_pkg_filelist_count(pkgdepdb_pkg *pkg_) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_count(*pkg, &Package::filelist_);
}

size_t pkgdepdb_pkg_filelist_get(pkgdepdb_pkg *pkg_,
                                 const char **out, size_t off, size_t count)
{
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_get(*pkg, &Package::filelist_, out, off, count);
}

size_t pkgdepdb_pkg_filelist_add(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_add_always(*pkg, &Package::filelist_, v);
}

size_t pkgdepdb_pkg_filelist_del_s(pkgdepdb_pkg *pkg_, const char *v) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_s_one(*pkg, &Package::filelist_, v);
}

size_t pkgdepdb_pkg_filelist_del_i(pkgdepdb_pkg *pkg_, size_t index) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  return pkgdepdb_strlist_del_i(*pkg, &Package::filelist_, index);
}

void pkgdepdb_pkg_guess_version(pkgdepdb_pkg *pkg_, const char *filename) {
  auto pkg = reinterpret_cast<Package*>(pkg_);
  pkg->Guess(filename);
}

int pkgdepdb_pkg_conflict(pkgdepdb_pkg *subj_, pkgdepdb_pkg *obj_) {
  auto pkg = reinterpret_cast<Package*>(subj_);
  auto obj = reinterpret_cast<Package*>(obj_);
  return pkg->ConflictsWith(*obj);
}

int pkgdepdb_pkg_replaces(pkgdepdb_pkg *subj_, pkgdepdb_pkg *obj_) {
  auto pkg = reinterpret_cast<Package*>(subj_);
  auto obj = reinterpret_cast<Package*>(obj_);
  return pkg->Replaces(*obj);
}

} // extern "C"
<|endoftext|>


<commit_before>// Copyright 2017 Adam Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cctype>
#include <sstream>
#include "as/serial_value/xml.hpp"

#define ASMITH_SERIAL_PTR "as::serial_value::pointer_t="
#define ASMITH_SERIAL_XML "__as_serial_xml_element"

bool write_attribute(std::ostream& aStream, const std::string& aName, const as::serial_value& aValue) {
	//! \todo Remove chars illegal in XML
	switch (aValue.get_type()) {
	case as::serial_value::NULL_T:
		aStream << aName << '=' << '"' << "null" << '"';
		return true;
	case as::serial_value::CHAR_T:
		aStream << aName << '=' << '"' << aValue.get_char() << '"';
		return true;
	case as::serial_value::BOOL_T:
		aStream << aName << '=' << '"' << (aValue.get_bool() ? "true" : "false") << '"';
		return true;
	case as::serial_value::UNSIGNED_T:
		aStream << aName << '=' << '"' << aValue.get_unsigned() << '"';
		return true;
	case as::serial_value::SIGNED_T:
		aStream << aName << '=' << '"' << aValue.get_signed() << '"';
		return true;
	case as::serial_value::FLOAT_T:
		aStream << aName << '=' << '"' << aValue.get_float() << '"';
		return true;
	case as::serial_value::POINTER_T:
		aStream << aName << '=' << '"' << ASMITH_SERIAL_PTR  << aValue.get_pointer() << '"';
		return true;
	case as::serial_value::STRING_T:
		aStream << aName << '=' << '"' << aValue.get_string() << '"';
		return true;
	default:
		return false;
	}
}

void write_element(std::ostream& aStream, const std::string& aName, const as::serial_value& aValue) {
	//! \todo Remove chars illegal in XML
	switch (aValue.get_type()) {
	case as::serial_value::NULL_T:
		aStream << '<' << aName << '/' << '>';
		break;
	case as::serial_value::CHAR_T:
		aStream << '<' << aName << '>' << aValue.get_char() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::BOOL_T:
		aStream << '<' << aName << '>' << (aValue.get_bool() ? "true" : "false") << '<' << '/' << aName << '>';
		break;
	case as::serial_value::UNSIGNED_T:
		aStream << '<' << aName << '>' << aValue.get_unsigned() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::SIGNED_T:
		aStream << '<' << aName << '>' << aValue.get_signed() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::FLOAT_T:
		aStream << '<' << aName << '>' << aValue.get_float() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::POINTER_T:
		aStream << '<' << aName << '>' << ASMITH_SERIAL_PTR << aValue.get_pointer() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::STRING_T:
		aStream << '<' << aName << '>' << aValue.get_string() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::ARRAY_T:
		{
			aStream << '<' << aName << '>';
			const as::serial_value::array_t& array_ = aValue.get_array();
			const size_t s = array_.size();
			for(size_t i = 0; i < s; ++i) write_element(aStream, std::to_string(i), array_[i]);
			aStream << '<' << '/' << aName << '>';
		}
		break;
	case as::serial_value::OBJECT_T:
		{
			const as::serial_value::object_t& object = aValue.get_object();
			aStream << '<' << aName;
			size_t attributes = 0;
			for(const auto& i : object) {
				const as::serial_value::type t = i.second.get_type();
				if(t != as::serial_value::ARRAY_T && t != as::serial_value::OBJECT_T) {
					write_attribute(aStream, i.first, i.second);
					++attributes;
				}
			}

			if(attributes == object.size()) {
				aStream << '/' << '>';
			}else {
				aStream << '>';
				for(const auto& i : object) {
					const as::serial_value::type t = i.second.get_type();
					if(t == as::serial_value::ARRAY_T || t == as::serial_value::OBJECT_T) {
						write_element(aStream, i.first, i.second);
						++attributes;
					}
				}
				aStream << '<' << '/' << aName << '>';
			}
		}
		break;
	}
}

struct element {
	std::string name;
	std::string body;
	std::map<std::string, std::string> attributes;
	std::vector<element> elements;
};

void ignore_whitespace_x(std::istream& aStream) {
	char c = aStream.peek();
	while (std::isspace(c)) {
		aStream >> c;
		c = aStream.peek();
	}
}

void close_closing_tag(std::istream& aStream, element& e) {
	//! \todo Implement
}

void read_closing_name(std::istream& aStream, element& e) {
	//! \todo Implement
	close_closing_tag(aStream, e);
}

void open_closing_tag(std::istream& aStream, element& e) {
	//! \todo Implement
	read_closing_name(aStream, e);
}

void read_elements(std::istream& aStream, element& e) {
	const auto pos = aStream.tellg();
	char c;
	c = aStream.peek();
	if(c != '<') throw std::runtime_error("as::deserialise_xml : Expected element to begin with '<'");
	c = aStream.peek();
	aStream.seekg(pos);
	if(c == '/') {
		// Closing tag of e
		aStream.seekg(pos);
	}else {
		element e2;
		open_opening_tag(aStream, e2);
		e.elements.push_back(e2);
		// Next state
		read_elements(aStream, e);
	}
}

void read_body(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;

	c = aStream.peek();
	if(c == '<') {
		read_elements(aStream, e);
	}else {
		 while (c != '<') {
			 e.body += c;
			 aStream >> c;
			 c = aStream.peek();
		 }
	}

	// Next state
	open_closing_tag(aStream, e);
}

void close_opening_tag(std::istream&, element&);

void read_attribute(std::istream& aStream, element& e) {
	std::string name;
	std::string value;
	char c;

	// Read name
	ignore_whitespace_x(aStream);
	aStream >> c;
	while(c != '='){
		name += c;
		aStream >> c;
	}

	// Read value
	ignore_whitespace_x(aStream);
	aStream >> c;
	if(c != '"') throw std::runtime_error("as::deserialise_xml : Expected attribute value to begin with '\"'");
	aStream >> c;
	while(c != '"') {
		value += c;
		aStream >> c;
	}

	// Next state
	e.attributes.emplace(name, value);
	close_opening_tag(aStream, e);
}

void close_opening_tag(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c = aStream.peek();
	if(c == '/') {
		// End element
		aStream >> c;
		aStream >> c;
		if(c != '>') throw std::runtime_error("as::deserialise_xml : Expected closing tag to end with '>'");
	}else if (c == '>') {
		// Next state
		read_body(aStream, e);
	}else {
		read_attribute(aStream, e);
	}
}

void read_opening_tag_name(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;
	ignore_whitespace_x(aStream);
	c = aStream.peek();
	while(c != '>' && c != '/' && !std::isspace(c)) {
		e.name += c;
		aStream >> c;
		c = aStream.peek();
	}
	// Next state
	close_opening_tag(aStream, e);
}

void open_opening_tag(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;
	aStream >> c;
	if(c != '<') throw std::runtime_error("as::deserialise_xml : Expected opening tag to begin with '<'");
	// Next state
	read_opening_tag_name(aStream, e);
}

as::serial_value convert_element(const element& aElement) {
	// Check if array
	size_t contiguousNames = 0;
	const size_t eCount = aElement.elements.size();
	for(size_t i = 0; i < eCount; ++i) if(aElement.elements[i].name == std::to_string(i)) ++contiguousNames;
	if(eCount > 0 && contiguousNames == eCount) {
		// Element is an array
		as::serial_value tmp;
		as::serial_value::array_t& array_ = tmp.set_array();
		for(size_t i = 0; i < eCount; ++i) array_.push_back(convert_element(aElement.elements[i]));
		return tmp;
	}

	// Check if value
	if(aElement.elements.empty() && aElement.attributes.empty()) {
		// Element is a value
		if(aElement.body.empty()) return as::serial_value();
		else return as::serial_value(aElement.body);
	}

	// Element is an object
	as::serial_value tmp;
	as::serial_value::object_t& object = tmp.set_object();
	if(! aElement.body.empty()) {
		//! \todo Handle body
	}
	for(const auto& i : aElement.attributes) {
		object.emplace(i.first, as::serial_value(i.second));
	}
	for(const auto& i : aElement.elements) {
		//! \todo Handle for name conflicts
		object.emplace(i.name, convert_element(i));
	}
	return tmp;
}

namespace as {
	void serialise_xml(std::ostream& aStream, const serial_value& aValue) {
		write_element(aStream, ASMITH_SERIAL_XML, aValue);
	}

	serial_value deserialise_xml(std::istream& aStream) {
		//! \todo Handle XML header
		//! \todo Handle XML comments
		element e;
		open_opening_tag(aStream, e);
		return convert_element(e);
	}

}<commit_msg>Implemented closing tag code<commit_after>// Copyright 2017 Adam Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cctype>
#include <sstream>
#include "as/serial_value/xml.hpp"

#define ASMITH_SERIAL_PTR "as::serial_value::pointer_t="
#define ASMITH_SERIAL_XML "__as_serial_xml_element"

bool write_attribute(std::ostream& aStream, const std::string& aName, const as::serial_value& aValue) {
	//! \todo Remove chars illegal in XML
	switch (aValue.get_type()) {
	case as::serial_value::NULL_T:
		aStream << aName << '=' << '"' << "null" << '"';
		return true;
	case as::serial_value::CHAR_T:
		aStream << aName << '=' << '"' << aValue.get_char() << '"';
		return true;
	case as::serial_value::BOOL_T:
		aStream << aName << '=' << '"' << (aValue.get_bool() ? "true" : "false") << '"';
		return true;
	case as::serial_value::UNSIGNED_T:
		aStream << aName << '=' << '"' << aValue.get_unsigned() << '"';
		return true;
	case as::serial_value::SIGNED_T:
		aStream << aName << '=' << '"' << aValue.get_signed() << '"';
		return true;
	case as::serial_value::FLOAT_T:
		aStream << aName << '=' << '"' << aValue.get_float() << '"';
		return true;
	case as::serial_value::POINTER_T:
		aStream << aName << '=' << '"' << ASMITH_SERIAL_PTR  << aValue.get_pointer() << '"';
		return true;
	case as::serial_value::STRING_T:
		aStream << aName << '=' << '"' << aValue.get_string() << '"';
		return true;
	default:
		return false;
	}
}

void write_element(std::ostream& aStream, const std::string& aName, const as::serial_value& aValue) {
	//! \todo Remove chars illegal in XML
	switch (aValue.get_type()) {
	case as::serial_value::NULL_T:
		aStream << '<' << aName << '/' << '>';
		break;
	case as::serial_value::CHAR_T:
		aStream << '<' << aName << '>' << aValue.get_char() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::BOOL_T:
		aStream << '<' << aName << '>' << (aValue.get_bool() ? "true" : "false") << '<' << '/' << aName << '>';
		break;
	case as::serial_value::UNSIGNED_T:
		aStream << '<' << aName << '>' << aValue.get_unsigned() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::SIGNED_T:
		aStream << '<' << aName << '>' << aValue.get_signed() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::FLOAT_T:
		aStream << '<' << aName << '>' << aValue.get_float() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::POINTER_T:
		aStream << '<' << aName << '>' << ASMITH_SERIAL_PTR << aValue.get_pointer() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::STRING_T:
		aStream << '<' << aName << '>' << aValue.get_string() << '<' << '/' << aName << '>';
		break;
	case as::serial_value::ARRAY_T:
		{
			aStream << '<' << aName << '>';
			const as::serial_value::array_t& array_ = aValue.get_array();
			const size_t s = array_.size();
			for(size_t i = 0; i < s; ++i) write_element(aStream, std::to_string(i), array_[i]);
			aStream << '<' << '/' << aName << '>';
		}
		break;
	case as::serial_value::OBJECT_T:
		{
			const as::serial_value::object_t& object = aValue.get_object();
			aStream << '<' << aName;
			size_t attributes = 0;
			for(const auto& i : object) {
				const as::serial_value::type t = i.second.get_type();
				if(t != as::serial_value::ARRAY_T && t != as::serial_value::OBJECT_T) {
					write_attribute(aStream, i.first, i.second);
					++attributes;
				}
			}

			if(attributes == object.size()) {
				aStream << '/' << '>';
			}else {
				aStream << '>';
				for(const auto& i : object) {
					const as::serial_value::type t = i.second.get_type();
					if(t == as::serial_value::ARRAY_T || t == as::serial_value::OBJECT_T) {
						write_element(aStream, i.first, i.second);
						++attributes;
					}
				}
				aStream << '<' << '/' << aName << '>';
			}
		}
		break;
	}
}

struct element {
	std::string name;
	std::string body;
	std::map<std::string, std::string> attributes;
	std::vector<element> elements;
};

void ignore_whitespace_x(std::istream& aStream) {
	char c = aStream.peek();
	while (std::isspace(c)) {
		aStream >> c;
		c = aStream.peek();
	}
}

void close_closing_tag(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;
	aStream >> c;
	if(c != '>') throw std::runtime_error("as::deserialise_xml : Expected closing tag to end with '>'");
}

void read_closing_name(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;
	ignore_whitespace_x(aStream);
	c = aStream.peek();
	std::string name;
	while(c != '>' && ! std::isspace(c)) {
		name += c;
		aStream >> c;
		c = aStream.peek();
	}
	if(name != e.name) throw std::runtime_error("as::deserialise_xml : Expected closing tag to have same name as opening tag");
	// Next state
	close_closing_tag(aStream, e);
}

void open_closing_tag(std::istream& aStream, element& e) {
	read_closing_name(aStream, e);
	char c;
	aStream >> c;
	if(c != '<') throw std::runtime_error("as::deserialise_xml : Expected closing tag to begin with '</'");
	aStream >> c;
	if(c != '/') throw std::runtime_error("as::deserialise_xml : Expected closing tag to begin with '</'");
	// Next state
	read_closing_name(aStream, e);
}

void open_opening_tag(std::istream&, element&);

void read_elements(std::istream& aStream, element& e) {
	const auto pos = aStream.tellg();
	char c;
	c = aStream.peek();
	if(c != '<') throw std::runtime_error("as::deserialise_xml : Expected element to begin with '<'");
	c = aStream.peek();
	aStream.seekg(pos);
	if(c == '/') {
		// Closing tag of e
		aStream.seekg(pos);
	}else {
		element e2;
		open_opening_tag(aStream, e2);
		e.elements.push_back(e2);
		// Next state
		read_elements(aStream, e);
	}
}

void read_body(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;

	c = aStream.peek();
	if(c == '<') {
		read_elements(aStream, e);
	}else {
		 while (c != '<') {
			 e.body += c;
			 aStream >> c;
			 c = aStream.peek();
		 }
	}

	// Next state
	open_closing_tag(aStream, e);
}

void close_opening_tag(std::istream&, element&);

void read_attribute(std::istream& aStream, element& e) {
	std::string name;
	std::string value;
	char c;

	// Read name
	ignore_whitespace_x(aStream);
	aStream >> c;
	while(c != '='){
		name += c;
		aStream >> c;
	}

	// Read value
	ignore_whitespace_x(aStream);
	aStream >> c;
	if(c != '"') throw std::runtime_error("as::deserialise_xml : Expected attribute value to begin with '\"'");
	aStream >> c;
	while(c != '"') {
		value += c;
		aStream >> c;
	}

	// Next state
	e.attributes.emplace(name, value);
	close_opening_tag(aStream, e);
}

void close_opening_tag(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c = aStream.peek();
	if(c == '/') {
		// End element
		aStream >> c;
		aStream >> c;
		if(c != '>') throw std::runtime_error("as::deserialise_xml : Expected closing tag to end with '>'");
	}else if (c == '>') {
		// Next state
		read_body(aStream, e);
	}else {
		read_attribute(aStream, e);
	}
}

void read_opening_tag_name(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;
	ignore_whitespace_x(aStream);
	c = aStream.peek();
	while(c != '>' && c != '/' && !std::isspace(c)) {
		e.name += c;
		aStream >> c;
		c = aStream.peek();
	}
	// Next state
	close_opening_tag(aStream, e);
}

void open_opening_tag(std::istream& aStream, element& e) {
	ignore_whitespace_x(aStream);
	char c;
	aStream >> c;
	if(c != '<') throw std::runtime_error("as::deserialise_xml : Expected opening tag to begin with '<'");
	// Next state
	read_opening_tag_name(aStream, e);
}

as::serial_value convert_element(const element& aElement) {
	// Check if array
	size_t contiguousNames = 0;
	const size_t eCount = aElement.elements.size();
	for(size_t i = 0; i < eCount; ++i) if(aElement.elements[i].name == std::to_string(i)) ++contiguousNames;
	if(eCount > 0 && contiguousNames == eCount) {
		// Element is an array
		as::serial_value tmp;
		as::serial_value::array_t& array_ = tmp.set_array();
		for(size_t i = 0; i < eCount; ++i) array_.push_back(convert_element(aElement.elements[i]));
		return tmp;
	}

	// Check if value
	if(aElement.elements.empty() && aElement.attributes.empty()) {
		// Element is a value
		if(aElement.body.empty()) return as::serial_value();
		else return as::serial_value(aElement.body);
	}

	// Element is an object
	as::serial_value tmp;
	as::serial_value::object_t& object = tmp.set_object();
	if(! aElement.body.empty()) {
		//! \todo Handle body
	}
	for(const auto& i : aElement.attributes) {
		object.emplace(i.first, as::serial_value(i.second));
	}
	for(const auto& i : aElement.elements) {
		//! \todo Handle for name conflicts
		object.emplace(i.name, convert_element(i));
	}
	return tmp;
}

namespace as {
	void serialise_xml(std::ostream& aStream, const serial_value& aValue) {
		write_element(aStream, ASMITH_SERIAL_XML, aValue);
	}

	serial_value deserialise_xml(std::istream& aStream) {
		//! \todo Handle XML header
		//! \todo Handle XML comments
		element e;
		open_opening_tag(aStream, e);
		return convert_element(e);
	}

}<|endoftext|>