<commit_before>// coding: utf-8
// ----------------------------------------------------------------------------
/* Copyright (c) 2009, Roboterclub Aachen e.V.
 * 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 Roboterclub Aachen e.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY ROBOTERCLUB AACHEN E.V. ''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 ROBOTERCLUB AACHEN E.V. 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.
 */
// ----------------------------------------------------------------------------

#ifdef __DOXYGEN__

/**
 * \brief	Compiler description
 * \ingroup	platform
 */
#define	XPCC__COMPILER_STRING

/**
 * \brief	Possible compilers
 * \ingroup	platform
 */
//@{
#define	XPCC__COMPILER_GCC
#define	XPCC__COMPILER_MSVC
//@}

/**
 * \brief	Operating system description
 * \ingroup	platform
 */
#define	XPCC__OS_STRING

/**
 * \brief	Possible operating systems
 * \ingroup	platform
 */
//@{
#define	XPCC__OS_UNIX
#define	XPCC__OS_LINUX
#define	XPCC__OS_OSX
#define	XPCC__OS_WIN32
#define	XPCC__OS_WIN64
//@}

/**
 * \brief	CPU description
 * \ingroup	platform
 */
#define	XPCC__CPU_STRING

//@{
/**
 * \brief	Possible CPU definitions
 * \ingroup	platform
 */
#define	XPCC__CPU_AVR
#define	XPCC__CPU_ATXMEGA
#define	XPCC__CPU_ATMEGA
#define	XPCC__CPU_ATTINY

#define	XPCC__CPU_ARM
#define	XPCC__CPU_ARM7TDMI
#define	XPCC__CPU_CORTEX_M0
#define	XPCC__CPU_CORTEX_M4
#define	XPCC__CPU_CORTEX_M4

#define	XPCC__CPU_HOSTED
#define	XPCC__CPU_HOSTED_64

//@{
/**
 * \brief	Memory descriptions
 * \ingroup	platform
 */
#define XPCC__ALIGNMENT

#define XPCC__ORDER_BIG_ENDIAN
#define XPCC__ORDER_LITTLE_ENDIAN
#define XPCC__ORDER_PDP_ENDIAN

#define XPCC__BYTE_ORDER

#define XPCC__IS_BIG_ENDIAN
#define XPCC__IS_LITTLE_ENDIAN

#define	XPCC__SIZEOF_POINTER
//@}

#else //!__DOXYGEN__

// ----------------------------------------------------------------------------
// Determine compilation environment

/**
 * This relies on the predefined defines of the compiler.
 * To display the defines run:
 * $your-gcc-compiler -dM -E - < /dev/null | sort | less
 *
 * e.g.
 * $arm-none-eabi-g++ -dM -E - < /dev/null | sort | less
 *
 * Be aware that the defines change when you set options
 * for a specific compiler at compile time:
 *
 * $arm-none-eabi-g++ -dM -E -mcpu=cortex-m0 -mthumb -D__ARM_LPC1114_301__ -D__ARM_LPC11XX__ - < /dev/null
 */

#if defined __clang__
#	define XPCC__COMPILER_STRING	"Clang"
#	define XPCC__COMPILER_CLANG 1
#elif defined __GNUC__
#	define XPCC__COMPILER_STRING	"Gnu GCC"
#	define XPCC__COMPILER_GCC 1
#endif

#if defined _MSC_VER
#	define XPCC__COMPILER_STRING 	"Microsoft Visual C++"
#	define XPCC__COMPILER_MSVC 1
#endif

#if !defined XPCC__COMPILER_STRING
#	define XPCC__COMPILER_STRING 	"Unknown compiler"
#	warning	"Couldn't determine the used compiler! Please add it to <xpcc/architecture/detect.hpp>"
#endif

// ----------------------------------------------------------------------------
// Determine target operating system

#if defined linux || defined __linux__
#	define XPCC__OS_LINUX 1
#	define XPCC__OS_STRING 			"Linux"
#endif

#if (defined __MWERKS__ && defined __powerc && !defined macintosh) || defined __APPLE_CC__ || defined macosx
#	define XPCC__OS_OSX 1
#	define XPCC__OS_STRING			"MacOS X"
#endif

#if defined __unix__
#	define XPCC__OS_UNIX 1
#	if !defined XPCC__OS_STRING
#		define XPCC__OS_STRING 		"Unix-like(generic)"
#	endif
#endif

#if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__
#	define XPCC__OS_WIN32 1
#	if defined _WIN64
#		define XPCC__OS_WIN64 1
#		define XPCC__OS_STRING		"Win64"
#	else
#		if !defined XPCC__OS_STRING
#			define XPCC__OS_STRING	"Win32"
#		endif
#	endif
#endif

#define XPCC__ORDER_BIG_ENDIAN 4321
#define XPCC__ORDER_LITTLE_ENDIAN 1234
#define XPCC__ORDER_PDP_ENDIAN 3412

// ----------------------------------------------------------------------------
// Determine CPU type

#if defined __AVR__
#	define	XPCC__CPU_AVR	1
#	define XPCC__ALIGNMENT	1
#	if defined __AVR_XMEGA__
#		define XPCC__CPU_ATXMEGA	1
#		define XPCC__CPU_STRING		"Atmel XMEGA"
#	else
		// see http://www.nongnu.org/avr-libc/user-manual/using_tools.html
#		if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25 || __AVR_ARCH__ == 1
#			define XPCC__CPU_ATTINY	1
#			define XPCC__CPU_STRING	"Atmel tinyAVR"
#		else
#			define XPCC__CPU_ATMEGA	1
#			define XPCC__CPU_STRING	"Atmel megaAVR"
#		endif
#	endif
#endif

#if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64
#	define XPCC__CPU_HOSTED 1
#	if defined __x86_64__ || defined _M_X64
#		define XPCC__CPU_HOSTED_64	1
#		define XPCC__CPU_STRING		"AMD x86-64"
#		define XPCC__ALIGNMENT	8
#	else
#		define XPCC__CPU_STRING		"Intel 386+"
#		define XPCC__ALIGNMENT	4
#	endif
#endif

#if defined __arm__ || defined __ARM_EABI__
#	define XPCC__CPU_ARM	1
#	define XPCC__ALIGNMENT	4
#	if defined __ARM_ARCH_4T__
#		define XPCC__CPU_ARM7TDMI	1
#		define XPCC__CPU_STRING		"ARM7TDMI"
#	elif defined __ARM_ARCH_6SM__ || defined __ARM_ARCH_6M__
#		define XPCC__CPU_CORTEX_M0	1
#		define XPCC__CPU_STRING		"Cortex-M0"
#	elif defined __ARM_ARCH_7M__
#		define XPCC__CPU_CORTEX_M3	1
#		define XPCC__CPU_STRING		"Cortex-M3"
#	elif defined __ARM_ARCH_7EM__
#		define XPCC__CPU_CORTEX_M4	1
#		define XPCC__CPU_STRING		"Cortex-M4"
#	endif
#endif

#if !defined XPCC__CPU_STRING
#	error "Couldn't determine target CPU!"
#	define XPCC__CPU_STRING 		"Unknown"
#endif

// ----------------------------------------------------------------------------
// Provide some additional information

#if defined __SIZEOF_POINTER__
#	define XPCC__SIZEOF_POINTER			__SIZEOF_POINTER__
#else
#	if defined(XPCC__CPU_HOSTED_64)
#		define XPCC__SIZEOF_POINTER		8
#	elif defined(XPCC__CPU_HOSTED_32)
#		define XPCC__SIZEOF_POINTER		4
#	endif
#endif

#if !defined XPCC__SIZEOF_POINTER
#	error "XPCC__SIZEOF_POINTER not defined! Please provide a suitable definition."
#endif

#if defined __BYTE_ORDER__
#	define XPCC__BYTE_ORDER		__BYTE_ORDER__
#endif

#if !defined XPCC__BYTE_ORDER
#	error "XPCC__BYTE_ORDER not defined! Please provide a suitable definition."
#endif

#define XPCC__IS_BIG_ENDIAN		(XPCC__BYTE_ORDER == XPCC__ORDER_BIG_ENDIAN)
#define XPCC__IS_LITTLE_ENDIAN	(XPCC__BYTE_ORDER == XPCC__ORDER_LITTLE_ENDIAN)

// ----------------------------------------------------------------------------
// Windows lacks support for some C99 macros and functions we need to
// provide here
#if defined XPCC__OS_WIN32
#	include "platform/hosted/windows.hpp"
#endif

#endif	// !__DOXYGEN__
<commit_msg>XPCC__CPU_HOSTED is not a CPU but an OS. Add Cortex-A7<commit_after>// coding: utf-8
// ----------------------------------------------------------------------------
/* Copyright (c) 2009, Roboterclub Aachen e.V.
 * 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 Roboterclub Aachen e.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY ROBOTERCLUB AACHEN E.V. ''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 ROBOTERCLUB AACHEN E.V. 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.
 */
// ----------------------------------------------------------------------------

#ifdef __DOXYGEN__

/**
 * \brief	Compiler description
 * \ingroup	platform
 */
#define	XPCC__COMPILER_STRING

/**
 * \brief	Possible compilers
 * \ingroup	platform
 */
//@{
#define	XPCC__COMPILER_GCC
#define	XPCC__COMPILER_MSVC
//@}

/**
 * \brief	Operating system description
 * \ingroup	platform
 */
#define	XPCC__OS_STRING

/**
 * \brief	Possible operating systems
 * \ingroup	platform
 */
//@{
#define	XPCC__OS_UNIX
#define	XPCC__OS_LINUX
#define	XPCC__OS_OSX
#define	XPCC__OS_WIN32
#define	XPCC__OS_WIN64
//@}

/**
 * \brief	CPU description
 * \ingroup	platform
 */
#define	XPCC__CPU_STRING

//@{
/**
 * \brief	Possible CPU definitions
 * \ingroup	platform
 */
#define	XPCC__CPU_AVR
#define	XPCC__CPU_ATXMEGA
#define	XPCC__CPU_ATMEGA
#define	XPCC__CPU_ATTINY

#define	XPCC__CPU_ARM
#define	XPCC__CPU_ARM7TDMI
#define	XPCC__CPU_CORTEX_M0
#define	XPCC__CPU_CORTEX_M4
#define	XPCC__CPU_CORTEX_M4

#define	XPCC__CPU_HOSTED
#define	XPCC__CPU_HOSTED_64

//@{
/**
 * \brief	Memory descriptions
 * \ingroup	platform
 */
#define XPCC__ALIGNMENT

#define XPCC__ORDER_BIG_ENDIAN
#define XPCC__ORDER_LITTLE_ENDIAN
#define XPCC__ORDER_PDP_ENDIAN

#define XPCC__BYTE_ORDER

#define XPCC__IS_BIG_ENDIAN
#define XPCC__IS_LITTLE_ENDIAN

#define	XPCC__SIZEOF_POINTER
//@}

#else //!__DOXYGEN__

// ----------------------------------------------------------------------------
// Determine compilation environment

/**
 * This relies on the predefined defines of the compiler.
 * To display the defines run:
 * $your-gcc-compiler -dM -E - < /dev/null | sort | less
 *
 * e.g.
 * $arm-none-eabi-g++ -dM -E - < /dev/null | sort | less
 *
 * Be aware that the defines change when you set options
 * for a specific compiler at compile time:
 *
 * $arm-none-eabi-g++ -dM -E -mcpu=cortex-m0 -mthumb -D__ARM_LPC1114_301__ -D__ARM_LPC11XX__ - < /dev/null
 */

#if defined __clang__
#	define XPCC__COMPILER_STRING	"Clang"
#	define XPCC__COMPILER_CLANG 1
#elif defined __GNUC__
#	define XPCC__COMPILER_STRING	"Gnu GCC"
#	define XPCC__COMPILER_GCC 1
#endif

#if defined _MSC_VER
#	define XPCC__COMPILER_STRING 	"Microsoft Visual C++"
#	define XPCC__COMPILER_MSVC 1
#endif

#if !defined XPCC__COMPILER_STRING
#	define XPCC__COMPILER_STRING 	"Unknown compiler"
#	warning	"Couldn't determine the used compiler! Please add it to <xpcc/architecture/detect.hpp>"
#endif

// ----------------------------------------------------------------------------
// Determine target operating system

#if defined linux || defined __linux__
#	define XPCC__OS_HOSTED 1
#	define XPCC__OS_LINUX 1
#	define XPCC__OS_STRING 			"Linux"
#endif

#if (defined __MWERKS__ && defined __powerc && !defined macintosh) || defined __APPLE_CC__ || defined macosx
#	define XPCC__OS_HOSTED 1
#	define XPCC__OS_OSX 1
#	define XPCC__OS_STRING			"MacOS X"
#endif

#if defined __unix__
#	define XPCC__OS_HOSTED 1
#	define XPCC__OS_UNIX 1
#	if !defined XPCC__OS_STRING
#		define XPCC__OS_STRING 		"Unix-like(generic)"
#	endif
#endif

#if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__
#	define XPCC__OS_HOSTED 1
#	define XPCC__OS_WIN32 1
#	if defined _WIN64
#		define XPCC__OS_WIN64 1
#		define XPCC__OS_STRING		"Win64"
#	else
#		if !defined XPCC__OS_STRING
#			define XPCC__OS_STRING	"Win32"
#		endif
#	endif
#endif

#define XPCC__ORDER_BIG_ENDIAN 4321
#define XPCC__ORDER_LITTLE_ENDIAN 1234
#define XPCC__ORDER_PDP_ENDIAN 3412

// If we did not detect any of Linux, OS X or Windows
#if !defined(XPCC__OS_HOSTED)
#	define XPCC__OS_NONE	1
#endif

// ----------------------------------------------------------------------------
// Determine CPU type

#if defined __AVR__
#	define XPCC__CPU_AVR	1
#	define XPCC__ALIGNMENT	1
#	if defined __AVR_XMEGA__
#		define XPCC__CPU_ATXMEGA	1
#		define XPCC__CPU_STRING		"Atmel XMEGA"
#	else
		// see http://www.nongnu.org/avr-libc/user-manual/using_tools.html
#		if __AVR_ARCH__ == 2 || __AVR_ARCH__ == 25 || __AVR_ARCH__ == 1
#			define XPCC__CPU_ATTINY	1
#			define XPCC__CPU_STRING	"Atmel tinyAVR"
#		else
#			define XPCC__CPU_ATMEGA	1
#			define XPCC__CPU_STRING	"Atmel megaAVR"
#		endif
#	endif
#endif

#if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64
#	if defined __x86_64__ || defined _M_X64
#		define XPCC__CPU_AMD64 1
#		define XPCC__CPU_STRING		"AMD x86-64"
#		define XPCC__ALIGNMENT	8
#	else
#		define XPCC__CPU_I386 1
#		define XPCC__CPU_STRING		"Intel 386+"
#		define XPCC__ALIGNMENT	4
#	endif
#endif

#if defined __arm__ || defined __ARM_EABI__
#	define XPCC__CPU_ARM	1
#	define XPCC__ALIGNMENT	4
#	if defined __ARM_ARCH_4T__
#		define XPCC__CPU_ARM7TDMI	1
#		define XPCC__CPU_STRING		"ARM7TDMI"
#	elif defined __ARM_ARCH_6SM__ || defined __ARM_ARCH_6M__
#		define XPCC__CPU_CORTEX_M0	1
#		define XPCC__CPU_STRING		"Cortex-M0"
#	elif defined __ARM_ARCH_7M__
#		define XPCC__CPU_CORTEX_M3	1
#		define XPCC__CPU_STRING		"Cortex-M3"
#	elif defined __ARM_ARCH_7EM__
#		define XPCC__CPU_CORTEX_M4	1
#		define XPCC__CPU_STRING		"Cortex-M4"
#	elif defined __ARM_ARCH_7A__
#		define XPCC__CPU_CORTEX_A7	1
#		define XPCC__CPU_STRING		"Cortex-A7"
#	endif
#endif

#if !defined XPCC__CPU_STRING
#	error "Couldn't determine target CPU!"
#	define XPCC__CPU_STRING 		"Unknown"
#endif

// ----------------------------------------------------------------------------
// Provide some additional information

#if defined __SIZEOF_POINTER__
#	define XPCC__SIZEOF_POINTER			__SIZEOF_POINTER__
#else
#	if defined(XPCC__CPU_HOSTED_64)
#		define XPCC__SIZEOF_POINTER		8
#	elif defined(XPCC__CPU_HOSTED_32)
#		define XPCC__SIZEOF_POINTER		4
#	endif
#endif

#if !defined XPCC__SIZEOF_POINTER
#	error "XPCC__SIZEOF_POINTER not defined! Please provide a suitable definition."
#endif

#if defined __BYTE_ORDER__
#	define XPCC__BYTE_ORDER		__BYTE_ORDER__
#endif

#if !defined XPCC__BYTE_ORDER
#	error "XPCC__BYTE_ORDER not defined! Please provide a suitable definition."
#endif

#define XPCC__IS_BIG_ENDIAN		(XPCC__BYTE_ORDER == XPCC__ORDER_BIG_ENDIAN)
#define XPCC__IS_LITTLE_ENDIAN	(XPCC__BYTE_ORDER == XPCC__ORDER_LITTLE_ENDIAN)

// ----------------------------------------------------------------------------
// Windows lacks support for some C99 macros and functions we need to
// provide here
#if defined XPCC__OS_WIN32
#	include "platform/hosted/windows.hpp"
#endif

#endif	// !__DOXYGEN__
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkElevationFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkElevationFilter.h"
#include "vtkMath.h"

// Description:
// Construct object with LowPoint=(0,0,0) and HighPoint=(0,0,1). Scalar
// range is (0,1).
vtkElevationFilter::vtkElevationFilter()
{
  this->LowPoint[0] = 0.0;
  this->LowPoint[1] = 0.0;
  this->LowPoint[2] = 0.0;

  this->HighPoint[0] = 0.0;
  this->HighPoint[1] = 0.0;
  this->HighPoint[2] = 1.0;

  this->ScalarRange[0] = 0.0;
  this->ScalarRange[1] = 1.0;
}

//
// Convert position along ray into scalar value.  Example use includes
// coloring terrain by elevation.
//
void vtkElevationFilter::Execute()
{
  int i, j, numPts;
  vtkScalars *newScalars;
  float l, *bounds, *x, s, v[3];
  float diffVector[3], diffScalar;
  vtkDataSet *input = (vtkDataSet *)this->Input;

  //
  // Initialize
  //
  vtkDebugMacro(<<"Generating elevation scalars!");

  if ( ((numPts=input->GetNumberOfPoints()) < 1) )
    {
    vtkErrorMacro(<< "No input!");
    return;
    }
//
// Allocate
//
  newScalars = vtkScalars::New();
  newScalars->Allocate(numPts);
//
// Set up 1D parametric system
//
  bounds = input->GetBounds();

  for (i=0; i<3; i++) diffVector[i] = this->HighPoint[i] - this->LowPoint[i];
  if ( (l = vtkMath::Dot(diffVector,diffVector)) == 0.0)
    {
    vtkErrorMacro(<< this << ": Bad vector, using (0,0,1)\n");
    diffVector[0] = diffVector[1] = 0.0; diffVector[2] = 1.0;
    l = 1.0;
    }
//
// Compute parametric coordinate and map into scalar range
//
  diffScalar = this->ScalarRange[1] - this->ScalarRange[0];
  for (i=0; i<numPts; i++)
    {
    x = input->GetPoint(i);
    for (j=0; j<3; j++) v[j] = x[j] - this->LowPoint[j];
    s = vtkMath::Dot(v,diffVector) / l;
    s = (s < 0.0 ? 0.0 : s > 1.0 ? 1.0 : s);
    newScalars->InsertScalar(i,this->ScalarRange[0]+s*diffScalar);
    }
//
// Update self
//
  ((vtkDataSet *)this->Output)->GetPointData()->CopyScalarsOff();
  ((vtkDataSet *)this->Output)->GetPointData()->PassData(input->GetPointData());

  ((vtkDataSet *)this->Output)->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();
}

void vtkElevationFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataSetFilter::PrintSelf(os,indent);

  os << indent << "Low Point: (" << this->LowPoint[0] << ", "
                                << this->LowPoint[1] << ", "
                                << this->LowPoint[2] << ")\n";
  os << indent << "High Point: (" << this->HighPoint[0] << ", "
                                << this->HighPoint[1] << ", "
                                << this->HighPoint[2] << ")\n";
  os << indent << "Scalar Range: (" << this->ScalarRange[0] << ", "
                                << this->ScalarRange[1] << ")\n";
}
<commit_msg>ENH: Changed InsertScalar to SetScalar<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkElevationFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkElevationFilter.h"
#include "vtkMath.h"

// Description:
// Construct object with LowPoint=(0,0,0) and HighPoint=(0,0,1). Scalar
// range is (0,1).
vtkElevationFilter::vtkElevationFilter()
{
  this->LowPoint[0] = 0.0;
  this->LowPoint[1] = 0.0;
  this->LowPoint[2] = 0.0;

  this->HighPoint[0] = 0.0;
  this->HighPoint[1] = 0.0;
  this->HighPoint[2] = 1.0;

  this->ScalarRange[0] = 0.0;
  this->ScalarRange[1] = 1.0;
}

//
// Convert position along ray into scalar value.  Example use includes
// coloring terrain by elevation.
//
void vtkElevationFilter::Execute()
{
  int i, j, numPts;
  vtkScalars *newScalars;
  float l, *bounds, *x, s, v[3];
  float diffVector[3], diffScalar;
  vtkDataSet *input = (vtkDataSet *)this->Input;

  //
  // Initialize
  //
  vtkDebugMacro(<<"Generating elevation scalars!");

  if ( ((numPts=input->GetNumberOfPoints()) < 1) )
    {
    vtkErrorMacro(<< "No input!");
    return;
    }
//
// Allocate
//
  newScalars = vtkScalars::New();
  newScalars->SetNumberOfScalars(numPts);
//
// Set up 1D parametric system
//
  bounds = input->GetBounds();

  for (i=0; i<3; i++) diffVector[i] = this->HighPoint[i] - this->LowPoint[i];
  if ( (l = vtkMath::Dot(diffVector,diffVector)) == 0.0)
    {
    vtkErrorMacro(<< this << ": Bad vector, using (0,0,1)\n");
    diffVector[0] = diffVector[1] = 0.0; diffVector[2] = 1.0;
    l = 1.0;
    }
//
// Compute parametric coordinate and map into scalar range
//
  diffScalar = this->ScalarRange[1] - this->ScalarRange[0];
  for (i=0; i<numPts; i++)
    {
    x = input->GetPoint(i);
    for (j=0; j<3; j++) v[j] = x[j] - this->LowPoint[j];
    s = vtkMath::Dot(v,diffVector) / l;
    s = (s < 0.0 ? 0.0 : s > 1.0 ? 1.0 : s);
    newScalars->SetScalar(i,this->ScalarRange[0]+s*diffScalar);
    }
//
// Update self
//
  ((vtkDataSet *)this->Output)->GetPointData()->CopyScalarsOff();
  ((vtkDataSet *)this->Output)->GetPointData()->PassData(input->GetPointData());

  ((vtkDataSet *)this->Output)->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();
}

void vtkElevationFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataSetFilter::PrintSelf(os,indent);

  os << indent << "Low Point: (" << this->LowPoint[0] << ", "
                                << this->LowPoint[1] << ", "
                                << this->LowPoint[2] << ")\n";
  os << indent << "High Point: (" << this->HighPoint[0] << ", "
                                << this->HighPoint[1] << ", "
                                << this->HighPoint[2] << ")\n";
  os << indent << "Scalar Range: (" << this->ScalarRange[0] << ", "
                                << this->ScalarRange[1] << ")\n";
}
<|endoftext|>


<commit_before><commit_msg>Fix misleading internal function in bdlde_sha2.cpp (#3799)<commit_after><|endoftext|>


<commit_before>#include <map>

#include <common/buffer.h>
#include <common/endian.h>

#include <ssh/ssh_algorithm_negotiation.h>
#include <ssh/ssh_protocol.h>

namespace {
	static uint8_t constant_cookie[16] = {
		0x00, 0x10, 0x20, 0x30,
		0x40, 0x50, 0x60, 0x70,
		0x80, 0x90, 0xa0, 0xb0,
		0xc0, 0xd0, 0xe0, 0xf0
	};

	template<typename T>
	Buffer name_list(T list)
	{
		typename T::const_iterator it;
		std::vector<Buffer> names;
		Buffer out;

		for (it = list.begin(); it != list.end(); ++it)
			names.push_back(it->first);
		SSH::NameList::encode(&out, names);
		return (out);
	}
}

bool
SSH::AlgorithmNegotiation::input(Buffer *in)
{
	switch (in->peek()) {
	case SSH::Message::KeyExchangeInitializationMessage:
		DEBUG(log_) << "Just ignoring initialization message.";
		return (true);
	default:
		DEBUG(log_) << "Unsupported algorithm negotiation message:" << std::endl << in->hexdump();
		return (false);
	}
}

bool
SSH::AlgorithmNegotiation::output(Buffer *out)
{
	ASSERT(log_, out->empty());

	out->append(SSH::Message::KeyExchangeInitializationMessage);
	out->append(constant_cookie, sizeof constant_cookie); /* XXX Synchronous random byte generation?  */
	out->append(name_list(algorithms_.key_exchange_map_));
	out->append(name_list(algorithms_.server_host_key_map_));
	out->append(name_list(algorithms_.encryption_client_to_server_map_));
	out->append(name_list(algorithms_.encryption_server_to_client_map_));
	out->append(name_list(algorithms_.mac_client_to_server_map_));
	out->append(name_list(algorithms_.mac_server_to_client_map_));
	out->append(name_list(algorithms_.compression_client_to_server_map_));
	out->append(name_list(algorithms_.compression_server_to_client_map_));
	out->append(name_list(algorithms_.language_client_to_server_map_));
	out->append(name_list(algorithms_.language_server_to_client_map_));
	out->append(SSH::Boolean::False);
	uint32_t reserved(0);
	out->append(&reserved);

	return (true);
}
<commit_msg>Use name-list encoding.<commit_after>#include <map>

#include <common/buffer.h>
#include <common/endian.h>

#include <ssh/ssh_algorithm_negotiation.h>
#include <ssh/ssh_protocol.h>

namespace {
	static uint8_t constant_cookie[16] = {
		0x00, 0x10, 0x20, 0x30,
		0x40, 0x50, 0x60, 0x70,
		0x80, 0x90, 0xa0, 0xb0,
		0xc0, 0xd0, 0xe0, 0xf0
	};

	template<typename T>
	std::vector<Buffer> names(T list)
	{
		typename T::const_iterator it;
		std::vector<Buffer> vec;

		for (it = list.begin(); it != list.end(); ++it)
			vec.push_back(it->first);
		return (vec);
	}
}

bool
SSH::AlgorithmNegotiation::input(Buffer *in)
{
	switch (in->peek()) {
	case SSH::Message::KeyExchangeInitializationMessage:
		DEBUG(log_) << "Just ignoring initialization message.";
		return (true);
	default:
		DEBUG(log_) << "Unsupported algorithm negotiation message:" << std::endl << in->hexdump();
		return (false);
	}
}

bool
SSH::AlgorithmNegotiation::output(Buffer *out)
{
	ASSERT(log_, out->empty());

	out->append(SSH::Message::KeyExchangeInitializationMessage);
	out->append(constant_cookie, sizeof constant_cookie); /* XXX Synchronous random byte generation?  */
	SSH::NameList::encode(out, names(algorithms_.key_exchange_map_));
	SSH::NameList::encode(out, names(algorithms_.server_host_key_map_));
	SSH::NameList::encode(out, names(algorithms_.encryption_client_to_server_map_));
	SSH::NameList::encode(out, names(algorithms_.encryption_server_to_client_map_));
	SSH::NameList::encode(out, names(algorithms_.mac_client_to_server_map_));
	SSH::NameList::encode(out, names(algorithms_.mac_server_to_client_map_));
	SSH::NameList::encode(out, names(algorithms_.compression_client_to_server_map_));
	SSH::NameList::encode(out, names(algorithms_.compression_server_to_client_map_));
	SSH::NameList::encode(out, names(algorithms_.language_client_to_server_map_));
	SSH::NameList::encode(out, names(algorithms_.language_server_to_client_map_));
	out->append(SSH::Boolean::False);
	uint32_t reserved(0);
	out->append(&reserved);

	return (true);
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_SCAL_META_GET_HPP
#define STAN_MATH_PRIM_SCAL_META_GET_HPP

#include <stan/math/prim/arr/meta/get.hpp>
#include <cmath>
#include <cstddef>

namespace stan {

template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, T>* = nullptr>
inline T get(const T& x, size_t n) {
  return x;
}

}  // namespace stan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0 (tags/google/stable/2017-11-14)<commit_after>#ifndef STAN_MATH_PRIM_SCAL_META_GET_HPP
#define STAN_MATH_PRIM_SCAL_META_GET_HPP

#include <stan/math/prim/arr/meta/get.hpp>
#include <cmath>
#include <cstddef>

namespace stan {

template <typename T,
          std::enable_if_t<std::is_arithmetic<T>::value, T>* = nullptr>
inline T get(const T& x, size_t n) {
  return x;
}

}  // namespace stan
#endif
<|endoftext|>


<commit_before>/* <src/HttpWorker.cpp>
 *
 * This file is part of the x0 web server project and is released under GPL-3.
 * http://www.xzero.io/
 *
 * (c) 2009-2013 Christian Parpart <trapni@gmail.com>
 */

#include <x0/http/HttpWorker.h>
#include <x0/http/HttpRequest.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpConnection.h>
#include <x0/ServerSocket.h>
#include <x0/DebugLogger.h>

#include <algorithm>
#include <cstdarg>
#include <ev++.h>
#include <signal.h>
#include <pthread.h>

// XXX one a connection has been passed to a worker, it is *bound* to it.

#if !defined(XZERO_NDEBUG)
//#	define TRACE(n, msg...) X0_DEBUG("worker", (n), msg)
#	define TRACE(n, msg...) log(Severity::debug ## n, msg)
#else
#	define TRACE(n, msg...) do {} while (0)
#endif

namespace x0 {

/*!
 * Creates an HTTP worker instance.
 *
 * \param server   the worker parents server instance
 * \param loop     the event loop to be used within this worker
 * \param id       unique ID within the server instance
 * \param threaded whether or not to spawn a thread to actually run this worker
 */
HttpWorker::HttpWorker(HttpServer& server, struct ev_loop *loop, unsigned int id, bool threaded) :
	id_(id),
	state_(Inactive),
	server_(server),
	loop_(loop),
	startupTime_(ev_now(loop_)),
	now_(),
	connectionLoad_(0),
	requestCount_(0),
	connectionCount_(0),
	thread_(pthread_self()),
	queue_(),
	resumeLock_(),
	resumeCondition_(),
	performanceCounter_(),
	stopHandler_(),
	killHandler_(),
	connections_(nullptr),
	freeConnections_(nullptr),
	evLoopCheck_(loop_),
	evNewConnection_(loop_),
	evWakeup_(loop_),
	fileinfo(loop_, &server_.fileinfoConfig_)
{
	evLoopCheck_.set<HttpWorker, &HttpWorker::onLoopCheck>(this);
	evLoopCheck_.start();

	evNewConnection_.set<HttpWorker, &HttpWorker::onNewConnection>(this);
	evNewConnection_.start();

	evWakeup_.set<&HttpWorker::onWakeup>();
	evWakeup_.start();

	pthread_mutex_init(&resumeLock_, nullptr);
	pthread_cond_init(&resumeCondition_, nullptr);

	if (threaded) {
		pthread_create(&thread_, nullptr, &HttpWorker::_run, this);
	}

	setName("worker/%d", id_);

	TRACE(1, "spawned");
}

HttpWorker::~HttpWorker()
{
	TRACE(1, "destroying");

	clearCustomData();

	pthread_cond_destroy(&resumeCondition_);
	pthread_mutex_destroy(&resumeLock_);

	evLoopCheck_.stop();
	evNewConnection_.stop();
	evWakeup_.stop();

	freeCache();

	ev_loop_destroy(loop_);
}

void* HttpWorker::_run(void* p)
{
	reinterpret_cast<HttpWorker*>(p)->run();
	return nullptr;
}

void HttpWorker::run()
{
	state_ = Running;

	// XXX invoke onWorkerSpawned-hook here because we want to ensure this hook is
	// XXX being invoked from *within* the worker-thread.
	server_.onWorkerSpawn(this);

	TRACE(1, "enter loop");
	ev_loop(loop_, 0);

	while (connections_)
		_kill();

	server_.onWorkerUnspawn(this);

	state_ = Inactive;
}

/*!
 * Sets the thread/process name that's running this worker.
 */
void HttpWorker::setName(const char* fmt, ...)
{
	char buf[17]; // the name may be at most 16 bytes long.
	va_list va;

	va_start(va, fmt);
	vsnprintf(buf, sizeof(buf), fmt, va);
	va_end(va);

	pthread_setname_np(thread_, buf);
}

void HttpWorker::log(LogMessage&& msg)
{
	msg.addTag("worker/%u", id());

	server().log(std::forward<LogMessage>(msg));
}

/** enqueues/assigns/registers given client connection information to this worker.
 */
void HttpWorker::enqueue(std::pair<Socket*, ServerSocket*>&& client)
{
	queue_.enqueue(client);
	evNewConnection_.send();
}

/** callback to be invoked when new connection(s) have been assigned to this worker.
 */
void HttpWorker::onNewConnection(ev::async& /*w*/, int /*revents*/)
{
	std::pair<Socket*, ServerSocket*> client;

	while (queue_.dequeue(&client)) {
		spawnConnection(client.first, client.second);
	}
}

void HttpWorker::onWakeup(ev::async& w, int revents)
{
	// no-op - this callback is simply used to wake up the worker's event loop
}

void HttpWorker::spawnConnection(Socket* client, ServerSocket* listener)
{
	TRACE(1, "client connected; fd:%d", client->handle());

	++connectionLoad_;
	++connectionCount_;

	// XXX since socket has not been used so far, I might be able to defer its creation out of its socket descriptor
	// XXX so that I do not have to double-initialize libev's loop handles for this socket.
	client->setLoop(loop_);

	HttpConnection* c;
	if (likely(freeConnections_ != nullptr)) {
		c = freeConnections_;
		c->id_ = connectionCount_;
		freeConnections_ = c->next_;
	}
	else {
		c = new HttpConnection(this, connectionCount_/*id*/);
	}

	if (connections_)
		connections_->prev_ = c;

	c->next_ = connections_;
	connections_ = c;

	c->start(listener, client);
}

/** releases/unregisters given (and to-be-destroyed) connection from this worker.
 *
 * This decrements the connection-load counter by one.
 */
void HttpWorker::release(HttpConnection* c)
{
	//    /--<--\   /--<--\   /--<--\
	// NULL     item1     item2     item3     NULL
	//              \-->--/   \-->--/   \-->--/

	--connectionLoad_;

	// unlink from active-list
	HttpConnection* prev = c->prev_;
	HttpConnection* next = c->next_;

	if (prev)
		prev->next_ = next;

	if (next)
		next->prev_ = prev;

	if (c == connections_)
		connections_ = next;

	// link into free-list
	c->next_ = freeConnections_;
	c->prev_ = nullptr;					// not needed
	if (freeConnections_ && freeConnections_->prev_)
		freeConnections_->prev_ = c;	// not needed
	freeConnections_ = c;
}

/**
 * Clear some cached objects to free up memory.
 */
void HttpWorker::freeCache()
{
	size_t i = 0;
	while (freeConnections_) {
		auto next = freeConnections_->next_;
		delete freeConnections_;
		freeConnections_ = next;
		++i;
	}
	TRACE(1, "cleared %zu free-connections items", i);
}

void HttpWorker::handleRequest(HttpRequest *r)
{
	++requestCount_;
	performanceCounter_.touch(now_.value());

	BufferRef expectHeader = r->requestHeader("Expect");
	bool contentRequired = r->method == "POST" || r->method == "PUT";

	if (contentRequired) {
		if (r->connection.contentLength() == -1 && !r->connection.isChunked()) {
			r->status = HttpStatus::LengthRequired;
			r->finish();
			return;
		}
	} else {
		if (r->contentAvailable()) {
			r->status = HttpStatus::BadRequest; // FIXME do we have a better status code?
			r->finish();
			return;
		}
	}

	if (expectHeader) {
		r->expectingContinue = equals(expectHeader, "100-continue");

		if (!r->expectingContinue || !r->supportsProtocol(1, 1)) {
			r->status = HttpStatus::ExpectationFailed;
			r->finish();
			return;
		}
	}

	server_.onPreProcess(r);

	if (!server_.requestHandler(r))
		r->finish();
}

void HttpWorker::_stop()
{
	TRACE(1, "_stop");

	evLoopCheck_.stop();
	evNewConnection_.stop();
	evWakeup_.stop();

	for (auto handler: stopHandler_)
		handler();
}

void HttpWorker::onLoopCheck(ev::check& /*w*/, int /*revents*/)
{
	// update server time
	now_.update(ev_now(loop_));
}

void HttpWorker::setAffinity(int cpu)
{
	cpu_set_t set;

	CPU_ZERO(&set);
	CPU_SET(cpu, &set);

	TRACE(1, "setAffinity: %d", cpu);

	int rv = pthread_setaffinity_np(thread_, sizeof(set), &set);
	if (rv < 0) {
		log(Severity::error, "setting scheduler affinity on CPU %d failed for worker %u. %s",
			cpu, id_, strerror(errno));
	}
}

void HttpWorker::bind(ServerSocket* s)
{
	s->set<HttpWorker, &HttpWorker::spawnConnection>(this);
}

/** suspend the execution of the worker thread until resume() is invoked.
 *
 * \note has no effect on main worker
 * \see resume()
 */
void HttpWorker::suspend()
{
	TRACE(1, "suspend");

	if (id_ != 0)
		post<HttpWorker, &HttpWorker::_suspend>(this);
}

void HttpWorker::_suspend()
{
	TRACE(1, "_suspend");
	pthread_mutex_lock(&resumeLock_);
	state_ = Suspended;
	pthread_cond_wait(&resumeCondition_, &resumeLock_);
	state_ = Running;
	pthread_mutex_unlock(&resumeLock_);
}

/** resumes the previousely suspended worker thread.
 *
 * \note has no effect on main worker
 * \see suspend()
 */
void HttpWorker::resume()
{
	TRACE(1, "resume");
	if (id_ != 0)
		pthread_cond_signal(&resumeCondition_);
}

void HttpWorker::stop()
{
	TRACE(1, "stop: post -> _stop()");
	post<HttpWorker, &HttpWorker::_stop>(this);
}

void HttpWorker::join()
{
	if (thread_ != pthread_self()) {
		pthread_join(thread_, nullptr);
	}
}

/*! Actually aborts all active connections.
 *
 * \see HttpConnection::abort()
 */
void HttpWorker::kill()
{
	TRACE(1, "kill: post -> _kill()");
	post<HttpWorker, &HttpWorker::_kill>(this);
}

/*! Actually aborts all active connections.
 *
 * \note Must be invoked from within the worker's thread.
 *
 * \see HttpConnection::abort()
 */
void HttpWorker::_kill()
{
	TRACE(1, "_kill()");
	while (connections_) {
		std::list<HttpConnection*> copy;

		for (HttpConnection* c = connections_; c != nullptr; c = c->next_)
			copy.push_back(c);

		for (auto c: copy)
			c->abort();

#ifndef XZERO_NDEBUG
		for (HttpConnection* c = connections_; c != nullptr; c = c->next_)
			c->log(Severity::debug, "connection still open");
#endif
	}

	for (auto handler: killHandler_) {
		TRACE(1, "_kill: invoke kill handler");
		handler();
	}
}

std::list<std::function<void()>>::iterator HttpWorker::registerStopHandler(std::function<void()> callback)
{
	stopHandler_.push_front(callback);
	return stopHandler_.begin();
}

void HttpWorker::unregisterStopHandler(std::list<std::function<void()>>::iterator handle)
{
	stopHandler_.erase(handle);
}

std::list<std::function<void()>>::iterator HttpWorker::registerKillHandler(std::function<void()> callback)
{
	killHandler_.push_front(callback);
	return killHandler_.begin();
}

void HttpWorker::unregisterKillHandler(std::list<std::function<void()>>::iterator handle)
{
	killHandler_.erase(handle);
}

void HttpWorker::post_thunk3(int revents, void* arg)
{
	std::function<void()>* callback = static_cast<std::function<void()>*>(arg);
	(*callback)();
	delete callback;
}

} // namespace x0
<commit_msg>[http] HttpWorker: set custom thread names to something more descriptive (/fancy)<commit_after>/* <src/HttpWorker.cpp>
 *
 * This file is part of the x0 web server project and is released under GPL-3.
 * http://www.xzero.io/
 *
 * (c) 2009-2013 Christian Parpart <trapni@gmail.com>
 */

#include <x0/http/HttpWorker.h>
#include <x0/http/HttpRequest.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpConnection.h>
#include <x0/ServerSocket.h>
#include <x0/DebugLogger.h>

#include <algorithm>
#include <cstdarg>
#include <ev++.h>
#include <signal.h>
#include <pthread.h>

// XXX one a connection has been passed to a worker, it is *bound* to it.

#if !defined(XZERO_NDEBUG)
//#	define TRACE(n, msg...) X0_DEBUG("worker", (n), msg)
#	define TRACE(n, msg...) log(Severity::debug ## n, msg)
#else
#	define TRACE(n, msg...) do {} while (0)
#endif

namespace x0 {

/*!
 * Creates an HTTP worker instance.
 *
 * \param server   the worker parents server instance
 * \param loop     the event loop to be used within this worker
 * \param id       unique ID within the server instance
 * \param threaded whether or not to spawn a thread to actually run this worker
 */
HttpWorker::HttpWorker(HttpServer& server, struct ev_loop *loop, unsigned int id, bool threaded) :
	id_(id),
	state_(Inactive),
	server_(server),
	loop_(loop),
	startupTime_(ev_now(loop_)),
	now_(),
	connectionLoad_(0),
	requestCount_(0),
	connectionCount_(0),
	thread_(pthread_self()),
	queue_(),
	resumeLock_(),
	resumeCondition_(),
	performanceCounter_(),
	stopHandler_(),
	killHandler_(),
	connections_(nullptr),
	freeConnections_(nullptr),
	evLoopCheck_(loop_),
	evNewConnection_(loop_),
	evWakeup_(loop_),
	fileinfo(loop_, &server_.fileinfoConfig_)
{
	evLoopCheck_.set<HttpWorker, &HttpWorker::onLoopCheck>(this);
	evLoopCheck_.start();

	evNewConnection_.set<HttpWorker, &HttpWorker::onNewConnection>(this);
	evNewConnection_.start();

	evWakeup_.set<&HttpWorker::onWakeup>();
	evWakeup_.start();

	pthread_mutex_init(&resumeLock_, nullptr);
	pthread_cond_init(&resumeCondition_, nullptr);

	if (threaded) {
		pthread_create(&thread_, nullptr, &HttpWorker::_run, this);
	}

	setName("xzero-io/%d", id_);

	TRACE(1, "spawned");
}

HttpWorker::~HttpWorker()
{
	TRACE(1, "destroying");

	clearCustomData();

	pthread_cond_destroy(&resumeCondition_);
	pthread_mutex_destroy(&resumeLock_);

	evLoopCheck_.stop();
	evNewConnection_.stop();
	evWakeup_.stop();

	freeCache();

	ev_loop_destroy(loop_);
}

void* HttpWorker::_run(void* p)
{
	reinterpret_cast<HttpWorker*>(p)->run();
	return nullptr;
}

void HttpWorker::run()
{
	state_ = Running;

	// XXX invoke onWorkerSpawned-hook here because we want to ensure this hook is
	// XXX being invoked from *within* the worker-thread.
	server_.onWorkerSpawn(this);

	TRACE(1, "enter loop");
	ev_loop(loop_, 0);

	while (connections_)
		_kill();

	server_.onWorkerUnspawn(this);

	state_ = Inactive;
}

/*!
 * Sets the thread/process name that's running this worker.
 */
void HttpWorker::setName(const char* fmt, ...)
{
	char buf[17]; // the name may be at most 16 bytes long.
	va_list va;

	va_start(va, fmt);
	vsnprintf(buf, sizeof(buf), fmt, va);
	va_end(va);

	pthread_setname_np(thread_, buf);
}

void HttpWorker::log(LogMessage&& msg)
{
	msg.addTag("worker/%u", id());

	server().log(std::forward<LogMessage>(msg));
}

/** enqueues/assigns/registers given client connection information to this worker.
 */
void HttpWorker::enqueue(std::pair<Socket*, ServerSocket*>&& client)
{
	queue_.enqueue(client);
	evNewConnection_.send();
}

/** callback to be invoked when new connection(s) have been assigned to this worker.
 */
void HttpWorker::onNewConnection(ev::async& /*w*/, int /*revents*/)
{
	std::pair<Socket*, ServerSocket*> client;

	while (queue_.dequeue(&client)) {
		spawnConnection(client.first, client.second);
	}
}

void HttpWorker::onWakeup(ev::async& w, int revents)
{
	// no-op - this callback is simply used to wake up the worker's event loop
}

void HttpWorker::spawnConnection(Socket* client, ServerSocket* listener)
{
	TRACE(1, "client connected; fd:%d", client->handle());

	++connectionLoad_;
	++connectionCount_;

	// XXX since socket has not been used so far, I might be able to defer its creation out of its socket descriptor
	// XXX so that I do not have to double-initialize libev's loop handles for this socket.
	client->setLoop(loop_);

	HttpConnection* c;
	if (likely(freeConnections_ != nullptr)) {
		c = freeConnections_;
		c->id_ = connectionCount_;
		freeConnections_ = c->next_;
	}
	else {
		c = new HttpConnection(this, connectionCount_/*id*/);
	}

	if (connections_)
		connections_->prev_ = c;

	c->next_ = connections_;
	connections_ = c;

	c->start(listener, client);
}

/** releases/unregisters given (and to-be-destroyed) connection from this worker.
 *
 * This decrements the connection-load counter by one.
 */
void HttpWorker::release(HttpConnection* c)
{
	//    /--<--\   /--<--\   /--<--\
	// NULL     item1     item2     item3     NULL
	//              \-->--/   \-->--/   \-->--/

	--connectionLoad_;

	// unlink from active-list
	HttpConnection* prev = c->prev_;
	HttpConnection* next = c->next_;

	if (prev)
		prev->next_ = next;

	if (next)
		next->prev_ = prev;

	if (c == connections_)
		connections_ = next;

	// link into free-list
	c->next_ = freeConnections_;
	c->prev_ = nullptr;					// not needed
	if (freeConnections_ && freeConnections_->prev_)
		freeConnections_->prev_ = c;	// not needed
	freeConnections_ = c;
}

/**
 * Clear some cached objects to free up memory.
 */
void HttpWorker::freeCache()
{
	size_t i = 0;
	while (freeConnections_) {
		auto next = freeConnections_->next_;
		delete freeConnections_;
		freeConnections_ = next;
		++i;
	}
	TRACE(1, "cleared %zu free-connections items", i);
}

void HttpWorker::handleRequest(HttpRequest *r)
{
	++requestCount_;
	performanceCounter_.touch(now_.value());

	BufferRef expectHeader = r->requestHeader("Expect");
	bool contentRequired = r->method == "POST" || r->method == "PUT";

	if (contentRequired) {
		if (r->connection.contentLength() == -1 && !r->connection.isChunked()) {
			r->status = HttpStatus::LengthRequired;
			r->finish();
			return;
		}
	} else {
		if (r->contentAvailable()) {
			r->status = HttpStatus::BadRequest; // FIXME do we have a better status code?
			r->finish();
			return;
		}
	}

	if (expectHeader) {
		r->expectingContinue = equals(expectHeader, "100-continue");

		if (!r->expectingContinue || !r->supportsProtocol(1, 1)) {
			r->status = HttpStatus::ExpectationFailed;
			r->finish();
			return;
		}
	}

	server_.onPreProcess(r);

	if (!server_.requestHandler(r))
		r->finish();
}

void HttpWorker::_stop()
{
	TRACE(1, "_stop");

	evLoopCheck_.stop();
	evNewConnection_.stop();
	evWakeup_.stop();

	for (auto handler: stopHandler_)
		handler();
}

void HttpWorker::onLoopCheck(ev::check& /*w*/, int /*revents*/)
{
	// update server time
	now_.update(ev_now(loop_));
}

void HttpWorker::setAffinity(int cpu)
{
	cpu_set_t set;

	CPU_ZERO(&set);
	CPU_SET(cpu, &set);

	TRACE(1, "setAffinity: %d", cpu);

	int rv = pthread_setaffinity_np(thread_, sizeof(set), &set);
	if (rv < 0) {
		log(Severity::error, "setting scheduler affinity on CPU %d failed for worker %u. %s",
			cpu, id_, strerror(errno));
	}
}

void HttpWorker::bind(ServerSocket* s)
{
	s->set<HttpWorker, &HttpWorker::spawnConnection>(this);
}

/** suspend the execution of the worker thread until resume() is invoked.
 *
 * \note has no effect on main worker
 * \see resume()
 */
void HttpWorker::suspend()
{
	TRACE(1, "suspend");

	if (id_ != 0)
		post<HttpWorker, &HttpWorker::_suspend>(this);
}

void HttpWorker::_suspend()
{
	TRACE(1, "_suspend");
	pthread_mutex_lock(&resumeLock_);
	state_ = Suspended;
	pthread_cond_wait(&resumeCondition_, &resumeLock_);
	state_ = Running;
	pthread_mutex_unlock(&resumeLock_);
}

/** resumes the previousely suspended worker thread.
 *
 * \note has no effect on main worker
 * \see suspend()
 */
void HttpWorker::resume()
{
	TRACE(1, "resume");
	if (id_ != 0)
		pthread_cond_signal(&resumeCondition_);
}

void HttpWorker::stop()
{
	TRACE(1, "stop: post -> _stop()");
	post<HttpWorker, &HttpWorker::_stop>(this);
}

void HttpWorker::join()
{
	if (thread_ != pthread_self()) {
		pthread_join(thread_, nullptr);
	}
}

/*! Actually aborts all active connections.
 *
 * \see HttpConnection::abort()
 */
void HttpWorker::kill()
{
	TRACE(1, "kill: post -> _kill()");
	post<HttpWorker, &HttpWorker::_kill>(this);
}

/*! Actually aborts all active connections.
 *
 * \note Must be invoked from within the worker's thread.
 *
 * \see HttpConnection::abort()
 */
void HttpWorker::_kill()
{
	TRACE(1, "_kill()");
	while (connections_) {
		std::list<HttpConnection*> copy;

		for (HttpConnection* c = connections_; c != nullptr; c = c->next_)
			copy.push_back(c);

		for (auto c: copy)
			c->abort();

#ifndef XZERO_NDEBUG
		for (HttpConnection* c = connections_; c != nullptr; c = c->next_)
			c->log(Severity::debug, "connection still open");
#endif
	}

	for (auto handler: killHandler_) {
		TRACE(1, "_kill: invoke kill handler");
		handler();
	}
}

std::list<std::function<void()>>::iterator HttpWorker::registerStopHandler(std::function<void()> callback)
{
	stopHandler_.push_front(callback);
	return stopHandler_.begin();
}

void HttpWorker::unregisterStopHandler(std::list<std::function<void()>>::iterator handle)
{
	stopHandler_.erase(handle);
}

std::list<std::function<void()>>::iterator HttpWorker::registerKillHandler(std::function<void()> callback)
{
	killHandler_.push_front(callback);
	return killHandler_.begin();
}

void HttpWorker::unregisterKillHandler(std::list<std::function<void()>>::iterator handle)
{
	killHandler_.erase(handle);
}

void HttpWorker::post_thunk3(int revents, void* arg)
{
	std::function<void()>* callback = static_cast<std::function<void()>*>(arg);
	(*callback)();
	delete callback;
}

} // namespace x0
<|endoftext|>


<commit_before>#include "manipulator.h"

/* Win32 math.h doesn't define M_PI. */
#if defined(_WIN32)
#if !defined(M_PI)
#define M_PI 3.14159265
#endif /* !defined(M_PI) */
#endif /* defined(WIN32) */

/* internal use */

static void drag_to_rotation(float dx, float dy, rot4f *rotation)
{
    float dist;

    /* XXX grantham 990825 - this "dist" doesn't make me confident. */
    /* but I put in the *10000 to decrease chance of underflow  (???) */
    dist = sqrt(dx * 10000 * dx * 10000 + dy * 10000 * dy * 10000) / 10000;
    /* dist = sqrt(dx * dx + dy * dy); */

    rotation->set(M_PI * dist, dy / dist, dx / dist, 0.0f);
}

static void calc_view_matrix(rot4f view_rotation, vec3f view_offset,
    vec3f obj_center, vec3f obj_scale, mat4f *view_matrix)
{
    *view_matrix = mat4f::translation(view_offset[0], view_offset[1], view_offset[2]);
    *view_matrix = mat4f(view_rotation) * *view_matrix;

    *view_matrix = mat4f::scale(obj_scale[0], obj_scale[1], obj_scale[2]) * *view_matrix;
    *view_matrix = mat4f::translation(-obj_center[0], -obj_center[1], -obj_center[2]) * *view_matrix;
}

/* external API */

void manipulator::calculate_matrix()
{
    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);
}

void manipulator::set_frame(const mat4f& frame)
{
    mat4f i;
    vec3f origin;

    m_frame = frame;

    i.invert(m_frame);
    origin = vec3f(0.0f, 0.0f, 0.0f) * i;
    m_worldX = vec3f(1.0f, 0.0f, 0.0f) * i - origin;
    m_worldY = vec3f(0.0f, 1.0f, 0.0f) * i - origin;
    m_worldZ = vec3f(0.0f, 0.0f, 1.0f) * i - origin;
}

void manipulator::move(float dx, float dy)
{
    switch(m_mode) {

	case ROTATE:
	    if(dx != 0 || dy != 0) {
		rot4f local_rotation;
		rot4f world_rotation;
		drag_to_rotation(dx, dy, &world_rotation);
		local_rotation[0] = world_rotation[0];
		vec3f axis = m_worldX * world_rotation[1] +
                    m_worldY * world_rotation[2];
		local_rotation.set_axis(axis);
		m_rotation = m_rotation * local_rotation;
	    }
	    break;

	case ROLL:
            m_rotation = m_rotation * rot4f(M_PI * 2 * -dy, 0, 0, 1);
	    break;

	case SCROLL:
	    m_translation = m_translation +
                m_worldX * dx * m_reference_size * m_motion_scale +
                m_worldY * dy * m_reference_size * m_motion_scale;
	    break;

	case DOLLY:
	    m_translation = m_translation + m_worldZ * dy * m_reference_size * m_motion_scale;
	    break;
    }

    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);
}

manipulator::manipulator()
{
    m_worldX = vec3f(1.0f, 0.0f, 0.0f);
    m_worldY = vec3f(0.0f, 1.0f, 0.0f);
    m_worldZ = vec3f(0.0f, 0.0f, 1.0f);

    m_center.set(0, 0, 0);

    m_scale.set(1, 1, 1);

    /* diagonal of 2-high cube */
    m_reference_size = 3.465;

    m_motion_scale = 1.0;

    m_translation.set(0, 0, 0);

    m_rotation.set(0, 1, 0, 0);

    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);

    m_mode = ROTATE;
}

manipulator::manipulator(const box& bounds, float fov)
{
    m_worldX = vec3f(1.0f, 0.0f, 0.0f);
    m_worldY = vec3f(0.0f, 1.0f, 0.0f);
    m_worldZ = vec3f(0.0f, 0.0f, 1.0f);

    m_center = vec3f(0.0f, 0.0f, 0.0f);

    m_scale = vec3f(1.0f, 1.0f, 1.0f);

    m_reference_size = bounds.largest_side();
    m_motion_scale = 1.0;

    m_translation.set(0, 0, -m_reference_size / cosf(fov / 2.0));

    m_rotation.set(0, 1, 0, 0);

    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);

    m_mode = manipulator::ROTATE;
}

<commit_msg>fix upside-down Y scroll; negate dy<commit_after>#include "manipulator.h"

/* Win32 math.h doesn't define M_PI. */
#if defined(_WIN32)
#if !defined(M_PI)
#define M_PI 3.14159265
#endif /* !defined(M_PI) */
#endif /* defined(WIN32) */

/* internal use */

static void drag_to_rotation(float dx, float dy, rot4f *rotation)
{
    float dist;

    /* XXX grantham 990825 - this "dist" doesn't make me confident. */
    /* but I put in the *10000 to decrease chance of underflow  (???) */
    dist = sqrt(dx * 10000 * dx * 10000 + dy * 10000 * dy * 10000) / 10000;
    /* dist = sqrt(dx * dx + dy * dy); */

    rotation->set(M_PI * dist, dy / dist, dx / dist, 0.0f);
}

static void calc_view_matrix(rot4f view_rotation, vec3f view_offset,
    vec3f obj_center, vec3f obj_scale, mat4f *view_matrix)
{
    *view_matrix = mat4f::translation(view_offset[0], view_offset[1], view_offset[2]);
    *view_matrix = mat4f(view_rotation) * *view_matrix;

    *view_matrix = mat4f::scale(obj_scale[0], obj_scale[1], obj_scale[2]) * *view_matrix;
    *view_matrix = mat4f::translation(-obj_center[0], -obj_center[1], -obj_center[2]) * *view_matrix;
}

/* external API */

void manipulator::calculate_matrix()
{
    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);
}

void manipulator::set_frame(const mat4f& frame)
{
    mat4f i;
    vec3f origin;

    m_frame = frame;

    i.invert(m_frame);
    origin = vec3f(0.0f, 0.0f, 0.0f) * i;
    m_worldX = vec3f(1.0f, 0.0f, 0.0f) * i - origin;
    m_worldY = vec3f(0.0f, 1.0f, 0.0f) * i - origin;
    m_worldZ = vec3f(0.0f, 0.0f, 1.0f) * i - origin;
}

void manipulator::move(float dx, float dy)
{
    switch(m_mode) {

	case ROTATE:
	    if(dx != 0 || dy != 0) {
		rot4f local_rotation;
		rot4f world_rotation;
		drag_to_rotation(dx, dy, &world_rotation);
		local_rotation[0] = world_rotation[0];
		vec3f axis = m_worldX * world_rotation[1] +
                    m_worldY * world_rotation[2];
		local_rotation.set_axis(axis);
		m_rotation = m_rotation * local_rotation;
	    }
	    break;

	case ROLL:
            m_rotation = m_rotation * rot4f(M_PI * 2 * -dy, 0, 0, 1);
	    break;

	case SCROLL:
	    m_translation = m_translation +
                m_worldX * dx * m_reference_size * m_motion_scale +
                m_worldY * -dy * m_reference_size * m_motion_scale;
	    break;

	case DOLLY:
	    m_translation = m_translation + m_worldZ * dy * m_reference_size * m_motion_scale;
	    break;
    }

    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);
}

manipulator::manipulator()
{
    m_worldX = vec3f(1.0f, 0.0f, 0.0f);
    m_worldY = vec3f(0.0f, 1.0f, 0.0f);
    m_worldZ = vec3f(0.0f, 0.0f, 1.0f);

    m_center.set(0, 0, 0);

    m_scale.set(1, 1, 1);

    /* diagonal of 2-high cube */
    m_reference_size = 3.465;

    m_motion_scale = 1.0;

    m_translation.set(0, 0, 0);

    m_rotation.set(0, 1, 0, 0);

    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);

    m_mode = ROTATE;
}

manipulator::manipulator(const box& bounds, float fov)
{
    m_worldX = vec3f(1.0f, 0.0f, 0.0f);
    m_worldY = vec3f(0.0f, 1.0f, 0.0f);
    m_worldZ = vec3f(0.0f, 0.0f, 1.0f);

    m_center = vec3f(0.0f, 0.0f, 0.0f);

    m_scale = vec3f(1.0f, 1.0f, 1.0f);

    m_reference_size = bounds.largest_side();
    m_motion_scale = 1.0;

    m_translation.set(0, 0, -m_reference_size / cosf(fov / 2.0));

    m_rotation.set(0, 1, 0, 0);

    calc_view_matrix(m_rotation, m_translation, m_center,
        m_scale, &m_matrix);

    m_mode = manipulator::ROTATE;
}

<|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 "TypeSystem.h"

#include "DexUtil.h"
#include "Timer.h"
#include "Resolver.h"

namespace {

void make_instanceof_table(
    InstanceOfTable& instance_of_table,
    const ClassHierarchy& hierarchy,
    const DexType* type,
    size_t depth = 1) {
  auto& parent_chain = instance_of_table[type];
  const auto cls = type_class(type);
  if (cls != nullptr) {
    const auto super = cls->get_super_class();
    if (super != nullptr) {
      const auto& super_chain = instance_of_table.find(super);
      always_assert(super_chain != instance_of_table.end());
      for (const auto& base : super_chain->second) {
        parent_chain.emplace_back(base);
      }
    }
  }
  parent_chain.emplace_back(type);
  always_assert(parent_chain.size() == depth);

  const auto& children = hierarchy.find(type);
  if (children == hierarchy.end()) return;
  for (const auto& child : children->second) {
    make_instanceof_table(instance_of_table, hierarchy, child, depth + 1);
  }
}

void load_interface_children(ClassHierarchy& children, const DexClass* intf) {
  for (const auto& super_intf : intf->get_interfaces()->get_type_list()) {
    children[super_intf].insert(intf->get_type());
    const auto super_intf_cls = type_class(super_intf);
    if (super_intf_cls != nullptr) {
      load_interface_children(children, super_intf_cls);
    }
  }
}

void load_interface_children(ClassHierarchy& children) {
  g_redex->walk_type_class(
      [&](const DexType* type, const DexClass* cls) {
        if (!cls->is_external() || !is_interface(cls)) return;
        load_interface_children(children, cls);
      });
}

void load_interface_children(const Scope& scope, ClassHierarchy& children) {
  for (const auto& cls : scope) {
    if (!is_interface(cls)) continue;
    load_interface_children(children, cls);
  }
  load_interface_children(children);
}

}

const TypeSet TypeSystem::empty_set = TypeSet();
const TypeVector TypeSystem::empty_vec = TypeVector();

TypeSystem::TypeSystem(const Scope& scope) : m_class_scopes(scope) {
  load_interface_children(scope, m_intf_children);
  make_instanceof_interfaces_table();
}

void TypeSystem::get_all_super_interfaces(
    const DexType* intf, TypeSet& supers) const {
  const auto cls = type_class(intf);
  if (cls == nullptr) return;
  for (const auto& super : cls->get_interfaces()->get_type_list()) {
    supers.insert(super);
    get_all_super_interfaces(super, supers);
  }
}

TypeSet TypeSystem::get_local_interfaces(const TypeSet& classes) {
  // Collect all implemented interfaces.
  TypeSet implemented_intfs = get_implemented_interfaces(classes);

  // Remove interfaces that are implemented by other classes too.
  for (auto it = implemented_intfs.begin(); it != implemented_intfs.end();) {
    bool keep = true;

    const auto& implementors = get_implementors(*it);
    for (const auto& cls : implementors) {
      if (!classes.count(cls)) {
        keep = false;
        break;
      }
    }

    if (keep) {
      ++it;
    } else {
      it = implemented_intfs.erase(it);
    }
  }

  return implemented_intfs;
}

const VirtualScope* TypeSystem::find_virtual_scope(
    const DexMethod* meth) const {

  const auto match = [](const DexMethod* meth1, const DexMethod* meth2) {
    return meth1->get_name() == meth2->get_name() &&
        meth1->get_proto() == meth2->get_proto();
  };

  auto type = meth->get_class();
  while (type != nullptr) {
    TRACE(VIRT, 1, "check... %s\n", SHOW(type));
    for (const auto& scope : m_class_scopes.get(type)) {
      TRACE(VIRT, 1, "check... %s\n", SHOW(scope->methods[0].first));
      if (match(scope->methods[0].first, meth)) {
        TRACE(VIRT, 1, "return scope\n");
        return scope;
      }
    }
    const auto cls = type_class(type);
    if (cls == nullptr) break;
    type = cls->get_super_class();
  }

  return nullptr;
}

std::vector<const DexMethod*> TypeSystem::select_from(
    const VirtualScope* scope, const DexType* type) const {
  std::vector<const DexMethod*> refined_scope;
  std::unordered_map<const DexType*, DexMethod*> non_child_methods;
  bool found_root_method = false;
  for (const auto& method : scope->methods) {
    if (is_subtype(type, method.first->get_class())) {
      found_root_method =
          found_root_method || type == method.first->get_class();
      refined_scope.emplace_back(method.first);
    } else {
      non_child_methods[method.first->get_class()] = method.first;
    }
  }
  if (!found_root_method) {
    const auto& parents = parent_chain(type);
    for (auto parent = parents.rbegin();
        parent != parents.rend();
        ++parent) {
      const auto& meth = non_child_methods.find(*parent);
      if (meth == non_child_methods.end()) continue;
      refined_scope.emplace_back(meth->second);
      break;
    }
  }
  return refined_scope;
}

void TypeSystem::make_instanceof_interfaces_table() {
  TypeVector no_parents;
  const auto& hierarchy = m_class_scopes.get_class_hierarchy();
  for (const auto& children_it : hierarchy) {
    const auto parent = children_it.first;
    const auto parent_cls = type_class(parent);
    if (parent_cls != nullptr) continue;
    no_parents.emplace_back(parent);
  }
  no_parents.emplace_back(get_object_type());
  for (const auto& root : no_parents) {
    make_instanceof_table(m_instanceof_table, hierarchy, root);
  }
  for (const auto& root : no_parents) {
    make_interfaces_table(root);
  }
}

void TypeSystem::make_interfaces_table(const DexType* type) {
  const auto cls = type_class(type);
  if (cls != nullptr) {
    const auto super = cls->get_super_class();
    if (super != nullptr) {
      const auto& parent_intfs = m_interfaces.find(super);
      if (parent_intfs != m_interfaces.end()) {
        m_interfaces[type].insert(
            parent_intfs->second.begin(), parent_intfs->second.end());
      }
    }
    for (const auto& intf : cls->get_interfaces()->get_type_list()) {
      m_interfaces[type].insert(intf);
      get_all_super_interfaces(intf, m_interfaces[type]);
    }
  }

  const auto& hierarchy = m_class_scopes.get_class_hierarchy();
  const auto& children = hierarchy.find(type);
  if (children == hierarchy.end()) return;
  for (const auto& child : children->second) {
    make_interfaces_table(child);
  }
}

void TypeSystem::select_methods(
    const VirtualScope& scope,
    const std::unordered_set<DexType*>& types,
    std::unordered_set<DexMethod*>& methods) const {
  TRACE(VIRT, 1, "select_methods make filter\n");
  std::unordered_set<DexType*> filter;
  filter.insert(types.begin(), types.end());

  TRACE(VIRT, 1, "select_methods make type_method map\n");
  std::unordered_map<const DexType*, DexMethod*> type_method;
  for (const auto& vmeth : scope.methods) {
    const auto meth = vmeth.first;
    if (!meth->is_def()) continue;
    type_method[meth->get_class()] = meth;
  }

  TRACE(VIRT, 1, "select_methods walk hierarchy\n");
  while (!filter.empty()) {
    const auto type = *filter.begin();
    filter.erase(filter.begin());
    TRACE(VIRT, 1, "check... %s\n", SHOW(type));
    if (!is_subtype(scope.type, type)) continue;
    const auto& meth = type_method.find(type);
    if (meth != type_method.end()) {
      methods.insert(meth->second);
      continue;
    }
    const auto super = type_class(type)->get_super_class();
    if (super == nullptr) continue;
    if (types.count(super) > 0) continue;
    filter.insert(super);
  }
}

void TypeSystem::select_methods(
    const InterfaceScope& scope,
    const std::unordered_set<DexType*>& types,
    std::unordered_set<DexMethod*>& methods) const {
  for (const auto& virt_scope : scope) {
    select_methods(*virt_scope, types, methods);
  }
}
<commit_msg>shush type erasure interdex plugin<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 "TypeSystem.h"

#include "DexUtil.h"
#include "Timer.h"
#include "Resolver.h"

namespace {

void make_instanceof_table(
    InstanceOfTable& instance_of_table,
    const ClassHierarchy& hierarchy,
    const DexType* type,
    size_t depth = 1) {
  auto& parent_chain = instance_of_table[type];
  const auto cls = type_class(type);
  if (cls != nullptr) {
    const auto super = cls->get_super_class();
    if (super != nullptr) {
      const auto& super_chain = instance_of_table.find(super);
      always_assert(super_chain != instance_of_table.end());
      for (const auto& base : super_chain->second) {
        parent_chain.emplace_back(base);
      }
    }
  }
  parent_chain.emplace_back(type);
  always_assert(parent_chain.size() == depth);

  const auto& children = hierarchy.find(type);
  if (children == hierarchy.end()) return;
  for (const auto& child : children->second) {
    make_instanceof_table(instance_of_table, hierarchy, child, depth + 1);
  }
}

void load_interface_children(ClassHierarchy& children, const DexClass* intf) {
  for (const auto& super_intf : intf->get_interfaces()->get_type_list()) {
    children[super_intf].insert(intf->get_type());
    const auto super_intf_cls = type_class(super_intf);
    if (super_intf_cls != nullptr) {
      load_interface_children(children, super_intf_cls);
    }
  }
}

void load_interface_children(ClassHierarchy& children) {
  g_redex->walk_type_class(
      [&](const DexType* type, const DexClass* cls) {
        if (!cls->is_external() || !is_interface(cls)) return;
        load_interface_children(children, cls);
      });
}

void load_interface_children(const Scope& scope, ClassHierarchy& children) {
  for (const auto& cls : scope) {
    if (!is_interface(cls)) continue;
    load_interface_children(children, cls);
  }
  load_interface_children(children);
}

}

const TypeSet TypeSystem::empty_set = TypeSet();
const TypeVector TypeSystem::empty_vec = TypeVector();

TypeSystem::TypeSystem(const Scope& scope) : m_class_scopes(scope) {
  load_interface_children(scope, m_intf_children);
  make_instanceof_interfaces_table();
}

void TypeSystem::get_all_super_interfaces(
    const DexType* intf, TypeSet& supers) const {
  const auto cls = type_class(intf);
  if (cls == nullptr) return;
  for (const auto& super : cls->get_interfaces()->get_type_list()) {
    supers.insert(super);
    get_all_super_interfaces(super, supers);
  }
}

TypeSet TypeSystem::get_local_interfaces(const TypeSet& classes) {
  // Collect all implemented interfaces.
  TypeSet implemented_intfs = get_implemented_interfaces(classes);

  // Remove interfaces that are implemented by other classes too.
  for (auto it = implemented_intfs.begin(); it != implemented_intfs.end();) {
    bool keep = true;

    const auto& implementors = get_implementors(*it);
    for (const auto& cls : implementors) {
      if (!classes.count(cls)) {
        keep = false;
        break;
      }
    }

    if (keep) {
      ++it;
    } else {
      it = implemented_intfs.erase(it);
    }
  }

  return implemented_intfs;
}

const VirtualScope* TypeSystem::find_virtual_scope(
    const DexMethod* meth) const {

  const auto match = [](const DexMethod* meth1, const DexMethod* meth2) {
    return meth1->get_name() == meth2->get_name() &&
        meth1->get_proto() == meth2->get_proto();
  };

  auto type = meth->get_class();
  while (type != nullptr) {
    TRACE(VIRT, 5, "check... %s\n", SHOW(type));
    for (const auto& scope : m_class_scopes.get(type)) {
      TRACE(VIRT, 5, "check... %s\n", SHOW(scope->methods[0].first));
      if (match(scope->methods[0].first, meth)) {
        TRACE(VIRT, 5, "return scope\n");
        return scope;
      }
    }
    const auto cls = type_class(type);
    if (cls == nullptr) break;
    type = cls->get_super_class();
  }

  return nullptr;
}

std::vector<const DexMethod*> TypeSystem::select_from(
    const VirtualScope* scope, const DexType* type) const {
  std::vector<const DexMethod*> refined_scope;
  std::unordered_map<const DexType*, DexMethod*> non_child_methods;
  bool found_root_method = false;
  for (const auto& method : scope->methods) {
    if (is_subtype(type, method.first->get_class())) {
      found_root_method =
          found_root_method || type == method.first->get_class();
      refined_scope.emplace_back(method.first);
    } else {
      non_child_methods[method.first->get_class()] = method.first;
    }
  }
  if (!found_root_method) {
    const auto& parents = parent_chain(type);
    for (auto parent = parents.rbegin();
        parent != parents.rend();
        ++parent) {
      const auto& meth = non_child_methods.find(*parent);
      if (meth == non_child_methods.end()) continue;
      refined_scope.emplace_back(meth->second);
      break;
    }
  }
  return refined_scope;
}

void TypeSystem::make_instanceof_interfaces_table() {
  TypeVector no_parents;
  const auto& hierarchy = m_class_scopes.get_class_hierarchy();
  for (const auto& children_it : hierarchy) {
    const auto parent = children_it.first;
    const auto parent_cls = type_class(parent);
    if (parent_cls != nullptr) continue;
    no_parents.emplace_back(parent);
  }
  no_parents.emplace_back(get_object_type());
  for (const auto& root : no_parents) {
    make_instanceof_table(m_instanceof_table, hierarchy, root);
  }
  for (const auto& root : no_parents) {
    make_interfaces_table(root);
  }
}

void TypeSystem::make_interfaces_table(const DexType* type) {
  const auto cls = type_class(type);
  if (cls != nullptr) {
    const auto super = cls->get_super_class();
    if (super != nullptr) {
      const auto& parent_intfs = m_interfaces.find(super);
      if (parent_intfs != m_interfaces.end()) {
        m_interfaces[type].insert(
            parent_intfs->second.begin(), parent_intfs->second.end());
      }
    }
    for (const auto& intf : cls->get_interfaces()->get_type_list()) {
      m_interfaces[type].insert(intf);
      get_all_super_interfaces(intf, m_interfaces[type]);
    }
  }

  const auto& hierarchy = m_class_scopes.get_class_hierarchy();
  const auto& children = hierarchy.find(type);
  if (children == hierarchy.end()) return;
  for (const auto& child : children->second) {
    make_interfaces_table(child);
  }
}

void TypeSystem::select_methods(
    const VirtualScope& scope,
    const std::unordered_set<DexType*>& types,
    std::unordered_set<DexMethod*>& methods) const {
  TRACE(VIRT, 1, "select_methods make filter\n");
  std::unordered_set<DexType*> filter;
  filter.insert(types.begin(), types.end());

  TRACE(VIRT, 1, "select_methods make type_method map\n");
  std::unordered_map<const DexType*, DexMethod*> type_method;
  for (const auto& vmeth : scope.methods) {
    const auto meth = vmeth.first;
    if (!meth->is_def()) continue;
    type_method[meth->get_class()] = meth;
  }

  TRACE(VIRT, 1, "select_methods walk hierarchy\n");
  while (!filter.empty()) {
    const auto type = *filter.begin();
    filter.erase(filter.begin());
    TRACE(VIRT, 1, "check... %s\n", SHOW(type));
    if (!is_subtype(scope.type, type)) continue;
    const auto& meth = type_method.find(type);
    if (meth != type_method.end()) {
      methods.insert(meth->second);
      continue;
    }
    const auto super = type_class(type)->get_super_class();
    if (super == nullptr) continue;
    if (types.count(super) > 0) continue;
    filter.insert(super);
  }
}

void TypeSystem::select_methods(
    const InterfaceScope& scope,
    const std::unordered_set<DexType*>& types,
    std::unordered_set<DexMethod*>& methods) const {
  for (const auto& virt_scope : scope) {
    select_methods(*virt_scope, types, methods);
  }
}
<|endoftext|>


<commit_before>/**
 * @file   utils.hpp
 * @brief  common macro utilities.
 * @author zer0
 * @date   2016-05-27
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_MACRO_UTILS_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_MACRO_UTILS_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

// --------------------------
// Inline information macros.
// --------------------------

#define TO_STRING_IMP(m) #m
#define TO_STRING(x) TO_STRING_IMP(x)

#define LINE_STRING TO_STRING(__LINE__)
#define FILE_STRING __FILE__
#define DATE_STRING __DATE__
#define TIME_STRING __TIME__

#define __DATETIME__  DATE_STRING  "T" TIME_STRING
#define __LOCATION__  FILE_STRING  ":" LINE_STRING
#define DEBUG_STAMP   __DATETIME__ " " __LOCATION__

#define VERSION_SEPARATOR "."

// ---------------
// Compare macros.
// ---------------

#define COMPARE_AND(x)      (x) && (x)
#define COMPARE_OR(x)       (x) || (x)
#define RANGE_OR(min, max)  (min) || (max)

// --------------
// Remove macros.
// --------------

#define UNUSED_PARAM(x)
#define NAMELESS(x)
#define COMMENT(x)
#define BRACE(x)

#ifndef REMOVE_UNUSED_DECLARATION
/** Remove unused declaration warning. */
#define REMOVE_UNUSED_DECLARATION(name, x) \
    inline void __remove_##unused##name##__() \
    { x; }
#endif

#ifndef REMOVE_UNUSED_VARIABLE
/** Remove unused variables warning. */
#define REMOVE_UNUSED_VARIABLE(x) \
    if (x) { }
#endif

// -----------------
// Namespace macros.
// -----------------

#ifndef NAMESPACE_ANONYMOUS
# define NAMESPACE_ANONYMOUS
# if defined(__cplusplus)
#  define NAMESPACE_ANONYMOUS_OPEN   namespace {
#  define NAMESPACE_ANONYMOUS_CLOSE  }
# else /* __cplusplus */
#  define NAMESPACE_ANONYMOUS_OPEN
#  define NAMESPACE_ANONYMOUS_CLOSE
# endif /* __cplusplus */
#endif

#endif // __INCLUDE_LIBTBAG__LIBTBAG_MACRO_UTILS_HPP__

<commit_msg>Create FUNC_STRING macro.<commit_after>/**
 * @file   utils.hpp
 * @brief  common macro utilities.
 * @author zer0
 * @date   2016-05-27
 */

#ifndef __INCLUDE_LIBTBAG__LIBTBAG_MACRO_UTILS_HPP__
#define __INCLUDE_LIBTBAG__LIBTBAG_MACRO_UTILS_HPP__

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif

// --------------------------
// Inline information macros.
// --------------------------

#define TO_STRING_IMP(m) #m
#define TO_STRING(x) TO_STRING_IMP(x)

#define LINE_STRING TO_STRING(__LINE__)
#define FILE_STRING __FILE__
#define DATE_STRING __DATE__
#define TIME_STRING __TIME__

#define FUNC_STRING __PRETTY_FUNCTION__

#define __DATETIME__  DATE_STRING  "T" TIME_STRING
#define __LOCATION__  FILE_STRING  ":" LINE_STRING
#define DEBUG_STAMP   __DATETIME__ " " __LOCATION__

#define VERSION_SEPARATOR "."

// ---------------
// Compare macros.
// ---------------

#define COMPARE_AND(x)      (x) && (x)
#define COMPARE_OR(x)       (x) || (x)
#define RANGE_OR(min, max)  (min) || (max)

// --------------
// Remove macros.
// --------------

#define UNUSED_PARAM(x)
#define NAMELESS(x)
#define COMMENT(x)
#define BRACE(x)

#ifndef REMOVE_UNUSED_DECLARATION
/** Remove unused declaration warning. */
#define REMOVE_UNUSED_DECLARATION(name, x) \
    inline void __remove_##unused##name##__() \
    { x; }
#endif

#ifndef REMOVE_UNUSED_VARIABLE
/** Remove unused variables warning. */
#define REMOVE_UNUSED_VARIABLE(x) \
    if (x) { }
#endif

// -----------------
// Namespace macros.
// -----------------

#ifndef NAMESPACE_ANONYMOUS
# define NAMESPACE_ANONYMOUS
# if defined(__cplusplus)
#  define NAMESPACE_ANONYMOUS_OPEN   namespace {
#  define NAMESPACE_ANONYMOUS_CLOSE  }
# else /* __cplusplus */
#  define NAMESPACE_ANONYMOUS_OPEN
#  define NAMESPACE_ANONYMOUS_CLOSE
# endif /* __cplusplus */
#endif

#endif // __INCLUDE_LIBTBAG__LIBTBAG_MACRO_UTILS_HPP__

<|endoftext|>


<commit_before>
#ifndef __MD5_HH__
#define __MD5_HH__

#include <string>
#include <qpdf/QEXC.hh>
#include <qpdf/qpdf-config.h>

class MD5
{
  public:
    typedef unsigned char Digest[16];

    MD5();
    void reset();

    // encodes string and finalizes
    void encodeString(char const* input_string);

    // encodes file and finalizes
    void encodeFile(char const* filename, int up_to_size = -1)
	throw(QEXC::System);

    // appends string to current md5 object
    void appendString(char const* input_string);

    // appends arbitrary data to current md5 object
    void encodeDataIncrementally(char const* input_data, int len);

    // computes a raw digest
    void digest(Digest);

    // prints the digest to stdout terminated with \r\n (primarily for
    // testing)
    void print();

    // returns the digest as a hexademical string
    std::string unparse();

    // Convenience functions
    static std::string getDataChecksum(char const* buf, int len);
    static std::string getFileChecksum(char const* filename, int up_to_size = -1);
    static bool checkDataChecksum(char const* const checksum,
				  char const* buf, int len);
    static bool checkFileChecksum(char const* const checksum,
				  char const* filename, int up_to_size = -1);

  private:
    // POINTER defines a generic pointer type
    typedef void *POINTER;

    // UINT2 defines a two byte word
    typedef uint16_t UINT2;

    // UINT4 defines a four byte word
    typedef uint32_t UINT4;

    void init();
    void update(unsigned char *, unsigned int);
    void final();

    static void transform(UINT4 [4], unsigned char [64]);
    static void encode(unsigned char *, UINT4 *, unsigned int);
    static void decode(UINT4 *, unsigned char *, unsigned int);

    UINT4 state[4];		// state (ABCD)
    UINT4 count[2];		// number of bits, modulo 2^64 (lsb first)
    unsigned char buffer[64];	// input buffer

    bool finalized;
    Digest digest_val;
};

#endif // __MD5_HH__
<commit_msg>conditionally include inttypes.h<commit_after>
#ifndef __MD5_HH__
#define __MD5_HH__

#include <string>
#include <qpdf/QEXC.hh>
#include <qpdf/qpdf-config.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif

class MD5
{
  public:
    typedef unsigned char Digest[16];

    MD5();
    void reset();

    // encodes string and finalizes
    void encodeString(char const* input_string);

    // encodes file and finalizes
    void encodeFile(char const* filename, int up_to_size = -1)
	throw(QEXC::System);

    // appends string to current md5 object
    void appendString(char const* input_string);

    // appends arbitrary data to current md5 object
    void encodeDataIncrementally(char const* input_data, int len);

    // computes a raw digest
    void digest(Digest);

    // prints the digest to stdout terminated with \r\n (primarily for
    // testing)
    void print();

    // returns the digest as a hexademical string
    std::string unparse();

    // Convenience functions
    static std::string getDataChecksum(char const* buf, int len);
    static std::string getFileChecksum(char const* filename, int up_to_size = -1);
    static bool checkDataChecksum(char const* const checksum,
				  char const* buf, int len);
    static bool checkFileChecksum(char const* const checksum,
				  char const* filename, int up_to_size = -1);

  private:
    // POINTER defines a generic pointer type
    typedef void *POINTER;

    // UINT2 defines a two byte word
    typedef uint16_t UINT2;

    // UINT4 defines a four byte word
    typedef uint32_t UINT4;

    void init();
    void update(unsigned char *, unsigned int);
    void final();

    static void transform(UINT4 [4], unsigned char [64]);
    static void encode(unsigned char *, UINT4 *, unsigned int);
    static void decode(UINT4 *, unsigned char *, unsigned int);

    UINT4 state[4];		// state (ABCD)
    UINT4 count[2];		// number of bits, modulo 2^64 (lsb first)
    unsigned char buffer[64];	// input buffer

    bool finalized;
    Digest digest_val;
};

#endif // __MD5_HH__
<|endoftext|>