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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"

#ifndef _SORTDYNRES_HXX
#include <sortdynres.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_
#include <com/sun/star/registry/XRegistryKey.hpp>
#endif

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

//=========================================================================
static sal_Bool writeInfo( void * pRegistryKey,
                           const OUString & rImplementationName,
                              Sequence< OUString > const & rServiceNames )
{
    OUString aKeyName( OUString::createFromAscii( "/" ) );
    aKeyName += rImplementationName;
    aKeyName += OUString::createFromAscii( "/UNO/SERVICES" );

    Reference< XRegistryKey > xKey;
    try
    {
        xKey = static_cast< XRegistryKey * >(
                                    pRegistryKey )->createKey( aKeyName );
    }
    catch ( InvalidRegistryException const & )
    {
    }

    if ( !xKey.is() )
        return sal_False;

    sal_Bool bSuccess = sal_True;

    for ( sal_Int32 n = 0; n < rServiceNames.getLength(); ++n )
    {
        try
        {
            xKey->createKey( rServiceNames[ n ] );
        }
        catch ( InvalidRegistryException const & )
        {
            bSuccess = sal_False;
            break;
        }
    }
    return bSuccess;
}

//=========================================================================
extern "C" void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//=========================================================================
extern "C" sal_Bool SAL_CALL component_writeInfo( void *, void * pRegistryKey )
{
    return pRegistryKey &&

    //////////////////////////////////////////////////////////////////////
    // SortedDynamicResultSetFactory.
    //////////////////////////////////////////////////////////////////////

    writeInfo( pRegistryKey,
       SortedDynamicResultSetFactory::getImplementationName_Static(),
       SortedDynamicResultSetFactory::getSupportedServiceNames_Static() );
}

//=========================================================================
extern "C" void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * )
{
    void * pRet = 0;

    Reference< XMultiServiceFactory > xSMgr(
            reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) );
    Reference< XSingleServiceFactory > xFactory;

    //////////////////////////////////////////////////////////////////////
    // SortedDynamicResultSetFactory.
    //////////////////////////////////////////////////////////////////////

    if ( SortedDynamicResultSetFactory::getImplementationName_Static().
                compareToAscii( pImplName ) == 0 )
    {
        xFactory = SortedDynamicResultSetFactory::createServiceFactory( xSMgr );
    }

    //////////////////////////////////////////////////////////////////////

    if ( xFactory.is() )
    {
        xFactory->acquire();
        pRet = xFactory.get();
    }

    return pRet;
}

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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
#include <sortdynres.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>

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

//=========================================================================
static sal_Bool writeInfo( void * pRegistryKey,
                           const OUString & rImplementationName,
                              Sequence< OUString > const & rServiceNames )
{
    OUString aKeyName( OUString::createFromAscii( "/" ) );
    aKeyName += rImplementationName;
    aKeyName += OUString::createFromAscii( "/UNO/SERVICES" );

    Reference< XRegistryKey > xKey;
    try
    {
        xKey = static_cast< XRegistryKey * >(
                                    pRegistryKey )->createKey( aKeyName );
    }
    catch ( InvalidRegistryException const & )
    {
    }

    if ( !xKey.is() )
        return sal_False;

    sal_Bool bSuccess = sal_True;

    for ( sal_Int32 n = 0; n < rServiceNames.getLength(); ++n )
    {
        try
        {
            xKey->createKey( rServiceNames[ n ] );
        }
        catch ( InvalidRegistryException const & )
        {
            bSuccess = sal_False;
            break;
        }
    }
    return bSuccess;
}

//=========================================================================
extern "C" void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//=========================================================================
extern "C" sal_Bool SAL_CALL component_writeInfo( void *, void * pRegistryKey )
{
    return pRegistryKey &&

    //////////////////////////////////////////////////////////////////////
    // SortedDynamicResultSetFactory.
    //////////////////////////////////////////////////////////////////////

    writeInfo( pRegistryKey,
       SortedDynamicResultSetFactory::getImplementationName_Static(),
       SortedDynamicResultSetFactory::getSupportedServiceNames_Static() );
}

//=========================================================================
extern "C" void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * )
{
    void * pRet = 0;

    Reference< XMultiServiceFactory > xSMgr(
            reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) );
    Reference< XSingleServiceFactory > xFactory;

    //////////////////////////////////////////////////////////////////////
    // SortedDynamicResultSetFactory.
    //////////////////////////////////////////////////////////////////////

    if ( SortedDynamicResultSetFactory::getImplementationName_Static().
                compareToAscii( pImplName ) == 0 )
    {
        xFactory = SortedDynamicResultSetFactory::createServiceFactory( xSMgr );
    }

    //////////////////////////////////////////////////////////////////////

    if ( xFactory.is() )
    {
        xFactory->acquire();
        pRet = xFactory.get();
    }

    return pRet;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: filnot.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2004-09-08 17:03:12 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _FILNOT_HXX_
#define _FILNOT_HXX_

#include <hash_map>
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYCHANGEEVENT_HPP_
#include <com/sun/star/beans/PropertyChangeEvent.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTIDENTIFIER_HPP_
#include <com/sun/star/ucb/XContentIdentifier.hpp>
#endif
#ifndef _FILGLOB_HXX_
#include "filglob.hxx"
#endif

namespace fileaccess {

    class shell;
    class BaseContent;

    class ContentEventNotifier
    {
    private:
        shell* m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xOldId;
        com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > > m_sListeners;
    public:

        ContentEventNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            const com::sun::star::uno::Sequence<
            com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners );

        ContentEventNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xOldId,
            const com::sun::star::uno::Sequence<
            com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners );

        void notifyChildInserted( const rtl::OUString& aChildName );
        void notifyDeleted( void );
        void notifyRemoved( const rtl::OUString& aChildName );
        void notifyExchanged( );
    };

    class PropertySetInfoChangeNotifier
    {
    private:
        shell* m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId;
        com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > > m_sListeners;
    public:
        PropertySetInfoChangeNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            const com::sun::star::uno::Sequence<
            com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners );

        void SAL_CALL notifyPropertyAdded( const rtl::OUString & aPropertyName );
        void SAL_CALL notifyPropertyRemoved( const rtl::OUString & aPropertyName );
    };

    typedef std::hash_map< rtl::OUString,
                           com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >,
                           hashOUString,
                           equalOUString >      ListenerMap;

    class PropertyChangeNotifier
    {
    private:
        shell* m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId;
        ListenerMap* m_pListeners;
    public:
        PropertyChangeNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            ListenerMap* pListeners );

        ~PropertyChangeNotifier();

        void notifyPropertyChanged(
            com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent > seqChanged );
    };

    class Notifier
    {
    public:
        // Side effect of this function is the change of the name
        virtual ContentEventNotifier*          cEXC( const rtl::OUString aNewName ) = 0;
        // Side effect is the change of the state of the object to "deleted".
        virtual ContentEventNotifier*          cDEL( void ) = 0;
        virtual ContentEventNotifier*          cCEL( void ) = 0;
        virtual PropertySetInfoChangeNotifier* cPSL( void ) = 0;
        virtual PropertyChangeNotifier*        cPCL( void ) = 0;
        virtual rtl::OUString                  getKey( void ) = 0;
    };

}   // end namespace fileaccess

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.4.68); FILE MERGED 2005/09/05 18:45:01 rt 1.4.68.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: filnot.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:26:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _FILNOT_HXX_
#define _FILNOT_HXX_

#include <hash_map>
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYCHANGEEVENT_HPP_
#include <com/sun/star/beans/PropertyChangeEvent.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTIDENTIFIER_HPP_
#include <com/sun/star/ucb/XContentIdentifier.hpp>
#endif
#ifndef _FILGLOB_HXX_
#include "filglob.hxx"
#endif

namespace fileaccess {

    class shell;
    class BaseContent;

    class ContentEventNotifier
    {
    private:
        shell* m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xOldId;
        com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > > m_sListeners;
    public:

        ContentEventNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            const com::sun::star::uno::Sequence<
            com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners );

        ContentEventNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xOldId,
            const com::sun::star::uno::Sequence<
            com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners );

        void notifyChildInserted( const rtl::OUString& aChildName );
        void notifyDeleted( void );
        void notifyRemoved( const rtl::OUString& aChildName );
        void notifyExchanged( );
    };

    class PropertySetInfoChangeNotifier
    {
    private:
        shell* m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId;
        com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > > m_sListeners;
    public:
        PropertySetInfoChangeNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            const com::sun::star::uno::Sequence<
            com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >& sListeners );

        void SAL_CALL notifyPropertyAdded( const rtl::OUString & aPropertyName );
        void SAL_CALL notifyPropertyRemoved( const rtl::OUString & aPropertyName );
    };

    typedef std::hash_map< rtl::OUString,
                           com::sun::star::uno::Sequence< com::sun::star::uno::Reference< com::sun::star::uno::XInterface > >,
                           hashOUString,
                           equalOUString >      ListenerMap;

    class PropertyChangeNotifier
    {
    private:
        shell* m_pMyShell;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContent > m_xCreatorContent;
        com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier > m_xCreatorId;
        ListenerMap* m_pListeners;
    public:
        PropertyChangeNotifier(
            shell* pMyShell,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContent >& xCreatorContent,
            const com::sun::star::uno::Reference< com::sun::star::ucb::XContentIdentifier >& xCreatorId,
            ListenerMap* pListeners );

        ~PropertyChangeNotifier();

        void notifyPropertyChanged(
            com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent > seqChanged );
    };

    class Notifier
    {
    public:
        // Side effect of this function is the change of the name
        virtual ContentEventNotifier*          cEXC( const rtl::OUString aNewName ) = 0;
        // Side effect is the change of the state of the object to "deleted".
        virtual ContentEventNotifier*          cDEL( void ) = 0;
        virtual ContentEventNotifier*          cCEL( void ) = 0;
        virtual PropertySetInfoChangeNotifier* cPSL( void ) = 0;
        virtual PropertyChangeNotifier*        cPCL( void ) = 0;
        virtual rtl::OUString                  getKey( void ) = 0;
    };

}   // end namespace fileaccess

#endif
<|endoftext|>


<commit_before>/** @file

  Http1ClientTransaction.cc - The Client Transaction class for Http1*

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "Http1ClientTransaction.h"
#include "Http1ClientSession.h"
#include "HttpSM.h"

void
Http1ClientTransaction::release()
{
  // Turn off reading until we are done with the SM
  // At that point the transaction/session with either be closed
  // or be put into keep alive state to wait from the next transaction
  this->do_io_read(this, 0, nullptr);
  _proxy_ssn->clear_session_active();
}

void
Http1ClientTransaction::transaction_done()
{
  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
  super_type::transaction_done();
  if (_proxy_ssn) {
    static_cast<Http1ClientSession *>(_proxy_ssn)->release_transaction();
  }
}

bool
Http1ClientTransaction::allow_half_open() const
{
  bool config_allows_it = (_sm) ? _sm->t_state.txn_conf->allow_half_open > 0 : true;
  if (config_allows_it) {
    // Check with the session to make sure the underlying transport allows the half open scenario
    return static_cast<Http1ClientSession *>(_proxy_ssn)->allow_half_open();
  }
  return false;
}

void
Http1ClientTransaction::increment_transactions_stat()
{
  HTTP_INCREMENT_DYN_STAT(http_current_client_transactions_stat);
}

void
Http1ClientTransaction::decrement_transactions_stat()
{
  HTTP_DECREMENT_DYN_STAT(http_current_client_transactions_stat);
}
<commit_msg>Don't use Http1ClientTransaction as an event handler (#8609)<commit_after>/** @file

  Http1ClientTransaction.cc - The Client Transaction class for Http1*

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "Http1ClientTransaction.h"
#include "Http1ClientSession.h"
#include "HttpSM.h"

void
Http1ClientTransaction::release()
{
  // Turn off reading until we are done with the SM
  // At that point the transaction/session with either be closed
  // or be put into keep alive state to wait from the next transaction
  this->do_io_read(this->_sm, 0, nullptr);
  _proxy_ssn->clear_session_active();
}

void
Http1ClientTransaction::transaction_done()
{
  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
  super_type::transaction_done();
  if (_proxy_ssn) {
    static_cast<Http1ClientSession *>(_proxy_ssn)->release_transaction();
  }
}

bool
Http1ClientTransaction::allow_half_open() const
{
  bool config_allows_it = (_sm) ? _sm->t_state.txn_conf->allow_half_open > 0 : true;
  if (config_allows_it) {
    // Check with the session to make sure the underlying transport allows the half open scenario
    return static_cast<Http1ClientSession *>(_proxy_ssn)->allow_half_open();
  }
  return false;
}

void
Http1ClientTransaction::increment_transactions_stat()
{
  HTTP_INCREMENT_DYN_STAT(http_current_client_transactions_stat);
}

void
Http1ClientTransaction::decrement_transactions_stat()
{
  HTTP_DECREMENT_DYN_STAT(http_current_client_transactions_stat);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractCells.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*----------------------------------------------------------------------------
 Copyright (c) Sandia Corporation
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/

#include "vtkExtractCells.h"

#include "vtkCellArray.h"
#include "vtkIntArray.h"
#include "vtkUnsignedCharArray.h"
#include "vtkUnstructuredGrid.h"
#include "vtkCell.h"
#include "vtkPoints.h"
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkIntArray.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkExtractCells, "1.8");
vtkStandardNewMacro(vtkExtractCells);

#include <vtkstd/set>
#include <vtkstd/algorithm>

class vtkExtractCellsSTLCloak
{
public:
  vtkstd::set<vtkIdType> IdTypeSet;
};

vtkExtractCells::vtkExtractCells()
{
  this->SubSetUGridCellArraySize = 0;
  this->InputIsUgrid = 0;
  this->CellList = new vtkExtractCellsSTLCloak;
}
vtkExtractCells::~vtkExtractCells()
{
  this->SetCellList(NULL);
}

void vtkExtractCells::SetCellList(vtkIdList *l)
{
  delete this->CellList;
  this->CellList = new vtkExtractCellsSTLCloak;

  if (l != NULL)
    {
    this->AddCellList(l);
    }
}
void vtkExtractCells::AddCellList(vtkIdList *l)
{
  if (l == NULL)
    {
    return;
    }

  vtkIdType ncells = l->GetNumberOfIds();

  if (ncells == 0)
    {
    return;
    }

  for (int i=0; i<ncells; i++)
    {
    this->CellList->IdTypeSet.insert(l->GetId(i));
    }

  this->Modified();

  return;
}
void vtkExtractCells::AddCellRange(vtkIdType from, vtkIdType to)
{
  if (to < from) return;

  for (vtkIdType id=from; id <= to; id++)
    {
    this->CellList->IdTypeSet.insert(id);
    }

  this->Modified();

  return;
}
void vtkExtractCells::Execute()
{
  vtkDataSet *input = this->GetInput();
  vtkUnstructuredGrid *output= this->GetOutput();

  this->InputIsUgrid =
    ((vtkUnstructuredGrid::SafeDownCast(input)) != NULL);

  int numCellsInput = input->GetNumberOfCells();

  int numCells = this->CellList->IdTypeSet.size();

  if (numCells == numCellsInput)
    {
    this->Copy();
    return;
    }
  vtkPointData *PD = input->GetPointData();
  vtkCellData *CD = input->GetCellData();

  if (numCells == 0)
    {
    // set up a ugrid with same data arrays as input, but
    // no points, cells or data.

    output->Allocate(1);

    output->GetPointData()->CopyAllocate(PD, VTK_CELL_SIZE);
    output->GetCellData()->CopyAllocate(CD, 1);

    vtkPoints *pts = vtkPoints::New();
    pts->SetNumberOfPoints(VTK_CELL_SIZE);

    output->SetPoints(pts);

    pts->Delete();

    return;
    }
  vtkPointData *newPD = output->GetPointData();
  vtkCellData *newCD  = output->GetCellData();

  vtkIdList *ptIdMap = reMapPointIds(input);

  vtkIdType numPoints = ptIdMap->GetNumberOfIds();

  newPD->CopyAllocate(PD, numPoints);

  newCD->CopyAllocate(CD, numCells);

  vtkPoints *pts = vtkPoints::New();
  pts->SetNumberOfPoints(numPoints);

  for (vtkIdType newId =0; newId<numPoints; newId++)
    {
    vtkIdType oldId = ptIdMap->GetId(newId);

    pts->SetPoint(newId, input->GetPoint(oldId));

    newPD->CopyData(PD, oldId, newId);
    }

  output->SetPoints(pts);
  pts->Delete();

  if (this->InputIsUgrid)
    {
    this->CopyCellsUnstructuredGrid(ptIdMap);
    }
  else
    {
    this->CopyCellsDataSet(ptIdMap);
    }

  ptIdMap->Delete();

  output->Squeeze();

  return;
}
void vtkExtractCells::Copy()
{
  int i;

  vtkDataSet *input = this->GetInput();
  vtkUnstructuredGrid *output= this->GetOutput();

  if (this->InputIsUgrid)
    {
    output->DeepCopy(vtkUnstructuredGrid::SafeDownCast(input));
    return;
    }

  int numCells = input->GetNumberOfCells();

  vtkPointData *PD = input->GetPointData();
  vtkCellData *CD = input->GetCellData();

  vtkPointData *newPD = output->GetPointData();
  vtkCellData *newCD  = output->GetCellData();

  int numPoints = input->GetNumberOfPoints();

  output->Allocate(numCells);

  newPD->CopyAllocate(PD, numPoints);

  newCD->CopyAllocate(CD, numCells);

  vtkPoints *pts = vtkPoints::New();
  pts->SetNumberOfPoints(numPoints);

  for (i=0; i<numPoints; i++)
    {
    pts->SetPoint(i, input->GetPoint(i));
    }
  newPD->DeepCopy(PD);

  output->SetPoints(pts);

  pts->Delete();

  vtkIdList *cellPoints = vtkIdList::New();

  for (vtkIdType cellId=0; cellId < numCells; cellId++)
    {
    input->GetCellPoints(cellId, cellPoints);

    output->InsertNextCell(input->GetCellType(cellId), cellPoints);
    }
  newCD->DeepCopy(CD);

  cellPoints->Delete();

  output->Squeeze();

  return;
}
vtkIdType vtkExtractCells::findInSortedList(vtkIdList *idList, vtkIdType id)
{
  vtkIdType numids = idList->GetNumberOfIds();

  if (numids < 8) return idList->IsId(id);

  int L, R, M;
  L=0;
  R=numids-1;

  vtkIdType *ids = idList->GetPointer(0);

  int loc = -1;

  while (R > L)
    {
    if (R == L+1)
      {
      if (ids[R] == id)
        {
        loc = R;
        }
      else if (ids[L] == id)
        {
        loc = L;
        }
      break;
      }

    M = (R + L) / 2;

    if (ids[M] > id)
      {
      R = M;
      continue;
      }
    else if (ids[M] < id)
      {
      L = M;
      continue;
      }
    else
      {
      loc = M;
      break;
      }
    }
  return loc;
}
vtkIdList *vtkExtractCells::reMapPointIds(vtkDataSet *grid)
{
  int totalPoints = grid->GetNumberOfPoints();

  char *temp = new char [totalPoints];

  if (!temp)
    {
    vtkErrorMacro(<< "vtkExtractCells::reMapPointIds memory allocation");
    return NULL;
    }
  memset(temp, 0, totalPoints);

  int numberOfIds = 0;
  int i;
  vtkIdType id;
  vtkIdList *ptIds = vtkIdList::New();
  vtkstd::set<vtkIdType>::iterator cellPtr;

  if (!this->InputIsUgrid)
    {
    for (cellPtr = this->CellList->IdTypeSet.begin();
         cellPtr != this->CellList->IdTypeSet.end();
         ++cellPtr)
      {
      grid->GetCellPoints(*cellPtr, ptIds);

      vtkIdType nIds = ptIds->GetNumberOfIds();

      vtkIdType *ptId = ptIds->GetPointer(0);

      for (i=0; i<nIds; i++)
        {
        id = *ptId++;

        if (temp[id] == 0)
          {
          numberOfIds++;
          temp[id] = 1;
          }
        }
      }
    }
  else
    {
    vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(grid);

    this->SubSetUGridCellArraySize = 0;

    vtkIdType *cellArray = ugrid->GetCells()->GetPointer();
    vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0);

    this->SubSetUGridCellArraySize = 0;
    vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId();

    for (cellPtr = this->CellList->IdTypeSet.begin();
         cellPtr != this->CellList->IdTypeSet.end();
         ++cellPtr)
      {
      if (*cellPtr > maxid) continue;

      int loc = locs[*cellPtr];

      vtkIdType nIds = cellArray[loc++];

      this->SubSetUGridCellArraySize += (1 + nIds);

      for (i=0; i<nIds; i++)
        {
        id = cellArray[loc++];

        if (temp[id] == 0)
          {
          numberOfIds++;
          temp[id] = 1;
          }
        }
      }
    }

  ptIds->SetNumberOfIds(numberOfIds);
  int next=0;

  for (id=0; id<totalPoints; id++)
    {
    if (temp[id]) ptIds->SetId(next++, id);
    }

  delete [] temp;

  return ptIds;
}
void vtkExtractCells::CopyCellsDataSet(vtkIdList *ptMap)
{
  vtkDataSet *input = this->GetInput();
  vtkUnstructuredGrid *output= this->GetOutput();

  output->Allocate(this->CellList->IdTypeSet.size());

  vtkCellData *oldCD = input->GetCellData();
  vtkCellData *newCD = output->GetCellData();

  vtkIdList *cellPoints = vtkIdList::New();

  vtkstd::set<vtkIdType>::iterator cellPtr;

  for (cellPtr = this->CellList->IdTypeSet.begin();
       cellPtr != this->CellList->IdTypeSet.end();
       ++cellPtr)
    {
    vtkIdType cellId = *cellPtr;

    input->GetCellPoints(cellId, cellPoints);

    for (int i=0; i < cellPoints->GetNumberOfIds(); i++)
      {
      vtkIdType oldId = cellPoints->GetId(i);

      vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId);

      cellPoints->SetId(i, newId);
      }
    int newId = output->InsertNextCell(input->GetCellType(cellId), cellPoints);

    newCD->CopyData(oldCD, cellId, newId);
    }

  cellPoints->Delete();

  return;
}
void vtkExtractCells::CopyCellsUnstructuredGrid(vtkIdList *ptMap)
{
  vtkDataSet *input = this->GetInput();

  vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(input);

  if (ugrid == NULL)
    {
    this->CopyCellsDataSet(ptMap);
    return;
    }

  vtkUnstructuredGrid *output= this->GetOutput();

  vtkCellData *oldCD = input->GetCellData();
  vtkCellData *newCD = output->GetCellData();

  int numCells = this->CellList->IdTypeSet.size();

  vtkCellArray *cellArray = vtkCellArray::New();                 // output
  vtkIdTypeArray *newcells = vtkIdTypeArray::New();
  newcells->SetNumberOfValues(this->SubSetUGridCellArraySize);
  cellArray->SetCells(numCells, newcells);
  int cellArrayIdx = 0;

  vtkIdTypeArray *locationArray = vtkIdTypeArray::New();
  locationArray->SetNumberOfValues(numCells);

  vtkUnsignedCharArray *typeArray = vtkUnsignedCharArray::New();
  typeArray->SetNumberOfValues(numCells);

  int nextCellId = 0;

  vtkstd::set<vtkIdType>::iterator cellPtr;                           // input
  vtkIdType *cells = ugrid->GetCells()->GetPointer();
  vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId();
  vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0);
  vtkUnsignedCharArray *types = ugrid->GetCellTypesArray();

  for (cellPtr = this->CellList->IdTypeSet.begin();
       cellPtr != this->CellList->IdTypeSet.end();
       ++cellPtr)
    {
      if (*cellPtr > maxid) continue;

    int oldCellId = *cellPtr;

    int loc = locs[oldCellId];
    int size = (int)cells[loc];
    vtkIdType *pts = cells + loc + 1;
    unsigned char type = types->GetValue(oldCellId);

    locationArray->SetValue(nextCellId, cellArrayIdx);
    typeArray->SetValue(nextCellId, type);

    newcells->SetValue(cellArrayIdx++, size);

    for (int i=0; i<size; i++)
      {
      vtkIdType oldId = *pts++;
      vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId);

      newcells->SetValue(cellArrayIdx++, newId);
      }

    newCD->CopyData(oldCD, oldCellId, nextCellId);

    nextCellId++;
    }

  output->SetCells(typeArray, locationArray, cellArray);

  typeArray->Delete();
  locationArray->Delete();
  newcells->Delete();
  cellArray->Delete();

  return;
}

void vtkExtractCells::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

<commit_msg>BUG: The Copy() method causes segfaults later on.  Don't use it.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkExtractCells.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*----------------------------------------------------------------------------
 Copyright (c) Sandia Corporation
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/

#include "vtkExtractCells.h"

#include "vtkCellArray.h"
#include "vtkIntArray.h"
#include "vtkUnsignedCharArray.h"
#include "vtkUnstructuredGrid.h"
#include "vtkCell.h"
#include "vtkPoints.h"
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkIntArray.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkExtractCells, "1.9");
vtkStandardNewMacro(vtkExtractCells);

#include <vtkstd/set>
#include <vtkstd/algorithm>

class vtkExtractCellsSTLCloak
{
public:
  vtkstd::set<vtkIdType> IdTypeSet;
};

vtkExtractCells::vtkExtractCells()
{
  this->SubSetUGridCellArraySize = 0;
  this->InputIsUgrid = 0;
  this->CellList = new vtkExtractCellsSTLCloak;
}
vtkExtractCells::~vtkExtractCells()
{
  this->SetCellList(NULL);
}

void vtkExtractCells::SetCellList(vtkIdList *l)
{
  delete this->CellList;
  this->CellList = new vtkExtractCellsSTLCloak;

  if (l != NULL)
    {
    this->AddCellList(l);
    }
}
void vtkExtractCells::AddCellList(vtkIdList *l)
{
  if (l == NULL)
    {
    return;
    }

  vtkIdType ncells = l->GetNumberOfIds();

  if (ncells == 0)
    {
    return;
    }

  for (int i=0; i<ncells; i++)
    {
    this->CellList->IdTypeSet.insert(l->GetId(i));
    }

  this->Modified();

  return;
}
void vtkExtractCells::AddCellRange(vtkIdType from, vtkIdType to)
{
  if (to < from) return;

  for (vtkIdType id=from; id <= to; id++)
    {
    this->CellList->IdTypeSet.insert(id);
    }

  this->Modified();

  return;
}
void vtkExtractCells::Execute()
{
  vtkDataSet *input = this->GetInput();
  vtkUnstructuredGrid *output= this->GetOutput();

  this->InputIsUgrid =
    ((vtkUnstructuredGrid::SafeDownCast(input)) != NULL);

  int numCellsInput = input->GetNumberOfCells();

  int numCells = this->CellList->IdTypeSet.size();

  if (numCells == numCellsInput)
    {
    #if 0
    this->Copy();
    return;
   #else
    // The Copy method seems to have a bug, causing codes using ExtractCells to die
    #endif
    }
  vtkPointData *PD = input->GetPointData();
  vtkCellData *CD = input->GetCellData();

  if (numCells == 0)
    {
    // set up a ugrid with same data arrays as input, but
    // no points, cells or data.

    output->Allocate(1);

    output->GetPointData()->CopyAllocate(PD, VTK_CELL_SIZE);
    output->GetCellData()->CopyAllocate(CD, 1);

    vtkPoints *pts = vtkPoints::New();
    pts->SetNumberOfPoints(VTK_CELL_SIZE);

    output->SetPoints(pts);

    pts->Delete();

    return;
    }
  vtkPointData *newPD = output->GetPointData();
  vtkCellData *newCD  = output->GetCellData();

  vtkIdList *ptIdMap = reMapPointIds(input);

  vtkIdType numPoints = ptIdMap->GetNumberOfIds();

  newPD->CopyAllocate(PD, numPoints);

  newCD->CopyAllocate(CD, numCells);

  vtkPoints *pts = vtkPoints::New();
  pts->SetNumberOfPoints(numPoints);

  for (vtkIdType newId =0; newId<numPoints; newId++)
    {
    vtkIdType oldId = ptIdMap->GetId(newId);

    pts->SetPoint(newId, input->GetPoint(oldId));

    newPD->CopyData(PD, oldId, newId);
    }

  output->SetPoints(pts);
  pts->Delete();

  if (this->InputIsUgrid)
    {
    this->CopyCellsUnstructuredGrid(ptIdMap);
    }
  else
    {
    this->CopyCellsDataSet(ptIdMap);
    }

  ptIdMap->Delete();

  output->Squeeze();

  return;
}
void vtkExtractCells::Copy()
{
  int i;

  vtkDataSet *input = this->GetInput();
  vtkUnstructuredGrid *output= this->GetOutput();

  if (this->InputIsUgrid)
    {
    output->DeepCopy(vtkUnstructuredGrid::SafeDownCast(input));
    return;
    }

  int numCells = input->GetNumberOfCells();

  vtkPointData *PD = input->GetPointData();
  vtkCellData *CD = input->GetCellData();

  vtkPointData *newPD = output->GetPointData();
  vtkCellData *newCD  = output->GetCellData();

  int numPoints = input->GetNumberOfPoints();

  output->Allocate(numCells);

  newPD->CopyAllocate(PD, numPoints);

  newCD->CopyAllocate(CD, numCells);

  vtkPoints *pts = vtkPoints::New();
  pts->SetNumberOfPoints(numPoints);

  for (i=0; i<numPoints; i++)
    {
    pts->SetPoint(i, input->GetPoint(i));
    }
  newPD->DeepCopy(PD);

  output->SetPoints(pts);

  pts->Delete();

  vtkIdList *cellPoints = vtkIdList::New();

  for (vtkIdType cellId=0; cellId < numCells; cellId++)
    {
    input->GetCellPoints(cellId, cellPoints);

    output->InsertNextCell(input->GetCellType(cellId), cellPoints);
    }
  newCD->DeepCopy(CD);

  cellPoints->Delete();

  output->Squeeze();

  return;
}
vtkIdType vtkExtractCells::findInSortedList(vtkIdList *idList, vtkIdType id)
{
  vtkIdType numids = idList->GetNumberOfIds();

  if (numids < 8) return idList->IsId(id);

  int L, R, M;
  L=0;
  R=numids-1;

  vtkIdType *ids = idList->GetPointer(0);

  int loc = -1;

  while (R > L)
    {
    if (R == L+1)
      {
      if (ids[R] == id)
        {
        loc = R;
        }
      else if (ids[L] == id)
        {
        loc = L;
        }
      break;
      }

    M = (R + L) / 2;

    if (ids[M] > id)
      {
      R = M;
      continue;
      }
    else if (ids[M] < id)
      {
      L = M;
      continue;
      }
    else
      {
      loc = M;
      break;
      }
    }
  return loc;
}
vtkIdList *vtkExtractCells::reMapPointIds(vtkDataSet *grid)
{
  int totalPoints = grid->GetNumberOfPoints();

  char *temp = new char [totalPoints];

  if (!temp)
    {
    vtkErrorMacro(<< "vtkExtractCells::reMapPointIds memory allocation");
    return NULL;
    }
  memset(temp, 0, totalPoints);

  int numberOfIds = 0;
  int i;
  vtkIdType id;
  vtkIdList *ptIds = vtkIdList::New();
  vtkstd::set<vtkIdType>::iterator cellPtr;

  if (!this->InputIsUgrid)
    {
    for (cellPtr = this->CellList->IdTypeSet.begin();
         cellPtr != this->CellList->IdTypeSet.end();
         ++cellPtr)
      {
      grid->GetCellPoints(*cellPtr, ptIds);

      vtkIdType nIds = ptIds->GetNumberOfIds();

      vtkIdType *ptId = ptIds->GetPointer(0);

      for (i=0; i<nIds; i++)
        {
        id = *ptId++;

        if (temp[id] == 0)
          {
          numberOfIds++;
          temp[id] = 1;
          }
        }
      }
    }
  else
    {
    vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(grid);

    this->SubSetUGridCellArraySize = 0;

    vtkIdType *cellArray = ugrid->GetCells()->GetPointer();
    vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0);

    this->SubSetUGridCellArraySize = 0;
    vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId();

    for (cellPtr = this->CellList->IdTypeSet.begin();
         cellPtr != this->CellList->IdTypeSet.end();
         ++cellPtr)
      {
      if (*cellPtr > maxid) continue;

      int loc = locs[*cellPtr];

      vtkIdType nIds = cellArray[loc++];

      this->SubSetUGridCellArraySize += (1 + nIds);

      for (i=0; i<nIds; i++)
        {
        id = cellArray[loc++];

        if (temp[id] == 0)
          {
          numberOfIds++;
          temp[id] = 1;
          }
        }
      }
    }

  ptIds->SetNumberOfIds(numberOfIds);
  int next=0;

  for (id=0; id<totalPoints; id++)
    {
    if (temp[id]) ptIds->SetId(next++, id);
    }

  delete [] temp;

  return ptIds;
}
void vtkExtractCells::CopyCellsDataSet(vtkIdList *ptMap)
{
  vtkDataSet *input = this->GetInput();
  vtkUnstructuredGrid *output= this->GetOutput();

  output->Allocate(this->CellList->IdTypeSet.size());

  vtkCellData *oldCD = input->GetCellData();
  vtkCellData *newCD = output->GetCellData();

  vtkIdList *cellPoints = vtkIdList::New();

  vtkstd::set<vtkIdType>::iterator cellPtr;

  for (cellPtr = this->CellList->IdTypeSet.begin();
       cellPtr != this->CellList->IdTypeSet.end();
       ++cellPtr)
    {
    vtkIdType cellId = *cellPtr;

    input->GetCellPoints(cellId, cellPoints);

    for (int i=0; i < cellPoints->GetNumberOfIds(); i++)
      {
      vtkIdType oldId = cellPoints->GetId(i);

      vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId);

      cellPoints->SetId(i, newId);
      }
    int newId = output->InsertNextCell(input->GetCellType(cellId), cellPoints);

    newCD->CopyData(oldCD, cellId, newId);
    }

  cellPoints->Delete();

  return;
}
void vtkExtractCells::CopyCellsUnstructuredGrid(vtkIdList *ptMap)
{
  vtkDataSet *input = this->GetInput();

  vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(input);

  if (ugrid == NULL)
    {
    this->CopyCellsDataSet(ptMap);
    return;
    }

  vtkUnstructuredGrid *output= this->GetOutput();

  vtkCellData *oldCD = input->GetCellData();
  vtkCellData *newCD = output->GetCellData();

  int numCells = this->CellList->IdTypeSet.size();

  vtkCellArray *cellArray = vtkCellArray::New();                 // output
  vtkIdTypeArray *newcells = vtkIdTypeArray::New();
  newcells->SetNumberOfValues(this->SubSetUGridCellArraySize);
  cellArray->SetCells(numCells, newcells);
  int cellArrayIdx = 0;

  vtkIdTypeArray *locationArray = vtkIdTypeArray::New();
  locationArray->SetNumberOfValues(numCells);

  vtkUnsignedCharArray *typeArray = vtkUnsignedCharArray::New();
  typeArray->SetNumberOfValues(numCells);

  int nextCellId = 0;

  vtkstd::set<vtkIdType>::iterator cellPtr;                           // input
  vtkIdType *cells = ugrid->GetCells()->GetPointer();
  vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId();
  vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0);
  vtkUnsignedCharArray *types = ugrid->GetCellTypesArray();

  for (cellPtr = this->CellList->IdTypeSet.begin();
       cellPtr != this->CellList->IdTypeSet.end();
       ++cellPtr)
    {
      if (*cellPtr > maxid) continue;

    int oldCellId = *cellPtr;

    int loc = locs[oldCellId];
    int size = (int)cells[loc];
    vtkIdType *pts = cells + loc + 1;
    unsigned char type = types->GetValue(oldCellId);

    locationArray->SetValue(nextCellId, cellArrayIdx);
    typeArray->SetValue(nextCellId, type);

    newcells->SetValue(cellArrayIdx++, size);

    for (int i=0; i<size; i++)
      {
      vtkIdType oldId = *pts++;
      vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId);

      newcells->SetValue(cellArrayIdx++, newId);
      }

    newCD->CopyData(oldCD, oldCellId, nextCellId);

    nextCellId++;
    }

  output->SetCells(typeArray, locationArray, cellArray);

  typeArray->Delete();
  locationArray->Delete();
  newcells->Delete();
  cellArray->Delete();

  return;
}

void vtkExtractCells::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

<|endoftext|>


<commit_before>
#include "Mesh_repair.h"

namespace P_RVD
{
	bool mesh_repair(Mesh& _M){};
}<commit_msg>updat<commit_after>
#include "Mesh_repair.h"

namespace P_RVD
{
	bool mesh_repair(Mesh& _M){ return true; };
}<|endoftext|>


<commit_before>#include "thcrap.h"
#include <sstream>
#include <cstring>
#include "update.h"
#include "server.h"
#include "strings_array.h"
#include "3rdparty/crc32.h"

Update::Update(Update::filter_t filterCallback,
               progress_callback_t progressCallback, void *progressData)
    : filterCallback(filterCallback), progressCallback(progressCallback), progressData(progressData)
{
    crc32::generate_table(this->crc32Table);
}

get_status_t Update::httpStatusToGetStatus(HttpStatus status)
{
    switch (status.get()) {
        case HttpStatus::Ok:
            return GET_OK;
        case HttpStatus::Cancelled:
            return GET_CANCELLED;
        case HttpStatus::ClientError:
            return GET_CLIENT_ERROR;
        case HttpStatus::ServerError:
            return GET_SERVER_ERROR;
        case HttpStatus::SystemError:
            return GET_SYSTEM_ERROR;
        default:
            throw std::invalid_argument("Invalid status");
    }
}

bool Update::callProgressCallback(const patch_t *patch, const std::string& fn, const DownloadUrl& url, get_status_t getStatus, std::string error,
                                  size_t file_progress, size_t file_size)
{
    if (this->progressCallback == nullptr) {
        return true;
    }

    progress_callback_status_t status;

    status.patch = patch;
    status.fn = fn.c_str();
    status.url = url.getUrl().c_str();
    status.file_progress = file_progress;
    status.file_size = file_size;

    status.status = getStatus;
    if (getStatus == GET_CLIENT_ERROR || getStatus == GET_SERVER_ERROR || getStatus == GET_SYSTEM_ERROR) {
        status.error = error.c_str();
    }
    else {
        status.error = nullptr;
    }

    status.nb_files_downloaded = this->mainDownloader.current();
    if (this->filesJsDownloader.current() == this->filesJsDownloader.total()) {
        status.nb_files_total = this->mainDownloader.total();
    }
    else {
        status.nb_files_total = 0;
    }

    return this->progressCallback(&status, this->progressData);
}

class AutoWriteJson
{
private:
    json_t *json;
    const patch_t *patch;
    const char *fn;

public:
    AutoWriteJson(const patch_t *patch, const char *fn)
        : json(patch_json_load(patch, fn, nullptr)), patch(patch), fn(fn)
    {
        if (!this->json) {
            this->json = json_object();
        }
    }
    ~AutoWriteJson()
    {
        patch_json_store(this->patch, fn, this->json);
        json_decref(this->json);
    }
    operator json_t*() {
        return this->json;
    }

    AutoWriteJson(const AutoWriteJson&) = delete;
    AutoWriteJson(AutoWriteJson&&) = delete;
    AutoWriteJson& operator=(const AutoWriteJson&) = delete;
    AutoWriteJson& operator=(AutoWriteJson&&) = delete;
};

std::string Update::fnToUrl(const std::string& url, uint32_t crc32)
{
    // Formatting with streams is trash. Hopefully we can replace this
    // with the C++20 std::format.
    std::ostringstream ss;
    ss << std::hex << std::setfill('0');

    auto is_valid_for_uri = [](unsigned char c) {
        if ('A' <= c && c <= 'Z') {
            return true;
        }
        if ('a' <= c && c <= 'z') {
            return true;
        }
        if ('0' <= c && c <= '9') {
            return true;
        }
        if (c == '-' || c == '_' || c == '.' || c == '~') {
            return true;
        }
        return false;
    };

    // Escape illegal characters
    for (unsigned char c : url) {
        if (is_valid_for_uri(c) || c == '/') {
            ss.put(c);
        }
        else {
            ss << '%'<< std::setw(2) << static_cast<unsigned int>(c) << std::setw(0);
        }
    }

    // Append CRC32 in order to get the correct version from the CDN
    ss << "?crc32=" << std::setw(8) << crc32 << std::setw(0);
    return ss.str();
}

void Update::onFilesJsComplete(const patch_t *patch, const std::vector<uint8_t>& data)
{
    auto localFilesJs = std::make_shared<AutoWriteJson>(patch, "files.js");
    ScopedJson remoteFilesJs = json_loadb(reinterpret_cast<const char*>(data.data()), data.size(), 0, nullptr);

    if (*remoteFilesJs == nullptr) {
        log_printf("%s: files.js isn't a valid json file!\n", patch->id);
        return ;
    }

    const char *fn;
    json_t *value;
    json_object_foreach(*remoteFilesJs, fn, value) {
        json_t *localValue = json_object_get(*localFilesJs, fn);
        // Did someone simply drop a full files.js into a standalone
        // package that doesn't actually come with the files for
        // every game?
        // (Necessary in case this patch installation should later
        // cover more games. If the remote files haven't changed by
        // then, they wouldn't be downloaded if files.js pretends
        // that these versions already exist locally.)
        if (localValue && !patch_file_exists(patch, fn)) {
            json_object_del(*localFilesJs, fn);
            localValue = nullptr;
        }
        if (localValue && json_equal(value, localValue)) {
            // The file didn't change since our last update, no need to update or delete it
            continue;
        }
        if (this->filterCallback != nullptr && this->filterCallback(fn) == false) {
            // We don't want to download this file
            continue;
        }
        if (json_is_null(value)) {
            // Delete file
            if (patch_file_exists(patch, fn)) {
                log_printf("Deleting %s/%s\n", patch->id, fn);
                patch_file_delete(patch, fn);
            }
            json_object_set(*localFilesJs, fn, json_null());
            continue;
        }

        this->mainDownloader.addFile(patch->servers, this->fnToUrl(fn, (uint32_t)json_integer_value(value)),

            // Success callback
            [this, patch, fn = std::string(fn), localFilesJs, value = ScopedJson(json_incref(value))]
            (const DownloadUrl& url, std::vector<uint8_t>& data) mutable {
                if (crc32::update(this->crc32Table, 0, data.data(), data.size()) != json_integer_value(*value)) {
                    this->callProgressCallback(patch, fn, url, GET_CRC32_ERROR);
                    return ;
                }
                if (patch_file_store(patch, fn.c_str(), data.data(), data.size()) != 0) {
                    this->callProgressCallback(patch, fn, url, GET_SYSTEM_ERROR, "file write failed");
                    return ;
                }
                this->callProgressCallback(patch, fn, url, GET_OK, "", data.size(), data.size());
                json_object_set(*localFilesJs, fn.c_str(), *value);
            },

            // Failure callback
            [this, patch, fn = std::string(fn)](const DownloadUrl& url, HttpStatus httpStatus) {
                get_status_t getStatus = this->httpStatusToGetStatus(httpStatus);
                this->callProgressCallback(patch, fn, url, getStatus, httpStatus.toString());
            },

            // Progress callback
            [this, patch, fn = std::string(fn)](const DownloadUrl& url, size_t file_progress, size_t file_size) {
                return this->callProgressCallback(patch, fn, url, GET_DOWNLOADING, "", file_progress, file_size);
            }
        );
    }
}

void Update::startPatchUpdate(const patch_t *patch)
{
    if (patch->id == nullptr) {
        log_printf("Invalid patch at %s\n", patch->archive);
        return ;
    }
    if (patch->servers == nullptr || patch->servers[0] == nullptr) {
        log_printf("(%s doesn't have any servers, not updating.)\n", patch->id);
        return;
    }
    // Assuming the repo/patch hierarchy here, but if we ever support
	// repository-less Git patches, they won't be using the files.js
	// protocol anyway.
    if (patch_file_exists(patch, "../.git")) {
		log_printf("(%s is under revision control, not updating.)\n", patch->id);
        return ;
    }
    if (patch->update == false) {
		// Updating manually deactivated on this patch
		log_printf("(%s has updates disabled, not updating.)\n", patch->id);
        return ;
    }

    this->filesJsDownloader.addFile(patch->servers, "files.js",
        [this, patch](const DownloadUrl&, std::vector<uint8_t>& data) {
            this->onFilesJsComplete(patch, data);
        },
        [patch_id = std::string(patch->id)](const DownloadUrl& url, HttpStatus httpStatus) {
            if (httpStatus.get() == HttpStatus::Cancelled) {
                // Another file finished before
                return ;
            }
            log_printf("Downloading files.js from %s failed\n", url.getUrl().c_str());
        }
    );
}

void Update::run(const std::list<const patch_t*>& patchs)
{
    for (const patch_t* patch : patchs) {
        this->startPatchUpdate(patch);
    }

    this->filesJsDownloader.wait();
    // At this point, dlPatchFiles have been fully populated
    this->mainDownloader.wait();
}

patch_t patch_bootstrap(const patch_desc_t *sel, const repo_t *repo)
{
    if (!repo) {
        patch_t empty_patch = { };
        return empty_patch;
    }

    std::string url = repo->servers[0];
    url += sel->patch_id;
    url += "/patch.js";
    auto [patch_js, _] = ServerCache::get().downloadJsonFile(url);

    RepoWrite(repo);
	patch_t patch_info = patch_build(sel);
	patch_json_store(&patch_info, "patch.js", *patch_js);
	// TODO: Nice, friendly error

	return patch_info;
}

int update_filter_global(const char *fn, void*)
{
	return strchr(fn, '/') == NULL;
}

int update_filter_games(const char *fn, void *param)
{
    const char **games = static_cast<const char **>(param);
	size_t fn_len = strlen(fn);

    if (!games) {
	    return update_filter_global(fn, nullptr);
    }

    for (size_t i = 0; games[i]; i++) {
		// We will need to match "th14", but not "th143".
		size_t game_len = strlen(games[i]);
		if(
			fn_len > game_len
			&& !strncmp(fn, games[i], game_len)
			&& fn[game_len] == '/'
		) {
			return 1;
		}
    }

	return update_filter_global(fn, NULL);
}

void stack_update(update_filter_func_t filter_func, void *filter_data, progress_callback_t progress_callback, void *progress_param)
{
    auto filter_lambda =
        [filter_func, filter_data](const std::string& fn) -> bool {
            return filter_func(fn.c_str(), filter_data) != 0;
        };
    Update update(filter_lambda, progress_callback, progress_param);

    std::list<const patch_t*> patches;
    stack_foreach_cpp([&patches](const patch_t *patch) {
        patches.push_back(patch);
    });
    update.run(patches);
}

// Helper class to free a patch automatically when it goes out of scope
class ScopedPatch
{
private:
    bool active = true;
    patch_t patch;

public:
    // Automatic lifetime management
    ScopedPatch(patch_t patch)
        : patch(patch)
    {}
    ~ScopedPatch()
    {
        if (active) {
            patch_free(&patch);
        }
    }

    // Disallow copy
    ScopedPatch(const ScopedPatch&) = delete;
    ScopedPatch& operator=(const ScopedPatch&) = delete;

    // Allow move (needed for containers)
    ScopedPatch(ScopedPatch&& src)
        : patch(src.patch)
    {
        this->patch = src.patch;
        src.active = false;
    }
    // Containers don't need that one
    ScopedPatch& operator=(ScopedPatch&&) = delete;

    // We want to use them
    operator patch_t*()
    {
        return &this->patch;
    }
};

void global_update(progress_callback_t progress_callback, void *progress_param)
{
	std::list<const patch_t*> patches;
    // We want to free the patches we created, but not the ones
    // from the stack.
    // The ScopedPatch wrapper will free these patches automatically
    // when patches_storage goes out of scope.
	std::vector<ScopedPatch> patches_storage;

	// Get the patches from the stack
	stack_foreach_cpp([&patches](const patch_t *patch) {
		if (patch->archive) {
			patches.push_back(patch);
		}
	});

	// Add all the patches we can find in config files
    if (std::filesystem::is_directory("config")) {
        for (auto& dir_entry : std::filesystem::directory_iterator("config")) {
            std::filesystem::path path = dir_entry.path();
            if (path.extension() != ".js") {
                continue;
            }

	    	ScopedJson config = json_load_file(path.u8string().c_str(), 0, nullptr);
	    	if (!*config) {
	    		continue;
	    	}

	    	size_t i;
	    	json_t *patch_info;
	    	json_array_foreach(json_object_get(*config, "patches"), i, patch_info) {
	    		patch_t patch = patch_init(json_object_get_string(patch_info, "archive"), patch_info, 0);
                if (patch.id == nullptr) {
                    log_printf("Error loading %s/patch.js\n", json_object_get_string(patch_info, "archive"));
                    continue;
                }
	    		patch_rel_to_abs(&patch, path.generic_u8string().c_str());
	    		if (patch.archive && !std::any_of(patches.begin(), patches.end(), [&patch](const patch_t *it) {
	    				return strcmp(patch.archive, it->archive) != 0;
	    			})) {
	    			patches_storage.push_back(patch);
	    			patches.push_back(patches_storage.back());
	    		}
	    		else {
	    			patch_free(&patch);
	    		}
	    	}
	    }
    }

    char **games = strings_array_create();
    {
	    ScopedJson games_js = json_load_file("config/games.js", 0, nullptr);
        const char *key;
        json_t *value;
        json_object_foreach(*games_js, key, value) {
            games = strings_array_add(games, key);
        }
    }

    auto filter_lambda =
        [games](const std::string& fn) -> bool {
            return update_filter_games(fn.c_str(), games);
        };
    Update update(filter_lambda, progress_callback, progress_param);
    update.run(patches);

    strings_array_free(games);
}
<commit_msg>thcrap_configure: fix patch selection on repos without servers<commit_after>#include "thcrap.h"
#include <sstream>
#include <cstring>
#include "update.h"
#include "server.h"
#include "strings_array.h"
#include "3rdparty/crc32.h"

Update::Update(Update::filter_t filterCallback,
               progress_callback_t progressCallback, void *progressData)
    : filterCallback(filterCallback), progressCallback(progressCallback), progressData(progressData)
{
    crc32::generate_table(this->crc32Table);
}

get_status_t Update::httpStatusToGetStatus(HttpStatus status)
{
    switch (status.get()) {
        case HttpStatus::Ok:
            return GET_OK;
        case HttpStatus::Cancelled:
            return GET_CANCELLED;
        case HttpStatus::ClientError:
            return GET_CLIENT_ERROR;
        case HttpStatus::ServerError:
            return GET_SERVER_ERROR;
        case HttpStatus::SystemError:
            return GET_SYSTEM_ERROR;
        default:
            throw std::invalid_argument("Invalid status");
    }
}

bool Update::callProgressCallback(const patch_t *patch, const std::string& fn, const DownloadUrl& url, get_status_t getStatus, std::string error,
                                  size_t file_progress, size_t file_size)
{
    if (this->progressCallback == nullptr) {
        return true;
    }

    progress_callback_status_t status;

    status.patch = patch;
    status.fn = fn.c_str();
    status.url = url.getUrl().c_str();
    status.file_progress = file_progress;
    status.file_size = file_size;

    status.status = getStatus;
    if (getStatus == GET_CLIENT_ERROR || getStatus == GET_SERVER_ERROR || getStatus == GET_SYSTEM_ERROR) {
        status.error = error.c_str();
    }
    else {
        status.error = nullptr;
    }

    status.nb_files_downloaded = this->mainDownloader.current();
    if (this->filesJsDownloader.current() == this->filesJsDownloader.total()) {
        status.nb_files_total = this->mainDownloader.total();
    }
    else {
        status.nb_files_total = 0;
    }

    return this->progressCallback(&status, this->progressData);
}

class AutoWriteJson
{
private:
    json_t *json;
    const patch_t *patch;
    const char *fn;

public:
    AutoWriteJson(const patch_t *patch, const char *fn)
        : json(patch_json_load(patch, fn, nullptr)), patch(patch), fn(fn)
    {
        if (!this->json) {
            this->json = json_object();
        }
    }
    ~AutoWriteJson()
    {
        patch_json_store(this->patch, fn, this->json);
        json_decref(this->json);
    }
    operator json_t*() {
        return this->json;
    }

    AutoWriteJson(const AutoWriteJson&) = delete;
    AutoWriteJson(AutoWriteJson&&) = delete;
    AutoWriteJson& operator=(const AutoWriteJson&) = delete;
    AutoWriteJson& operator=(AutoWriteJson&&) = delete;
};

std::string Update::fnToUrl(const std::string& url, uint32_t crc32)
{
    // Formatting with streams is trash. Hopefully we can replace this
    // with the C++20 std::format.
    std::ostringstream ss;
    ss << std::hex << std::setfill('0');

    auto is_valid_for_uri = [](unsigned char c) {
        if ('A' <= c && c <= 'Z') {
            return true;
        }
        if ('a' <= c && c <= 'z') {
            return true;
        }
        if ('0' <= c && c <= '9') {
            return true;
        }
        if (c == '-' || c == '_' || c == '.' || c == '~') {
            return true;
        }
        return false;
    };

    // Escape illegal characters
    for (unsigned char c : url) {
        if (is_valid_for_uri(c) || c == '/') {
            ss.put(c);
        }
        else {
            ss << '%'<< std::setw(2) << static_cast<unsigned int>(c) << std::setw(0);
        }
    }

    // Append CRC32 in order to get the correct version from the CDN
    ss << "?crc32=" << std::setw(8) << crc32 << std::setw(0);
    return ss.str();
}

void Update::onFilesJsComplete(const patch_t *patch, const std::vector<uint8_t>& data)
{
    auto localFilesJs = std::make_shared<AutoWriteJson>(patch, "files.js");
    ScopedJson remoteFilesJs = json_loadb(reinterpret_cast<const char*>(data.data()), data.size(), 0, nullptr);

    if (*remoteFilesJs == nullptr) {
        log_printf("%s: files.js isn't a valid json file!\n", patch->id);
        return ;
    }

    const char *fn;
    json_t *value;
    json_object_foreach(*remoteFilesJs, fn, value) {
        json_t *localValue = json_object_get(*localFilesJs, fn);
        // Did someone simply drop a full files.js into a standalone
        // package that doesn't actually come with the files for
        // every game?
        // (Necessary in case this patch installation should later
        // cover more games. If the remote files haven't changed by
        // then, they wouldn't be downloaded if files.js pretends
        // that these versions already exist locally.)
        if (localValue && !patch_file_exists(patch, fn)) {
            json_object_del(*localFilesJs, fn);
            localValue = nullptr;
        }
        if (localValue && json_equal(value, localValue)) {
            // The file didn't change since our last update, no need to update or delete it
            continue;
        }
        if (this->filterCallback != nullptr && this->filterCallback(fn) == false) {
            // We don't want to download this file
            continue;
        }
        if (json_is_null(value)) {
            // Delete file
            if (patch_file_exists(patch, fn)) {
                log_printf("Deleting %s/%s\n", patch->id, fn);
                patch_file_delete(patch, fn);
            }
            json_object_set(*localFilesJs, fn, json_null());
            continue;
        }

        this->mainDownloader.addFile(patch->servers, this->fnToUrl(fn, (uint32_t)json_integer_value(value)),

            // Success callback
            [this, patch, fn = std::string(fn), localFilesJs, value = ScopedJson(json_incref(value))]
            (const DownloadUrl& url, std::vector<uint8_t>& data) mutable {
                if (crc32::update(this->crc32Table, 0, data.data(), data.size()) != json_integer_value(*value)) {
                    this->callProgressCallback(patch, fn, url, GET_CRC32_ERROR);
                    return ;
                }
                if (patch_file_store(patch, fn.c_str(), data.data(), data.size()) != 0) {
                    this->callProgressCallback(patch, fn, url, GET_SYSTEM_ERROR, "file write failed");
                    return ;
                }
                this->callProgressCallback(patch, fn, url, GET_OK, "", data.size(), data.size());
                json_object_set(*localFilesJs, fn.c_str(), *value);
            },

            // Failure callback
            [this, patch, fn = std::string(fn)](const DownloadUrl& url, HttpStatus httpStatus) {
                get_status_t getStatus = this->httpStatusToGetStatus(httpStatus);
                this->callProgressCallback(patch, fn, url, getStatus, httpStatus.toString());
            },

            // Progress callback
            [this, patch, fn = std::string(fn)](const DownloadUrl& url, size_t file_progress, size_t file_size) {
                return this->callProgressCallback(patch, fn, url, GET_DOWNLOADING, "", file_progress, file_size);
            }
        );
    }
}

void Update::startPatchUpdate(const patch_t *patch)
{
    if (patch->id == nullptr) {
        log_printf("Invalid patch at %s\n", patch->archive);
        return ;
    }
    if (patch->servers == nullptr || patch->servers[0] == nullptr) {
        log_printf("(%s doesn't have any servers, not updating.)\n", patch->id);
        return;
    }
    // Assuming the repo/patch hierarchy here, but if we ever support
	// repository-less Git patches, they won't be using the files.js
	// protocol anyway.
    if (patch_file_exists(patch, "../.git")) {
		log_printf("(%s is under revision control, not updating.)\n", patch->id);
        return ;
    }
    if (patch->update == false) {
		// Updating manually deactivated on this patch
		log_printf("(%s has updates disabled, not updating.)\n", patch->id);
        return ;
    }

    this->filesJsDownloader.addFile(patch->servers, "files.js",
        [this, patch](const DownloadUrl&, std::vector<uint8_t>& data) {
            this->onFilesJsComplete(patch, data);
        },
        [patch_id = std::string(patch->id)](const DownloadUrl& url, HttpStatus httpStatus) {
            if (httpStatus.get() == HttpStatus::Cancelled) {
                // Another file finished before
                return ;
            }
            log_printf("Downloading files.js from %s failed\n", url.getUrl().c_str());
        }
    );
}

void Update::run(const std::list<const patch_t*>& patchs)
{
    for (const patch_t* patch : patchs) {
        this->startPatchUpdate(patch);
    }

    this->filesJsDownloader.wait();
    // At this point, dlPatchFiles have been fully populated
    this->mainDownloader.wait();
}

patch_t patch_bootstrap(const patch_desc_t *sel, const repo_t *repo)
{
    if (!repo || !repo->servers) {
        return patch_build(sel);
    }

    std::string url = repo->servers[0];
    url += sel->patch_id;
    url += "/patch.js";
    auto [patch_js, _] = ServerCache::get().downloadJsonFile(url);

    RepoWrite(repo);
	patch_t patch_info = patch_build(sel);
	patch_json_store(&patch_info, "patch.js", *patch_js);
	// TODO: Nice, friendly error

	return patch_info;
}

int update_filter_global(const char *fn, void*)
{
	return strchr(fn, '/') == NULL;
}

int update_filter_games(const char *fn, void *param)
{
    const char **games = static_cast<const char **>(param);
	size_t fn_len = strlen(fn);

    if (!games) {
	    return update_filter_global(fn, nullptr);
    }

    for (size_t i = 0; games[i]; i++) {
		// We will need to match "th14", but not "th143".
		size_t game_len = strlen(games[i]);
		if(
			fn_len > game_len
			&& !strncmp(fn, games[i], game_len)
			&& fn[game_len] == '/'
		) {
			return 1;
		}
    }

	return update_filter_global(fn, NULL);
}

void stack_update(update_filter_func_t filter_func, void *filter_data, progress_callback_t progress_callback, void *progress_param)
{
    auto filter_lambda =
        [filter_func, filter_data](const std::string& fn) -> bool {
            return filter_func(fn.c_str(), filter_data) != 0;
        };
    Update update(filter_lambda, progress_callback, progress_param);

    std::list<const patch_t*> patches;
    stack_foreach_cpp([&patches](const patch_t *patch) {
        patches.push_back(patch);
    });
    update.run(patches);
}

// Helper class to free a patch automatically when it goes out of scope
class ScopedPatch
{
private:
    bool active = true;
    patch_t patch;

public:
    // Automatic lifetime management
    ScopedPatch(patch_t patch)
        : patch(patch)
    {}
    ~ScopedPatch()
    {
        if (active) {
            patch_free(&patch);
        }
    }

    // Disallow copy
    ScopedPatch(const ScopedPatch&) = delete;
    ScopedPatch& operator=(const ScopedPatch&) = delete;

    // Allow move (needed for containers)
    ScopedPatch(ScopedPatch&& src)
        : patch(src.patch)
    {
        this->patch = src.patch;
        src.active = false;
    }
    // Containers don't need that one
    ScopedPatch& operator=(ScopedPatch&&) = delete;

    // We want to use them
    operator patch_t*()
    {
        return &this->patch;
    }
};

void global_update(progress_callback_t progress_callback, void *progress_param)
{
	std::list<const patch_t*> patches;
    // We want to free the patches we created, but not the ones
    // from the stack.
    // The ScopedPatch wrapper will free these patches automatically
    // when patches_storage goes out of scope.
	std::vector<ScopedPatch> patches_storage;

	// Get the patches from the stack
	stack_foreach_cpp([&patches](const patch_t *patch) {
		if (patch->archive) {
			patches.push_back(patch);
		}
	});

	// Add all the patches we can find in config files
    if (std::filesystem::is_directory("config")) {
        for (auto& dir_entry : std::filesystem::directory_iterator("config")) {
            std::filesystem::path path = dir_entry.path();
            if (path.extension() != ".js") {
                continue;
            }

	    	ScopedJson config = json_load_file(path.u8string().c_str(), 0, nullptr);
	    	if (!*config) {
	    		continue;
	    	}

	    	size_t i;
	    	json_t *patch_info;
	    	json_array_foreach(json_object_get(*config, "patches"), i, patch_info) {
	    		patch_t patch = patch_init(json_object_get_string(patch_info, "archive"), patch_info, 0);
                if (patch.id == nullptr) {
                    log_printf("Error loading %s/patch.js\n", json_object_get_string(patch_info, "archive"));
                    continue;
                }
	    		patch_rel_to_abs(&patch, path.generic_u8string().c_str());
	    		if (patch.archive && !std::any_of(patches.begin(), patches.end(), [&patch](const patch_t *it) {
	    				return strcmp(patch.archive, it->archive) != 0;
	    			})) {
	    			patches_storage.push_back(patch);
	    			patches.push_back(patches_storage.back());
	    		}
	    		else {
	    			patch_free(&patch);
	    		}
	    	}
	    }
    }

    char **games = strings_array_create();
    {
	    ScopedJson games_js = json_load_file("config/games.js", 0, nullptr);
        const char *key;
        json_t *value;
        json_object_foreach(*games_js, key, value) {
            games = strings_array_add(games, key);
        }
    }

    auto filter_lambda =
        [games](const std::string& fn) -> bool {
            return update_filter_games(fn.c_str(), games);
        };
    Update update(filter_lambda, progress_callback, progress_param);
    update.run(patches);

    strings_array_free(games);
}
<|endoftext|>


<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <cctype>
#include <stdexcept>
#include "Bundle.hpp"
#include "Cache.hpp"
#include "Loader.hpp"
#include "utils/Json.hpp"
#include "utils/Utils.hpp"

namespace ouzel
{
    namespace assets
    {
        Bundle::Bundle(Cache& initCache, storage::FileSystem& initFileSystem):
            cache(initCache), fileSystem(initFileSystem)
        {
            cache.addBundle(this);
        }

        Bundle::~Bundle()
        {
            cache.removeBundle(this);
        }

        void Bundle::loadAsset(uint32_t loaderType, const std::string& name,
                               const std::string& filename, bool mipmaps)
        {
            const std::vector<uint8_t> data = fileSystem.readFile(filename);

            const auto& loaders = cache.getLoaders();

            for (auto i = loaders.rbegin(); i != loaders.rend(); ++i)
            {
                Loader* loader = i->get();
                if (loader->getType() == loaderType &&
                    loader->loadAsset(*this, name, data, mipmaps))
                    return;
            }

            throw std::runtime_error("Failed to load asset " + filename);
        }

        void Bundle::loadAssets(const std::string& filename)
        {
            const json::Data data(fileSystem.readFile(filename));

            for (const json::Value& asset : data["assets"])
            {
                auto file = asset["filename"].as<std::string>();
                auto name = asset.hasMember("name") ? asset["name"].as<std::string>() : file;
                auto mipmaps = asset.hasMember("mipmaps") ? asset["mipmaps"].as<bool>() : true;
                loadAsset(asset["type"].as<uint32_t>(), name, file, mipmaps);
            }
        }

        void Bundle::loadAssets(const std::vector<Asset>& assets)
        {
            for (const Asset& asset : assets)
                loadAsset(asset.type, asset.name, asset.filename, asset.mipmaps);
        }

        std::shared_ptr<graphics::Texture> Bundle::getTexture(const std::string& name) const
        {
            auto i = textures.find(name);

            if (i != textures.end())
                return i->second;

            return nullptr;
        }

        void Bundle::setTexture(const std::string& name, const std::shared_ptr<graphics::Texture>& texture)
        {
            textures[name] = texture;
        }

        void Bundle::releaseTextures()
        {
            textures.clear();
        }

        const graphics::Shader* Bundle::getShader(const std::string& name) const
        {
            auto i = shaders.find(name);

            if (i != shaders.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setShader(const std::string& name, std::unique_ptr<graphics::Shader> shader)
        {
            shaders[name] = std::move(shader);
        }

        void Bundle::releaseShaders()
        {
            shaders.clear();
        }

        const graphics::BlendState* Bundle::getBlendState(const std::string& name) const
        {
            auto i = blendStates.find(name);

            if (i != blendStates.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setBlendState(const std::string& name, std::unique_ptr<graphics::BlendState> blendState)
        {
            blendStates[name] = std::move(blendState);
        }

        void Bundle::releaseBlendStates()
        {
            blendStates.clear();
        }

        const graphics::DepthStencilState* Bundle::getDepthStencilState(const std::string& name) const
        {
            auto i = depthStencilStates.find(name);

            if (i != depthStencilStates.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setDepthStencilState(const std::string& name, std::unique_ptr<graphics::DepthStencilState> depthStencilState)
        {
            depthStencilStates[name] = std::move(depthStencilState);
        }

        void Bundle::releaseDepthStencilStates()
        {
            depthStencilStates.clear();
        }

        void Bundle::preloadSpriteData(const std::string& filename, bool mipmaps,
                                       uint32_t spritesX, uint32_t spritesY,
                                       const Vector2F& pivot)
        {
            auto extension = storage::FileSystem::getExtensionPart(filename);
            std::transform(extension.begin(), extension.end(), extension.begin(), [](unsigned char c){ return toLower(c); });
            std::vector<std::string> imageExtensions{"jpg", "jpeg", "png", "bmp", "tga"};

            if (std::find(imageExtensions.begin(), imageExtensions.end(), extension) != imageExtensions.end())
            {
                scene::SpriteData newSpriteData;

                if (spritesX == 0) spritesX = 1;
                if (spritesY == 0) spritesY = 1;

                newSpriteData.texture = getTexture(filename);

                const Size2F textureSize(static_cast<float>(newSpriteData.texture->getSize().v[0]),
                                         static_cast<float>(newSpriteData.texture->getSize().v[1]));

                if (newSpriteData.texture)
                {
                    auto spriteSize = Size2F(textureSize.v[0] / spritesX,
                                             textureSize.v[1] / spritesY);

                    scene::SpriteData::Animation animation;
                    animation.frames.reserve(spritesX * spritesY);

                    for (uint32_t x = 0; x < spritesX; ++x)
                    {
                        for (uint32_t y = 0; y < spritesY; ++y)
                        {
                            RectF rectangle(spriteSize.v[0] * x,
                                            spriteSize.v[1] * y,
                                            spriteSize.v[0],
                                            spriteSize.v[1]);

                            animation.frames.emplace_back(filename, textureSize, rectangle, false, spriteSize, Vector2F(), pivot);
                        }
                    }

                    newSpriteData.animations[""] = std::move(animation);

                    spriteData[filename] = newSpriteData;
                }
            }
            else
                loadAsset(Loader::Sprite, filename, filename, mipmaps);
        }

        const scene::SpriteData* Bundle::getSpriteData(const std::string& name) const
        {
            auto i = spriteData.find(name);

            if (i != spriteData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setSpriteData(const std::string& name, const scene::SpriteData& newSpriteData)
        {
            spriteData[name] = newSpriteData;
        }

        void Bundle::releaseSpriteData()
        {
            spriteData.clear();
        }

        const scene::ParticleSystemData* Bundle::getParticleSystemData(const std::string& name) const
        {
            auto i = particleSystemData.find(name);

            if (i != particleSystemData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setParticleSystemData(const std::string& name, const scene::ParticleSystemData& newParticleSystemData)
        {
            particleSystemData[name] = newParticleSystemData;
        }

        void Bundle::releaseParticleSystemData()
        {
            particleSystemData.clear();
        }

        const gui::Font* Bundle::getFont(const std::string& name) const
        {
            auto i = fonts.find(name);

            if (i != fonts.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setFont(const std::string& name, std::unique_ptr<gui::Font> font)
        {
            fonts[name] = std::move(font);
        }

        void Bundle::releaseFonts()
        {
            fonts.clear();
        }

        const audio::Cue* Bundle::getCue(const std::string& name) const
        {
            auto i = cues.find(name);

            if (i != cues.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setCue(const std::string& name, std::unique_ptr<audio::Cue> cue)
        {
            cues[name] = std::move(cue);
        }

        void Bundle::releaseCues()
        {
            cues.clear();
        }

        const audio::Sound* Bundle::getSound(const std::string& name) const
        {
            auto i = sounds.find(name);

            if (i != sounds.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setSound(const std::string& name, std::unique_ptr<audio::Sound> sound)
        {
            sounds[name] = std::move(sound);
        }

        void Bundle::releaseSounds()
        {
            sounds.clear();
        }

        const graphics::Material* Bundle::getMaterial(const std::string& name) const
        {
            auto i = materials.find(name);

            if (i != materials.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setMaterial(const std::string& name, std::unique_ptr<graphics::Material> material)
        {
            materials[name] = std::move(material);
        }

        void Bundle::releaseMaterials()
        {
            materials.clear();
        }

        const scene::SkinnedMeshData* Bundle::getSkinnedMeshData(const std::string& name) const
        {
            auto i = skinnedMeshData.find(name);

            if (i != skinnedMeshData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setSkinnedMeshData(const std::string& name, scene::SkinnedMeshData&& newSkinnedMeshData)
        {
            skinnedMeshData[name] = std::move(newSkinnedMeshData);
        }

        void Bundle::releaseSkinnedMeshData()
        {
            skinnedMeshData.clear();
        }

        const scene::StaticMeshData* Bundle::getStaticMeshData(const std::string& name) const
        {
            auto i = staticMeshData.find(name);

            if (i != staticMeshData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setStaticMeshData(const std::string& name, scene::StaticMeshData&& newStaticMeshData)
        {
            staticMeshData[name] = std::move(newStaticMeshData);
        }

        void Bundle::releaseStaticMeshData()
        {
            staticMeshData.clear();
        }
    } // namespace assets
} // namespace ouzel
<commit_msg>Make variables const in Bundle.cpp<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include <cctype>
#include <stdexcept>
#include "Bundle.hpp"
#include "Cache.hpp"
#include "Loader.hpp"
#include "utils/Json.hpp"
#include "utils/Utils.hpp"

namespace ouzel
{
    namespace assets
    {
        Bundle::Bundle(Cache& initCache, storage::FileSystem& initFileSystem):
            cache(initCache), fileSystem(initFileSystem)
        {
            cache.addBundle(this);
        }

        Bundle::~Bundle()
        {
            cache.removeBundle(this);
        }

        void Bundle::loadAsset(uint32_t loaderType, const std::string& name,
                               const std::string& filename, bool mipmaps)
        {
            const std::vector<uint8_t> data = fileSystem.readFile(filename);

            const auto& loaders = cache.getLoaders();

            for (auto i = loaders.rbegin(); i != loaders.rend(); ++i)
            {
                Loader* loader = i->get();
                if (loader->getType() == loaderType &&
                    loader->loadAsset(*this, name, data, mipmaps))
                    return;
            }

            throw std::runtime_error("Failed to load asset " + filename);
        }

        void Bundle::loadAssets(const std::string& filename)
        {
            const json::Data data(fileSystem.readFile(filename));

            for (const json::Value& asset : data["assets"])
            {
                const auto file = asset["filename"].as<std::string>();
                const auto name = asset.hasMember("name") ? asset["name"].as<std::string>() : file;
                const auto mipmaps = asset.hasMember("mipmaps") ? asset["mipmaps"].as<bool>() : true;
                loadAsset(asset["type"].as<uint32_t>(), name, file, mipmaps);
            }
        }

        void Bundle::loadAssets(const std::vector<Asset>& assets)
        {
            for (const Asset& asset : assets)
                loadAsset(asset.type, asset.name, asset.filename, asset.mipmaps);
        }

        std::shared_ptr<graphics::Texture> Bundle::getTexture(const std::string& name) const
        {
            auto i = textures.find(name);

            if (i != textures.end())
                return i->second;

            return nullptr;
        }

        void Bundle::setTexture(const std::string& name, const std::shared_ptr<graphics::Texture>& texture)
        {
            textures[name] = texture;
        }

        void Bundle::releaseTextures()
        {
            textures.clear();
        }

        const graphics::Shader* Bundle::getShader(const std::string& name) const
        {
            auto i = shaders.find(name);

            if (i != shaders.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setShader(const std::string& name, std::unique_ptr<graphics::Shader> shader)
        {
            shaders[name] = std::move(shader);
        }

        void Bundle::releaseShaders()
        {
            shaders.clear();
        }

        const graphics::BlendState* Bundle::getBlendState(const std::string& name) const
        {
            auto i = blendStates.find(name);

            if (i != blendStates.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setBlendState(const std::string& name, std::unique_ptr<graphics::BlendState> blendState)
        {
            blendStates[name] = std::move(blendState);
        }

        void Bundle::releaseBlendStates()
        {
            blendStates.clear();
        }

        const graphics::DepthStencilState* Bundle::getDepthStencilState(const std::string& name) const
        {
            auto i = depthStencilStates.find(name);

            if (i != depthStencilStates.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setDepthStencilState(const std::string& name, std::unique_ptr<graphics::DepthStencilState> depthStencilState)
        {
            depthStencilStates[name] = std::move(depthStencilState);
        }

        void Bundle::releaseDepthStencilStates()
        {
            depthStencilStates.clear();
        }

        void Bundle::preloadSpriteData(const std::string& filename, bool mipmaps,
                                       uint32_t spritesX, uint32_t spritesY,
                                       const Vector2F& pivot)
        {
            auto extension = storage::FileSystem::getExtensionPart(filename);
            std::transform(extension.begin(), extension.end(), extension.begin(), [](unsigned char c){ return toLower(c); });
            const std::vector<std::string> imageExtensions{"jpg", "jpeg", "png", "bmp", "tga"};

            if (std::find(imageExtensions.begin(), imageExtensions.end(), extension) != imageExtensions.end())
            {
                scene::SpriteData newSpriteData;

                if (spritesX == 0) spritesX = 1;
                if (spritesY == 0) spritesY = 1;

                newSpriteData.texture = getTexture(filename);

                const Size2F textureSize(static_cast<float>(newSpriteData.texture->getSize().v[0]),
                                         static_cast<float>(newSpriteData.texture->getSize().v[1]));

                if (newSpriteData.texture)
                {
                    const auto spriteSize = Size2F(textureSize.v[0] / spritesX,
                                                   textureSize.v[1] / spritesY);

                    scene::SpriteData::Animation animation;
                    animation.frames.reserve(spritesX * spritesY);

                    for (uint32_t x = 0; x < spritesX; ++x)
                    {
                        for (uint32_t y = 0; y < spritesY; ++y)
                        {
                            RectF rectangle(spriteSize.v[0] * x,
                                            spriteSize.v[1] * y,
                                            spriteSize.v[0],
                                            spriteSize.v[1]);

                            animation.frames.emplace_back(filename, textureSize, rectangle, false, spriteSize, Vector2F(), pivot);
                        }
                    }

                    newSpriteData.animations[""] = std::move(animation);

                    spriteData[filename] = newSpriteData;
                }
            }
            else
                loadAsset(Loader::Sprite, filename, filename, mipmaps);
        }

        const scene::SpriteData* Bundle::getSpriteData(const std::string& name) const
        {
            auto i = spriteData.find(name);

            if (i != spriteData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setSpriteData(const std::string& name, const scene::SpriteData& newSpriteData)
        {
            spriteData[name] = newSpriteData;
        }

        void Bundle::releaseSpriteData()
        {
            spriteData.clear();
        }

        const scene::ParticleSystemData* Bundle::getParticleSystemData(const std::string& name) const
        {
            auto i = particleSystemData.find(name);

            if (i != particleSystemData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setParticleSystemData(const std::string& name, const scene::ParticleSystemData& newParticleSystemData)
        {
            particleSystemData[name] = newParticleSystemData;
        }

        void Bundle::releaseParticleSystemData()
        {
            particleSystemData.clear();
        }

        const gui::Font* Bundle::getFont(const std::string& name) const
        {
            auto i = fonts.find(name);

            if (i != fonts.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setFont(const std::string& name, std::unique_ptr<gui::Font> font)
        {
            fonts[name] = std::move(font);
        }

        void Bundle::releaseFonts()
        {
            fonts.clear();
        }

        const audio::Cue* Bundle::getCue(const std::string& name) const
        {
            auto i = cues.find(name);

            if (i != cues.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setCue(const std::string& name, std::unique_ptr<audio::Cue> cue)
        {
            cues[name] = std::move(cue);
        }

        void Bundle::releaseCues()
        {
            cues.clear();
        }

        const audio::Sound* Bundle::getSound(const std::string& name) const
        {
            auto i = sounds.find(name);

            if (i != sounds.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setSound(const std::string& name, std::unique_ptr<audio::Sound> sound)
        {
            sounds[name] = std::move(sound);
        }

        void Bundle::releaseSounds()
        {
            sounds.clear();
        }

        const graphics::Material* Bundle::getMaterial(const std::string& name) const
        {
            auto i = materials.find(name);

            if (i != materials.end())
                return i->second.get();

            return nullptr;
        }

        void Bundle::setMaterial(const std::string& name, std::unique_ptr<graphics::Material> material)
        {
            materials[name] = std::move(material);
        }

        void Bundle::releaseMaterials()
        {
            materials.clear();
        }

        const scene::SkinnedMeshData* Bundle::getSkinnedMeshData(const std::string& name) const
        {
            auto i = skinnedMeshData.find(name);

            if (i != skinnedMeshData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setSkinnedMeshData(const std::string& name, scene::SkinnedMeshData&& newSkinnedMeshData)
        {
            skinnedMeshData[name] = std::move(newSkinnedMeshData);
        }

        void Bundle::releaseSkinnedMeshData()
        {
            skinnedMeshData.clear();
        }

        const scene::StaticMeshData* Bundle::getStaticMeshData(const std::string& name) const
        {
            auto i = staticMeshData.find(name);

            if (i != staticMeshData.end())
                return &i->second;

            return nullptr;
        }

        void Bundle::setStaticMeshData(const std::string& name, scene::StaticMeshData&& newStaticMeshData)
        {
            staticMeshData[name] = std::move(newStaticMeshData);
        }

        void Bundle::releaseStaticMeshData()
        {
            staticMeshData.clear();
        }
    } // namespace assets
} // namespace ouzel
<|endoftext|>