<commit_before>/*************************************************************************
 *
 *  $RCSfile: servprov.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2004-02-25 17:09:48 $
 *
 *  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 "servprov.hxx"
#include "embeddoc.hxx"

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif

using namespace com::sun::star;

const GUID* guidList[ SUPPORTED_FACTORIES_NUM ] = {
    &OID_WriterTextServer,
//  &OID_WriterWebServer,
//  &OID_WriterGlobalServer,
    &OID_CalcServer,
    &OID_DrawingServer,
    &OID_PresentationServer,
    &OID_MathServer
};

class CurThreadData
{
    public:
        CurThreadData();
        virtual ~CurThreadData();

        sal_Bool SAL_CALL setData(void *pData);

        void* SAL_CALL getData();

    protected:
        oslThreadKey m_hKey;
};

CurThreadData::CurThreadData()
{
    m_hKey = osl_createThreadKey( (oslThreadKeyCallbackFunction)NULL );
}

CurThreadData::~CurThreadData()
{
    osl_destroyThreadKey(m_hKey);
}

sal_Bool CurThreadData::setData(void *pData)
{
    OSL_ENSURE( m_hKey, "No thread key!\n" );
    return (osl_setThreadKeyData(m_hKey, pData));
}

void *CurThreadData::getData()
{
    OSL_ENSURE( m_hKey, "No thread key!\n" );
    return (osl_getThreadKeyData(m_hKey));
}

// CoInitializeEx *
typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInitEx)( LPVOID, DWORD);
// CoInitialize *
typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInit)( LPVOID);

void o2u_attachCurrentThread()
{
    static CurThreadData oleThreadData;

    if ((sal_Bool)oleThreadData.getData() != sal_True)
    {
        HINSTANCE inst= LoadLibrary( _T("ole32.dll"));
        if( inst )
        {
            HRESULT hr;
            ptrCoInitEx initFuncEx= (ptrCoInitEx)GetProcAddress( inst, _T("CoInitializeEx"));
            if( initFuncEx)
                hr= initFuncEx( NULL, COINIT_MULTITHREADED);
            else
            {
                ptrCoInit initFunc= (ptrCoInit)GetProcAddress( inst,_T("CoInitialize"));
                if( initFunc)
                    hr= initFunc( NULL);
            }
        }
        oleThreadData.setData((void*)sal_True);
    }
}

//===============================================================================
// EmbedServer_Impl

EmbedServer_Impl::EmbedServer_Impl( const uno::Reference<lang::XMultiServiceFactory>& xFactory):
    m_xFactory( xFactory)
{
    for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
    {
        m_pOLEFactories[nInd] = new EmbedProviderFactory_Impl( m_xFactory, guidList[nInd] );
        m_pOLEFactories[nInd]->registerClass();
    }
}

EmbedServer_Impl::~EmbedServer_Impl()
{
    for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
    {
        if ( m_pOLEFactories[nInd] )
            m_pOLEFactories[nInd]->deregisterClass();
    }
}

// XInterface --------------------------------------------------
uno::Any SAL_CALL
EmbedServer_Impl::queryInterface(
    const uno::Type& aType )
    throw(
        uno::RuntimeException
    )
{
    uno::Any a=
        ::cppu::queryInterface(
            aType, static_cast<lang::XTypeProvider*>(this));
    if( a == uno::Any())
        return OWeakObject::queryInterface( aType);
    else
        return a;
}

void SAL_CALL EmbedServer_Impl::acquire(  ) throw(uno::RuntimeException)
{
    OWeakObject::acquire();
}

void SAL_CALL EmbedServer_Impl::release(  ) throw (uno::RuntimeException)
{
    OWeakObject::release();
}

// XTypeProvider --------------------------------------------------
uno::Sequence< uno::Type > SAL_CALL
EmbedServer_Impl::getTypes( )
    throw(
        uno::RuntimeException
    )
{
    static ::cppu::OTypeCollection *pCollection = 0;
    if( ! pCollection )
    {
        ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
        if( ! pCollection )
        {
            static ::cppu::OTypeCollection collection(
                getCppuType(
                    reinterpret_cast<uno::Reference< uno::XWeak>*>(0)),
                getCppuType(
                    reinterpret_cast<
                    uno::Reference< lang::XTypeProvider>*>(0)));
            pCollection = &collection;
        }
    }
    return (*pCollection).getTypes();
}

uno::Sequence< sal_Int8 > SAL_CALL EmbedServer_Impl::getImplementationId() throw(uno::RuntimeException)
{
    static ::cppu::OImplementationId *pId = 0;
    if( ! pId )
    {
        ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
        if( ! pId )
        {
            static ::cppu::OImplementationId id( sal_False );
            pId = &id;
        }
    }
    return (*pId).getImplementationId();
}

//===============================================================================
// EmbedProviderFactory_Impl

EmbedProviderFactory_Impl::EmbedProviderFactory_Impl(const uno::Reference<lang::XMultiServiceFactory>& xFactory, const GUID* pGuid)
    : m_refCount( 0L )
    , m_xFactory( xFactory )
    , m_guid( *pGuid )
{
}

EmbedProviderFactory_Impl::~EmbedProviderFactory_Impl()
{
}

sal_Bool EmbedProviderFactory_Impl::registerClass()
{
    HRESULT hresult;

    o2u_attachCurrentThread();

    hresult = CoRegisterClassObject(
            m_guid,
            this,
            CLSCTX_LOCAL_SERVER,
            REGCLS_MULTIPLEUSE,
            &m_factoryHandle);

    return (hresult == NOERROR);
}

sal_Bool EmbedProviderFactory_Impl::deregisterClass()
{
    HRESULT hresult = CoRevokeClassObject( m_factoryHandle );

    return (hresult == NOERROR);
}

STDMETHODIMP EmbedProviderFactory_Impl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
    if(IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppv = (IUnknown*) (IClassFactory*) this;
        return NOERROR;
    }
    else if (IsEqualIID(riid, IID_IClassFactory))
    {
        AddRef();
        *ppv = (IClassFactory*) this;
        return NOERROR;
    }

    *ppv = NULL;
    return ResultFromScode(E_NOINTERFACE);
}

STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::AddRef()
{
    return osl_incrementInterlockedCount( &m_refCount);
}

STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::Release()
{
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex());
    m_refCount--;
    if (m_refCount == 0)
    {
        delete this;
    }

    return m_refCount;
}

STDMETHODIMP EmbedProviderFactory_Impl::CreateInstance(IUnknown FAR* punkOuter,
                                                     REFIID riid,
                                                     void FAR* FAR* ppv)
{
    punkOuter = NULL;

    IUnknown* pEmbedDocument = (IUnknown*)(IPersistStorage*)( new EmbedDocument_Impl( m_xFactory, &m_guid ) );

    return pEmbedDocument->QueryInterface( riid, ppv );
}

STDMETHODIMP EmbedProviderFactory_Impl::LockServer( int fLock )
{
    return NOERROR;
}

<commit_msg>INTEGRATION: CWS fwkmerge1 (1.3.42); FILE MERGED 2004/02/19 15:52:16 mav 1.3.42.1: #115237# integrate fix for 111921<commit_after>/*************************************************************************
 *
 *  $RCSfile: servprov.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2004-03-09 10:06:10 $
 *
 *  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 "servprov.hxx"
#include "embeddoc.hxx"

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _OSL_THREAD_H_
#include <osl/thread.h>
#endif

using namespace com::sun::star;

const GUID* guidList[ SUPPORTED_FACTORIES_NUM ] = {
    &OID_WriterTextServer,
//  &OID_WriterWebServer,
//  &OID_WriterGlobalServer,
    &OID_CalcServer,
    &OID_DrawingServer,
    &OID_PresentationServer,
    &OID_MathServer
};

class CurThreadData
{
    public:
        CurThreadData();
        virtual ~CurThreadData();

        sal_Bool SAL_CALL setData(void *pData);

        void* SAL_CALL getData();

    protected:
        oslThreadKey m_hKey;
};

CurThreadData::CurThreadData()
{
    m_hKey = osl_createThreadKey( (oslThreadKeyCallbackFunction)NULL );
}

CurThreadData::~CurThreadData()
{
    osl_destroyThreadKey(m_hKey);
}

sal_Bool CurThreadData::setData(void *pData)
{
    OSL_ENSURE( m_hKey, "No thread key!\n" );
    return (osl_setThreadKeyData(m_hKey, pData));
}

void *CurThreadData::getData()
{
    OSL_ENSURE( m_hKey, "No thread key!\n" );
    return (osl_getThreadKeyData(m_hKey));
}

// CoInitializeEx *
typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInitEx)( LPVOID, DWORD);
// CoInitialize *
typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInit)( LPVOID);

void o2u_attachCurrentThread()
{
    static CurThreadData oleThreadData;

    if ((sal_Bool)oleThreadData.getData() != sal_True)
    {
        HINSTANCE inst= LoadLibrary( _T("ole32.dll"));
        if( inst )
        {
            HRESULT hr;
            ptrCoInitEx initFuncEx= (ptrCoInitEx)GetProcAddress( inst, _T("CoInitializeEx"));
            if( initFuncEx)
                hr= initFuncEx( NULL, COINIT_MULTITHREADED);
            else
            {
                ptrCoInit initFunc= (ptrCoInit)GetProcAddress( inst,_T("CoInitialize"));
                if( initFunc)
                    hr= initFunc( NULL);
            }
        }
        oleThreadData.setData((void*)sal_True);
    }
}

//===============================================================================
// EmbedServer_Impl

EmbedServer_Impl::EmbedServer_Impl( const uno::Reference<lang::XMultiServiceFactory>& xFactory):
    m_xFactory( xFactory)
{
    for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
    {
        m_pOLEFactories[nInd] = new EmbedProviderFactory_Impl( m_xFactory, guidList[nInd] );
        m_pOLEFactories[nInd]->registerClass();
    }
}

EmbedServer_Impl::~EmbedServer_Impl()
{
    for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
    {
        if ( m_pOLEFactories[nInd] )
            m_pOLEFactories[nInd]->deregisterClass();
    }
}

// XInterface --------------------------------------------------
uno::Any SAL_CALL
EmbedServer_Impl::queryInterface(
    const uno::Type& aType )
    throw(
        uno::RuntimeException
    )
{
    uno::Any a=
        ::cppu::queryInterface(
            aType, static_cast<lang::XTypeProvider*>(this));
    if( a == uno::Any())
        return OWeakObject::queryInterface( aType);
    else
        return a;
}

void SAL_CALL EmbedServer_Impl::acquire(  ) throw(uno::RuntimeException)
{
    OWeakObject::acquire();
}

void SAL_CALL EmbedServer_Impl::release(  ) throw (uno::RuntimeException)
{
    OWeakObject::release();
}

// XTypeProvider --------------------------------------------------
uno::Sequence< uno::Type > SAL_CALL
EmbedServer_Impl::getTypes( )
    throw(
        uno::RuntimeException
    )
{
    static ::cppu::OTypeCollection *pCollection = 0;
    if( ! pCollection )
    {
        ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
        if( ! pCollection )
        {
            static ::cppu::OTypeCollection collection(
                getCppuType(
                    reinterpret_cast<uno::Reference< uno::XWeak>*>(0)),
                getCppuType(
                    reinterpret_cast<
                    uno::Reference< lang::XTypeProvider>*>(0)));
            pCollection = &collection;
        }
    }
    return (*pCollection).getTypes();
}

uno::Sequence< sal_Int8 > SAL_CALL EmbedServer_Impl::getImplementationId() throw(uno::RuntimeException)
{
    static ::cppu::OImplementationId *pId = 0;
    if( ! pId )
    {
        ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
        if( ! pId )
        {
            static ::cppu::OImplementationId id( sal_False );
            pId = &id;
        }
    }
    return (*pId).getImplementationId();
}

//===============================================================================
// EmbedProviderFactory_Impl

EmbedProviderFactory_Impl::EmbedProviderFactory_Impl(const uno::Reference<lang::XMultiServiceFactory>& xFactory, const GUID* pGuid)
    : m_refCount( 0L )
    , m_xFactory( xFactory )
    , m_guid( *pGuid )
{
}

EmbedProviderFactory_Impl::~EmbedProviderFactory_Impl()
{
}

sal_Bool EmbedProviderFactory_Impl::registerClass()
{
    HRESULT hresult;

    o2u_attachCurrentThread();

    hresult = CoRegisterClassObject(
            m_guid,
            this,
            CLSCTX_LOCAL_SERVER,
            REGCLS_MULTIPLEUSE,
            &m_factoryHandle);

    return (hresult == NOERROR);
}

sal_Bool EmbedProviderFactory_Impl::deregisterClass()
{
    HRESULT hresult = CoRevokeClassObject( m_factoryHandle );

    return (hresult == NOERROR);
}

STDMETHODIMP EmbedProviderFactory_Impl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
    if(IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppv = (IUnknown*) (IClassFactory*) this;
        return NOERROR;
    }
    else if (IsEqualIID(riid, IID_IClassFactory))
    {
        AddRef();
        *ppv = (IClassFactory*) this;
        return NOERROR;
    }

    *ppv = NULL;
    return ResultFromScode(E_NOINTERFACE);
}

STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::AddRef()
{
    return osl_incrementInterlockedCount( &m_refCount);
}

STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::Release()
{
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex());
    sal_Int32 nCount = --m_refCount;
    if ( nCount == 0 )
    {
        delete this;
    }

    return nCount;
}

STDMETHODIMP EmbedProviderFactory_Impl::CreateInstance(IUnknown FAR* punkOuter,
                                                     REFIID riid,
                                                     void FAR* FAR* ppv)
{
    punkOuter = NULL;

    IUnknown* pEmbedDocument = (IUnknown*)(IPersistStorage*)( new EmbedDocument_Impl( m_xFactory, &m_guid ) );

    return pEmbedDocument->QueryInterface( riid, ppv );
}

STDMETHODIMP EmbedProviderFactory_Impl::LockServer( int fLock )
{
    return NOERROR;
}

<|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

#include "libbirch/external.hpp"
#include "libbirch/memory.hpp"
#include "libbirch/Atomic.hpp"

namespace libbirch {
class Label;
class Finisher;
class Freezer;
class Copier;
class Recycler;
class Discarder;
class Restorer;

/**
 * Base class for reference counted objects.
 *
 * @ingroup libbirch
 *
 * @attention In order to work correctly with multiple inheritance, Any must
 * be the *first* base class.
 *
 * Reference-counted objects in LibBirch require four counts, rather than
 * the usual two (shared and weak), in order to support lazy deep copy
 * operations. These are:
 *
 *   - a *shared* count,
 *   - a *memo shared* count,
 *   - a *weak* count, and
 *   - a *memo weak* count.
 *
 * The shared and weak counts behave as normal. The memo shared and memo weak
 * counts serve to determine when an object is only reachable via a memo used
 * to bookkeep lazy deep copy operations. Objects that are only reachable via
 * a memo may be eligible for collection.
 *
 * The movement of the four counts triggers the following operations:
 *
 *   -# When the shared count reaches zero, the object is *discarded*.
 *   -# If the shared count subsequently becomes nonzero again (this is
 *      allowed as long as the memo shared count is nonzero), the object is
 *      *restored*.
 *   -# If the shared and memo shared counts reach 0, the object is
 *      *destroyed*.
 *   -# If the weak and memo weak counts reach 0, the object is *deallocated*.
 *
 * These operations behave as follows:
 *
 *   - **Discard** downgrades all shared pointers in the object to memo
 *     shared pointers.
 *   - **Restore** upgrades those memo shared pointers to shared pointers
 *     again.
 *   - **Destroy** calls the destructor of the object.
 *   - **Deallocate** collects the memory allocated to the object.
 *
 * The discard operation may be skipped when the destroy operation would
 * immediately follow anyway; i.e. when the shared count reaches zero and the
 * memo shared count is already at zero.
 *
 * At a high level, shared and weak pointers serve to determine which objects
 * are reachable from the user program, while memo shared and memo weak
 * pointers are used to determine which objects are reachable via a memo,
 * and to break reference cycles that are induced by the memo, but which
 * do not exist in the user program *per se*.
 *
 * A discarded object is in a state where reference cycles induced by a memo
 * are broken, but it is otherwise still a valid object, and may still be
 * accessible via a weak pointer in the user program.
 */
class Any {
public:
  using class_type_ = Any;
  using this_type_ = Any;

  /**
   * Constructor.
   */
  Any() :
      sharedCount(0u),
      memoSharedCount(0u),
      weakCount(1u),
      memoWeakCount(1u),
      label(rootLabel),
      finished(false),
      frozen(false),
      frozenUnique(false),
      discarded(false) {
    // size and tid set by operator new
  }

  /**
   * Special constructor for the root label.
   */
  Any(int) :
      sharedCount(0u),
      memoSharedCount(0u),
      weakCount(1u),
      memoWeakCount(1u),
      label(nullptr),
      finished(false),
      frozen(false),
      frozenUnique(false),
      discarded(false) {
    // size and tid set by operator new
  }

  /**
   * Copy constructor.
   */
  Any(const Any& o) : Any() {
    //
  }

  /**
   * Destructor.
   */
  virtual ~Any() {
    assert(sharedCount.load() == 0u);
    assert(memoSharedCount.load() == 0u);
  }

  /**
   * New operator.
   */
  void* operator new(std::size_t size) {
    auto ptr = static_cast<Any*>(allocate(size));
    ptr->size = static_cast<unsigned>(size);
    ptr->tid = get_thread_num();
    return ptr;
  }

  /**
   * Delete operator.
   */
  void operator delete(void* ptr) {
    auto o = static_cast<Any*>(ptr);
    o->destroy();
    o->deallocate();
  }

  /**
   * Assignment operator.
   */
  Any& operator=(const Any&) {
    return *this;
  }

  /**
   * Get the size, in bytes, of the object.
   */
  unsigned getSize() const {
    return size;
  }

  /**
   * Is this object reachable? An object is reachable if there exists a
   * shared, memo shared, or weak pointer to it. If only a memo weak pointer
   * to it exists, it is not considered reachable, and it may be cleaned up
   * during memo maintenance.
   */
  bool isReachable() const {
    return numWeak() > 0u;
  }

  /**
   * Is there definitely only one pointer to this object? This is
   * conservative; it returns true if there is at most one shared or weak
   * pointer to the object. Note, in particular, that the presence of a memo
   * shared pointer means that an unknown number of pointers (including zero
   * pointers) may update to the object in future.
   */
  bool isUnique() const {
    auto sharedCount = numShared();
    auto memoSharedCount = numMemoShared();
    auto weakCount = numWeak();
    auto memoWeakCount = numMemoWeak();

    return (sharedCount == 1u && memoSharedCount == 1u && weakCount == 1u && memoWeakCount == 1u) ||
        (sharedCount == 0u && memoSharedCount == 0u && weakCount == 1u && memoWeakCount == 1u);
  }

  /**
   * Get the class name.
   */
  virtual const char* getClassName() const {
    return "Any";
  }

  /**
   * Finish the object.
   */
  void finish(Label* label) {
    if (!finished.exchange(true)) {
      /* proceed with finish */
      finish_(label);
    }
  }

  /**
   * Freeze the object.
   */
  void freeze() {
    assert(finished.load());
    if (!frozen.exchange(true)) {
      /* proceed with freeze */
      frozenUnique.store(isUnique());
      freeze_();
    }
  }

  /**
   * Copy the object.
   *
   * @param label The new label.
   */
  Any* copy(Label* label) {
    auto o = copy_(label);
    o->sharedCount.set(0u);
    o->memoSharedCount.set(0u);
    o->weakCount.set(1u);
    o->memoWeakCount.set(1u);
    o->label = label;
    o->finished.set(false);
    o->frozen.set(false);
    o->frozenUnique.set(false);
    o->discarded.set(false);
    return o;
  }

  /**
   * Recycle the object.
   *
   * @param label The new label.
   */
  Any* recycle(Label* label) {
    auto o = recycle_(label);
    o->releaseLabel();
    o->label = label;
    o->holdLabel();
    o->thaw();
    return this;
  }

  /**
   * Thaw the object.
   */
  void thaw() {
    finished.store(false);
    frozen.store(false);
    frozenUnique.store(false);
    discarded.store(false);
  }

  /**
   * Discard the object.
   */
  void discard() {
    if (!discarded.exchange(true)) {
      discard_();
    }
  }

  /**
   * Restore the object.
   */
  void restore() {
    if (discarded.exchange(false)) {
      restore_();
    }
  }

  /**
   * Shared count.
   */
  unsigned numShared() const {
    return sharedCount.load();
  }

  /**
   * Increment the shared count.
   */
  void incShared() {
    if (++sharedCount == 1u) {
      incMemoShared();
      holdLabel();
      if (discarded.load()) {  // only false when initializing object
        restore();
      }
    }
  }

  /**
   * Decrement the shared count.
   */
  void decShared() {
    assert(numShared() > 0u);
    if (--sharedCount == 0u) {
      releaseLabel();
      assert(numMemoShared() > 0u);
      if (--memoSharedCount == 0u) {
        /* skip the discard() in this case, just destroy() */
        destroy();
        decWeak();
      } else {
        discard();
      }
    }
  }

  /**
   * Memo shared count.
   */
  unsigned numMemoShared() const {
    return memoSharedCount.load();
  }

  /**
   * Increment the memo shared count.
   */
  void incMemoShared() {
    memoSharedCount.increment();
  }

  /**
   * Decrement the memo shared count.
   */
  void decMemoShared() {
    assert(numMemoShared() > 0u);
    if (--memoSharedCount == 0u) {
      assert(numShared() == 0u);
      destroy();
      decWeak();
    }
  }

  /**
   * Simultaneously decrement the shared count and increment the shared memo
   * count.
   */
  void discardShared() {
    assert(numShared() > 0u);
    if (--sharedCount == 0u) {
      assert(!discarded.load());
      discard();
      releaseLabel();
    } else {
      incMemoShared();
    }
  }

  /**
   * Simultaneously increment the shared count and decrement the shared memo
   * count.
   */
  void restoreShared() {
    if (++sharedCount == 1u) {
      assert(discarded.load());
      holdLabel();
      restore();
    } else {
      decMemoShared();
    }
  }

  /**
   * Weak count.
   */
  unsigned numWeak() const {
    return weakCount.load();
  }

  /**
   * Increment the weak count.
   */
  void incWeak() {
    weakCount.increment();
  }

  /**
   * Decrement the weak count.
   */
  void decWeak() {
    assert(weakCount.load() > 0u);
    if (--weakCount == 0u) {
      assert(numShared() == 0u);
      assert(numMemoShared() == 0u);
      decMemoWeak();
    }
  }

  /**
   * Memo weak count.
   */
  unsigned numMemoWeak() const {
    return memoWeakCount.load();
  }

  /**
   * Increment the memo weak count.
   */
  void incMemoWeak() {
    memoWeakCount.increment();
  }

  /**
   * Decrement the memo weak count.
   */
  void decMemoWeak() {
    assert(memoWeakCount.load() > 0u);
    if (--memoWeakCount == 0u) {
      assert(numShared() == 0u);
      assert(numMemoShared() == 0u);
      assert(numWeak() == 0u);
      deallocate();
    }
  }

  /**
   * Get the label assigned to the object.
   */
  Label* getLabel() const {
    return label;
  }

  /**
   * Is the object finished?
   */
  bool isFinished() const {
    return finished.load();
  }

  /**
   * Is the object frozen?
   */
  bool isFrozen() const {
    return frozen.load();
  }

  /**
   * Is the object frozen, and at the time of freezing, was there only one
   * pointer to it?
   */
  bool isFrozenUnique() const {
    return frozenUnique.load();
  }

  /**
   * Is the object discarded?
   */
  bool isDiscarded() const {
    return discarded.load();
  }

protected:
  /**
   * Increment the shared count of the label. This is used during
   * initialization and restoration.
   */
  void holdLabel();

  /**
   * Decrement the shared count of the label. This is used during discard.
   */
  void releaseLabel();

  /**
   * Finish the member variables of the object.
   */
  virtual void finish_(Label* label) = 0;

  /**
   * Freeze the member variables of the object.
   */
  virtual void freeze_() = 0;

  /**
   * Copy the object.
   *
   * @param label The new label.
   */
  virtual Any* copy_(Label* label) const = 0;

  /**
   * Recycle the object.
   *
   * @param label The new label.
   */
  virtual Any* recycle_(Label* label) = 0;

  /**
   * Discard the object.
   */
  virtual void discard_() = 0;

  /**
   * Restore the object.
   */
  virtual void restore_() = 0;

  /**
   * Accept a visitor across member variables.
   */
  template<class Visitor>
  void accept_(const Visitor& v) {
    //
  }

private:
  /**
   * Destroy, but do not deallocate, the object.
   */
  void destroy() {
    assert(sharedCount.load() == 0u);
    assert(memoSharedCount.load() == 0u);
    this->~Any();
  }

  /**
   * Deallocate the object. It should have previously been destroyed.
   */
  void deallocate() {
    assert(sharedCount.load() == 0u);
    assert(memoSharedCount.load() == 0u);
    assert(weakCount.load() == 0u);
    assert(memoWeakCount.load() == 0u);
    libbirch::deallocate(this, size, tid);
  }

  /**
   * Shared count.
   */
  Atomic<unsigned> sharedCount;

  /**
   * Memo shared count, or, if the shared count is nonzero, one plus the memo
   * shared count.
   */
  Atomic<unsigned> memoSharedCount;

  /**
   * Weak count, or, if the memo shared count is nonzero, one plus the weak
   * count.
   */
  Atomic<unsigned> weakCount;

  /**
   * Memo weak count, or, if the weak count is nonzero, one plus the memo
   * weak count.
   */
  Atomic<unsigned> memoWeakCount;

  /**
   * Label of the object.
   */
  Label* label;

  /**
   * Size of the object. This is set immediately after construction. A value
   * of zero is also indicative that the object is still being constructed.
   * Consequently, if the shared count reaches zero while the size is zero,
   * the object is not destroyed. This can happen when constructors create
   * shared pointers to `this`.
   */
  unsigned size;

  /**
   * Id of the thread associated with the object. This is used to return the
   * allocation to the correct pool after use, even when returned by a
   * different thread.
   */
  int tid;

  /**
   * Finished flag.
   */
  Atomic<bool> finished;

  /**
   * Frozen flag. A frozen object is read-only.
   */
  Atomic<bool> frozen;

  /**
   * Is the object frozen, and at the time of freezing, was there only one
   * pointer to it?
   */
  Atomic<bool> frozenUnique;

  /**
   * Discard flag.
   */
  Atomic<bool> discarded;
};
}
<commit_msg>Fixed allocations being returned to wrong memory pool due to thread id being overwritten in new bitwise implementation of deep copy.<commit_after>/**
 * @file
 */
#pragma once

#include "libbirch/external.hpp"
#include "libbirch/memory.hpp"
#include "libbirch/Atomic.hpp"

namespace libbirch {
class Label;
class Finisher;
class Freezer;
class Copier;
class Recycler;
class Discarder;
class Restorer;

/**
 * Base class for reference counted objects.
 *
 * @ingroup libbirch
 *
 * @attention In order to work correctly with multiple inheritance, Any must
 * be the *first* base class.
 *
 * Reference-counted objects in LibBirch require four counts, rather than
 * the usual two (shared and weak), in order to support lazy deep copy
 * operations. These are:
 *
 *   - a *shared* count,
 *   - a *memo shared* count,
 *   - a *weak* count, and
 *   - a *memo weak* count.
 *
 * The shared and weak counts behave as normal. The memo shared and memo weak
 * counts serve to determine when an object is only reachable via a memo used
 * to bookkeep lazy deep copy operations. Objects that are only reachable via
 * a memo may be eligible for collection.
 *
 * The movement of the four counts triggers the following operations:
 *
 *   -# When the shared count reaches zero, the object is *discarded*.
 *   -# If the shared count subsequently becomes nonzero again (this is
 *      allowed as long as the memo shared count is nonzero), the object is
 *      *restored*.
 *   -# If the shared and memo shared counts reach 0, the object is
 *      *destroyed*.
 *   -# If the weak and memo weak counts reach 0, the object is *deallocated*.
 *
 * These operations behave as follows:
 *
 *   - **Discard** downgrades all shared pointers in the object to memo
 *     shared pointers.
 *   - **Restore** upgrades those memo shared pointers to shared pointers
 *     again.
 *   - **Destroy** calls the destructor of the object.
 *   - **Deallocate** collects the memory allocated to the object.
 *
 * The discard operation may be skipped when the destroy operation would
 * immediately follow anyway; i.e. when the shared count reaches zero and the
 * memo shared count is already at zero.
 *
 * At a high level, shared and weak pointers serve to determine which objects
 * are reachable from the user program, while memo shared and memo weak
 * pointers are used to determine which objects are reachable via a memo,
 * and to break reference cycles that are induced by the memo, but which
 * do not exist in the user program *per se*.
 *
 * A discarded object is in a state where reference cycles induced by a memo
 * are broken, but it is otherwise still a valid object, and may still be
 * accessible via a weak pointer in the user program.
 */
class Any {
public:
  using class_type_ = Any;
  using this_type_ = Any;

  /**
   * Constructor.
   */
  Any() :
      sharedCount(0u),
      memoSharedCount(0u),
      weakCount(1u),
      memoWeakCount(1u),
      label(rootLabel),
      finished(false),
      frozen(false),
      frozenUnique(false),
      discarded(false) {
    // size and tid set by operator new
  }

  /**
   * Special constructor for the root label.
   */
  Any(int) :
      sharedCount(0u),
      memoSharedCount(0u),
      weakCount(1u),
      memoWeakCount(1u),
      label(nullptr),
      finished(false),
      frozen(false),
      frozenUnique(false),
      discarded(false) {
    // size and tid set by operator new
  }

  /**
   * Copy constructor.
   */
  Any(const Any& o) : Any() {
    //
  }

  /**
   * Destructor.
   */
  virtual ~Any() {
    assert(sharedCount.load() == 0u);
    assert(memoSharedCount.load() == 0u);
  }

  /**
   * New operator.
   */
  void* operator new(std::size_t size) {
    auto ptr = static_cast<Any*>(allocate(size));
    ptr->size = static_cast<unsigned>(size);
    ptr->tid = get_thread_num();
    return ptr;
  }

  /**
   * Delete operator.
   */
  void operator delete(void* ptr) {
    auto o = static_cast<Any*>(ptr);
    o->destroy();
    o->deallocate();
  }

  /**
   * Assignment operator.
   */
  Any& operator=(const Any&) {
    return *this;
  }

  /**
   * Get the size, in bytes, of the object.
   */
  unsigned getSize() const {
    return size;
  }

  /**
   * Is this object reachable? An object is reachable if there exists a
   * shared, memo shared, or weak pointer to it. If only a memo weak pointer
   * to it exists, it is not considered reachable, and it may be cleaned up
   * during memo maintenance.
   */
  bool isReachable() const {
    return numWeak() > 0u;
  }

  /**
   * Is there definitely only one pointer to this object? This is
   * conservative; it returns true if there is at most one shared or weak
   * pointer to the object. Note, in particular, that the presence of a memo
   * shared pointer means that an unknown number of pointers (including zero
   * pointers) may update to the object in future.
   */
  bool isUnique() const {
    auto sharedCount = numShared();
    auto memoSharedCount = numMemoShared();
    auto weakCount = numWeak();
    auto memoWeakCount = numMemoWeak();

    return (sharedCount == 1u && memoSharedCount == 1u && weakCount == 1u && memoWeakCount == 1u) ||
        (sharedCount == 0u && memoSharedCount == 0u && weakCount == 1u && memoWeakCount == 1u);
  }

  /**
   * Get the class name.
   */
  virtual const char* getClassName() const {
    return "Any";
  }

  /**
   * Finish the object.
   */
  void finish(Label* label) {
    if (!finished.exchange(true)) {
      /* proceed with finish */
      finish_(label);
    }
  }

  /**
   * Freeze the object.
   */
  void freeze() {
    assert(finished.load());
    if (!frozen.exchange(true)) {
      /* proceed with freeze */
      frozenUnique.store(isUnique());
      freeze_();
    }
  }

  /**
   * Copy the object.
   *
   * @param label The new label.
   */
  Any* copy(Label* label) {
    auto o = copy_(label);
    o->sharedCount.set(0u);
    o->memoSharedCount.set(0u);
    o->weakCount.set(1u);
    o->memoWeakCount.set(1u);
    o->label = label;
    o->tid = get_thread_num();
    o->finished.set(false);
    o->frozen.set(false);
    o->frozenUnique.set(false);
    o->discarded.set(false);
    return o;
  }

  /**
   * Recycle the object.
   *
   * @param label The new label.
   */
  Any* recycle(Label* label) {
    auto o = recycle_(label);
    o->releaseLabel();
    o->label = label;
    o->holdLabel();
    o->thaw();
    return this;
  }

  /**
   * Thaw the object.
   */
  void thaw() {
    finished.store(false);
    frozen.store(false);
    frozenUnique.store(false);
    discarded.store(false);
  }

  /**
   * Discard the object.
   */
  void discard() {
    if (!discarded.exchange(true)) {
      discard_();
    }
  }

  /**
   * Restore the object.
   */
  void restore() {
    if (discarded.exchange(false)) {
      restore_();
    }
  }

  /**
   * Shared count.
   */
  unsigned numShared() const {
    return sharedCount.load();
  }

  /**
   * Increment the shared count.
   */
  void incShared() {
    if (++sharedCount == 1u) {
      incMemoShared();
      holdLabel();
      if (discarded.load()) {  // only false when initializing object
        restore();
      }
    }
  }

  /**
   * Decrement the shared count.
   */
  void decShared() {
    assert(numShared() > 0u);
    if (--sharedCount == 0u) {
      releaseLabel();
      assert(numMemoShared() > 0u);
      if (--memoSharedCount == 0u) {
        /* skip the discard() in this case, just destroy() */
        destroy();
        decWeak();
      } else {
        discard();
      }
    }
  }

  /**
   * Memo shared count.
   */
  unsigned numMemoShared() const {
    return memoSharedCount.load();
  }

  /**
   * Increment the memo shared count.
   */
  void incMemoShared() {
    memoSharedCount.increment();
  }

  /**
   * Decrement the memo shared count.
   */
  void decMemoShared() {
    assert(numMemoShared() > 0u);
    if (--memoSharedCount == 0u) {
      assert(numShared() == 0u);
      destroy();
      decWeak();
    }
  }

  /**
   * Simultaneously decrement the shared count and increment the shared memo
   * count.
   */
  void discardShared() {
    assert(numShared() > 0u);
    if (--sharedCount == 0u) {
      assert(!discarded.load());
      discard();
      releaseLabel();
    } else {
      incMemoShared();
    }
  }

  /**
   * Simultaneously increment the shared count and decrement the shared memo
   * count.
   */
  void restoreShared() {
    if (++sharedCount == 1u) {
      assert(discarded.load());
      holdLabel();
      restore();
    } else {
      decMemoShared();
    }
  }

  /**
   * Weak count.
   */
  unsigned numWeak() const {
    return weakCount.load();
  }

  /**
   * Increment the weak count.
   */
  void incWeak() {
    weakCount.increment();
  }

  /**
   * Decrement the weak count.
   */
  void decWeak() {
    assert(weakCount.load() > 0u);
    if (--weakCount == 0u) {
      assert(numShared() == 0u);
      assert(numMemoShared() == 0u);
      decMemoWeak();
    }
  }

  /**
   * Memo weak count.
   */
  unsigned numMemoWeak() const {
    return memoWeakCount.load();
  }

  /**
   * Increment the memo weak count.
   */
  void incMemoWeak() {
    memoWeakCount.increment();
  }

  /**
   * Decrement the memo weak count.
   */
  void decMemoWeak() {
    assert(memoWeakCount.load() > 0u);
    if (--memoWeakCount == 0u) {
      assert(numShared() == 0u);
      assert(numMemoShared() == 0u);
      assert(numWeak() == 0u);
      deallocate();
    }
  }

  /**
   * Get the label assigned to the object.
   */
  Label* getLabel() const {
    return label;
  }

  /**
   * Is the object finished?
   */
  bool isFinished() const {
    return finished.load();
  }

  /**
   * Is the object frozen?
   */
  bool isFrozen() const {
    return frozen.load();
  }

  /**
   * Is the object frozen, and at the time of freezing, was there only one
   * pointer to it?
   */
  bool isFrozenUnique() const {
    return frozenUnique.load();
  }

  /**
   * Is the object discarded?
   */
  bool isDiscarded() const {
    return discarded.load();
  }

protected:
  /**
   * Increment the shared count of the label. This is used during
   * initialization and restoration.
   */
  void holdLabel();

  /**
   * Decrement the shared count of the label. This is used during discard.
   */
  void releaseLabel();

  /**
   * Finish the member variables of the object.
   */
  virtual void finish_(Label* label) = 0;

  /**
   * Freeze the member variables of the object.
   */
  virtual void freeze_() = 0;

  /**
   * Copy the object.
   *
   * @param label The new label.
   */
  virtual Any* copy_(Label* label) const = 0;

  /**
   * Recycle the object.
   *
   * @param label The new label.
   */
  virtual Any* recycle_(Label* label) = 0;

  /**
   * Discard the object.
   */
  virtual void discard_() = 0;

  /**
   * Restore the object.
   */
  virtual void restore_() = 0;

  /**
   * Accept a visitor across member variables.
   */
  template<class Visitor>
  void accept_(const Visitor& v) {
    //
  }

private:
  /**
   * Destroy, but do not deallocate, the object.
   */
  void destroy() {
    assert(sharedCount.load() == 0u);
    assert(memoSharedCount.load() == 0u);
    this->~Any();
  }

  /**
   * Deallocate the object. It should have previously been destroyed.
   */
  void deallocate() {
    assert(sharedCount.load() == 0u);
    assert(memoSharedCount.load() == 0u);
    assert(weakCount.load() == 0u);
    assert(memoWeakCount.load() == 0u);
    libbirch::deallocate(this, size, tid);
  }

  /**
   * Shared count.
   */
  Atomic<unsigned> sharedCount;

  /**
   * Memo shared count, or, if the shared count is nonzero, one plus the memo
   * shared count.
   */
  Atomic<unsigned> memoSharedCount;

  /**
   * Weak count, or, if the memo shared count is nonzero, one plus the weak
   * count.
   */
  Atomic<unsigned> weakCount;

  /**
   * Memo weak count, or, if the weak count is nonzero, one plus the memo
   * weak count.
   */
  Atomic<unsigned> memoWeakCount;

  /**
   * Label of the object.
   */
  Label* label;

  /**
   * Size of the object. This is set immediately after construction. A value
   * of zero is also indicative that the object is still being constructed.
   * Consequently, if the shared count reaches zero while the size is zero,
   * the object is not destroyed. This can happen when constructors create
   * shared pointers to `this`.
   */
  unsigned size;

  /**
   * Id of the thread associated with the object. This is used to return the
   * allocation to the correct pool after use, even when returned by a
   * different thread.
   */
  int tid;

  /**
   * Finished flag.
   */
  Atomic<bool> finished;

  /**
   * Frozen flag. A frozen object is read-only.
   */
  Atomic<bool> frozen;

  /**
   * Is the object frozen, and at the time of freezing, was there only one
   * pointer to it?
   */
  Atomic<bool> frozenUnique;

  /**
   * Discard flag.
   */
  Atomic<bool> discarded;
};
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "organizeritemtypetransform.h"

void OrganizerItemTypeTransform::modifyBaseSchemaDefinitions(QMap<QString, QMap<QString, QOrganizerItemDetailDefinition> > &schemaDefs) const
{
#ifndef AGENDA_EXT_SUPPORT
    // Note not supported on legacy platforms
    schemaDefs.remove(QOrganizerItemType::TypeNote);
#endif
    // Journal is not supported on Symbian. Remove the type itself
    schemaDefs.remove(QOrganizerItemType::TypeJournal);
}

void OrganizerItemTypeTransform::transformToDetailL(const CCalEntry& entry, QOrganizerItem *item)
{
    CCalEntry::TType entryType = entry.EntryTypeL();
    QString itemType;

    if (entryType == CCalEntry::ETodo)
        itemType = QLatin1String(QOrganizerItemType::TypeTodo);
    else if (entryType == CCalEntry::EEvent)
        itemType = QLatin1String(QOrganizerItemType::TypeEvent);
    else if (entryType == CCalEntry::EAppt) {
        // Assume this is an event occurrence if the recurrence id is set
        if (entry.RecurrenceIdL().TimeUtcL() != Time::NullTTime())
            itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
        else
            itemType = QLatin1String(QOrganizerItemType::TypeEvent);
    }
    else if (entryType == CCalEntry::EAnniv)
        itemType = QLatin1String(QOrganizerItemType::TypeEvent);
    else if (CCalEntry::ENote == entryType) {
        itemType = QLatin1String(QOrganizerItemType::TypeNote);
    } else
        User::Leave(KErrUnknown); // unknown type

    // TODO: CCalEntry::EReminder

    item->setType(itemType);
}

void OrganizerItemTypeTransform::transformToDetailL(const CCalInstance& instance, QOrganizerItem *itemInstance)
{
    CCalEntry::TType entryType = instance.Entry().EntryTypeL();
    QString itemType;

    if (entryType == CCalEntry::ETodo)
        itemType = QLatin1String(QOrganizerItemType::TypeTodoOccurrence);
    else if (entryType == CCalEntry::EEvent)
        itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
    else if (entryType == CCalEntry::EAppt)
        itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
    else if (entryType == CCalEntry::EAnniv)
        itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
    else
        User::Leave(KErrUnknown); // unknown type

    // TODO: CCalEntry::EReminder

    itemInstance->setType(itemType);
}

void OrganizerItemTypeTransform::transformToEntryL(const QOrganizerItem& item, CCalEntry* entry)
{
    Q_UNUSED(item);
    Q_UNUSED(entry);
    // Not used. Entry type is already set when CCalEntry was created.
}

QString OrganizerItemTypeTransform::detailDefinitionName()
{
    return QOrganizerItemType::DefinitionName;
}

CCalEntry::TType OrganizerItemTypeTransform::entryTypeL(const QOrganizerItem &item)
{
    QString itemType = item.type();
    CCalEntry::TType entryType(CCalEntry::EAppt);

    if (itemType == QOrganizerItemType::TypeTodo || itemType == QOrganizerItemType::TypeTodoOccurrence)
        entryType = CCalEntry::ETodo;
    else if (itemType == QOrganizerItemType::TypeEvent || itemType == QOrganizerItemType::TypeEventOccurrence)
        entryType = CCalEntry::EAppt;
    else if (QOrganizerItemType::TypeNote == itemType) {
        entryType = CCalEntry::ENote;
    } else {
        User::Leave(KErrUnknown); // unknown type
    }

    // TODO: CCalEntry::EEvent???
    // TODO: CCalEntry::EReminder
    // TODO: CCalEntry::EAnniv if itemType=event & category=anniversary

    return entryType;
}
<commit_msg>Only S^4 and later has support for the AGENDA extensions<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "organizeritemtypetransform.h"

void OrganizerItemTypeTransform::modifyBaseSchemaDefinitions(QMap<QString, QMap<QString, QOrganizerItemDetailDefinition> > &schemaDefs) const
{
#ifndef AGENDA_EXT_SUPPORT
    // Note not supported on legacy platforms
    schemaDefs.remove(QOrganizerItemType::TypeNote);
#endif
    // Journal is not supported on Symbian. Remove the type itself
    schemaDefs.remove(QOrganizerItemType::TypeJournal);
}

void OrganizerItemTypeTransform::transformToDetailL(const CCalEntry& entry, QOrganizerItem *item)
{
    CCalEntry::TType entryType = entry.EntryTypeL();
    QString itemType;

    if (entryType == CCalEntry::ETodo)
        itemType = QLatin1String(QOrganizerItemType::TypeTodo);
    else if (entryType == CCalEntry::EEvent)
        itemType = QLatin1String(QOrganizerItemType::TypeEvent);
    else if (entryType == CCalEntry::EAppt) {
        // Assume this is an event occurrence if the recurrence id is set
        if (entry.RecurrenceIdL().TimeUtcL() != Time::NullTTime())
            itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
        else
            itemType = QLatin1String(QOrganizerItemType::TypeEvent);
    }
    else if (entryType == CCalEntry::EAnniv)
        itemType = QLatin1String(QOrganizerItemType::TypeEvent);
#ifdef AGENDA_EXT_SUPPORT
    else if (CCalEntry::ENote == entryType) {
        itemType = QLatin1String(QOrganizerItemType::TypeNote);
    }
#endif
    else
        User::Leave(KErrUnknown); // unknown type

    // TODO: CCalEntry::EReminder

    item->setType(itemType);
}

void OrganizerItemTypeTransform::transformToDetailL(const CCalInstance& instance, QOrganizerItem *itemInstance)
{
    CCalEntry::TType entryType = instance.Entry().EntryTypeL();
    QString itemType;

    if (entryType == CCalEntry::ETodo)
        itemType = QLatin1String(QOrganizerItemType::TypeTodoOccurrence);
    else if (entryType == CCalEntry::EEvent)
        itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
    else if (entryType == CCalEntry::EAppt)
        itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
    else if (entryType == CCalEntry::EAnniv)
        itemType = QLatin1String(QOrganizerItemType::TypeEventOccurrence);
    else
        User::Leave(KErrUnknown); // unknown type

    // TODO: CCalEntry::EReminder

    itemInstance->setType(itemType);
}

void OrganizerItemTypeTransform::transformToEntryL(const QOrganizerItem& item, CCalEntry* entry)
{
    Q_UNUSED(item);
    Q_UNUSED(entry);
    // Not used. Entry type is already set when CCalEntry was created.
}

QString OrganizerItemTypeTransform::detailDefinitionName()
{
    return QOrganizerItemType::DefinitionName;
}

CCalEntry::TType OrganizerItemTypeTransform::entryTypeL(const QOrganizerItem &item)
{
    QString itemType = item.type();
    CCalEntry::TType entryType(CCalEntry::EAppt);

    if (itemType == QOrganizerItemType::TypeTodo || itemType == QOrganizerItemType::TypeTodoOccurrence)
        entryType = CCalEntry::ETodo;
    else if (itemType == QOrganizerItemType::TypeEvent || itemType == QOrganizerItemType::TypeEventOccurrence)
        entryType = CCalEntry::EAppt;
#ifdef AGENDA_EXT_SUPPORT
    else if (QOrganizerItemType::TypeNote == itemType) {
        entryType = CCalEntry::ENote;
    }
#endif
    else
        User::Leave(KErrUnknown); // unknown type

    // TODO: CCalEntry::EEvent???
    // TODO: CCalEntry::EReminder
    // TODO: CCalEntry::EAnniv if itemType=event & category=anniversary

    return entryType;
}
<|endoftext|>


<commit_before>/*
    This file is part of libkcal.

    Copyright (c) 2001-2003 Cornelius Schumacher <schumacher@kde.org>

    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., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>

#include "todo.h"

using namespace KCal;

Todo::Todo()
{
  mHasDueDate = false;
  mHasStartDate = false;

  mHasCompletedDate = false;
  mPercentComplete = 0;
}

Todo::Todo(const Todo &t) : Incidence(t)
{
  mDtDue = t.mDtDue;
  mHasDueDate = t.mHasDueDate;
  mHasStartDate = t.mHasStartDate;
  mCompleted = t.mCompleted;
  mHasCompletedDate = t.mHasCompletedDate;
  mPercentComplete = t.mPercentComplete;
  mDtRecurrence = t.mDtRecurrence;
}

Todo::~Todo()
{
}

Todo *Todo::clone()
{
  return new Todo( *this );
}

bool Todo::operator==( const Todo& t2 ) const
{
    return
        static_cast<const Incidence&>(*this) == static_cast<const Incidence&>(t2) &&
        dtDue() == t2.dtDue() &&
        hasDueDate() == t2.hasDueDate() &&
        hasStartDate() == t2.hasStartDate() &&
        completed() == t2.completed() &&
        hasCompletedDate() == t2.hasCompletedDate() &&
        percentComplete() == t2.percentComplete();
}

void Todo::setDtDue(const QDateTime &dtDue, bool first )
{
  //int diffsecs = mDtDue.secsTo(dtDue);

  /*if (mReadOnly) return;
  const Alarm::List& alarms = alarms();
  for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) {
    if (alarm->enabled()) {
      alarm->setTime(alarm->time().addSecs(diffsecs));
    }
  }*/
  if( doesRecur() && !first ) {
    mDtRecurrence = dtDue;
  } else {
    mDtDue = dtDue;
    // TODO: This doesn't seem right...
    recurrence()->setRecurStart( dtDue );
  }

  if ( doesRecur() && dtDue < recurrence()->recurStart() )
    setDtStart( dtDue );

  //kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl;

  /*const Alarm::List& alarms = alarms();
  for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next())
    alarm->setAlarmStart(mDtDue);*/

  updated();
}

QDateTime Todo::dtDue( bool first ) const
{
  if ( doesRecur() && !first && mDtRecurrence.isValid() )
    return mDtRecurrence;

  return mDtDue;
}

QString Todo::dtDueTimeStr() const
{
  return KGlobal::locale()->formatTime( dtDue(!doesRecur()).time() );
}

QString Todo::dtDueDateStr(bool shortfmt) const
{
  return KGlobal::locale()->formatDate(dtDue( !doesRecur() ).date(),shortfmt);
}

QString Todo::dtDueStr() const
{
  return KGlobal::locale()->formatDateTime( dtDue( !doesRecur() ) );
}

bool Todo::hasDueDate() const
{
  return mHasDueDate;
}

void Todo::setHasDueDate(bool f)
{
  if (mReadOnly) return;
  mHasDueDate = f;
  updated();
}

bool Todo::hasStartDate() const
{
  return mHasStartDate;
}

void Todo::setHasStartDate(bool f)
{
  if (mReadOnly) return;

  if ( doesRecur() && !f ) {
    if ( !comments().grep("NoStartDate").count() )
      addComment("NoStartDate"); //TODO: --> custom flag?
  } else {
    QString s("NoStartDate");
    removeComment(s);
  }
  mHasStartDate = f;
  updated();
}

QDateTime Todo::dtStart( bool first ) const
{
  if ( doesRecur() && !first )
    return mDtRecurrence.addDays( dtDue( true ).daysTo( IncidenceBase::dtStart() ) );
  else
    return IncidenceBase::dtStart();
}

void Todo::setDtStart( const QDateTime &dtStart )
{
  // TODO: This doesn't seem right (rfc 2445/6 says, recurrence is calculated from the dtstart...)
  if ( doesRecur() )
    recurrence()->setRecurStart( mDtDue );
  IncidenceBase::setDtStart( dtStart );
}

QString Todo::dtStartTimeStr( bool first ) const
{
  return KGlobal::locale()->formatTime(dtStart(first).time());
}

QString Todo::dtStartDateStr(bool shortfmt, bool first) const
{
  return KGlobal::locale()->formatDate(dtStart(first).date(),shortfmt);
}

QString Todo::dtStartStr(bool first) const
{
  return KGlobal::locale()->formatDateTime(dtStart(first));
}

bool Todo::isCompleted() const
{
  if (mPercentComplete == 100) return true;
  else return false;
}

void Todo::setCompleted(bool completed)
{
  if (completed) mPercentComplete = 100;
  else mPercentComplete = 0;
  updated();
}

QDateTime Todo::completed() const
{
  return mCompleted;
}

QString Todo::completedStr() const
{
  return KGlobal::locale()->formatDateTime(mCompleted);
}

void Todo::setCompleted(const QDateTime &completed)
{
  if( !recurTodo() ) {
    mHasCompletedDate = true;
    mPercentComplete = 100;
    mCompleted = completed;
  }
  updated();
}

bool Todo::hasCompletedDate() const
{
  return mHasCompletedDate;
}

int Todo::percentComplete() const
{
  return mPercentComplete;
}

void Todo::setPercentComplete(int v)
{
  mPercentComplete = v;
  updated();
}

void Todo::setDtRecurrence( const QDateTime &dt )
{
  mDtRecurrence = dt;
}

QDateTime Todo::dtRecurrence() const
{
  return mDtRecurrence.isValid() ? mDtRecurrence : mDtDue;
}

bool Todo::recursOn( const QDate &date ) const
{
  QDate today = QDate::currentDate();
  return ( Incidence::recursOn(date) &&
           !( date < today && mDtRecurrence.date() < today &&
              mDtRecurrence > recurrence()->recurStart() ) );
}

bool Todo::recurTodo()
{
  if ( doesRecur() ) {
    Recurrence *r = recurrence();
    QDateTime endDateTime = r->endDateTime();
    QDateTime nextDate = r->getNextDateTime( dtDue() );

    if ( ( r->duration() == -1 || ( nextDate.isValid() && endDateTime.isValid()
           && nextDate <= endDateTime ) ) ) {
      setDtDue( nextDate );
      while ( !recursAt( dtDue() ) || dtDue() <= QDateTime::currentDateTime() ) {
        setDtDue( r->getNextDateTime( dtDue() ) );
      }

      setCompleted( false );
      setRevision( revision() + 1 );

      return true;
    }
  }

  return false;
}

bool Todo::isOverdue() const
{
  bool inPast = doesFloat() ? mDtDue.date() < QDate::currentDate()
                            : mDtDue < QDateTime::currentDateTime();
  return ( inPast && !isCompleted() );
}
<commit_msg>Drop completed dates when not completing tasks.<commit_after>/*
    This file is part of libkcal.

    Copyright (c) 2001-2003 Cornelius Schumacher <schumacher@kde.org>

    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., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>

#include "todo.h"

using namespace KCal;

Todo::Todo()
{
  mHasDueDate = false;
  mHasStartDate = false;

  mHasCompletedDate = false;
  mPercentComplete = 0;
}

Todo::Todo(const Todo &t) : Incidence(t)
{
  mDtDue = t.mDtDue;
  mHasDueDate = t.mHasDueDate;
  mHasStartDate = t.mHasStartDate;
  mCompleted = t.mCompleted;
  mHasCompletedDate = t.mHasCompletedDate;
  mPercentComplete = t.mPercentComplete;
  mDtRecurrence = t.mDtRecurrence;
}

Todo::~Todo()
{
}

Todo *Todo::clone()
{
  return new Todo( *this );
}

bool Todo::operator==( const Todo& t2 ) const
{
    return
        static_cast<const Incidence&>(*this) == static_cast<const Incidence&>(t2) &&
        dtDue() == t2.dtDue() &&
        hasDueDate() == t2.hasDueDate() &&
        hasStartDate() == t2.hasStartDate() &&
        completed() == t2.completed() &&
        hasCompletedDate() == t2.hasCompletedDate() &&
        percentComplete() == t2.percentComplete();
}

void Todo::setDtDue(const QDateTime &dtDue, bool first )
{
  //int diffsecs = mDtDue.secsTo(dtDue);

  /*if (mReadOnly) return;
  const Alarm::List& alarms = alarms();
  for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) {
    if (alarm->enabled()) {
      alarm->setTime(alarm->time().addSecs(diffsecs));
    }
  }*/
  if( doesRecur() && !first ) {
    mDtRecurrence = dtDue;
  } else {
    mDtDue = dtDue;
    // TODO: This doesn't seem right...
    recurrence()->setRecurStart( dtDue );
  }

  if ( doesRecur() && dtDue < recurrence()->recurStart() )
    setDtStart( dtDue );

  //kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl;

  /*const Alarm::List& alarms = alarms();
  for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next())
    alarm->setAlarmStart(mDtDue);*/

  updated();
}

QDateTime Todo::dtDue( bool first ) const
{
  if ( doesRecur() && !first && mDtRecurrence.isValid() )
    return mDtRecurrence;

  return mDtDue;
}

QString Todo::dtDueTimeStr() const
{
  return KGlobal::locale()->formatTime( dtDue(!doesRecur()).time() );
}

QString Todo::dtDueDateStr(bool shortfmt) const
{
  return KGlobal::locale()->formatDate(dtDue( !doesRecur() ).date(),shortfmt);
}

QString Todo::dtDueStr() const
{
  return KGlobal::locale()->formatDateTime( dtDue( !doesRecur() ) );
}

bool Todo::hasDueDate() const
{
  return mHasDueDate;
}

void Todo::setHasDueDate(bool f)
{
  if (mReadOnly) return;
  mHasDueDate = f;
  updated();
}

bool Todo::hasStartDate() const
{
  return mHasStartDate;
}

void Todo::setHasStartDate(bool f)
{
  if (mReadOnly) return;

  if ( doesRecur() && !f ) {
    if ( !comments().grep("NoStartDate").count() )
      addComment("NoStartDate"); //TODO: --> custom flag?
  } else {
    QString s("NoStartDate");
    removeComment(s);
  }
  mHasStartDate = f;
  updated();
}

QDateTime Todo::dtStart( bool first ) const
{
  if ( doesRecur() && !first )
    return mDtRecurrence.addDays( dtDue( true ).daysTo( IncidenceBase::dtStart() ) );
  else
    return IncidenceBase::dtStart();
}

void Todo::setDtStart( const QDateTime &dtStart )
{
  // TODO: This doesn't seem right (rfc 2445/6 says, recurrence is calculated from the dtstart...)
  if ( doesRecur() )
    recurrence()->setRecurStart( mDtDue );
  IncidenceBase::setDtStart( dtStart );
}

QString Todo::dtStartTimeStr( bool first ) const
{
  return KGlobal::locale()->formatTime(dtStart(first).time());
}

QString Todo::dtStartDateStr(bool shortfmt, bool first) const
{
  return KGlobal::locale()->formatDate(dtStart(first).date(),shortfmt);
}

QString Todo::dtStartStr(bool first) const
{
  return KGlobal::locale()->formatDateTime(dtStart(first));
}

bool Todo::isCompleted() const
{
  if (mPercentComplete == 100) return true;
  else return false;
}

void Todo::setCompleted(bool completed)
{
  if (completed)
    mPercentComplete = 100;
  else {
    mPercentComplete = 0;
    mHasCompletedDate = false;
  }
  updated();
}

QDateTime Todo::completed() const
{
  return mCompleted;
}

QString Todo::completedStr() const
{
  return KGlobal::locale()->formatDateTime(mCompleted);
}

void Todo::setCompleted(const QDateTime &completed)
{
  if( !recurTodo() ) {
    mHasCompletedDate = true;
    mPercentComplete = 100;
    mCompleted = completed;
  }
  updated();
}

bool Todo::hasCompletedDate() const
{
  return mHasCompletedDate;
}

int Todo::percentComplete() const
{
  return mPercentComplete;
}

void Todo::setPercentComplete(int v)
{
  mPercentComplete = v;
  if ( v != 100 ) mHasCompletedDate = false;
  updated();
}

void Todo::setDtRecurrence( const QDateTime &dt )
{
  mDtRecurrence = dt;
}

QDateTime Todo::dtRecurrence() const
{
  return mDtRecurrence.isValid() ? mDtRecurrence : mDtDue;
}

bool Todo::recursOn( const QDate &date ) const
{
  QDate today = QDate::currentDate();
  return ( Incidence::recursOn(date) &&
           !( date < today && mDtRecurrence.date() < today &&
              mDtRecurrence > recurrence()->recurStart() ) );
}

bool Todo::recurTodo()
{
  if ( doesRecur() ) {
    Recurrence *r = recurrence();
    QDateTime endDateTime = r->endDateTime();
    QDateTime nextDate = r->getNextDateTime( dtDue() );

    if ( ( r->duration() == -1 || ( nextDate.isValid() && endDateTime.isValid()
           && nextDate <= endDateTime ) ) ) {
      setDtDue( nextDate );
      while ( !recursAt( dtDue() ) || dtDue() <= QDateTime::currentDateTime() ) {
        setDtDue( r->getNextDateTime( dtDue() ) );
      }

      setCompleted( false );
      setRevision( revision() + 1 );

      return true;
    }
  }

  return false;
}

bool Todo::isOverdue() const
{
  bool inPast = doesFloat() ? mDtDue.date() < QDate::currentDate()
                            : mDtDue < QDateTime::currentDateTime();
  return ( inPast && !isCompleted() );
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "VideoReEncoder.h"
#include "Exceptions.h"

namespace WPFAnimationEncoding
{
	struct VideoReEncoderSession
	{
		VideoReEncoderSession() :
			inputFormatContext(NULL),
			inputCodecContext(NULL),
			inputVideoStream(NULL),
			outputFormatContext(NULL),
			codec(NULL),
			videoFrame(NULL),
			convertContext(NULL)
		{
			packet.data = NULL;
			packet.size = 0;
		}
		// input
		libffmpeg::AVFormatContext *inputFormatContext;
		libffmpeg::AVCodecContext *inputCodecContext;
		libffmpeg::AVStream *inputVideoStream;
		// output
		libffmpeg::AVFormatContext *outputFormatContext;
		// general
		libffmpeg::AVCodec *codec;
		libffmpeg::AVFrame *videoFrame;
		libffmpeg::SwsContext *convertContext;
		libffmpeg::AVPacket packet;
	};

	static void open_video(VideoReEncoderSession* session, char* fileName)
	{
		int result = libffmpeg::avformat_open_input(&session->inputFormatContext, fileName, NULL, NULL);
		if (result != 0)
			throw gcnew VideoException("Input avformat_alloc_output_context2 error " + result);
		if (!session->inputFormatContext)
			throw gcnew VideoException("Couldn't create input format context.");

		// retrieve stream information
		if (libffmpeg::avformat_find_stream_info(session->inputFormatContext, NULL) < 0)
			throw gcnew VideoException("Cannot find stream information.");
	}

	// Class constructor
	VideoReEncoder::VideoReEncoder(void) :
		disposed(false)
	{
		libffmpeg::av_register_all();
	}

	// start the reencoding of the video file
	void VideoReEncoder::StartReEncoding(String^ inputFileName, String^ outputFileName, VideoReEncodeCallback^ callback)
	{
		// http://ffmpeg.org/doxygen/trunk/doc_2examples_2transcoding_8c-example.html

		IntPtr nativeInputFileNamePointer = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(inputFileName);
		char* nativeInputFileName = static_cast<char*>(nativeInputFileNamePointer.ToPointer());

		IntPtr nativeOutputFileNamePointer = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(outputFileName);
		char* nativeOutputFileName = static_cast<char*>(nativeOutputFileNamePointer.ToPointer());

		int result = -1;
		VideoReEncoderSession session;

		try
		{
			// open the input file
			open_video(&session, nativeInputFileName);

			// search for the first video stream
			for (unsigned int i = 0; i < session.inputFormatContext->nb_streams; i++)
			{
				if (session.inputFormatContext->streams[i]->codec->codec_type == libffmpeg::AVMEDIA_TYPE_VIDEO)
				{
					// get the pointer to the codec context for the video stream
					session.inputCodecContext = session.inputFormatContext->streams[i]->codec;
					session.inputVideoStream = session.inputFormatContext->streams[i];
					break;
				}
			}
			if (session.inputVideoStream == NULL)
				throw gcnew VideoException("Cannot find video stream in the specified file.");
			if (session.inputCodecContext == NULL)
				throw gcnew VideoException("Cannot create the input video codec context.");

			// find decoder for the video stream
			session.codec = libffmpeg::avcodec_find_decoder(session.inputCodecContext->codec_id);
			if (session.codec == NULL)
				throw gcnew VideoException("Cannot find codec to decode the video stream with");

			// open the codec
			if (libffmpeg::avcodec_open2(session.inputCodecContext, session.codec, NULL) < 0)
				throw gcnew VideoException("Cannot open video codec.");

			// allocate video frame
			session.videoFrame = libffmpeg::avcodec_alloc_frame();
			if (session.videoFrame == NULL)
				throw gcnew VideoException("Couldn't allocate the video frame.");

			// prepare scaling context to convert RGB image to video format
			session.convertContext = libffmpeg::sws_getContext(session.inputCodecContext->width, session.inputCodecContext->height, session.inputCodecContext->pix_fmt,
				session.inputCodecContext->width, session.inputCodecContext->height, libffmpeg::PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
			if (session.convertContext == NULL)
				throw gcnew VideoException("Cannot initialize frames conversion context.");

			// open the output file
			result = libffmpeg::avformat_alloc_output_context2(&session.outputFormatContext, NULL, NULL, nativeOutputFileName);
			if (result != 0)
				throw gcnew VideoException("Output avformat_alloc_output_context2 error " + result);
			if (!session.inputFormatContext)
				throw gcnew VideoException("Couldn't create output format context.");

			// copy all the stream information from the input file, to the output file
			for (int i = 0; i < session.inputFormatContext->nb_streams; i++)
			{
				if (i <= 1){
					// create the new stream
					libffmpeg::AVStream *outStream = libffmpeg::avformat_new_stream(session.outputFormatContext, NULL);
					if (!outStream)
						throw gcnew VideoException("Failed allocating output stream");

					// cope all the information about the stream from the input, to the output
					result = libffmpeg::avcodec_copy_context(session.outputFormatContext->streams[i]->codec,
						session.inputFormatContext->streams[i]->codec);
					if (result < 0)
						throw gcnew VideoException("Copying stream context failed. " + result);
				}
			}

			// init muxer and write output file header
			if (!(session.outputFormatContext->oformat->flags & AVFMT_NOFILE)) {
				result = libffmpeg::avio_open(&session.outputFormatContext->pb, nativeOutputFileName, AVIO_FLAG_WRITE);
				if (result < 0)
					throw gcnew VideoException("Could not open output file. " + result);
			}
			result = libffmpeg::avformat_write_header(session.outputFormatContext, NULL);
			if (result < 0)
				throw gcnew VideoException("Error occurred when opening output file. " + result);

			bool hasFrame = true;

			while (hasFrame) {
				hasFrame = libffmpeg::av_read_frame(session.inputFormatContext, &session.packet) == 0;
				if (hasFrame) {

					//type = data->FormatContext->streams[packet.stream_index]->codec->codec_type;

					/* remux this frame without reencoding */
					session.packet.dts = libffmpeg::av_rescale_q_rnd(session.packet.dts,
						session.inputFormatContext->streams[session.packet.stream_index]->time_base,
						session.outputFormatContext->streams[session.packet.stream_index]->time_base,
						(libffmpeg::AVRounding)(libffmpeg::AV_ROUND_NEAR_INF | libffmpeg::AV_ROUND_PASS_MINMAX));

					session.packet.pts = libffmpeg::av_rescale_q_rnd(session.packet.pts,
						session.inputFormatContext->streams[session.packet.stream_index]->time_base,
						session.outputFormatContext->streams[session.packet.stream_index]->time_base,
						(libffmpeg::AVRounding)(libffmpeg::AV_ROUND_NEAR_INF | libffmpeg::AV_ROUND_PASS_MINMAX));

					result = libffmpeg::av_interleaved_write_frame(session.outputFormatContext, &session.packet);

					if (result < 0)
						throw gcnew VideoException("av_interleaved_write_frame error. " + result);

					av_free_packet(&session.packet);

				}
			}

			libffmpeg::av_write_trailer(session.outputFormatContext);
		}
		finally
		{
			System::Runtime::InteropServices::Marshal::FreeHGlobal(nativeInputFileNamePointer);
			System::Runtime::InteropServices::Marshal::FreeHGlobal(nativeOutputFileNamePointer);

			// free general stuff
			if (session.packet.data != NULL)
				av_free_packet(&session.packet);
			if (session.videoFrame != NULL)
				libffmpeg::av_free(session.videoFrame);
			if (session.inputCodecContext != NULL)
				libffmpeg::avcodec_close(session.inputCodecContext);
			if (session.convertContext != NULL)
				libffmpeg::sws_freeContext(session.convertContext);

			// close the output file
			if (session.outputFormatContext != NULL) {
				if (session.outputFormatContext && !(session.outputFormatContext->oformat->flags & AVFMT_NOFILE))
					libffmpeg::avio_close(session.outputFormatContext->pb);
				libffmpeg::avformat_free_context(session.outputFormatContext);
			}

			// close the input file
			if (session.inputFormatContext != NULL)
				libffmpeg::avformat_close_input(&session.inputFormatContext);
		}
	}
}<commit_msg>Minor changes<commit_after>#include "stdafx.h"
#include "VideoReEncoder.h"
#include "Exceptions.h"

namespace WPFAnimationEncoding
{
	struct VideoReEncoderSession
	{
		VideoReEncoderSession() :
			inputFormatContext(NULL),
			inputCodecContext(NULL),
			inputVideoStream(NULL),
			outputFormatContext(NULL),
			codec(NULL),
			videoFrame(NULL),
			convertContext(NULL)
		{
			packet.data = NULL;
			packet.size = 0;
		}
		// input
		libffmpeg::AVFormatContext *inputFormatContext;
		libffmpeg::AVCodecContext *inputCodecContext;
		libffmpeg::AVStream *inputVideoStream;
		// output
		libffmpeg::AVFormatContext *outputFormatContext;
		// general
		libffmpeg::AVCodec *codec;
		libffmpeg::AVFrame *videoFrame;
		libffmpeg::SwsContext *convertContext;
		libffmpeg::AVPacket packet;
	};

	static void open_video(VideoReEncoderSession* session, char* fileName)
	{
		int result = libffmpeg::avformat_open_input(&session->inputFormatContext, fileName, NULL, NULL);
		if (result != 0)
			throw gcnew VideoException("Input avformat_alloc_output_context2 error " + result);
		if (!session->inputFormatContext)
			throw gcnew VideoException("Couldn't create input format context.");

		// retrieve stream information
		if (libffmpeg::avformat_find_stream_info(session->inputFormatContext, NULL) < 0)
			throw gcnew VideoException("Cannot find stream information.");
	}

	static void find_input_video_stream(VideoReEncoderSession* session)
	{
		// search for the first video stream
		for (unsigned int i = 0; i < session->inputFormatContext->nb_streams; i++)
		{
			if (session->inputFormatContext->streams[i]->codec->codec_type == libffmpeg::AVMEDIA_TYPE_VIDEO)
			{
				// get the pointer to the codec context for the video stream
				session->inputCodecContext = session->inputFormatContext->streams[i]->codec;
				session->inputVideoStream = session->inputFormatContext->streams[i];
				break;
			}
		}
		if (session->inputVideoStream == NULL)
			throw gcnew VideoException("Cannot find video stream in the specified file.");
		if (session->inputCodecContext == NULL)
			throw gcnew VideoException("Cannot create the input video codec context.");
	}

	static void open_input_video_codec()
	{

	}

	// Class constructor
	VideoReEncoder::VideoReEncoder(void) :
		disposed(false)
	{
		libffmpeg::av_register_all();
	}

	// start the reencoding of the video file
	void VideoReEncoder::StartReEncoding(String^ inputFileName, String^ outputFileName, VideoReEncodeCallback^ callback)
	{
		// http://ffmpeg.org/doxygen/trunk/doc_2examples_2transcoding_8c-example.html

		IntPtr nativeInputFileNamePointer = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(inputFileName);
		char* nativeInputFileName = static_cast<char*>(nativeInputFileNamePointer.ToPointer());

		IntPtr nativeOutputFileNamePointer = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(outputFileName);
		char* nativeOutputFileName = static_cast<char*>(nativeOutputFileNamePointer.ToPointer());

		int result = -1;
		VideoReEncoderSession session;

		try
		{
			open_video(&session, nativeInputFileName);

			find_input_video_stream(&session);

			// find decoder for the video stream
			session.codec = libffmpeg::avcodec_find_decoder(session.inputCodecContext->codec_id);
			if (session.codec == NULL)
				throw gcnew VideoException("Cannot find codec to decode the video stream with");

			// open the codec
			if (libffmpeg::avcodec_open2(session.inputCodecContext, session.codec, NULL) < 0)
				throw gcnew VideoException("Cannot open video codec.");

			// allocate video frame
			session.videoFrame = libffmpeg::avcodec_alloc_frame();
			if (session.videoFrame == NULL)
				throw gcnew VideoException("Couldn't allocate the video frame.");

			// prepare scaling context to convert RGB image to video format
			session.convertContext = libffmpeg::sws_getContext(session.inputCodecContext->width, session.inputCodecContext->height, session.inputCodecContext->pix_fmt,
				session.inputCodecContext->width, session.inputCodecContext->height, libffmpeg::PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
			if (session.convertContext == NULL)
				throw gcnew VideoException("Cannot initialize frames conversion context.");

			// open the output file
			result = libffmpeg::avformat_alloc_output_context2(&session.outputFormatContext, NULL, NULL, nativeOutputFileName);
			if (result != 0)
				throw gcnew VideoException("Output avformat_alloc_output_context2 error " + result);
			if (!session.inputFormatContext)
				throw gcnew VideoException("Couldn't create output format context.");

			// copy all the stream information from the input file, to the output file
			for (int i = 0; i < session.inputFormatContext->nb_streams; i++)
			{
				if (i <= 1){
					// create the new stream
					libffmpeg::AVStream *outStream = libffmpeg::avformat_new_stream(session.outputFormatContext, NULL);
					if (!outStream)
						throw gcnew VideoException("Failed allocating output stream");

					// cope all the information about the stream from the input, to the output
					result = libffmpeg::avcodec_copy_context(session.outputFormatContext->streams[i]->codec,
						session.inputFormatContext->streams[i]->codec);
					if (result < 0)
						throw gcnew VideoException("Copying stream context failed. " + result);
				}
			}

			// init muxer and write output file header
			if (!(session.outputFormatContext->oformat->flags & AVFMT_NOFILE)) {
				result = libffmpeg::avio_open(&session.outputFormatContext->pb, nativeOutputFileName, AVIO_FLAG_WRITE);
				if (result < 0)
					throw gcnew VideoException("Could not open output file. " + result);
			}
			result = libffmpeg::avformat_write_header(session.outputFormatContext, NULL);
			if (result < 0)
				throw gcnew VideoException("Error occurred when opening output file. " + result);

			bool hasFrame = true;

			while (hasFrame) {
				hasFrame = libffmpeg::av_read_frame(session.inputFormatContext, &session.packet) == 0;
				if (hasFrame) {

					//type = data->FormatContext->streams[packet.stream_index]->codec->codec_type;

					/* remux this frame without reencoding */
					session.packet.dts = libffmpeg::av_rescale_q_rnd(session.packet.dts,
						session.inputFormatContext->streams[session.packet.stream_index]->time_base,
						session.outputFormatContext->streams[session.packet.stream_index]->time_base,
						(libffmpeg::AVRounding)(libffmpeg::AV_ROUND_NEAR_INF | libffmpeg::AV_ROUND_PASS_MINMAX));

					session.packet.pts = libffmpeg::av_rescale_q_rnd(session.packet.pts,
						session.inputFormatContext->streams[session.packet.stream_index]->time_base,
						session.outputFormatContext->streams[session.packet.stream_index]->time_base,
						(libffmpeg::AVRounding)(libffmpeg::AV_ROUND_NEAR_INF | libffmpeg::AV_ROUND_PASS_MINMAX));

					result = libffmpeg::av_interleaved_write_frame(session.outputFormatContext, &session.packet);

					if (result < 0)
						throw gcnew VideoException("av_interleaved_write_frame error. " + result);

					av_free_packet(&session.packet);

				}
			}

			libffmpeg::av_write_trailer(session.outputFormatContext);
		}
		finally
		{
			System::Runtime::InteropServices::Marshal::FreeHGlobal(nativeInputFileNamePointer);
			System::Runtime::InteropServices::Marshal::FreeHGlobal(nativeOutputFileNamePointer);

			// free general stuff
			if (session.packet.data != NULL)
				av_free_packet(&session.packet);
			if (session.videoFrame != NULL)
				libffmpeg::av_free(session.videoFrame);
			if (session.inputCodecContext != NULL)
				libffmpeg::avcodec_close(session.inputCodecContext);
			if (session.convertContext != NULL)
				libffmpeg::sws_freeContext(session.convertContext);

			// close the output file
			if (session.outputFormatContext != NULL) {
				if (session.outputFormatContext && !(session.outputFormatContext->oformat->flags & AVFMT_NOFILE))
					libffmpeg::avio_close(session.outputFormatContext->pb);
				libffmpeg::avformat_free_context(session.outputFormatContext);
			}

			// close the input file
			if (session.inputFormatContext != NULL)
				libffmpeg::avformat_close_input(&session.inputFormatContext);
		}
	}
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include "levelextractor.h"
#include "algorithmfactory.h"
#include "poolstorage.h"

using namespace std;

namespace essentia {
namespace streaming {

const char* LevelExtractor::name = "LevelExtractor";
const char* LevelExtractor::description = DOC("this algorithm extracts the loudness of an audio signal");

LevelExtractor::LevelExtractor() {

  declareInput(_signal, "signal", "the input audio signal");
  declareOutput(_loudnessValue, "loudness", "the loudness values");

  AlgorithmFactory& factory = AlgorithmFactory::instance();

  _frameCutter = factory.create("FrameCutter",
                                "silentFrames", "noise",
                                "startFromZero", true);

  _loudness = factory.create("Loudness");

  _signal                        >>  _frameCutter->input("signal");
  _frameCutter->output("frame")  >>  _loudness->input("signal");
  _loudness->output("loudness")  >>  _loudnessValue;
}

void LevelExtractor::configure() {
  _frameCutter->configure(INHERIT("frameSize"),
                          INHERIT("hopSize"));
}

LevelExtractor::~LevelExtractor() {
  delete _frameCutter;
  delete _loudness;
}

} // namespace streaming
} // namespace essentia

namespace essentia {
namespace standard {

const char* LevelExtractor::name = "LevelExtractor";
const char* LevelExtractor::description = DOC("this algorithm extracts the loudness of an audio signal");

LevelExtractor::LevelExtractor() {
  declareInput(_signal, "signal", "the audio input signal");
  declareOutput(_loudness, "loudness", "the loudness values");

  createInnerNetwork();
}

LevelExtractor::~LevelExtractor() {
  delete _network;
}

void LevelExtractor::reset() {
  _network->reset();
  _pool.clear();
}

void LevelExtractor::configure() {
  _levelExtractor->configure(INHERIT("frameSize"), INHERIT("hopSize"));
}

void LevelExtractor::createInnerNetwork() {
  _levelExtractor = streaming::AlgorithmFactory::create("LevelExtractor");
  _vectorInput = new streaming::VectorInput<Real>();

  *_vectorInput                        >>  _levelExtractor->input("signal");
  _levelExtractor->output("loudness")  >>  PC(_pool, "internal.loudness");

  _network = new scheduler::Network(_vectorInput);
}

 void LevelExtractor::compute() {
  const vector<Real>& signal = _signal.get();
  _vectorInput->setVector(&signal);

  _network->run();

  vector<Real>& loudness = _loudness.get();

  loudness = _pool.value<vector<Real> >("internal.loudness");
}

} // namespace standard
} // namespace essentia

<commit_msg>Improve doc for LevelExtractor algo<commit_after>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

#include "levelextractor.h"
#include "algorithmfactory.h"
#include "poolstorage.h"

using namespace std;

namespace essentia {
namespace streaming {

const char* LevelExtractor::name = "LevelExtractor";
const char* LevelExtractor::description = DOC("This algorithm extracts the loudness of an audio signal in frames using Loudness algorithm.");

LevelExtractor::LevelExtractor() {

  declareInput(_signal, "signal", "the input audio signal");
  declareOutput(_loudnessValue, "loudness", "the loudness values");

  AlgorithmFactory& factory = AlgorithmFactory::instance();

  _frameCutter = factory.create("FrameCutter",
                                "silentFrames", "noise",
                                "startFromZero", true);

  _loudness = factory.create("Loudness");

  _signal                        >>  _frameCutter->input("signal");
  _frameCutter->output("frame")  >>  _loudness->input("signal");
  _loudness->output("loudness")  >>  _loudnessValue;
}

void LevelExtractor::configure() {
  _frameCutter->configure(INHERIT("frameSize"),
                          INHERIT("hopSize"));
}

LevelExtractor::~LevelExtractor() {
  delete _frameCutter;
  delete _loudness;
}

} // namespace streaming
} // namespace essentia

namespace essentia {
namespace standard {

const char* LevelExtractor::name = "LevelExtractor";
const char* LevelExtractor::description = DOC("this algorithm extracts the loudness of an audio signal");

LevelExtractor::LevelExtractor() {
  declareInput(_signal, "signal", "the audio input signal");
  declareOutput(_loudness, "loudness", "the loudness values");

  createInnerNetwork();
}

LevelExtractor::~LevelExtractor() {
  delete _network;
}

void LevelExtractor::reset() {
  _network->reset();
  _pool.clear();
}

void LevelExtractor::configure() {
  _levelExtractor->configure(INHERIT("frameSize"), INHERIT("hopSize"));
}

void LevelExtractor::createInnerNetwork() {
  _levelExtractor = streaming::AlgorithmFactory::create("LevelExtractor");
  _vectorInput = new streaming::VectorInput<Real>();

  *_vectorInput                        >>  _levelExtractor->input("signal");
  _levelExtractor->output("loudness")  >>  PC(_pool, "internal.loudness");

  _network = new scheduler::Network(_vectorInput);
}

 void LevelExtractor::compute() {
  const vector<Real>& signal = _signal.get();
  _vectorInput->setVector(&signal);

  _network->run();

  vector<Real>& loudness = _loudness.get();

  loudness = _pool.value<vector<Real> >("internal.loudness");
}

} // namespace standard
} // namespace essentia

<|endoftext|>


<commit_before>/**
 * (c) 2019 by Mega Limited, Wellsford, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include <gtest/gtest.h>

#include <mega/share.h>

void checkNewShares(const mega::NewShare& exp, const mega::NewShare& act)
{
    ASSERT_EQ(exp.h, act.h);
    ASSERT_EQ(exp.outgoing, act.outgoing);
    ASSERT_EQ(exp.peer, act.peer);
    ASSERT_EQ(exp.access, act.access);
    ASSERT_EQ(exp.ts, act.ts);
    ASSERT_TRUE(std::equal(exp.key, exp.key + mega::SymmCipher::BLOCKSIZE, act.key));
    ASSERT_EQ(exp.have_key, act.have_key);
    ASSERT_EQ(exp.have_auth, act.have_auth);
    ASSERT_EQ(exp.pending, act.pending);
}

TEST(Share, serialize_unserialize)
{
    mega::User user;
    user.userhandle = 42;
    mega::PendingContactRequest pcr{123};
    mega::Share share{&user, mega::RDONLY, 13, &pcr};
    std::string d;
    share.serialize(&d);

    mega::byte key[mega::SymmCipher::BLOCKSIZE];
    std::fill(key, key + mega::SymmCipher::BLOCKSIZE, 'X');
    auto data = d.c_str();
    auto newShare = mega::Share::unserialize(-1, 100, key, &data, d.data() + d.size());

    const mega::NewShare expectedNewShare{100, -1, user.userhandle, mega::RDONLY, 13, key, NULL, 123};
    checkNewShares(expectedNewShare, *newShare);
}

TEST(Share, unserialize_32bit)
{
    // This is the result of serialization on 32bit Windows
    const std::array<char, 26> rawData = {
        0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00
    };
    const std::string d(rawData.data(), rawData.size());

    mega::byte key[mega::SymmCipher::BLOCKSIZE];
    std::fill(key, key + mega::SymmCipher::BLOCKSIZE, 'X');
    auto data = d.c_str();
    auto newShare = mega::Share::unserialize(-1, 100, key, &data, d.data() + d.size());

    const mega::NewShare expectedNewShare{ 100, -1, 42, mega::RDONLY, 13, key, NULL, 123 };
    checkNewShares(expectedNewShare, *newShare);
}
<commit_msg>fix formatting<commit_after>/**
 * (c) 2019 by Mega Limited, Wellsford, New Zealand
 *
 * This file is part of the MEGA SDK - Client Access Engine.
 *
 * Applications using the MEGA API must present a valid application key
 * and comply with the the rules set forth in the Terms of Service.
 *
 * The MEGA SDK 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.
 *
 * @copyright Simplified (2-clause) BSD License.
 *
 * You should have received a copy of the license along with this
 * program.
 */

#include <gtest/gtest.h>

#include <mega/share.h>

void checkNewShares(const mega::NewShare& exp, const mega::NewShare& act)
{
    ASSERT_EQ(exp.h, act.h);
    ASSERT_EQ(exp.outgoing, act.outgoing);
    ASSERT_EQ(exp.peer, act.peer);
    ASSERT_EQ(exp.access, act.access);
    ASSERT_EQ(exp.ts, act.ts);
    ASSERT_TRUE(std::equal(exp.key, exp.key + mega::SymmCipher::BLOCKSIZE, act.key));
    ASSERT_EQ(exp.have_key, act.have_key);
    ASSERT_EQ(exp.have_auth, act.have_auth);
    ASSERT_EQ(exp.pending, act.pending);
}

TEST(Share, serialize_unserialize)
{
    mega::User user;
    user.userhandle = 42;
    mega::PendingContactRequest pcr{123};
    mega::Share share{&user, mega::RDONLY, 13, &pcr};
    std::string d;
    share.serialize(&d);

    mega::byte key[mega::SymmCipher::BLOCKSIZE];
    std::fill(key, key + mega::SymmCipher::BLOCKSIZE, 'X');
    auto data = d.c_str();
    auto newShare = mega::Share::unserialize(-1, 100, key, &data, d.data() + d.size());

    const mega::NewShare expectedNewShare{100, -1, user.userhandle, mega::RDONLY, 13, key, NULL, 123};
    checkNewShares(expectedNewShare, *newShare);
}

TEST(Share, unserialize_32bit)
{
    // This is the result of serialization on 32bit Windows
    const std::array<char, 26> rawData = {
        0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00
    };
    const std::string d(rawData.data(), rawData.size());

    mega::byte key[mega::SymmCipher::BLOCKSIZE];
    std::fill(key, key + mega::SymmCipher::BLOCKSIZE, 'X');
    auto data = d.c_str();
    auto newShare = mega::Share::unserialize(-1, 100, key, &data, d.data() + d.size());

    const mega::NewShare expectedNewShare{100, -1, 42, mega::RDONLY, 13, key, NULL, 123};
    checkNewShares(expectedNewShare, *newShare);
}
<|endoftext|>