<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include "expr-precomp.h"  // Precompiled headers

#include <mrpt/expr/CRuntimeCompiledExpression.h>
#include <mrpt/core/exceptions.h>
#include <cmath>  // M_PI

#define exprtk_disable_string_capabilities  // Workaround a bug in Ubuntu
// precise's GCC+libstdc++
#include <mrpt/otherlibs/exprtk.hpp>

// We only need this to be on this translation unit, hence the advantage of
// using our MRPT wrapper instead
// of the original exprtk sources.
PIMPL_IMPLEMENT(exprtk::expression<double>)

using namespace mrpt;
using namespace mrpt::expr;

CRuntimeCompiledExpression::CRuntimeCompiledExpression()
{
	PIMPL_CONSTRUCT(exprtk::expression<double>, m_compiled_formula);
}

void CRuntimeCompiledExpression::compile(
	/** [in] The expression to be compiled. */
	const std::string& expression,
	/** [in] Map of variables/constants by `name` ->  `value`. The references to
	   the values in this map **must** be ensured to be valid thoughout all the
	   life of the compiled expression. */
	const std::map<std::string, double>& variables,
	/** A descriptive name of this formula, to be used when generating error
	   reports via an  exception, if needed */
	const std::string& expr_name_for_error_reporting)
{
	m_original_expr_str = expression;

	exprtk::symbol_table<double> symbol_table;
	for (const auto& v : variables)
	{
		double& var = const_cast<double&>(v.second);
		symbol_table.add_variable(v.first, var);
	}
	symbol_table.add_constant("M_PI", M_PI);
	symbol_table.add_constants();

	PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula)
		.register_symbol_table(symbol_table);
	// Compile user-given expressions:
	exprtk::parser<double> parser;
	if (!parser.compile(
			expression,
			PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula)))
		THROW_EXCEPTION_FMT(
			"Error compiling expression (name=`%s`): `%s`. Error: `%s`",
			expr_name_for_error_reporting.c_str(), expression.c_str(),
			parser.error().c_str());
}

double CRuntimeCompiledExpression::eval() const
{
	ASSERT_(m_compiled_formula.ptr.get() != nullptr);
	return PIMPL_GET_CONSTREF(exprtk::expression<double>, m_compiled_formula)
		.value();
}

void CRuntimeCompiledExpression::register_symbol_table(
	/** [in] Map of variables/constants by `name` ->  `value`. The
	   references to the values in this map **must** be ensured to be valid
	   thoughout all the life of the compiled expression. */
	const std::map<std::string, double*>& variables)
{
	exprtk::symbol_table<double> symbol_table;
	for (const auto& v : variables)
	{
		double* var = const_cast<double*>(v.second);
		symbol_table.add_variable(v.first, *var);
	}
	PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula)
		.register_symbol_table(symbol_table);
}

exprtk::expression<double>& CRuntimeCompiledExpression::get_raw_exprtk_expr()
{
	ASSERT_(m_compiled_formula.ptr.get() != nullptr);
	return PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula);
}
const exprtk::expression<double>&
	CRuntimeCompiledExpression::get_raw_exprtk_expr() const
{
	ASSERT_(m_compiled_formula.ptr.get() != nullptr);
	return PIMPL_GET_CONSTREF(exprtk::expression<double>, m_compiled_formula);
}

bool CRuntimeCompiledExpression::is_compiled() const
{
	return m_compiled_formula.ptr.get() != nullptr;
}
const std::string& CRuntimeCompiledExpression::get_original_expression() const
{
	return m_original_expr_str;
}
<commit_msg>exprtk: disable features for faster build and smaller libs<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include "expr-precomp.h"  // Precompiled headers

#include <mrpt/expr/CRuntimeCompiledExpression.h>
#include <mrpt/core/exceptions.h>
#include <cmath>  // M_PI

#define exprtk_disable_string_capabilities  // Workaround a bug in Ubuntu
// precise's GCC+libstdc++

// Disable some parts of exprtk to build faster and reduce lib size:
#define exprtk_disable_enhanced_features
#define exprtk_disable_superscalar_unroll
#define exprtk_disable_rtl_vecops
#define exprtk_disable_rtl_io_file
#include <mrpt/otherlibs/exprtk.hpp>

// We only need this to be on this translation unit, hence the advantage of
// using our MRPT wrapper instead
// of the original exprtk sources.
PIMPL_IMPLEMENT(exprtk::expression<double>)

using namespace mrpt;
using namespace mrpt::expr;

CRuntimeCompiledExpression::CRuntimeCompiledExpression()
{
	PIMPL_CONSTRUCT(exprtk::expression<double>, m_compiled_formula);
}

void CRuntimeCompiledExpression::compile(
	/** [in] The expression to be compiled. */
	const std::string& expression,
	/** [in] Map of variables/constants by `name` ->  `value`. The references to
	   the values in this map **must** be ensured to be valid thoughout all the
	   life of the compiled expression. */
	const std::map<std::string, double>& variables,
	/** A descriptive name of this formula, to be used when generating error
	   reports via an  exception, if needed */
	const std::string& expr_name_for_error_reporting)
{
	m_original_expr_str = expression;

	exprtk::symbol_table<double> symbol_table;
	for (const auto& v : variables)
	{
		double& var = const_cast<double&>(v.second);
		symbol_table.add_variable(v.first, var);
	}
	symbol_table.add_constant("M_PI", M_PI);
	symbol_table.add_constants();

	PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula)
		.register_symbol_table(symbol_table);
	// Compile user-given expressions:
	exprtk::parser<double> parser;
	if (!parser.compile(
			expression,
			PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula)))
		THROW_EXCEPTION_FMT(
			"Error compiling expression (name=`%s`): `%s`. Error: `%s`",
			expr_name_for_error_reporting.c_str(), expression.c_str(),
			parser.error().c_str());
}

double CRuntimeCompiledExpression::eval() const
{
	ASSERT_(m_compiled_formula.ptr.get() != nullptr);
	return PIMPL_GET_CONSTREF(exprtk::expression<double>, m_compiled_formula)
		.value();
}

void CRuntimeCompiledExpression::register_symbol_table(
	/** [in] Map of variables/constants by `name` ->  `value`. The
	   references to the values in this map **must** be ensured to be valid
	   thoughout all the life of the compiled expression. */
	const std::map<std::string, double*>& variables)
{
	exprtk::symbol_table<double> symbol_table;
	for (const auto& v : variables)
	{
		double* var = const_cast<double*>(v.second);
		symbol_table.add_variable(v.first, *var);
	}
	PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula)
		.register_symbol_table(symbol_table);
}

exprtk::expression<double>& CRuntimeCompiledExpression::get_raw_exprtk_expr()
{
	ASSERT_(m_compiled_formula.ptr.get() != nullptr);
	return PIMPL_GET_REF(exprtk::expression<double>, m_compiled_formula);
}
const exprtk::expression<double>&
	CRuntimeCompiledExpression::get_raw_exprtk_expr() const
{
	ASSERT_(m_compiled_formula.ptr.get() != nullptr);
	return PIMPL_GET_CONSTREF(exprtk::expression<double>, m_compiled_formula);
}

bool CRuntimeCompiledExpression::is_compiled() const
{
	return m_compiled_formula.ptr.get() != nullptr;
}
const std::string& CRuntimeCompiledExpression::get_original_expression() const
{
	return m_original_expr_str;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: zipfileaccess.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kz $ $Date: 2004-05-18 17:22:25 $
 *
 *  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): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/

#ifndef _ZIPFILEACCESS_HXX_
#define _ZIPFILEACCESS_HXX_

#ifndef _COM_SUN_STAR_PACKAGES_ZIP_XZIPFILEACCESS_HPP_
#include <com/sun/star/packages/zip/XZipFileAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

#include <cppuhelper/interfacecontainer.h>
#include <cppuhelper/implbase5.hxx>
#include <osl/mutex.hxx>

#include <ZipFile.hxx>
#include <HashMaps.hxx>

class OZipFileAccess : public ::cppu::WeakImplHelper5<
                        ::com::sun::star::packages::zip::XZipFileAccess,
                        ::com::sun::star::container::XNameAccess,
                        ::com::sun::star::lang::XInitialization,
                        ::com::sun::star::lang::XComponent,
                        ::com::sun::star::lang::XServiceInfo >
{
    ::osl::Mutex m_aMutex;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > m_xContentStream;
    ZipFile* m_pZipFile;

    EntryHash m_aEntries;

    ::cppu::OInterfaceContainerHelper* m_pListenersContainer;

    sal_Bool m_bDisposed;

public:
    OZipFileAccess( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory );

    virtual ~OZipFileAccess();

    EntryHash& GetEntryHash_Impl();

    ::com::sun::star::uno::Sequence< ::rtl::OUString > GetPatternsFromString_Impl( const ::rtl::OUString& aString );

    sal_Bool StringGoodForPattern_Impl( const ::rtl::OUString& aString,
                                        const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPattern );

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XInitialization
    virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XNameAccess
    virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Type SAL_CALL getElementType(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasElements(  ) throw (::com::sun::star::uno::RuntimeException);

    // XZipFileAccess
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getStreamByPattern( const ::rtl::OUString& aPattern ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.82); FILE MERGED 2005/09/05 18:49:02 rt 1.2.82.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: zipfileaccess.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:00:27 $
 *
 *  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 _ZIPFILEACCESS_HXX_
#define _ZIPFILEACCESS_HXX_

#ifndef _COM_SUN_STAR_PACKAGES_ZIP_XZIPFILEACCESS_HPP_
#include <com/sun/star/packages/zip/XZipFileAccess.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

#include <cppuhelper/interfacecontainer.h>
#include <cppuhelper/implbase5.hxx>
#include <osl/mutex.hxx>

#include <ZipFile.hxx>
#include <HashMaps.hxx>

class OZipFileAccess : public ::cppu::WeakImplHelper5<
                        ::com::sun::star::packages::zip::XZipFileAccess,
                        ::com::sun::star::container::XNameAccess,
                        ::com::sun::star::lang::XInitialization,
                        ::com::sun::star::lang::XComponent,
                        ::com::sun::star::lang::XServiceInfo >
{
    ::osl::Mutex m_aMutex;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > m_xContentStream;
    ZipFile* m_pZipFile;

    EntryHash m_aEntries;

    ::cppu::OInterfaceContainerHelper* m_pListenersContainer;

    sal_Bool m_bDisposed;

public:
    OZipFileAccess( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory );

    virtual ~OZipFileAccess();

    EntryHash& GetEntryHash_Impl();

    ::com::sun::star::uno::Sequence< ::rtl::OUString > GetPatternsFromString_Impl( const ::rtl::OUString& aString );

    sal_Bool StringGoodForPattern_Impl( const ::rtl::OUString& aString,
                                        const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPattern );

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XInitialization
    virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XNameAccess
    virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Type SAL_CALL getElementType(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL hasElements(  ) throw (::com::sun::star::uno::RuntimeException);

    // XZipFileAccess
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getStreamByPattern( const ::rtl::OUString& aPattern ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

    // XComponent
    virtual void SAL_CALL dispose(  ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);

};

#endif

<|endoftext|>


<commit_before>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2010 Alessandro Tasora
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

//////////////////////////////////////////////////
//
//   ChCCollisionSystemBullet.cpp
//
// ------------------------------------------------
//             www.deltaknowledge.com
// ------------------------------------------------
///////////////////////////////////////////////////

#include "collision/ChCCollisionSystemBullet.h"
#include "collision/ChCModelBullet.h"
#include "collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h"
#include "physics/ChBody.h"
#include "physics/ChContactContainerBase.h"
#include "physics/ChProximityContainerBase.h"
#include "LinearMath/btPoolAllocator.h"

namespace chrono
{
namespace collision
{

/*
void defaultChronoNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
{
	btCollisionDispatcher::defaultNearCallback(collisionPair, dispatcher, dispatchInfo);
	if (broad_callback)
		broad_callback(collisionPair, dispatcher, dispatchInfo);
}
*/

ChCollisionSystemBullet::ChCollisionSystemBullet(unsigned int max_objects, double scene_size)
{
	// btDefaultCollisionConstructionInfo conf_info(...); ***TODO***
	bt_collision_configuration = new btDefaultCollisionConfiguration();
	bt_dispatcher = new btCollisionDispatcher(bt_collision_configuration);

	  //***OLD***

	btScalar sscene_size = (btScalar)scene_size;
	 btVector3	worldAabbMin(-sscene_size,-sscene_size,-sscene_size);
	 btVector3	worldAabbMax(sscene_size,sscene_size,sscene_size);
	bt_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax, max_objects, 0, true); // true for disabling raycast accelerator

	  //***NEW***
	//bt_broadphase = new btDbvtBroadphase();

	bt_collision_world = new btCollisionWorld(bt_dispatcher, bt_broadphase, bt_collision_configuration);

	// custom collision for sphere-sphere case ***OBSOLETE***
	//bt_dispatcher->registerCollisionCreateFunc(SPHERE_SHAPE_PROXYTYPE,SPHERE_SHAPE_PROXYTYPE,new btSphereSphereCollisionAlgorithm::CreateFunc);

	// register custom collision for GIMPACT mesh case too
	btGImpactCollisionAlgorithm::registerAlgorithm(bt_dispatcher);
}

ChCollisionSystemBullet::~ChCollisionSystemBullet()
{
	if(bt_collision_world) delete bt_collision_world;
	if(bt_broadphase) delete bt_broadphase;
	if(bt_dispatcher) delete bt_dispatcher;
	if(bt_collision_configuration) delete bt_collision_configuration;
}

void ChCollisionSystemBullet::Clear(void)
{
	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
		contactManifold->clearManifold();
	}
}

void ChCollisionSystemBullet::Add(ChCollisionModel* model)
{
	if (((ChModelBullet*)model)->GetBulletModel()->getCollisionShape())
	{
		model->SyncPosition();
		bt_collision_world->addCollisionObject(((ChModelBullet*)model)->GetBulletModel(),
			((ChModelBullet*)model)->GetFamilyGroup(),
			((ChModelBullet*)model)->GetFamilyMask());
	}
}

void ChCollisionSystemBullet::Remove(ChCollisionModel* model)
{
	if (((ChModelBullet*)model)->GetBulletModel()->getCollisionShape())
	{
		bt_collision_world->removeCollisionObject(((ChModelBullet*)model)->GetBulletModel());
	}
}

void ChCollisionSystemBullet::Run()
{
	if (bt_collision_world)
	{
		bt_collision_world->performDiscreteCollisionDetection();
	}
}

void ChCollisionSystemBullet::ReportContacts(ChContactContainerBase* mcontactcontainer)
{
	// This should remove all old contacts (or at least rewind the index)
	mcontactcontainer->BeginAddContact();

	ChCollisionInfo icontact;

	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());

		icontact.modelA = (ChCollisionModel*)obA->getUserPointer();
		icontact.modelB = (ChCollisionModel*)obB->getUserPointer();

		double envelopeA = icontact.modelA->GetEnvelope();
		double envelopeB = icontact.modelB->GetEnvelope();

		double marginA = icontact.modelA->GetSafeMargin();
		double marginB = icontact.modelB->GetSafeMargin();

		// Execute custom broadphase callback, if any
		bool do_narrow_contactgeneration = true;
		if (this->broad_callback)
			do_narrow_contactgeneration = this->broad_callback->BroadCallback(icontact.modelA, icontact.modelB);

		if (do_narrow_contactgeneration)
		{
			int numContacts = contactManifold->getNumContacts();

			for (int j=0;j<numContacts;j++)
			{
				btManifoldPoint& pt = contactManifold->getContactPoint(j);

				if (pt.getDistance() < marginA+marginB) // to discard "too far" constraints (the Bullet engine also has its threshold)
				{
					btVector3 ptA = pt.getPositionWorldOnA();
					btVector3 ptB = pt.getPositionWorldOnB();

					icontact.vpA.Set(ptA.getX(), ptA.getY(), ptA.getZ());
					icontact.vpB.Set(ptB.getX(), ptB.getY(), ptB.getZ());

					icontact.vN.Set( -pt.m_normalWorldOnB.getX(),
									 -pt.m_normalWorldOnB.getY(),
									 -pt.m_normalWorldOnB.getZ());
					icontact.vN.Normalize();

					double ptdist = pt.getDistance();

					icontact.vpA = icontact.vpA - icontact.vN*envelopeA;
					icontact.vpB = icontact.vpB + icontact.vN*envelopeB;
					icontact.distance = ptdist + envelopeA + envelopeB;

					icontact.reaction_cache = pt.reactions_cache;

					// Execute some user custom callback, if any
					if (this->narrow_callback)
						this->narrow_callback->NarrowCallback(icontact);

					// Add to contact container
					mcontactcontainer->AddContact(icontact);
				}

			}
		}

		//you can un-comment out this line, and then all points are removed
		//contactManifold->clearManifold();
	}
	mcontactcontainer->EndAddContact();
}

void ChCollisionSystemBullet::ReportProximities(ChProximityContainerBase* mproximitycontainer)
{
	mproximitycontainer->BeginAddProximities();

	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());

		ChCollisionModel* modelA = (ChCollisionModel*)obA->getUserPointer();
		ChCollisionModel* modelB = (ChCollisionModel*)obB->getUserPointer();

		// Add to proximity container
		mproximitycontainer->AddProximity(modelA, modelB);
	}
	mproximitycontainer->EndAddProximities();
}

bool ChCollisionSystemBullet::RayHit(const ChVector<>& from, const ChVector<>& to, ChRayhitResult& mresult)
{
	btVector3 btfrom((btScalar)from.x, (btScalar)from.y, (btScalar)from.z);
	btVector3 btto  ((btScalar)to.x,   (btScalar)to.y,   (btScalar)to.z);

	btCollisionWorld::ClosestRayResultCallback rayCallback(btfrom,btto);

	this->bt_collision_world->rayTest(btfrom, btto, rayCallback);

	if (rayCallback.hasHit())
	{
		mresult.hitModel = (ChCollisionModel*)(rayCallback.m_collisionObject->getUserPointer());
		if (mresult.hitModel)
		{
			mresult.hit = true;
			mresult.abs_hitPoint.Set(rayCallback.m_hitPointWorld.x(),rayCallback.m_hitPointWorld.y(),rayCallback.m_hitPointWorld.z());
			mresult.abs_hitNormal.Set(rayCallback.m_hitNormalWorld.x(),rayCallback.m_hitNormalWorld.y(),rayCallback.m_hitNormalWorld.z());
			mresult.abs_hitNormal.Normalize();
			mresult.hit = true;
			mresult.dist_factor = rayCallback.m_closestHitFraction;
			return true;
		}
	}
	mresult.hit = false;
	return false;
}

} // END_OF_NAMESPACE____
} // END_OF_NAMESPACE____

<commit_msg>The default GJK algorithm of Bullet is a bit unaccurate for very odd size ratios. Since I needed to simulate small spherical particles that touch a large cylinder, I registered a new lgorithm into Bullet for an analytical solution for the sphere-cylinder case.<commit_after>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2010 Alessandro Tasora
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

//////////////////////////////////////////////////
//
//   ChCCollisionSystemBullet.cpp
//
// ------------------------------------------------
//             www.deltaknowledge.com
// ------------------------------------------------
///////////////////////////////////////////////////

#include "collision/ChCCollisionSystemBullet.h"
#include "collision/ChCModelBullet.h"
#include "collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h"
#include "physics/ChBody.h"
#include "physics/ChContactContainerBase.h"
#include "physics/ChProximityContainerBase.h"
#include "LinearMath/btPoolAllocator.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btCylinderShape.h"

namespace chrono
{
namespace collision
{

// Utility class that we use to override the default cylinder-sphere collision
// case, because the default behavior in Bullet was using the GJK algorithm, that
// gives not 100% precise results if the cylinder is much larger than the sphere:
class btSphereCylinderCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
	bool	m_ownManifold;
	btPersistentManifold*	m_manifoldPtr;
	bool	m_isSwapped;

public:
	btSphereCylinderCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
		: btActivatingCollisionAlgorithm(ci,col0,col1),
			m_ownManifold(false),
			m_manifoldPtr(mf),
			m_isSwapped(isSwapped)
			{
				if (!m_manifoldPtr)
				{
					m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
					m_ownManifold = true;
				}
			}

	btSphereCylinderCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
		: btActivatingCollisionAlgorithm(ci) {}

	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
	{
		(void)dispatchInfo;

		if (!m_manifoldPtr)
			return;

		btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
		btCollisionObject* cylObj = m_isSwapped? body0 : body1;

		resultOut->setPersistentManifold(m_manifoldPtr);

		btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
		btCylinderShape* cylinder = (btCylinderShape*)cylObj->getCollisionShape();

		const btTransform&	m44T = cylObj->getWorldTransform();
		btVector3 diff = m44T.invXform(sphereObj->getWorldTransform().getOrigin()); //col0->getWorldTransform().getOrigin()-  col1->getWorldTransform().getOrigin();
		btScalar radius0 = sphere0->getRadius();
		btScalar radius1 = cylinder->getHalfExtentsWithMargin().getX(); //cylinder->getRadius();
		btScalar H1 = cylinder->getHalfExtentsWithMargin().getY();

		btVector3 r1 = diff;
		r1.setY(0);

		btScalar y1 = diff.y();

		btScalar r1_len = r1.length();

		btVector3 pos1;
		btVector3 normalOnSurfaceB(1,0,0);
		btScalar dist;

		// Case A
		if ((y1 <= H1)&&(y1 >= -H1))
		{

			///iff distance positive, don't generate a new contact
			if ( r1_len > (radius0+radius1))
			{
				resultOut->refreshContactPoints();
				return;
			}
			///distance (negative means penetration)
			dist = r1_len - (radius0+radius1);

			btVector3 localnormalOnSurfaceB;
			if (r1_len > SIMD_EPSILON)
			{
				localnormalOnSurfaceB = r1 / r1_len;
				normalOnSurfaceB =  m44T.getBasis() * localnormalOnSurfaceB;
			}
			///point on B (worldspace)
			pos1 = m44T(btVector3(0, y1,0)) + radius1* normalOnSurfaceB;
		}
		else
		{
			btScalar side = 1;
			if (y1 < -H1)
				side = -1;

			if (r1_len > radius1)
			{
				// case B
				btVector3 pos_loc = r1.normalized() * radius1 + btVector3(0, H1*side, 0);
				pos1 = m44T(pos_loc);
				btVector3 d = sphereObj->getWorldTransform().getOrigin() - pos1;
				normalOnSurfaceB = d.normalized();
				dist = d.length() - radius0;
			}
			else
			{
				// case C
				normalOnSurfaceB = m44T.getBasis() * btVector3(0, 1*side, 0);
				btVector3 pos_loc = r1 + btVector3(0, H1*side, 0);
				pos1 = m44T(pos_loc);
				dist = side*(y1 - H1) - radius0;
			}
		}
		/// report a contact. internally this will be kept persistent, and contact reduction is done
		resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);

		resultOut->refreshContactPoints();
	}

	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
	{
		//not yet
		return btScalar(1.);
	}

	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
	{
		if (m_manifoldPtr && m_ownManifold)
		{
			manifoldArray.push_back(m_manifoldPtr);
		}
	}

	virtual ~btSphereCylinderCollisionAlgorithm()
		{
			if (m_ownManifold)
			{
				if (m_manifoldPtr)
					m_dispatcher->releaseManifold(m_manifoldPtr);
			}
		}

	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
	{
		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
		{
			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereCylinderCollisionAlgorithm));
			if (!m_swapped)
			{
				return new(mem) btSphereCylinderCollisionAlgorithm(0,ci,body0,body1,false);
			} else
			{
				return new(mem) btSphereCylinderCollisionAlgorithm(0,ci,body0,body1,true);
			}
		}
	};

};

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

ChCollisionSystemBullet::ChCollisionSystemBullet(unsigned int max_objects, double scene_size)
{
	// btDefaultCollisionConstructionInfo conf_info(...); ***TODO***
	bt_collision_configuration = new btDefaultCollisionConfiguration();

	bt_dispatcher = new btCollisionDispatcher(bt_collision_configuration);

	  //***OLD***

	btScalar sscene_size = (btScalar)scene_size;
	 btVector3	worldAabbMin(-sscene_size,-sscene_size,-sscene_size);
	 btVector3	worldAabbMax(sscene_size,sscene_size,sscene_size);
	bt_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax, max_objects, 0, true); // true for disabling raycast accelerator

	  //***NEW***
	//bt_broadphase = new btDbvtBroadphase();

	bt_collision_world = new btCollisionWorld(bt_dispatcher, bt_broadphase, bt_collision_configuration);

	// custom collision for sphere-sphere case ***OBSOLETE*** // already registered by btDefaultCollisionConfiguration
	//bt_dispatcher->registerCollisionCreateFunc(SPHERE_SHAPE_PROXYTYPE,SPHERE_SHAPE_PROXYTYPE,new btSphereSphereCollisionAlgorithm::CreateFunc);

	// custom collision for cylinder-sphere case, for improved precision
	bt_dispatcher->registerCollisionCreateFunc(SPHERE_SHAPE_PROXYTYPE, CYLINDER_SHAPE_PROXYTYPE,new btSphereCylinderCollisionAlgorithm::CreateFunc);
	bt_dispatcher->registerCollisionCreateFunc(CYLINDER_SHAPE_PROXYTYPE, SPHERE_SHAPE_PROXYTYPE,new btSphereCylinderCollisionAlgorithm::CreateFunc);

	// custom collision for GIMPACT mesh case too
	btGImpactCollisionAlgorithm::registerAlgorithm(bt_dispatcher);
}

ChCollisionSystemBullet::~ChCollisionSystemBullet()
{
	if(bt_collision_world) delete bt_collision_world;
	if(bt_broadphase) delete bt_broadphase;
	if(bt_dispatcher) delete bt_dispatcher;
	if(bt_collision_configuration) delete bt_collision_configuration;
}

void ChCollisionSystemBullet::Clear(void)
{
	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
		contactManifold->clearManifold();
	}
}

void ChCollisionSystemBullet::Add(ChCollisionModel* model)
{
	if (((ChModelBullet*)model)->GetBulletModel()->getCollisionShape())
	{
		model->SyncPosition();
		bt_collision_world->addCollisionObject(((ChModelBullet*)model)->GetBulletModel(),
			((ChModelBullet*)model)->GetFamilyGroup(),
			((ChModelBullet*)model)->GetFamilyMask());
	}
}

void ChCollisionSystemBullet::Remove(ChCollisionModel* model)
{
	if (((ChModelBullet*)model)->GetBulletModel()->getCollisionShape())
	{
		bt_collision_world->removeCollisionObject(((ChModelBullet*)model)->GetBulletModel());
	}
}

void ChCollisionSystemBullet::Run()
{
	if (bt_collision_world)
	{
		bt_collision_world->performDiscreteCollisionDetection();
	}
}

void ChCollisionSystemBullet::ReportContacts(ChContactContainerBase* mcontactcontainer)
{
	// This should remove all old contacts (or at least rewind the index)
	mcontactcontainer->BeginAddContact();

	ChCollisionInfo icontact;

	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());

		icontact.modelA = (ChCollisionModel*)obA->getUserPointer();
		icontact.modelB = (ChCollisionModel*)obB->getUserPointer();

		double envelopeA = icontact.modelA->GetEnvelope();
		double envelopeB = icontact.modelB->GetEnvelope();

		double marginA = icontact.modelA->GetSafeMargin();
		double marginB = icontact.modelB->GetSafeMargin();

		// Execute custom broadphase callback, if any
		bool do_narrow_contactgeneration = true;
		if (this->broad_callback)
			do_narrow_contactgeneration = this->broad_callback->BroadCallback(icontact.modelA, icontact.modelB);

		if (do_narrow_contactgeneration)
		{
			int numContacts = contactManifold->getNumContacts();

			for (int j=0;j<numContacts;j++)
			{
				btManifoldPoint& pt = contactManifold->getContactPoint(j);

				if (pt.getDistance() < marginA+marginB) // to discard "too far" constraints (the Bullet engine also has its threshold)
				{
					btVector3 ptA = pt.getPositionWorldOnA();
					btVector3 ptB = pt.getPositionWorldOnB();

					icontact.vpA.Set(ptA.getX(), ptA.getY(), ptA.getZ());
					icontact.vpB.Set(ptB.getX(), ptB.getY(), ptB.getZ());

					icontact.vN.Set( -pt.m_normalWorldOnB.getX(),
									 -pt.m_normalWorldOnB.getY(),
									 -pt.m_normalWorldOnB.getZ());
					icontact.vN.Normalize();

					double ptdist = pt.getDistance();

					icontact.vpA = icontact.vpA - icontact.vN*envelopeA;
					icontact.vpB = icontact.vpB + icontact.vN*envelopeB;
					icontact.distance = ptdist + envelopeA + envelopeB;

					icontact.reaction_cache = pt.reactions_cache;

					// Execute some user custom callback, if any
					if (this->narrow_callback)
						this->narrow_callback->NarrowCallback(icontact);

					// Add to contact container
					mcontactcontainer->AddContact(icontact);
				}

			}
		}

		//you can un-comment out this line, and then all points are removed
		//contactManifold->clearManifold();
	}
	mcontactcontainer->EndAddContact();
}

void ChCollisionSystemBullet::ReportProximities(ChProximityContainerBase* mproximitycontainer)
{
	mproximitycontainer->BeginAddProximities();

	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());

		ChCollisionModel* modelA = (ChCollisionModel*)obA->getUserPointer();
		ChCollisionModel* modelB = (ChCollisionModel*)obB->getUserPointer();

		// Add to proximity container
		mproximitycontainer->AddProximity(modelA, modelB);
	}
	mproximitycontainer->EndAddProximities();
}

bool ChCollisionSystemBullet::RayHit(const ChVector<>& from, const ChVector<>& to, ChRayhitResult& mresult)
{
	btVector3 btfrom((btScalar)from.x, (btScalar)from.y, (btScalar)from.z);
	btVector3 btto  ((btScalar)to.x,   (btScalar)to.y,   (btScalar)to.z);

	btCollisionWorld::ClosestRayResultCallback rayCallback(btfrom,btto);

	this->bt_collision_world->rayTest(btfrom, btto, rayCallback);

	if (rayCallback.hasHit())
	{
		mresult.hitModel = (ChCollisionModel*)(rayCallback.m_collisionObject->getUserPointer());
		if (mresult.hitModel)
		{
			mresult.hit = true;
			mresult.abs_hitPoint.Set(rayCallback.m_hitPointWorld.x(),rayCallback.m_hitPointWorld.y(),rayCallback.m_hitPointWorld.z());
			mresult.abs_hitNormal.Set(rayCallback.m_hitNormalWorld.x(),rayCallback.m_hitNormalWorld.y(),rayCallback.m_hitNormalWorld.z());
			mresult.abs_hitNormal.Normalize();
			mresult.hit = true;
			mresult.dist_factor = rayCallback.m_closestHitFraction;
			return true;
		}
	}
	mresult.hit = false;
	return false;
}

} // END_OF_NAMESPACE____
} // END_OF_NAMESPACE____

<|endoftext|>


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

#define VK_PROTOTYPES
#include "vkjson.h"

#include <utility>

namespace {
bool EnumerateExtensions(const char* layer_name,
                         std::vector<VkExtensionProperties>* extensions) {
  VkResult result;
  uint32_t count = 0;
  result = vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
  if (result != VK_SUCCESS)
    return false;
  extensions->resize(count);
  result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
                                                  extensions->data());
  if (result != VK_SUCCESS)
    return false;
  return true;
}

}  // anonymous namespace

VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) {
  VkJsonDevice device;
  vkGetPhysicalDeviceProperties(physical_device, &device.properties);
  vkGetPhysicalDeviceFeatures(physical_device, &device.features);
  vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory);

  uint32_t queue_family_count = 0;
  vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count,
                                           nullptr);
  if (queue_family_count > 0) {
    device.queues.resize(queue_family_count);
    vkGetPhysicalDeviceQueueFamilyProperties(
        physical_device, &queue_family_count, device.queues.data());
  }

  // Only device extensions.
  // TODO(piman): do we want to show layer extensions?
  uint32_t extension_count = 0;
  vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
                                       &extension_count, nullptr);
  if (extension_count > 0) {
    device.extensions.resize(extension_count);
    vkEnumerateDeviceExtensionProperties(
        physical_device, nullptr, &extension_count, device.extensions.data());
  }

  uint32_t layer_count = 0;
  vkEnumerateDeviceLayerProperties(physical_device, &layer_count, nullptr);
  if (layer_count > 0) {
    device.layers.resize(layer_count);
    vkEnumerateDeviceLayerProperties(physical_device, &layer_count,
                                     device.layers.data());
  }

  VkFormatProperties format_properties = {};
  for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8;
       format <= VK_FORMAT_END_RANGE;
       format = static_cast<VkFormat>(format + 1)) {
    vkGetPhysicalDeviceFormatProperties(physical_device, format,
                                        &format_properties);
    if (format_properties.linearTilingFeatures ||
        format_properties.optimalTilingFeatures ||
        format_properties.bufferFeatures) {
      device.formats.insert(std::make_pair(format, format_properties));
    }
  }
  return device;
}

VkJsonInstance VkJsonGetInstance() {
  VkJsonInstance instance;
  VkResult result;
  uint32_t count;

  count = 0;
  result = vkEnumerateInstanceLayerProperties(&count, nullptr);
  if (result != VK_SUCCESS)
    return VkJsonInstance();
  if (count > 0) {
    std::vector<VkLayerProperties> layers(count);
    result = vkEnumerateInstanceLayerProperties(&count, layers.data());
    if (result != VK_SUCCESS)
      return VkJsonInstance();
    instance.layers.reserve(count);
    for (auto& layer : layers) {
      instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()});
      if (!EnumerateExtensions(layer.layerName,
                               &instance.layers.back().extensions))
        return VkJsonInstance();
    }
  }

  if (!EnumerateExtensions(nullptr, &instance.extensions))
    return VkJsonInstance();

  std::vector<const char*> layer_names;
  layer_names.reserve(instance.layers.size());
  for (auto& layer : instance.layers)
    layer_names.push_back(layer.properties.layerName);

  const VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO,
                                      nullptr,
                                      "vkjson_info",
                                      1,
                                      "",
                                      0,
                                      VK_API_VERSION_1_0};
  VkInstanceCreateInfo instance_info = {
      VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
      nullptr,
      0,
      &app_info,
      static_cast<uint32_t>(layer_names.size()),
      layer_names.data(),
      0,
      nullptr};
  VkInstance vkinstance;
  result = vkCreateInstance(&instance_info, nullptr, &vkinstance);
  if (result != VK_SUCCESS)
    return VkJsonInstance();

  count = 0;
  result = vkEnumeratePhysicalDevices(vkinstance, &count, nullptr);
  if (result != VK_SUCCESS) {
    vkDestroyInstance(vkinstance, nullptr);
    return VkJsonInstance();
  }
  std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE);
  result = vkEnumeratePhysicalDevices(vkinstance, &count, devices.data());
  if (result != VK_SUCCESS) {
    vkDestroyInstance(vkinstance, nullptr);
    return VkJsonInstance();
  }

  instance.devices.reserve(devices.size());
  for (auto device : devices)
    instance.devices.emplace_back(VkJsonGetDevice(device));

  vkDestroyInstance(vkinstance, nullptr);
  return instance;
}
<commit_msg>vkjson: Don't enable any instance layers<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015-2016 The Khronos Group Inc.
// Copyright (c) 2015-2016 Valve Corporation
// Copyright (c) 2015-2016 LunarG, Inc.
// Copyright (c) 2015-2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////////

#define VK_PROTOTYPES
#include "vkjson.h"

#include <utility>

namespace {
bool EnumerateExtensions(const char* layer_name,
                         std::vector<VkExtensionProperties>* extensions) {
  VkResult result;
  uint32_t count = 0;
  result = vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
  if (result != VK_SUCCESS)
    return false;
  extensions->resize(count);
  result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
                                                  extensions->data());
  if (result != VK_SUCCESS)
    return false;
  return true;
}

}  // anonymous namespace

VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) {
  VkJsonDevice device;
  vkGetPhysicalDeviceProperties(physical_device, &device.properties);
  vkGetPhysicalDeviceFeatures(physical_device, &device.features);
  vkGetPhysicalDeviceMemoryProperties(physical_device, &device.memory);

  uint32_t queue_family_count = 0;
  vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count,
                                           nullptr);
  if (queue_family_count > 0) {
    device.queues.resize(queue_family_count);
    vkGetPhysicalDeviceQueueFamilyProperties(
        physical_device, &queue_family_count, device.queues.data());
  }

  // Only device extensions.
  // TODO(piman): do we want to show layer extensions?
  uint32_t extension_count = 0;
  vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
                                       &extension_count, nullptr);
  if (extension_count > 0) {
    device.extensions.resize(extension_count);
    vkEnumerateDeviceExtensionProperties(
        physical_device, nullptr, &extension_count, device.extensions.data());
  }

  uint32_t layer_count = 0;
  vkEnumerateDeviceLayerProperties(physical_device, &layer_count, nullptr);
  if (layer_count > 0) {
    device.layers.resize(layer_count);
    vkEnumerateDeviceLayerProperties(physical_device, &layer_count,
                                     device.layers.data());
  }

  VkFormatProperties format_properties = {};
  for (VkFormat format = VK_FORMAT_R4G4_UNORM_PACK8;
       format <= VK_FORMAT_END_RANGE;
       format = static_cast<VkFormat>(format + 1)) {
    vkGetPhysicalDeviceFormatProperties(physical_device, format,
                                        &format_properties);
    if (format_properties.linearTilingFeatures ||
        format_properties.optimalTilingFeatures ||
        format_properties.bufferFeatures) {
      device.formats.insert(std::make_pair(format, format_properties));
    }
  }
  return device;
}

VkJsonInstance VkJsonGetInstance() {
  VkJsonInstance instance;
  VkResult result;
  uint32_t count;

  count = 0;
  result = vkEnumerateInstanceLayerProperties(&count, nullptr);
  if (result != VK_SUCCESS)
    return VkJsonInstance();
  if (count > 0) {
    std::vector<VkLayerProperties> layers(count);
    result = vkEnumerateInstanceLayerProperties(&count, layers.data());
    if (result != VK_SUCCESS)
      return VkJsonInstance();
    instance.layers.reserve(count);
    for (auto& layer : layers) {
      instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()});
      if (!EnumerateExtensions(layer.layerName,
                               &instance.layers.back().extensions))
        return VkJsonInstance();
    }
  }

  if (!EnumerateExtensions(nullptr, &instance.extensions))
    return VkJsonInstance();

  const VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO,
                                      nullptr,
                                      "vkjson_info",
                                      1,
                                      "",
                                      0,
                                      VK_API_VERSION_1_0};
  VkInstanceCreateInfo instance_info = {
      VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
      nullptr,
      0,
      &app_info,
      0,
      nullptr,
      0,
      nullptr};
  VkInstance vkinstance;
  result = vkCreateInstance(&instance_info, nullptr, &vkinstance);
  if (result != VK_SUCCESS)
    return VkJsonInstance();

  count = 0;
  result = vkEnumeratePhysicalDevices(vkinstance, &count, nullptr);
  if (result != VK_SUCCESS) {
    vkDestroyInstance(vkinstance, nullptr);
    return VkJsonInstance();
  }
  std::vector<VkPhysicalDevice> devices(count, VK_NULL_HANDLE);
  result = vkEnumeratePhysicalDevices(vkinstance, &count, devices.data());
  if (result != VK_SUCCESS) {
    vkDestroyInstance(vkinstance, nullptr);
    return VkJsonInstance();
  }

  instance.devices.reserve(devices.size());
  for (auto device : devices)
    instance.devices.emplace_back(VkJsonGetDevice(device));

  vkDestroyInstance(vkinstance, nullptr);
  return instance;
}
<|endoftext|>


<commit_before>#include <stan/agrad/rev/functions/erfc.hpp>
#include <test/unit/agrad/util.hpp>
#include <gtest/gtest.h>

TEST(AgradRev,erfc) {
  AVAR a = 1.3;
  AVAR f = erfc(a);
  EXPECT_FLOAT_EQ(boost::math::erfc(1.3), f.val());

  AVEC x = createAVEC(a);
  VEC grad_f;
  f.grad(x,grad_f);
  EXPECT_FLOAT_EQ(-2.0 / std::sqrt(boost::math::constants::pi<double>()) * std::exp(- 1.3 * 1.3), grad_f[0]);
}
<commit_msg>added failing test<commit_after>#include <stan/agrad/rev/functions/erfc.hpp>
#include <test/unit/agrad/util.hpp>
#include <gtest/gtest.h>

TEST(AgradRev,erfc) {
  AVAR a = 1.3;
  AVAR f = erfc(a);
  EXPECT_FLOAT_EQ(boost::math::erfc(1.3), f.val());

  AVEC x = createAVEC(a);
  VEC grad_f;
  f.grad(x,grad_f);
  EXPECT_FLOAT_EQ(-2.0 / std::sqrt(boost::math::constants::pi<double>()) * std::exp(- 1.3 * 1.3), grad_f[0]);
}

TEST(AgradRev,erfc_nan) {
  AVAR a = std::numeric_limits<double>::quiet_NaN();
  AVAR f = stan::agrad::erfc(a);

  AVEC x = createAVEC(a);
  VEC g;
  f.grad(x,g);

  EXPECT_TRUE(boost::math::isnan(f.val()));
  ASSERT_EQ(1U,g.size());
  EXPECT_TRUE(boost::math::isnan(g[0]));
}
<|endoftext|>


<commit_before>#include <stan/math/matrix/value_of_rec.hpp>
#include <stan/agrad/rev/var.hpp>
#include <stan/agrad/fwd/fvar.hpp>
#include <test/unit/agrad/util.hpp>
#include <gtest/gtest.h>

TEST(MathMatrix,value_of_rec) {
  using stan::math::value_of_rec;
  using std::vector;

  vector<double> a_vals;

  for (size_t i = 0; i < 10; ++i)
    a_vals.push_back(i + 1);

  vector<double> b_vals;

  for (size_t i = 10; i < 15; ++i)
    b_vals.push_back(i + 1);

  Eigen::Matrix<double,2,5> a;
  fill(a_vals, a);
  Eigen::Matrix<double,5,1> b;
  fill(b_vals, b);

  Eigen::MatrixXd d_a = value_of_rec(a);
  Eigen::VectorXd d_b = value_of_rec(b);

  for (size_type i = 0; i < 5; ++i){
    EXPECT_FLOAT_EQ(b(i), d_b(i));
  }

  for (size_type i = 0; i < 2; ++i)
    for (size_type j = 0; j < 5; ++j){
      EXPECT_FLOAT_EQ(a(i,j), d_a(i,j));
    }
}
<commit_msg>math/matrix/value_of_test.cpp<commit_after>#include <stan/math/matrix/value_of.hpp>
#include <test/unit/agrad/util.hpp>
#include <gtest/gtest.h>

TEST(MathMatrix,value_of_rec) {
  using stan::math::value_of_rec;
  using std::vector;

  vector<double> a_vals;

  for (size_t i = 0; i < 10; ++i)
    a_vals.push_back(i + 1);

  vector<double> b_vals;

  for (size_t i = 10; i < 15; ++i)
    b_vals.push_back(i + 1);

  Eigen::Matrix<double,2,5> a;
  fill(a_vals, a);
  Eigen::Matrix<double,5,1> b;
  fill(b_vals, b);

  Eigen::MatrixXd d_a = value_of_rec(a);
  Eigen::VectorXd d_b = value_of_rec(b);

  for (size_type i = 0; i < 5; ++i){
    EXPECT_FLOAT_EQ(b(i), d_b(i));
  }

  for (size_type i = 0; i < 2; ++i)
    for (size_type j = 0; j < 5; ++j){
      EXPECT_FLOAT_EQ(a(i,j), d_a(i,j));
    }
}
<|endoftext|>


<commit_before>/*
 *   Copyright (c) 2006, Mathieu Champlon
 *   All rights reserved.
 *
 *   Redistribution  and use  in source  and binary  forms, with  or without
 *   modification, are permitted provided  that the following conditions are
 *   met :
 *
 *   . Redistributions  of  source  code  must  retain  the  above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   . Redistributions in  binary form  must reproduce  the above  copyright
 *     notice, this list of conditions  and the following disclaimer in  the
 *     documentation and/or other materials provided with the distribution.
 *
 *   . Neither  the name  of  the  copyright  holders  nor the names  of the
 *     contributors may be used to endorse  or promote products derived from
 *     this software without specific prior written permission.
 *
 *   THIS SOFTWARE  IS  PROVIDED  BY THE  COPYRIGHT HOLDERS  AND CONTRIBUTORS
 *   ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 *   LIMITED TO, THE IMPLIED  WARRANTIES  OF MERCHANTABILITY AND  FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE THE COPYRIGHT
 *   OWNERS OR CONTRIBUTORS  BE LIABLE FOR ANY  DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT
 *   LIMITED TO,  PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES;  LOSS OF USE,
 *   DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON  ANY
 *   THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,  STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY  WAY  OUT OF  THE USE
 *   OF THIS SOFTWARE, EVEN  IF  ADVISED OF  THE POSSIBILITY  OF SUCH DAMAGE.
 */

#include "xeumeuleu_test_pch.h"
#include <string>

namespace
{
    static std::string data_directory;

    void set_data_directory( int argc, char* argv[] )
    {
        while( argc-- )
        {
            const std::string argument( argv[argc] );
            const std::string::size_type n = argument.find( '=' );
            if( n != std::string::npos )
            {
                const std::string option = argument.substr( 0, n );
                if( option == "--data_directory" )
                    data_directory = argument.substr( n+1 );
            }
        }
    }
}

boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv [] )
{
    set_data_directory( argc, argv );
    return boost::unit_test::ut_detail::auto_unit_test_suite(); // $$$$ MAT 2006-04-20: remove ut_detail:: for boost 1_33
}

std::string BOOST_RESOLVE( const std::string& filename )
{
    if( data_directory.empty() )
        return filename;
    return data_directory + '/' + filename;
}
<commit_msg>Changing log format upon exception<commit_after>/*
 *   Copyright (c) 2006, Mathieu Champlon
 *   All rights reserved.
 *
 *   Redistribution  and use  in source  and binary  forms, with  or without
 *   modification, are permitted provided  that the following conditions are
 *   met :
 *
 *   . Redistributions  of  source  code  must  retain  the  above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   . Redistributions in  binary form  must reproduce  the above  copyright
 *     notice, this list of conditions  and the following disclaimer in  the
 *     documentation and/or other materials provided with the distribution.
 *
 *   . Neither  the name  of  the  copyright  holders  nor the names  of the
 *     contributors may be used to endorse  or promote products derived from
 *     this software without specific prior written permission.
 *
 *   THIS SOFTWARE  IS  PROVIDED  BY THE  COPYRIGHT HOLDERS  AND CONTRIBUTORS
 *   ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 *   LIMITED TO, THE IMPLIED  WARRANTIES  OF MERCHANTABILITY AND  FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE THE COPYRIGHT
 *   OWNERS OR CONTRIBUTORS  BE LIABLE FOR ANY  DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL   DAMAGES  (INCLUDING,  BUT  NOT
 *   LIMITED TO,  PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES;  LOSS OF USE,
 *   DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON  ANY
 *   THEORY  OF  LIABILITY,  WHETHER IN  CONTRACT,  STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY  WAY  OUT OF  THE USE
 *   OF THIS SOFTWARE, EVEN  IF  ADVISED OF  THE POSSIBILITY  OF SUCH DAMAGE.
 */

#include "xeumeuleu_test_pch.h"
#include <string>
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/detail/supplied_log_formatters.hpp>

using namespace boost::unit_test;
using namespace boost::unit_test::ut_detail;

namespace
{
    static std::string data_directory;

    void set_data_directory( int argc, char* argv[] )
    {
        while( argc-- )
        {
            const std::string argument( argv[argc] );
            const std::string::size_type n = argument.find( '=' );
            if( n != std::string::npos )
            {
                const std::string option = argument.substr( 0, n );
                if( option == "--data_directory" )
                    data_directory = argument.substr( n+1 );
            }
        }
    }

    class msvc_log_formatter : public msvc65_like_log_formatter
    {
    public:
        msvc_log_formatter()
            : msvc65_like_log_formatter( unit_test_log::instance() )
        {}

        virtual void log_exception( std::ostream& output, const_string test_case_name, const_string explanation )
        {
            output << "Exception in '" << test_case_name << "': error: " << explanation;
        }
    };

}

test_suite* init_unit_test_suite( int argc, char* argv [] )
{
    unit_test_log::instance().set_log_formatter( new msvc_log_formatter() );
    set_data_directory( argc, argv );
    return ut_detail::auto_unit_test_suite();
}

std::string BOOST_RESOLVE( const std::string& filename )
{
    if( data_directory.empty() )
        return filename;
    return data_directory + '/' + filename;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include "RenameClasses.h"

#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "Walkers.h"
#include "DexClass.h"
#include "DexInstruction.h"
#include "DexUtil.h"
#include "ReachableClasses.h"

#define MAX_DESCRIPTOR_LENGTH (1024)
#define MAX_IDENT_CHAR (52)
#define MAX_IDENT (MAX_IDENT_CHAR * MAX_IDENT_CHAR * MAX_IDENT_CHAR)

#define METRIC_CLASSES_IN_SCOPE "num_classes_in_scope"
#define METRIC_RENAMED_CLASSES "**num_renamed**"
#define METRIC_CANT_RENAME_ANNOTATION "num_cant_rename_annotations"
#define METRIC_CANT_RENAME_UNTOUCHABLE "num_cant_rename_untouchable"
#define METRIC_CANT_RENAME_AND_CANT_DELETE "num_cant_rename_and_cant_delete"
#define METRIC_NOT_WHITELISTED "num_not_whitelisted"

int match_short = 0;
int match_long = 0;
int match_inner = 0;

int base_strings_size = 0;
int ren_strings_size = 0;

static char getident(int num) {
  if (num < 26) {
    return 'a' + num;
  } else {
    return 'A' + num - 26;
  }
}

void get_next_ident(char *out, int &num) {
  // *sigh* re-write when not tired.
  int low = num;
  int mid = (num / 52);
  int top = (mid / 52);
  always_assert_log(num <= MAX_IDENT,
                    "Bailing, Ident %d, greater than maximum\n", num);
  if (top) {
    *out++ = getident(top - 1);
    low -= (top *52*52);
  }
  if (mid) {
    mid -= (top * 52);
    *out++ = getident(mid);
    low -= (mid * 52);
  }
  *out++ = getident(low);
  *out++ = '\0';
  num++;
}

void unpackage_private(Scope &scope) {
  walk_methods(scope,
      [&](DexMethod *method) {
        if (is_package_protected(method)) set_public(method);
      });
  walk_fields(scope,
      [&](DexField *field) {
        if (is_package_protected(field)) set_public(field);
      });
  for (auto clazz : scope) {
    if (is_package_protected(clazz)) set_public(clazz);
  }
}

bool should_rename(DexClass *clazz,
    std::vector<std::string>& pre_patterns,
    std::vector<std::string>& post_patterns,
    std::unordered_set<const DexType*>& untouchables,
    bool rename_annotations,
    PassManager& mgr) {
  if (!rename_annotations && is_annotation(clazz)) {
    mgr.incr_metric(METRIC_CANT_RENAME_ANNOTATION, 1);
    return false;
  }
  if (untouchables.count(clazz->get_type())) {
    mgr.incr_metric(METRIC_CANT_RENAME_UNTOUCHABLE, 1);
    return false;
  }
  auto chstring = clazz->get_type()->get_name()->c_str();
  /* We're assuming anonymous classes are safe always safe to rename. */
  auto substr = strrchr(chstring, '$');
  if (substr != nullptr) {
    auto val = *++substr;
    if (val >= '0' && val <= '9') {
      match_inner++;
      return true;
    }
  }
  /* Check for more aggressive, but finer grained filters first */
  for (auto p : pre_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  if (!can_rename(clazz) && !can_delete(clazz)) {
    mgr.incr_metric(METRIC_CANT_RENAME_AND_CANT_DELETE, 1);
    return false;
  }
  /* Check for wider, less precise filters */
  for (auto p : post_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  mgr.incr_metric(METRIC_NOT_WHITELISTED, 1);
  return false;
}

void rename_classes(
    Scope& scope,
    std::vector<std::string>& pre_whitelist_patterns,
    std::vector<std::string>& post_whitelist_patterns,
    const std::string& path,
    std::unordered_set<const DexType*>& untouchables,
    ProguardMap& proguard_map,
    bool rename_annotations,
    PassManager& mgr) {
  unpackage_private(scope);
  int clazz_ident = 0;
  std::map<DexString*, DexString*> aliases;
  for(auto clazz: scope) {
    if (!should_rename(
        clazz, pre_whitelist_patterns, post_whitelist_patterns,
        untouchables, rename_annotations, mgr)) {
      continue;
    }
    char clzname[4];
    get_next_ident(clzname, clazz_ident);

    auto dtype = clazz->get_type();
    auto oldname = dtype->get_name();

    // The X helps our hacked Dalvik classloader recognize that a
    // class name is the output of the redex renamer and thus will
    // never be found in the Android platform.
    // The $ indicates that the class was originally an inner class.
    // Some code, most notably android instrumentation runner, uses
    // this information to decide whether or not to classload the class.
    bool inner = strrchr(oldname->c_str(), '$');
    char descriptor[10];
    sprintf(descriptor, "LX%s%s;", inner ? "$" : "", clzname);
    auto dstring = DexString::make_string(descriptor);
    aliases[oldname] = dstring;
    dtype->assign_name_alias(dstring);
    std::string old_str(oldname->c_str());
    std::string new_str(descriptor);
    base_strings_size += strlen(oldname->c_str());
    base_strings_size += strlen(dstring->c_str());
    TRACE(RENAME, 4, "'%s'->'%s'\n", oldname->c_str(), descriptor);
    while (1) {
     std::string arrayop("[");
      arrayop += oldname->c_str();
      oldname = DexString::get_string(arrayop.c_str());
      if (oldname == nullptr) {
        break;
      }
      auto arraytype = DexType::get_type(oldname);
      if (arraytype == nullptr) {
        break;
      }
      std::string newarraytype("[");
      newarraytype += dstring->c_str();
      dstring = DexString::make_string(newarraytype.c_str());
      aliases[oldname] = dstring;
      arraytype->assign_name_alias(dstring);
    }
  }
  mgr.incr_metric(METRIC_RENAMED_CLASSES, match_short + match_long + match_inner);
  /* Now we need to re-write the Signature annotations.  They use
   * Strings rather than Type's, so they have to be explicitly
   * handled.
   */

  /* Generics of the form Type<> turn into the Type string
   * sans the ';'.  So, we have to alias those if they
   * exist.  Signature annotations suck.
   */
  for (auto apair : aliases) {
    char buf[MAX_DESCRIPTOR_LENGTH];
    const char *sourcestr = apair.first->c_str();
    size_t sourcelen = strlen(sourcestr);
    if (sourcestr[sourcelen - 1] != ';') continue;
    strcpy(buf, sourcestr);
    buf[sourcelen - 1] = '\0';
    auto dstring = DexString::get_string(buf);
    if (dstring == nullptr) continue;
    strcpy(buf, apair.second->c_str());
    buf[strlen(apair.second->c_str()) - 1] = '\0';
    auto target = DexString::make_string(buf);
    aliases[dstring] = target;
  }
  walk_annotations(scope, [&](DexAnnotation* anno) {
    static DexType *dalviksig =
      DexType::get_type("Ldalvik/annotation/Signature;");
    if (anno->type() != dalviksig) return;
    auto elems = anno->anno_elems();
    for (auto elem : elems) {
      auto ev = elem.encoded_value;
      if (ev->evtype() != DEVT_ARRAY) continue;
      auto arrayev = static_cast<DexEncodedValueArray*>(ev);
      auto const& evs = arrayev->evalues();
      for (auto strev : *evs) {
        if (strev->evtype() != DEVT_STRING) continue;
        auto stringev = static_cast<DexEncodedValueString*>(strev);
        if (aliases.count(stringev->string())) {
          TRACE(RENAME, 5, "Rewriting Signature from '%s' to '%s'\n",
              stringev->string()->c_str(),
              aliases[stringev->string()]->c_str());
          stringev->string(aliases[stringev->string()]);
        }
      }
    }
  });

  if (!path.empty()) {
    FILE* fd = fopen(path.c_str(), "w");
    if (fd == nullptr) {
      perror("Error writing rename file");
      return;
    }
    for (const auto &it : aliases) {
      // record for later processing and back map generation
      fprintf(fd, "%s -> %s\n",it.first->c_str(),
      it.second->c_str());
    }
    fclose(fd);
  }

  for (auto clazz : scope) {
    clazz->get_vmethods().sort(compare_dexmethods);
    clazz->get_dmethods().sort(compare_dexmethods);
    clazz->get_sfields().sort(compare_dexfields);
    clazz->get_ifields().sort(compare_dexfields);
  }
}

void RenameClassesPass::run_pass(DexStoresVector& stores, ConfigFiles& cfg, PassManager& mgr) {
  auto scope = build_class_scope(stores);
  std::unordered_set<const DexType*> untouchables;
  for (const auto& base : m_untouchable_hierarchies) {
    auto base_type = DexType::get_type(base.c_str());
    if (base_type != nullptr) {
      untouchables.insert(base_type);
      TypeVector children;
      get_all_children(base_type, children);
      untouchables.insert(children.begin(), children.end());
    }
  }
  mgr.incr_metric(METRIC_CLASSES_IN_SCOPE, scope.size());
  rename_classes(
      scope, m_pre_filter_whitelist, m_post_filter_whitelist, m_path,
      untouchables, cfg.get_proguard_map(), m_rename_annotations, mgr);
  TRACE(RENAME, 1,
      "renamed classes: %d anon classes, %d from single char patterns, "
      "%d from multi char patterns\n",
      match_inner,
      match_short,
      match_long);
  TRACE(RENAME, 1, "String savings, at least %d bytes \n",
      base_strings_size - ren_strings_size);
}

static RenameClassesPass s_pass;
<commit_msg>fix class name encoding not matching with ascii encoding ordering<commit_after>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#include "RenameClasses.h"

#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include "Walkers.h"
#include "DexClass.h"
#include "DexInstruction.h"
#include "DexUtil.h"
#include "ReachableClasses.h"

#define MAX_DESCRIPTOR_LENGTH (1024)
#define MAX_IDENT_CHAR (52)
#define MAX_IDENT (MAX_IDENT_CHAR * MAX_IDENT_CHAR * MAX_IDENT_CHAR)

#define METRIC_CLASSES_IN_SCOPE "num_classes_in_scope"
#define METRIC_RENAMED_CLASSES "**num_renamed**"
#define METRIC_CANT_RENAME_ANNOTATION "num_cant_rename_annotations"
#define METRIC_CANT_RENAME_UNTOUCHABLE "num_cant_rename_untouchable"
#define METRIC_CANT_RENAME_AND_CANT_DELETE "num_cant_rename_and_cant_delete"
#define METRIC_NOT_WHITELISTED "num_not_whitelisted"

int match_short = 0;
int match_long = 0;
int match_inner = 0;

int base_strings_size = 0;
int ren_strings_size = 0;

static char getident(int num) {
  if (num < 26) {
    return 'A' + num;
  } else {
    return 'a' + num - 26;
  }
}

void get_next_ident(char *out, int &num) {
  // *sigh* re-write when not tired.
  int low = num;
  int mid = (num / 52);
  int top = (mid / 52);
  always_assert_log(num <= MAX_IDENT,
                    "Bailing, Ident %d, greater than maximum\n", num);
  if (top) {
    *out++ = getident(top - 1);
    low -= (top *52*52);
  }
  if (mid) {
    mid -= (top * 52);
    *out++ = getident(mid);
    low -= (mid * 52);
  }
  *out++ = getident(low);
  *out++ = '\0';
  num++;
}

void unpackage_private(Scope &scope) {
  walk_methods(scope,
      [&](DexMethod *method) {
        if (is_package_protected(method)) set_public(method);
      });
  walk_fields(scope,
      [&](DexField *field) {
        if (is_package_protected(field)) set_public(field);
      });
  for (auto clazz : scope) {
    if (is_package_protected(clazz)) set_public(clazz);
  }
}

bool should_rename(DexClass *clazz,
    std::vector<std::string>& pre_patterns,
    std::vector<std::string>& post_patterns,
    std::unordered_set<const DexType*>& untouchables,
    bool rename_annotations,
    PassManager& mgr) {
  if (!rename_annotations && is_annotation(clazz)) {
    mgr.incr_metric(METRIC_CANT_RENAME_ANNOTATION, 1);
    return false;
  }
  if (untouchables.count(clazz->get_type())) {
    mgr.incr_metric(METRIC_CANT_RENAME_UNTOUCHABLE, 1);
    return false;
  }
  auto chstring = clazz->get_type()->get_name()->c_str();
  /* We're assuming anonymous classes are safe always safe to rename. */
  auto substr = strrchr(chstring, '$');
  if (substr != nullptr) {
    auto val = *++substr;
    if (val >= '0' && val <= '9') {
      match_inner++;
      return true;
    }
  }
  /* Check for more aggressive, but finer grained filters first */
  for (auto p : pre_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  if (!can_rename(clazz) && !can_delete(clazz)) {
    mgr.incr_metric(METRIC_CANT_RENAME_AND_CANT_DELETE, 1);
    return false;
  }
  /* Check for wider, less precise filters */
  for (auto p : post_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  mgr.incr_metric(METRIC_NOT_WHITELISTED, 1);
  return false;
}

void rename_classes(
    Scope& scope,
    std::vector<std::string>& pre_whitelist_patterns,
    std::vector<std::string>& post_whitelist_patterns,
    const std::string& path,
    std::unordered_set<const DexType*>& untouchables,
    ProguardMap& proguard_map,
    bool rename_annotations,
    PassManager& mgr) {
  unpackage_private(scope);
  int clazz_ident = 0;
  std::map<DexString*, DexString*> aliases;
  for(auto clazz: scope) {
    if (!should_rename(
        clazz, pre_whitelist_patterns, post_whitelist_patterns,
        untouchables, rename_annotations, mgr)) {
      continue;
    }
    char clzname[4];
    get_next_ident(clzname, clazz_ident);

    auto dtype = clazz->get_type();
    auto oldname = dtype->get_name();

    // The X helps our hacked Dalvik classloader recognize that a
    // class name is the output of the redex renamer and thus will
    // never be found in the Android platform.
    // The $ indicates that the class was originally an inner class.
    // Some code, most notably android instrumentation runner, uses
    // this information to decide whether or not to classload the class.
    bool inner = strrchr(oldname->c_str(), '$');
    char descriptor[10];
    sprintf(descriptor, "LX%s%s;", inner ? "$" : "", clzname);
    auto dstring = DexString::make_string(descriptor);
    aliases[oldname] = dstring;
    dtype->assign_name_alias(dstring);
    std::string old_str(oldname->c_str());
    std::string new_str(descriptor);
    base_strings_size += strlen(oldname->c_str());
    base_strings_size += strlen(dstring->c_str());
    TRACE(RENAME, 4, "'%s'->'%s'\n", oldname->c_str(), descriptor);
    while (1) {
     std::string arrayop("[");
      arrayop += oldname->c_str();
      oldname = DexString::get_string(arrayop.c_str());
      if (oldname == nullptr) {
        break;
      }
      auto arraytype = DexType::get_type(oldname);
      if (arraytype == nullptr) {
        break;
      }
      std::string newarraytype("[");
      newarraytype += dstring->c_str();
      dstring = DexString::make_string(newarraytype.c_str());
      aliases[oldname] = dstring;
      arraytype->assign_name_alias(dstring);
    }
  }
  mgr.incr_metric(METRIC_RENAMED_CLASSES, match_short + match_long + match_inner);
  /* Now we need to re-write the Signature annotations.  They use
   * Strings rather than Type's, so they have to be explicitly
   * handled.
   */

  /* Generics of the form Type<> turn into the Type string
   * sans the ';'.  So, we have to alias those if they
   * exist.  Signature annotations suck.
   */
  for (auto apair : aliases) {
    char buf[MAX_DESCRIPTOR_LENGTH];
    const char *sourcestr = apair.first->c_str();
    size_t sourcelen = strlen(sourcestr);
    if (sourcestr[sourcelen - 1] != ';') continue;
    strcpy(buf, sourcestr);
    buf[sourcelen - 1] = '\0';
    auto dstring = DexString::get_string(buf);
    if (dstring == nullptr) continue;
    strcpy(buf, apair.second->c_str());
    buf[strlen(apair.second->c_str()) - 1] = '\0';
    auto target = DexString::make_string(buf);
    aliases[dstring] = target;
  }
  walk_annotations(scope, [&](DexAnnotation* anno) {
    static DexType *dalviksig =
      DexType::get_type("Ldalvik/annotation/Signature;");
    if (anno->type() != dalviksig) return;
    auto elems = anno->anno_elems();
    for (auto elem : elems) {
      auto ev = elem.encoded_value;
      if (ev->evtype() != DEVT_ARRAY) continue;
      auto arrayev = static_cast<DexEncodedValueArray*>(ev);
      auto const& evs = arrayev->evalues();
      for (auto strev : *evs) {
        if (strev->evtype() != DEVT_STRING) continue;
        auto stringev = static_cast<DexEncodedValueString*>(strev);
        if (aliases.count(stringev->string())) {
          TRACE(RENAME, 5, "Rewriting Signature from '%s' to '%s'\n",
              stringev->string()->c_str(),
              aliases[stringev->string()]->c_str());
          stringev->string(aliases[stringev->string()]);
        }
      }
    }
  });

  if (!path.empty()) {
    FILE* fd = fopen(path.c_str(), "w");
    if (fd == nullptr) {
      perror("Error writing rename file");
      return;
    }
    for (const auto &it : aliases) {
      // record for later processing and back map generation
      fprintf(fd, "%s -> %s\n",it.first->c_str(),
      it.second->c_str());
    }
    fclose(fd);
  }

  for (auto clazz : scope) {
    clazz->get_vmethods().sort(compare_dexmethods);
    clazz->get_dmethods().sort(compare_dexmethods);
    clazz->get_sfields().sort(compare_dexfields);
    clazz->get_ifields().sort(compare_dexfields);
  }
}

void RenameClassesPass::run_pass(DexStoresVector& stores, ConfigFiles& cfg, PassManager& mgr) {
  auto scope = build_class_scope(stores);
  std::unordered_set<const DexType*> untouchables;
  for (const auto& base : m_untouchable_hierarchies) {
    auto base_type = DexType::get_type(base.c_str());
    if (base_type != nullptr) {
      untouchables.insert(base_type);
      TypeVector children;
      get_all_children(base_type, children);
      untouchables.insert(children.begin(), children.end());
    }
  }
  mgr.incr_metric(METRIC_CLASSES_IN_SCOPE, scope.size());
  rename_classes(
      scope, m_pre_filter_whitelist, m_post_filter_whitelist, m_path,
      untouchables, cfg.get_proguard_map(), m_rename_annotations, mgr);
  TRACE(RENAME, 1,
      "renamed classes: %d anon classes, %d from single char patterns, "
      "%d from multi char patterns\n",
      match_inner,
      match_short,
      match_long);
  TRACE(RENAME, 1, "String savings, at least %d bytes \n",
      base_strings_size - ren_strings_size);
}

static RenameClassesPass s_pass;
<|endoftext|>


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

#include "src/traced/probes/ftrace/ftrace_config_utils.h"

#include "perfetto/base/logging.h"

namespace perfetto {
namespace {

bool IsGoodFtracePunctuation(char c) {
  return c == '_' || c == '/' || c == '*';
}

bool IsGoodAtracePunctuation(char c) {
  return c == '_' || c == '.' || c == '*';
}

bool IsValidAtraceEventName(const std::string& str) {
  for (size_t i = 0; i < str.size(); i++) {
    if (!isalnum(str[i]) && !IsGoodAtracePunctuation(str[i]))
      return false;
  }
  return true;
}

bool IsValidFtraceEventName(const std::string& str) {
  int slash_count = 0;
  for (size_t i = 0; i < str.size(); i++) {
    if (!isalnum(str[i]) && !IsGoodFtracePunctuation(str[i]))
      return false;
    if (str[i] == '/') {
      slash_count++;
      // At most one '/' allowed and not at the beginning or end.
      if (slash_count > 1 || i == 0 || i == str.size() - 1)
        return false;
    }
    if (str[i] == '*' && i != str.size() - 1)
      return false;
  }
  return true;
}

}  // namespace

FtraceConfig CreateFtraceConfig(std::set<std::string> names) {
  FtraceConfig config;
  for (const std::string& name : names)
    *config.add_ftrace_events() = name;
  return config;
}

bool RequiresAtrace(const FtraceConfig& config) {
  return !config.atrace_categories().empty() || !config.atrace_apps().empty();
}

bool ValidConfig(const FtraceConfig& config) {
  for (const std::string& event_name : config.ftrace_events()) {
    if (!IsValidFtraceEventName(event_name)) {
      PERFETTO_ELOG("Bad event name '%s'", event_name.c_str());
      return false;
    }
  }
  for (const std::string& category : config.atrace_categories()) {
    if (!IsValidAtraceEventName(category)) {
      PERFETTO_ELOG("Bad category name '%s'", category.c_str());
      return false;
    }
  }
  for (const std::string& app : config.atrace_apps()) {
    if (!IsValidAtraceEventName(app)) {
      PERFETTO_ELOG("Bad app '%s'", app.c_str());
      return false;
    }
  }
  return true;
}

}  // namespace perfetto
<commit_msg>traced_probes: relax string filtering for atrace events<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/traced/probes/ftrace/ftrace_config_utils.h"

#include "perfetto/base/logging.h"

namespace perfetto {
namespace {

// Excludes \r, \n, escape sequences and control chars.
bool IsPrintableASCIIOrSpace(char c) {
  return c >= 32 && c < 127;
}

bool IsValidAtraceEventName(const std::string& str) {
  for (size_t i = 0; i < str.size(); i++) {
    if (!IsPrintableASCIIOrSpace(str[i]))
      return false;
  }
  return true;
}

bool IsValidFtraceEventName(const std::string& str) {
  int slash_count = 0;
  for (size_t i = 0; i < str.size(); i++) {
    if (!IsPrintableASCIIOrSpace(str[i]))
      return false;
    if (str[i] == '/') {
      slash_count++;
      // At most one '/' allowed and not at the beginning or end.
      if (slash_count > 1 || i == 0 || i == str.size() - 1)
        return false;
    }
    if (str[i] == '*' && i != str.size() - 1)
      return false;
  }
  return true;
}

}  // namespace

FtraceConfig CreateFtraceConfig(std::set<std::string> names) {
  FtraceConfig config;
  for (const std::string& name : names)
    *config.add_ftrace_events() = name;
  return config;
}

bool RequiresAtrace(const FtraceConfig& config) {
  return !config.atrace_categories().empty() || !config.atrace_apps().empty();
}

bool ValidConfig(const FtraceConfig& config) {
  for (const std::string& event_name : config.ftrace_events()) {
    if (!IsValidFtraceEventName(event_name)) {
      PERFETTO_ELOG("Bad event name '%s'", event_name.c_str());
      return false;
    }
  }
  for (const std::string& category : config.atrace_categories()) {
    if (!IsValidAtraceEventName(category)) {
      PERFETTO_ELOG("Bad category name '%s'", category.c_str());
      return false;
    }
  }
  for (const std::string& app : config.atrace_apps()) {
    if (!IsValidAtraceEventName(app)) {
      PERFETTO_ELOG("Bad app '%s'", app.c_str());
      return false;
    }
  }
  return true;
}

}  // namespace perfetto
<|endoftext|>