<commit_before>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbMultivariateAlterationDetectorImageFilter.h"

namespace otb
{
namespace Wrapper
{

class MultivariateAlterationDetector: public Application
{
public:
  /** Standard class typedefs. */
  typedef MultivariateAlterationDetector          Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(MultivariateAlterationDetector, otb::Wrapper::Application);

private:
  void DoInit() override
  {
    SetName("MultivariateAlterationDetector");
    SetDescription("Change detection by Multivariate Alteration Detector (MAD) algorithm");

    // Documentation
    SetDocLongDescription("This application performs change detection between two multispectral"
                          " images using the Multivariate Alteration Detector (MAD) [1]"
                          " algorithm.\n\n"
                          "The MAD algorithm produces a set of N change maps (where N is the"
                          " maximum number of bands in first and second input images), with the"
                          " following properties:\n\n"

                          "* Change maps are differences of a pair of linear combinations of "
                          " bands from image 1 and bands from image 2 chosen to maximize the "
                          " correlation, \n"
                          "* Each change map is orthogonal to the others.\n\n"

                          "This is a statistical method which can handle different modalities"
                          " and even different bands and number of bands between images. \n"
                          " \n"
                          "The application will output all change maps into a single multiband"
                          " image. If numbers of bands in image 1 and 2 are equal, then change"
                          " maps are sorted by increasing correlation. If number of bands is"
                          " different, the change maps are sorted by decreasing correlation. \n"
                          " \n"
                          "The application will also print the following information:\n"
                          "- Mean1 and Mean2 which are the mean values of bands for both input"
                          " images,\n"
                          "- V1 and V2 which are the two linear transform that are applied to"
                          " input image 1 and input image 2 to build the change map,\n"
                          "- Rho, the vector of correlation associated to each change map.\n"
                          " \n"
                          "The OTB filter used in this application has been implemented from the"
                          " Matlab code kindly made available by the authors here [2]. Both cases"
                          " (same and different number of bands) have been validated"
                          " by comparing the output image to the output produced by the Matlab "
                          " code, and the reference images for testing have been generated from "
                          " the Matlab code using Octave." );

    SetDocLimitations("Input images 1 and 2 should share exactly the same origin, spacing, size, and projection if any.");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("[1] Nielsen, A. A., & Conradsen, K. (1997). Multivariate alteration"
                  "detection (MAD) in multispectral, bi-temporal image data: A new"
                  "approach to change detection studies.\n"
                  "[2] http://www2.imm.dtu.dk/~aa/software.html");

    AddDocTag(Tags::ChangeDetection);

    AddParameter(ParameterType_InputImage,  "in1", "Input Image 1");
    SetParameterDescription("in1","Multiband image of the scene before perturbations");
    AddParameter(ParameterType_InputImage,  "in2", "Input Image 2");
    SetParameterDescription("in2","Mutliband image of the scene after perturbations.");
    AddParameter(ParameterType_OutputImage, "out", "Change Map");
    SetParameterDescription("out","Multiband image containing change maps. Each map will be in the range [-1,1], so a floating point output type is advised.");

    AddRAMParameter();

    // Doc example parameter settings
    SetDocExampleParameterValue("in1", "Spot5-Gloucester-before.tif");
    SetDocExampleParameterValue("in2", "Spot5-Gloucester-after.tif");
    SetDocExampleParameterValue("out", "detectedChangeImage.tif");

  SetOfficialDocLink();
  }

  void DoUpdateParameters() override
  {
  }

  void DoExecute() override
  {
    typedef otb::MultivariateAlterationDetectorImageFilter<
        FloatVectorImageType,
        FloatVectorImageType> ChangeFilterType;

    ChangeFilterType::Pointer changeFilter = ChangeFilterType::New();

    changeFilter->SetInput1(GetParameterImage("in1"));
    changeFilter->SetInput2(GetParameterImage("in2"));
    changeFilter->GetOutput()->UpdateOutputInformation();

    otbAppLogINFO("Input 1 mean: "<<changeFilter->GetMean1());
    otbAppLogINFO("Input 2 mean: "<<changeFilter->GetMean2());
    otbAppLogINFO("Input 1 transform: "<<changeFilter->GetV1());
    otbAppLogINFO("Input 2 transform: "<<changeFilter->GetV2());
    otbAppLogINFO("Rho: "<<changeFilter->GetRho());

    m_Ref = changeFilter;

    SetParameterOutputImage("out", changeFilter->GetOutput());
  }

  itk::LightObject::Pointer m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::MultivariateAlterationDetector)
<commit_msg>DOC: fix errors in the MAD application documentation<commit_after>/*
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbMultivariateAlterationDetectorImageFilter.h"

namespace otb
{
namespace Wrapper
{

class MultivariateAlterationDetector: public Application
{
public:
  /** Standard class typedefs. */
  typedef MultivariateAlterationDetector          Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(MultivariateAlterationDetector, otb::Wrapper::Application);

private:
  void DoInit() override
  {
    SetName("MultivariateAlterationDetector");
    SetDescription("Change detection by Multivariate Alteration Detector (MAD) algorithm");

    // Documentation
    SetDocLongDescription("This application performs change detection between two multispectral"
                          " images using the Multivariate Alteration Detector (MAD) [1]"
                          " algorithm.\n\n"
                          "The MAD algorithm produces a set of N change maps (where N is the"
                          " maximum number of bands in first and second input images), with the"
                          " following properties:\n\n"

                          "* Change maps are differences of a pair of linear combinations of "
                          " bands from image 1 and bands from image 2 chosen to maximize the "
                          " correlation, \n"
                          "* Each change map is orthogonal to the others.\n\n"

                          "This is a statistical method which can handle different modalities"
                          " and even different bands and number of bands between images. \n"
                          " \n"
                          "The application will output all change maps into a single multiband"
                          " image. Change maps are sorted by increasing correlation. \n"
                          " \n"
                          "The application will also print the following information:\n\n"
                          "- Mean1 and Mean2 which are the mean values of bands for both input"
                          " images,\n"
                          "- V1 and V2 which are the two linear transform that are applied to"
                          " input image 1 and input image 2 to build the change map,\n"
                          "- Rho, the vector of correlation associated to each change map.\n"
                          " \n"
                          "The OTB filter used in this application has been implemented from the"
                          " Matlab code kindly made available by the authors here [2]. Both cases"
                          " (same and different number of bands) have been validated"
                          " by comparing the output image to the output produced by the Matlab "
                          " code, and the reference images for testing have been generated from "
                          " the Matlab code using Octave." );

    SetDocLimitations("Input images 1 and 2 should share exactly the same origin, spacing, size, and projection if any.");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("[1] Nielsen, A. A., & Conradsen, K. (1997). Multivariate alteration"
                  "detection (MAD) in multispectral, bi-temporal image data: A new"
                  "approach to change detection studies.\n"
                  "[2] http://www2.imm.dtu.dk/~aa/software.html");

    AddDocTag(Tags::ChangeDetection);

    AddParameter(ParameterType_InputImage,  "in1", "Input Image 1");
    SetParameterDescription("in1","Multiband image of the scene before perturbations");
    AddParameter(ParameterType_InputImage,  "in2", "Input Image 2");
    SetParameterDescription("in2","Mutliband image of the scene after perturbations.");
    AddParameter(ParameterType_OutputImage, "out", "Change Map");
    SetParameterDescription("out","Multiband image containing change maps.");

    AddRAMParameter();

    // Doc example parameter settings
    SetDocExampleParameterValue("in1", "Spot5-Gloucester-before.tif");
    SetDocExampleParameterValue("in2", "Spot5-Gloucester-after.tif");
    SetDocExampleParameterValue("out", "detectedChangeImage.tif");

  SetOfficialDocLink();
  }

  void DoUpdateParameters() override
  {
  }

  void DoExecute() override
  {
    typedef otb::MultivariateAlterationDetectorImageFilter<
        FloatVectorImageType,
        FloatVectorImageType> ChangeFilterType;

    ChangeFilterType::Pointer changeFilter = ChangeFilterType::New();

    changeFilter->SetInput1(GetParameterImage("in1"));
    changeFilter->SetInput2(GetParameterImage("in2"));
    changeFilter->GetOutput()->UpdateOutputInformation();

    otbAppLogINFO("Input 1 mean: "<<changeFilter->GetMean1());
    otbAppLogINFO("Input 2 mean: "<<changeFilter->GetMean2());
    otbAppLogINFO("Input 1 transform: "<<changeFilter->GetV1());
    otbAppLogINFO("Input 2 transform: "<<changeFilter->GetV2());
    otbAppLogINFO("Rho: "<<changeFilter->GetRho());

    m_Ref = changeFilter;

    SetParameterOutputImage("out", changeFilter->GetOutput());
  }

  itk::LightObject::Pointer m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::MultivariateAlterationDetector)
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkVectorGradientMagnitudeImageFilter_hxx
#define itkVectorGradientMagnitudeImageFilter_hxx

#include "itkVectorGradientMagnitudeImageFilter.h"

#include "itkNeighborhoodAlgorithm.h"
#include "itkImageRegionIterator.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"
#include "itkProgressReporter.h"
#include "itkVectorCastImageFilter.h"

#include "itkMath.h"

namespace itk
{
template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  unsigned i;

  Superclass::PrintSelf(os, indent);
  os << indent << "m_UseImageSpacing = "          << m_UseImageSpacing
     << std::endl;
  os << indent << "m_UsePrincipleComponents = "   << m_UseImageSpacing
     << std::endl;
  os << indent << "m_RequestedNumberOfThreads = " << m_RequestedNumberOfThreads
     << std::endl;
  os << indent << "m_DerivativeWeights = ";
  for ( i = 0; i < ImageDimension; i++ )
    {
    os << m_DerivativeWeights[i] << " ";
    }
  os << std::endl;
  os << indent << "m_ComponentWeights = ";
  for ( i = 0; i < VectorDimension; i++ )
    {
    os << m_ComponentWeights[i] << " ";
    }
  os << std::endl;
  os << indent << "m_RealValuedInputImage = "          << m_RealValuedInputImage.GetPointer()
     << std::endl;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::VectorGradientMagnitudeImageFilter()
{
  unsigned int i;

  m_UseImageSpacing = true;
  m_UsePrincipleComponents = true;
  m_RequestedNumberOfThreads = this->GetNumberOfThreads();
  for ( i = 0; i < ImageDimension; i++ )
    {
    m_DerivativeWeights[i] = static_cast< TRealType >( 1.0 );
    }
  for ( i = 0; i < VectorDimension; i++ )
    {
    m_ComponentWeights[i] = static_cast< TRealType >( 1.0 );
    m_SqrtComponentWeights[i] = static_cast< TRealType >( 1.0 );
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::SetUseImageSpacing(bool f)
{
  if ( m_UseImageSpacing == f ) { return; }

  // Only reset the weights if they were previously set to the image spacing,
  // otherwise, the user may have provided their own weightings.
  if ( f == false && m_UseImageSpacing == true )
    {
    for ( unsigned i = 0; i < ImageDimension; ++i )
      {
      m_DerivativeWeights[i] = static_cast< TRealType >( 1.0 );
      }
    }

  m_UseImageSpacing = f;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::GenerateInputRequestedRegion()
{
  // call the superclass' implementation of this method
  Superclass::GenerateInputRequestedRegion();

  // get pointers to the input and output
  InputImagePointer inputPtr =
    const_cast< InputImageType * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  if ( !inputPtr || !outputPtr )
    {
    return;
    }

  // get a copy of the input requested region (should equal the output
  // requested region)
  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion = inputPtr->GetRequestedRegion();

  RadiusType r1;
  r1.Fill(1);
  // pad the input requested region by the operator radius
  inputRequestedRegion.PadByRadius(r1);

  // crop the input requested region at the input's largest possible region
  if ( inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() ) )
    {
    inputPtr->SetRequestedRegion(inputRequestedRegion);
    return;
    }
  else
    {
    // Couldn't crop the region (requested region is outside the largest
    // possible region).  Throw an exception.

    // store what we tried to request (prior to trying to crop)
    inputPtr->SetRequestedRegion(inputRequestedRegion);

    // build an exception
    InvalidRequestedRegionError e(__FILE__, __LINE__);
    e.SetLocation(ITK_LOCATION);
    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
    e.SetDataObject(inputPtr);
    throw e;
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::BeforeThreadedGenerateData()
{
  Superclass::BeforeThreadedGenerateData();

  // Calculate the square-roots of the component weights.
  for ( unsigned i = 0; i < VectorDimension; ++i )
    {
    if ( m_ComponentWeights[i] < 0 )
      {
      itkExceptionMacro(<< "Component weights must be positive numbers");
      }
    m_SqrtComponentWeights[i] = std::sqrt(m_ComponentWeights[i]);
    }

  // Set the weights on the derivatives.
  // Are we using image spacing in the calculations?  If so we must update now
  // in case our input image has changed.
  if ( m_UseImageSpacing == true )
    {
    for ( unsigned i = 0; i < ImageDimension; i++ )
      {
      if ( static_cast< TRealType >( this->GetInput()->GetSpacing()[i] ) == 0.0 )
        {
        itkExceptionMacro(<< "Image spacing in dimension " << i << " is zero.");
        }
      m_DerivativeWeights[i] =
        static_cast< TRealType >( 1.0
                                  / static_cast< TRealType >( this->GetInput()->GetSpacing()[i] ) );
      }
    }

  // If using the principle components method, then force this filter to use a
  // single thread because vnl eigensystem objects are not thread-safe.  3D
  // data is ok because we have a special solver.
  if ( m_UsePrincipleComponents == true && ImageDimension != 3 )
    {
    m_RequestedNumberOfThreads = this->GetNumberOfThreads();
    this->SetNumberOfThreads(1);
    }
  else
    {
    this->SetNumberOfThreads(m_RequestedNumberOfThreads);
    }
  //
  // cast might not be necessary, but CastImagefilter is optimized for
  // the case where the InputImageType == OutputImageType
  typename VectorCastImageFilter< TInputImage, RealVectorImageType >::Pointer
    caster = VectorCastImageFilter< TInputImage, RealVectorImageType >::New();
  caster->SetInput( this->GetInput() );
  caster->GetOutput()->SetRequestedRegion( this->GetInput()->GetRequestedRegion() );
  caster->Update();
  m_RealValuedInputImage = caster->GetOutput();
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
                       ThreadIdType threadId)
{
  ZeroFluxNeumannBoundaryCondition< RealVectorImageType > nbc;
  ConstNeighborhoodIteratorType                           bit;
  ImageRegionIterator< TOutputImage >                     it;

  // Find the data-set boundary "faces"
  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< RealVectorImageType >::
  FaceListType faceList;
  NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< RealVectorImageType > bC;
  RadiusType r1;
  r1.Fill(1);
  faceList = bC(dynamic_cast< const RealVectorImageType * >( m_RealValuedInputImage.GetPointer() ),
                outputRegionForThread, r1);

  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< RealVectorImageType >::
  FaceListType::iterator fit;
  fit = faceList.begin();

  // Support progress methods/callbacks
  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() );

  // Process each of the data set faces.  The iterator is reinitialized on each
  // face so that it can determine whether or not to check for boundary
  // conditions.
  for ( fit = faceList.begin(); fit != faceList.end(); ++fit )
    {
    bit = ConstNeighborhoodIteratorType(r1,
                                        dynamic_cast< const RealVectorImageType * >( m_RealValuedInputImage.GetPointer() ),
                                        *fit);
    it = ImageRegionIterator< TOutputImage >(this->GetOutput(), *fit);
    bit.OverrideBoundaryCondition(&nbc);
    bit.GoToBegin();

    if ( m_UsePrincipleComponents == true )
      {
      if ( ImageDimension == 3 )
        { // Use the specialized eigensolve which can be threaded
        while ( !bit.IsAtEnd() )
          {
          it.Set( this->EvaluateAtNeighborhood3D(bit) );
          ++bit;
          ++it;
          progress.CompletedPixel();
          }
        }
      else
        {
        while ( !bit.IsAtEnd() )
          {
          it.Set( this->EvaluateAtNeighborhood(bit) );
          ++bit;
          ++it;
          progress.CompletedPixel();
          }
        }
      }
    else
      {
      while ( !bit.IsAtEnd() )
        {
        it.Set( this->NonPCEvaluateAtNeighborhood(bit) );
        ++bit;
        ++it;
        progress.CompletedPixel();
        }
      }
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
int
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::CubicSolver(double *c, double *s)
{
  // IMPORTANT
  // This code is specialized for particular case of positive symmetric
  // matrix.   It also assumes that x^3 coefficient is 1. c contains the
  // coefficients of the polynomial: x^3 + c[2]x^2 + c[1]x^1 + c[0].  The roots
  // s are not necessarily sorted, and int is the number of distinct roots
  // found in s.
  int          num;
  const double dpi = itk::Math::pi;
  const double epsilon = 1.0e-11;

  // Substitution of  x = y - c[2]/3 eliminate the quadric term  x^3 +px + q = 0
  double sq_c2 = c[2] * c[2];
  double p = 1.0 / 3 * ( -1.0 / 3.0 * sq_c2 + c[1] );
  double q = 1.0 / 2 * ( 2.0 / 27.0 * c[2] * sq_c2 - 1.0 / 3.0 * c[2] * c[1] + c[0] );

  // Cardano's formula
  double cb_p = p * p * p;
  double D = q * q + cb_p;

  if ( D < -epsilon ) // D < 0, three real solutions, by far the common case.
    {
    double phi = 1.0 / 3.0 * std::acos( -q / std::sqrt(-cb_p) );
    double t = 2.0 * std::sqrt(-p);

    s[0] =   t * std::cos(phi);
    s[1] = -t *std::cos(phi + dpi / 3);
    s[2] = -t *std::cos(phi - dpi / 3);
    num = 3;
    }

  else if ( D < epsilon ) // D == 0
    {
    if ( q > -epsilon && q < epsilon )
      {
      s[0] = 0.0;
      num = 1;
      }
    else
      {
      double u = itk::Math::cbrt(-q);
      s[0] = 2 * u;
      s[1] = -u;
      num = 2;
      }
    }
  else // Only one real solution. This case misses a double root on rare
       // occasions with very large char eqn coefficients.
    {
    double sqrt_D = std::sqrt(D);
    double u = itk::Math::cbrt(sqrt_D - q);
    double v = -itk::Math::cbrt(sqrt_D + q);

    s[0] = u + v;
    num = 1;
    }

  // Resubstitute
  double sub = 1.0 / 3.0 * c[2];

  for ( int i = 0; i < num; ++i )
    {
    s[i] -= sub;
    }

  return num;
}
} // end namespace itk

#endif
<commit_msg>DOC: PrincipleComponent flag incorrectly reported by PrintSelf<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkVectorGradientMagnitudeImageFilter_hxx
#define itkVectorGradientMagnitudeImageFilter_hxx

#include "itkVectorGradientMagnitudeImageFilter.h"

#include "itkNeighborhoodAlgorithm.h"
#include "itkImageRegionIterator.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"
#include "itkProgressReporter.h"
#include "itkVectorCastImageFilter.h"

#include "itkMath.h"

namespace itk
{
template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  unsigned i;

  Superclass::PrintSelf(os, indent);
  os << indent << "m_UseImageSpacing = "          << m_UseImageSpacing
     << std::endl;
  os << indent << "m_UsePrincipleComponents = "   << m_UsePrincipleComponents
     << std::endl;
  os << indent << "m_RequestedNumberOfThreads = " << m_RequestedNumberOfThreads
     << std::endl;
  os << indent << "m_DerivativeWeights = ";
  for ( i = 0; i < ImageDimension; i++ )
    {
    os << m_DerivativeWeights[i] << " ";
    }
  os << std::endl;
  os << indent << "m_ComponentWeights = ";
  for ( i = 0; i < VectorDimension; i++ )
    {
    os << m_ComponentWeights[i] << " ";
    }
  os << std::endl;
  os << indent << "m_RealValuedInputImage = "          << m_RealValuedInputImage.GetPointer()
     << std::endl;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::VectorGradientMagnitudeImageFilter()
{
  unsigned int i;

  m_UseImageSpacing = true;
  m_UsePrincipleComponents = true;
  m_RequestedNumberOfThreads = this->GetNumberOfThreads();
  for ( i = 0; i < ImageDimension; i++ )
    {
    m_DerivativeWeights[i] = static_cast< TRealType >( 1.0 );
    }
  for ( i = 0; i < VectorDimension; i++ )
    {
    m_ComponentWeights[i] = static_cast< TRealType >( 1.0 );
    m_SqrtComponentWeights[i] = static_cast< TRealType >( 1.0 );
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::SetUseImageSpacing(bool f)
{
  if ( m_UseImageSpacing == f ) { return; }

  // Only reset the weights if they were previously set to the image spacing,
  // otherwise, the user may have provided their own weightings.
  if ( f == false && m_UseImageSpacing == true )
    {
    for ( unsigned i = 0; i < ImageDimension; ++i )
      {
      m_DerivativeWeights[i] = static_cast< TRealType >( 1.0 );
      }
    }

  m_UseImageSpacing = f;
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::GenerateInputRequestedRegion()
{
  // call the superclass' implementation of this method
  Superclass::GenerateInputRequestedRegion();

  // get pointers to the input and output
  InputImagePointer inputPtr =
    const_cast< InputImageType * >( this->GetInput() );
  OutputImagePointer outputPtr = this->GetOutput();

  if ( !inputPtr || !outputPtr )
    {
    return;
    }

  // get a copy of the input requested region (should equal the output
  // requested region)
  typename TInputImage::RegionType inputRequestedRegion;
  inputRequestedRegion = inputPtr->GetRequestedRegion();

  RadiusType r1;
  r1.Fill(1);
  // pad the input requested region by the operator radius
  inputRequestedRegion.PadByRadius(r1);

  // crop the input requested region at the input's largest possible region
  if ( inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() ) )
    {
    inputPtr->SetRequestedRegion(inputRequestedRegion);
    return;
    }
  else
    {
    // Couldn't crop the region (requested region is outside the largest
    // possible region).  Throw an exception.

    // store what we tried to request (prior to trying to crop)
    inputPtr->SetRequestedRegion(inputRequestedRegion);

    // build an exception
    InvalidRequestedRegionError e(__FILE__, __LINE__);
    e.SetLocation(ITK_LOCATION);
    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
    e.SetDataObject(inputPtr);
    throw e;
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::BeforeThreadedGenerateData()
{
  Superclass::BeforeThreadedGenerateData();

  // Calculate the square-roots of the component weights.
  for ( unsigned i = 0; i < VectorDimension; ++i )
    {
    if ( m_ComponentWeights[i] < 0 )
      {
      itkExceptionMacro(<< "Component weights must be positive numbers");
      }
    m_SqrtComponentWeights[i] = std::sqrt(m_ComponentWeights[i]);
    }

  // Set the weights on the derivatives.
  // Are we using image spacing in the calculations?  If so we must update now
  // in case our input image has changed.
  if ( m_UseImageSpacing == true )
    {
    for ( unsigned i = 0; i < ImageDimension; i++ )
      {
      if ( static_cast< TRealType >( this->GetInput()->GetSpacing()[i] ) == 0.0 )
        {
        itkExceptionMacro(<< "Image spacing in dimension " << i << " is zero.");
        }
      m_DerivativeWeights[i] =
        static_cast< TRealType >( 1.0
                                  / static_cast< TRealType >( this->GetInput()->GetSpacing()[i] ) );
      }
    }

  // If using the principle components method, then force this filter to use a
  // single thread because vnl eigensystem objects are not thread-safe.  3D
  // data is ok because we have a special solver.
  if ( m_UsePrincipleComponents == true && ImageDimension != 3 )
    {
    m_RequestedNumberOfThreads = this->GetNumberOfThreads();
    this->SetNumberOfThreads(1);
    }
  else
    {
    this->SetNumberOfThreads(m_RequestedNumberOfThreads);
    }
  //
  // cast might not be necessary, but CastImagefilter is optimized for
  // the case where the InputImageType == OutputImageType
  typename VectorCastImageFilter< TInputImage, RealVectorImageType >::Pointer
    caster = VectorCastImageFilter< TInputImage, RealVectorImageType >::New();
  caster->SetInput( this->GetInput() );
  caster->GetOutput()->SetRequestedRegion( this->GetInput()->GetRequestedRegion() );
  caster->Update();
  m_RealValuedInputImage = caster->GetOutput();
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
void
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
                       ThreadIdType threadId)
{
  ZeroFluxNeumannBoundaryCondition< RealVectorImageType > nbc;
  ConstNeighborhoodIteratorType                           bit;
  ImageRegionIterator< TOutputImage >                     it;

  // Find the data-set boundary "faces"
  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< RealVectorImageType >::
  FaceListType faceList;
  NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< RealVectorImageType > bC;
  RadiusType r1;
  r1.Fill(1);
  faceList = bC(dynamic_cast< const RealVectorImageType * >( m_RealValuedInputImage.GetPointer() ),
                outputRegionForThread, r1);

  typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< RealVectorImageType >::
  FaceListType::iterator fit;
  fit = faceList.begin();

  // Support progress methods/callbacks
  ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels() );

  // Process each of the data set faces.  The iterator is reinitialized on each
  // face so that it can determine whether or not to check for boundary
  // conditions.
  for ( fit = faceList.begin(); fit != faceList.end(); ++fit )
    {
    bit = ConstNeighborhoodIteratorType(r1,
                                        dynamic_cast< const RealVectorImageType * >( m_RealValuedInputImage.GetPointer() ),
                                        *fit);
    it = ImageRegionIterator< TOutputImage >(this->GetOutput(), *fit);
    bit.OverrideBoundaryCondition(&nbc);
    bit.GoToBegin();

    if ( m_UsePrincipleComponents == true )
      {
      if ( ImageDimension == 3 )
        { // Use the specialized eigensolve which can be threaded
        while ( !bit.IsAtEnd() )
          {
          it.Set( this->EvaluateAtNeighborhood3D(bit) );
          ++bit;
          ++it;
          progress.CompletedPixel();
          }
        }
      else
        {
        while ( !bit.IsAtEnd() )
          {
          it.Set( this->EvaluateAtNeighborhood(bit) );
          ++bit;
          ++it;
          progress.CompletedPixel();
          }
        }
      }
    else
      {
      while ( !bit.IsAtEnd() )
        {
        it.Set( this->NonPCEvaluateAtNeighborhood(bit) );
        ++bit;
        ++it;
        progress.CompletedPixel();
        }
      }
    }
}

template< typename TInputImage, typename TRealType, typename TOutputImage >
int
VectorGradientMagnitudeImageFilter< TInputImage, TRealType, TOutputImage >
::CubicSolver(double *c, double *s)
{
  // IMPORTANT
  // This code is specialized for particular case of positive symmetric
  // matrix.   It also assumes that x^3 coefficient is 1. c contains the
  // coefficients of the polynomial: x^3 + c[2]x^2 + c[1]x^1 + c[0].  The roots
  // s are not necessarily sorted, and int is the number of distinct roots
  // found in s.
  int          num;
  const double dpi = itk::Math::pi;
  const double epsilon = 1.0e-11;

  // Substitution of  x = y - c[2]/3 eliminate the quadric term  x^3 +px + q = 0
  double sq_c2 = c[2] * c[2];
  double p = 1.0 / 3 * ( -1.0 / 3.0 * sq_c2 + c[1] );
  double q = 1.0 / 2 * ( 2.0 / 27.0 * c[2] * sq_c2 - 1.0 / 3.0 * c[2] * c[1] + c[0] );

  // Cardano's formula
  double cb_p = p * p * p;
  double D = q * q + cb_p;

  if ( D < -epsilon ) // D < 0, three real solutions, by far the common case.
    {
    double phi = 1.0 / 3.0 * std::acos( -q / std::sqrt(-cb_p) );
    double t = 2.0 * std::sqrt(-p);

    s[0] =   t * std::cos(phi);
    s[1] = -t *std::cos(phi + dpi / 3);
    s[2] = -t *std::cos(phi - dpi / 3);
    num = 3;
    }

  else if ( D < epsilon ) // D == 0
    {
    if ( q > -epsilon && q < epsilon )
      {
      s[0] = 0.0;
      num = 1;
      }
    else
      {
      double u = itk::Math::cbrt(-q);
      s[0] = 2 * u;
      s[1] = -u;
      num = 2;
      }
    }
  else // Only one real solution. This case misses a double root on rare
       // occasions with very large char eqn coefficients.
    {
    double sqrt_D = std::sqrt(D);
    double u = itk::Math::cbrt(sqrt_D - q);
    double v = -itk::Math::cbrt(sqrt_D + q);

    s[0] = u + v;
    num = 1;
    }

  // Resubstitute
  double sub = 1.0 / 3.0 * c[2];

  for ( int i = 0; i < num; ++i )
    {
    s[i] -= sub;
    }

  return num;
}
} // end namespace itk

#endif
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef itkVectorRescaleIntensityImageFilter_hxx
#define itkVectorRescaleIntensityImageFilter_hxx

#include "itkVectorRescaleIntensityImageFilter.h"
#include "itkImageRegionConstIterator.h"

namespace itk
{
/**
 *
 */
template< typename TInputImage, typename TOutputImage >
VectorRescaleIntensityImageFilter< TInputImage, TOutputImage >
::VectorRescaleIntensityImageFilter() :
  m_Scale(1.0),
  m_Shift(1.0),
  m_InputMaximumMagnitude(NumericTraits< InputRealType  >::ZeroValue()),
  m_OutputMaximumMagnitude(NumericTraits< OutputRealType >::ZeroValue())
{
}

/**
 *
 */
template< typename TInputImage, typename TOutputImage >
void
VectorRescaleIntensityImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Output Maximum Magnitude: "
     << static_cast< typename NumericTraits< OutputRealType >::PrintType >( m_OutputMaximumMagnitude )
     << std::endl;
  os << indent << "Input Maximum Magnitude: "
     << static_cast< typename NumericTraits< InputRealType >::PrintType >( m_InputMaximumMagnitude )
     << std::endl;
  os << indent << "Internal Scale : "
     << static_cast< typename NumericTraits< InputRealType >::PrintType >( m_Scale )
     << std::endl;
}

/**
 *
 */
template< typename TInputImage, typename TOutputImage >
void
VectorRescaleIntensityImageFilter< TInputImage, TOutputImage >
::BeforeThreadedGenerateData()
{
  if ( m_OutputMaximumMagnitude < NumericTraits< OutputRealType >::ZeroValue() )
    {
    itkExceptionMacro(<< "Maximum output value cannot be negative. You are passing " << m_OutputMaximumMagnitude);
    return;
    }

  InputImagePointer inputImage =   this->GetInput();

  typedef ImageRegionConstIterator< InputImageType > InputIterator;

  InputIterator it( inputImage, inputImage->GetBufferedRegion() );

  it.GoToBegin();

  InputRealType maximumSquaredMagnitude = NumericTraits< InputRealType >::ZeroValue();

  while ( !it.IsAtEnd() )
    {
    InputRealType magnitude = it.Get().GetSquaredNorm();
    if ( magnitude > maximumSquaredMagnitude )
      {
      maximumSquaredMagnitude = magnitude;
      }
    ++it;
    }

  m_InputMaximumMagnitude = std::sqrt(maximumSquaredMagnitude);

  m_Scale = static_cast< InputRealType >( m_OutputMaximumMagnitude )
            / static_cast< InputRealType >( m_InputMaximumMagnitude  );

  // set up the functor values
  this->GetFunctor().SetFactor(m_Scale);
}
} // end namespace itk

#endif
<commit_msg>ENH: Print missing ivar in filter PrintSelf method.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
/*=========================================================================
 *
 *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
 *
 *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
 *
 *  For complete copyright, license and disclaimer of warranty information
 *  please refer to the NOTICE file at the top of the ITK source tree.
 *
 *=========================================================================*/
#ifndef itkVectorRescaleIntensityImageFilter_hxx
#define itkVectorRescaleIntensityImageFilter_hxx

#include "itkVectorRescaleIntensityImageFilter.h"
#include "itkImageRegionConstIterator.h"

namespace itk
{
/**
 *
 */
template< typename TInputImage, typename TOutputImage >
VectorRescaleIntensityImageFilter< TInputImage, TOutputImage >
::VectorRescaleIntensityImageFilter() :
  m_Scale(1.0),
  m_Shift(1.0),
  m_InputMaximumMagnitude(NumericTraits< InputRealType  >::ZeroValue()),
  m_OutputMaximumMagnitude(NumericTraits< OutputRealType >::ZeroValue())
{
}

/**
 *
 */
template< typename TInputImage, typename TOutputImage >
void
VectorRescaleIntensityImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Output Maximum Magnitude: "
     << static_cast< typename NumericTraits< OutputRealType >::PrintType >( m_OutputMaximumMagnitude )
     << std::endl;
  os << indent << "Input Maximum Magnitude: "
     << static_cast< typename NumericTraits< InputRealType >::PrintType >( m_InputMaximumMagnitude )
     << std::endl;
  os << indent << "Internal Scale : "
     << static_cast< typename NumericTraits< InputRealType >::PrintType >( m_Scale )
     << std::endl;
  os << indent << "Internal Shift : "
     << static_cast< typename NumericTraits< InputRealType >::PrintType >( m_Shift )
     << std::endl;
}

/**
 *
 */
template< typename TInputImage, typename TOutputImage >
void
VectorRescaleIntensityImageFilter< TInputImage, TOutputImage >
::BeforeThreadedGenerateData()
{
  if ( m_OutputMaximumMagnitude < NumericTraits< OutputRealType >::ZeroValue() )
    {
    itkExceptionMacro(<< "Maximum output value cannot be negative. You are passing " << m_OutputMaximumMagnitude);
    return;
    }

  InputImagePointer inputImage =   this->GetInput();

  typedef ImageRegionConstIterator< InputImageType > InputIterator;

  InputIterator it( inputImage, inputImage->GetBufferedRegion() );

  it.GoToBegin();

  InputRealType maximumSquaredMagnitude = NumericTraits< InputRealType >::ZeroValue();

  while ( !it.IsAtEnd() )
    {
    InputRealType magnitude = it.Get().GetSquaredNorm();
    if ( magnitude > maximumSquaredMagnitude )
      {
      maximumSquaredMagnitude = magnitude;
      }
    ++it;
    }

  m_InputMaximumMagnitude = std::sqrt(maximumSquaredMagnitude);

  m_Scale = static_cast< InputRealType >( m_OutputMaximumMagnitude )
            / static_cast< InputRealType >( m_InputMaximumMagnitude  );

  // set up the functor values
  this->GetFunctor().SetFactor(m_Scale);
}
} // end namespace itk

#endif
<|endoftext|>


<commit_before>#include <node.h>
#include <node_buffer.h>
#include <string.h>
#include <stdlib.h>

#include "magic.h"

using namespace node;
using namespace v8;

struct Baton {
    uv_work_t request;
    Persistent<Function> callback;

    char* data;
    uint32_t dataLen;
    bool dataIsPath;

    // libmagic info
    const char* path;
    int flags;

    bool error;
    char* error_message;

    const char* result;
};

static Persistent<FunctionTemplate> constructor;
const char* fallbackPath;

struct magic_set* init_magic(const char* path, int mflags, char* err) {
  struct magic_set *magic = magic_open(mflags | MAGIC_NO_CHECK_COMPRESS);
  if (magic == NULL) {
    err = strdup(uv_strerror(uv_last_error(uv_default_loop())));
    return NULL;
  }
  if (magic_load(magic, NULL) == -1) {
    /* Use magic file contained in addon distribution as last resort */
    if (magic_load(magic, fallbackPath) == -1) {
      err = strdup(magic_error(magic));
      magic_close(magic);
      return NULL;
    }
  }
  return magic;
}

class Magic : public ObjectWrap {
  public:
    const char* mpath;
    int mflags;

    Magic(const char* path, int flags) {
      if (path != NULL) {
        /* Windows blows up trying to look up the path '(null)' returned by
           magic_getpath() */
        if (strncmp(path, "(null)", 6) == 0)
          path = NULL;
      }
      mpath = path;
      mflags = flags;
    }
    ~Magic() {
      if (mpath != NULL) {
        free((void*)mpath);
        mpath = NULL;
      }
    }

    static Handle<Value> New(const Arguments& args) {
      HandleScope scope;
#ifndef _WIN32
      int mflags = MAGIC_SYMLINK;
#else
      int mflags = MAGIC_NONE;
#endif
      char* path = NULL;

      if (!args.IsConstructCall()) {
        return ThrowException(Exception::TypeError(
            String::New("Use `new` to create instances of this object."))
        );
      }

      if (args.Length() > 0) {
        if (args[0]->IsString()) {
          String::Utf8Value str(args[0]->ToString());
          path = strdup((const char*)(*str));
        } else if (args[0]->IsInt32())
          mflags = args[0]->Int32Value();
        else {
          return ThrowException(Exception::TypeError(
              String::New("First argument must be a string or integer")));
        }
      }
      if (args.Length() > 1) {
        if (args[1]->IsInt32())
          mflags = args[1]->Int32Value();
        else {
          if (path)
            free(path);
          return ThrowException(Exception::TypeError(
              String::New("Second argument must be an integer")));
        }
      }

      Magic* obj = new Magic(magic_getpath(path, 0/*FILE_LOAD*/), mflags);
      obj->Wrap(args.This());

      return args.This();
    }

    static Handle<Value> DetectFile(const Arguments& args) {
      HandleScope scope;
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (!args[0]->IsString()) {
        return ThrowException(Exception::TypeError(
            String::New("First argument must be a string")));
      }
      if (!args[1]->IsFunction()) {
        return ThrowException(Exception::TypeError(
            String::New("Second argument must be a callback function")));
      }

      Local<Function> callback = Local<Function>::Cast(args[1]);

      String::Utf8Value str(args[0]->ToString());

      Baton* baton = new Baton();
      baton->error = false;
      baton->request.data = baton;
      baton->callback = Persistent<Function>::New(callback);
      baton->data = strdup((const char*)*str);
      baton->dataIsPath = true;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;

      int status = uv_queue_work(uv_default_loop(), &baton->request,
                                 Magic::DetectWork, Magic::DetectAfter);
      assert(status == 0);

      return Undefined();
    }

    static Handle<Value> Detect(const Arguments& args) {
      HandleScope scope;
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (args.Length() < 2) {
        return ThrowException(Exception::TypeError(
            String::New("Expecting 2 arguments")));
      }
      if (!Buffer::HasInstance(args[0])) {
        return ThrowException(Exception::TypeError(
            String::New("First argument must be a Buffer")));
      }
      if (!args[1]->IsFunction()) {
        return ThrowException(Exception::TypeError(
            String::New("Second argument must be a callback function")));
      }

      Local<Function> callback = Local<Function>::Cast(args[1]);
      Local<Object> buffer_obj = args[0]->ToObject();

      Baton* baton = new Baton();
      baton->error = false;
      baton->request.data = baton;
      baton->callback = Persistent<Function>::New(callback);
      baton->data = Buffer::Data(buffer_obj);
      baton->dataLen = Buffer::Length(buffer_obj);
      baton->dataIsPath = false;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;

      int status = uv_queue_work(uv_default_loop(), &baton->request,
                                 Magic::DetectWork, Magic::DetectAfter);
      assert(status == 0);

      return Undefined();
    }

    static void DetectWork(uv_work_t* req) {
      Baton* baton = static_cast<Baton*>(req->data);
      const char* result;

      struct magic_set* magic = init_magic(baton->path, baton->flags,
                                           baton->error_message);
      if (magic == NULL) {
        if (baton->error_message)
          baton->error = true;
        return;
      }

      if (baton->dataIsPath)
        result = magic_file(magic, baton->data);
      else
        result = magic_buffer(magic, (const void*)baton->data, baton->dataLen);

      if (result == NULL) {
        baton->error = true;
        baton->error_message = strdup(magic_error(magic));
      } else
        baton->result = strdup(result);

      magic_close(magic);
    }

    static void DetectAfter(uv_work_t* req) {
      HandleScope scope;
      Baton* baton = static_cast<Baton*>(req->data);

      if (baton->error) {
        Local<Value> err = Exception::Error(String::New(baton->error_message));
        free(baton->error_message);

        const unsigned argc = 1;
        Local<Value> argv[argc] = { err };

        TryCatch try_catch;
        baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);
        if (try_catch.HasCaught())
          FatalException(try_catch);
      } else {
        const unsigned argc = 2;
        Local<Value> argv[argc] = {
          Local<Value>::New(Null()),
          Local<Value>::New(String::New(baton->result))
        };

        free((void*)baton->result);

        TryCatch try_catch;
        baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);
        if (try_catch.HasCaught())
          FatalException(try_catch);
      }

      if (baton->dataIsPath)
        free(baton->data);
      baton->callback.Dispose();
      delete baton;
    }

    static Handle<Value> SetFallback(const Arguments& args) {
      HandleScope scope;

      if (fallbackPath)
        free((void*)fallbackPath);

      if (args.Length() > 0 && args[0]->IsString()
          && args[0]->ToString()->Length() > 0) {
        String::Utf8Value str(args[0]->ToString());
        fallbackPath = strdup((const char*)(*str));
      } else
        fallbackPath = NULL;

      return Undefined();
    }

    static void Initialize(Handle<Object> target) {
      HandleScope scope;

      Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
      Local<String> name = String::NewSymbol("Magic");

      constructor = Persistent<FunctionTemplate>::New(tpl);
      constructor->InstanceTemplate()->SetInternalFieldCount(1);
      constructor->SetClassName(name);

      NODE_SET_PROTOTYPE_METHOD(constructor, "detectFile", DetectFile);
      NODE_SET_PROTOTYPE_METHOD(constructor, "detect", Detect);
      target->Set(String::NewSymbol("setFallback"),
        FunctionTemplate::New(SetFallback)->GetFunction());

      target->Set(name, constructor->GetFunction());
    }
};

extern "C" {
  void init(Handle<Object> target) {
    HandleScope scope;
    Magic::Initialize(target);
  }

  NODE_MODULE(magic, init);
}
<commit_msg>Fix pointer errors<commit_after>#include <node.h>
#include <node_buffer.h>
#include <string.h>
#include <stdlib.h>

#include "magic.h"

using namespace node;
using namespace v8;

struct Baton {
    uv_work_t request;
    Persistent<Function> callback;

    char* data;
    uint32_t dataLen;
    bool dataIsPath;

    // libmagic info
    const char* path;
    int flags;

    bool error;
    char* error_message;

    const char* result;
};

static Persistent<FunctionTemplate> constructor;
static const char* fallbackPath;

class Magic : public ObjectWrap {
  public:
    const char* mpath;
    int mflags;

    Magic(const char* path, int flags) {
      if (path != NULL) {
        /* Windows blows up trying to look up the path '(null)' returned by
           magic_getpath() */
        if (strncmp(path, "(null)", 6) == 0)
          path = NULL;
      }
      mpath = (path == NULL ? strdup(fallbackPath) : path);
      mflags = flags;
    }
    ~Magic() {
      if (mpath != NULL) {
        free((void*)mpath);
        mpath = NULL;
      }
    }

    static Handle<Value> New(const Arguments& args) {
      HandleScope scope;
#ifndef _WIN32
      int mflags = MAGIC_SYMLINK;
#else
      int mflags = MAGIC_NONE;
#endif
      char* path = NULL;
      bool use_bundled = true;

      if (!args.IsConstructCall()) {
        return ThrowException(Exception::TypeError(
            String::New("Use `new` to create instances of this object."))
        );
      }

      if (args.Length() > 0) {
        if (args[0]->IsString()) {
          use_bundled = false;
          String::Utf8Value str(args[0]->ToString());
          path = strdup((const char*)(*str));
        } else if (args[0]->IsInt32())
          mflags = args[0]->Int32Value();
        else if (args[0]->IsBoolean() && !args[0]->BooleanValue()) {
          use_bundled = false;
          path = strdup(magic_getpath(NULL, 0/*FILE_LOAD*/));
        } else {
          return ThrowException(Exception::TypeError(
              String::New("First argument must be a string or integer")));
        }
      }
      if (args.Length() > 1) {
        if (args[1]->IsInt32())
          mflags = args[1]->Int32Value();
        else {
          if (path)
            free(path);
          return ThrowException(Exception::TypeError(
              String::New("Second argument must be an integer")));
        }
      }

      Magic* obj = new Magic((use_bundled ? NULL : path), mflags);
      obj->Wrap(args.This());
      obj->Ref();

      return args.This();
    }

    static Handle<Value> DetectFile(const Arguments& args) {
      HandleScope scope;
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (!args[0]->IsString()) {
        return ThrowException(Exception::TypeError(
            String::New("First argument must be a string")));
      }
      if (!args[1]->IsFunction()) {
        return ThrowException(Exception::TypeError(
            String::New("Second argument must be a callback function")));
      }

      Local<Function> callback = Local<Function>::Cast(args[1]);

      String::Utf8Value str(args[0]->ToString());

      Baton* baton = new Baton();
      baton->error = false;
      baton->error_message = NULL;
      baton->request.data = baton;
      baton->callback = Persistent<Function>::New(callback);
      baton->data = strdup((const char*)*str);
      baton->dataIsPath = true;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;

      int status = uv_queue_work(uv_default_loop(), &baton->request,
                                 Magic::DetectWork, Magic::DetectAfter);
      assert(status == 0);

      return Undefined();
    }

    static Handle<Value> Detect(const Arguments& args) {
      HandleScope scope;
      Magic* obj = ObjectWrap::Unwrap<Magic>(args.This());

      if (args.Length() < 2) {
        return ThrowException(Exception::TypeError(
            String::New("Expecting 2 arguments")));
      }
      if (!Buffer::HasInstance(args[0])) {
        return ThrowException(Exception::TypeError(
            String::New("First argument must be a Buffer")));
      }
      if (!args[1]->IsFunction()) {
        return ThrowException(Exception::TypeError(
            String::New("Second argument must be a callback function")));
      }

      Local<Function> callback = Local<Function>::Cast(args[1]);
      Local<Object> buffer_obj = args[0]->ToObject();

      Baton* baton = new Baton();
      baton->error = false;
      baton->error_message = NULL;
      baton->request.data = baton;
      baton->callback = Persistent<Function>::New(callback);
      baton->data = Buffer::Data(buffer_obj);
      baton->dataLen = Buffer::Length(buffer_obj);
      baton->dataIsPath = false;
      baton->path = obj->mpath;
      baton->flags = obj->mflags;

      int status = uv_queue_work(uv_default_loop(), &baton->request,
                                 Magic::DetectWork, Magic::DetectAfter);
      assert(status == 0);

      return Undefined();
    }

    static void DetectWork(uv_work_t* req) {
      Baton* baton = static_cast<Baton*>(req->data);
      const char* result;
      struct magic_set *magic = magic_open(baton->flags | MAGIC_NO_CHECK_COMPRESS);

      if (magic == NULL) {
        baton->error_message = strdup(uv_strerror(
                                        uv_last_error(uv_default_loop())));
      } else if (magic_load(magic, baton->path) == -1
                 && magic_load(magic, fallbackPath) == -1) {
        baton->error_message = strdup(magic_error(magic));
        magic_close(magic);
      }

      if (magic == NULL) {
        if (baton->error_message)
          baton->error = true;
        return;
      }

      if (baton->dataIsPath)
        result = magic_file(magic, baton->data);
      else
        result = magic_buffer(magic, (const void*)baton->data, baton->dataLen);

      if (result == NULL) {
        baton->error = true;
        baton->error_message = strdup(magic_error(magic));
      } else
        baton->result = strdup(result);

      magic_close(magic);
    }

    static void DetectAfter(uv_work_t* req) {
      HandleScope scope;
      Baton* baton = static_cast<Baton*>(req->data);

      if (baton->error) {
        Local<Value> err = Exception::Error(String::New(baton->error_message));
        free(baton->error_message);

        const unsigned argc = 1;
        Local<Value> argv[argc] = { err };

        TryCatch try_catch;
        baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);
        if (try_catch.HasCaught())
          FatalException(try_catch);
      } else {
        const unsigned argc = 2;
        Local<Value> argv[argc] = {
          Local<Value>::New(Null()),
          Local<Value>::New(String::New(baton->result))
        };

        free((void*)baton->result);

        TryCatch try_catch;
        baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);
        if (try_catch.HasCaught())
          FatalException(try_catch);
      }

      if (baton->dataIsPath)
        free(baton->data);
      baton->callback.Dispose();
      delete baton;
    }

    static Handle<Value> SetFallback(const Arguments& args) {
      HandleScope scope;

      if (fallbackPath)
        free((void*)fallbackPath);

      if (args.Length() > 0 && args[0]->IsString()
          && args[0]->ToString()->Length() > 0) {
        String::Utf8Value str(args[0]->ToString());
        fallbackPath = strdup((const char*)(*str));
      } else
        fallbackPath = NULL;

      return Undefined();
    }

    static void Initialize(Handle<Object> target) {
      HandleScope scope;

      Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
      Local<String> name = String::NewSymbol("Magic");

      constructor = Persistent<FunctionTemplate>::New(tpl);
      constructor->InstanceTemplate()->SetInternalFieldCount(1);
      constructor->SetClassName(name);

      NODE_SET_PROTOTYPE_METHOD(constructor, "detectFile", DetectFile);
      NODE_SET_PROTOTYPE_METHOD(constructor, "detect", Detect);
      target->Set(String::NewSymbol("setFallback"),
        FunctionTemplate::New(SetFallback)->GetFunction());

      target->Set(name, constructor->GetFunction());
    }
};

extern "C" {
  void init(Handle<Object> target) {
    HandleScope scope;
    Magic::Initialize(target);
  }

  NODE_MODULE(magic, init);
}
<|endoftext|>


<commit_before>#include "manip.h"

using namespace std;

// Manipulator stuff is _always_ in namespace mysqlpp.
namespace mysqlpp {

bool dont_quote_auto = false;

// quote manipulator

SQLQueryParms& operator <<(quote_type2 p, SQLString& in)
{
	if (in.is_string) {
		if (in.dont_escape) {
			SQLString in2 = "'" + in + "'";
			 in2.processed = true;
			 return *p.qparms << in2;
		}
		else {
			char *s = new char[in.size() * 2 + 1];
			mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
			SQLString in2 = SQLString("'") + s + "'";
			in2.processed = true;
			*p.qparms << in2;
			delete[]s;
			return *p.qparms;
		}
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(quote_type1 o, const string& in)
{
	char *s = new char[in.size() * 2 + 1];
	mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
	*o.ostr << "'" << s << "'";
	delete[] s;
	return *o.ostr;
}

template<>
ostream& operator<<(quote_type1 o, const char* const& in)
{
	unsigned int size;
	for (size = 0; in[size]; size++) ;
	char *s = new char[size * 2 + 1];
	mysql_escape_string(s, const_cast < char *>(in), size);
	*o.ostr << "'" << s << "'";
	delete[] s;
	return *o.ostr;
}

template<class Str>
inline ostream& _manip(quote_type1 o, const ColData_Tmpl<Str>& in)
{
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
		if (in.quote_q())
			*o.ostr << "'" << s << "'";
		else
			*o.ostr << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(quote_type1 o, const ColData_Tmpl<string>& in)
{
	return _manip(o, in);
}

template<>
ostream& operator<<(quote_type1 o, const ColData_Tmpl<const_string>& in)
{
	return _manip(o, in);
}

ostream& operator<<(ostream& o, const ColData_Tmpl<string>& in)
{
	if (dont_quote_auto || (o.rdbuf() == cout.rdbuf()) ||
			(o.rdbuf() == cerr.rdbuf())) {
		return o << in.get_string();
	}

	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
		if (in.quote_q())
			o << "'" << s << "'";
		else
			o << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		o << "'" << in.get_string() << "'";
	}
	else {
		o << in.get_string();
	}
	return o;
}

ostream& operator<<(ostream& o, const ColData_Tmpl<const_string>& in)
{
	if (dont_quote_auto || (o.rdbuf() == cout.rdbuf()) ||
			(o.rdbuf() == cerr.rdbuf())) {
		return o << in.get_string();
	}

	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, const_cast < char *>(in.c_str()),
							in.size());
		if (in.quote_q())
			o << "'" << s << "'";
		else
			o << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		o << "'" << in.get_string() << "'";
	}
	else {
		o << in.get_string();
	}
	return o;
}

SQLQuery& operator<<(SQLQuery& o, const ColData_Tmpl<string>& in)
{
	if (dont_quote_auto) {
		o << in.get_string();
		return o;
	}
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
		if (in.quote_q())
			static_cast<ostream &>(o) << "'" << s << "'";
		else
			static_cast<ostream &>(o) << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		static_cast<ostream &>(o) << "'" << in.get_string() << "'";
	}
	else {
		static_cast<ostream &>(o) << in.get_string();
	}
	return o;
}

SQLQuery& operator<<(SQLQuery& o, const ColData_Tmpl<const_string>& in)
{
	if (dont_quote_auto) {
		o << in.get_string();
		return o;
	}
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, const_cast < char *>(in.c_str()),
							in.size());
		if (in.quote_q())
			static_cast<ostream &>(o) << "'" << s << "'";
		else
			static_cast<ostream &>(o) << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		static_cast<ostream &>(o) << "'" << in.get_string() << "'";
	}
	else {
		static_cast<ostream &>(o) << in.get_string();
	}
	return o;
}

// quote only manipulator

SQLQueryParms& operator<<(quote_only_type2 p, SQLString& in)
{
	if (in.is_string) {
		SQLString in2 = "'" + in + "'";
		in2.processed = true;
		return *p.qparms << in2;
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(quote_only_type1 o, const ColData_Tmpl<string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(quote_only_type1 o,
		const ColData_Tmpl<const_string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

// quote double only manipulator

SQLQueryParms& operator<<(quote_double_only_type2 p, SQLString& in)
{
	if (in.is_string) {
		SQLString in2 = "\"" + in + "\"";
		in2.processed = true;
		return *p.qparms << in2;
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(quote_double_only_type1 o,
		const ColData_Tmpl<string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(quote_double_only_type1 o,
		const ColData_Tmpl<const_string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

// escape manipulator

SQLQueryParms& operator<<(escape_type2 p, SQLString& in)
{
	if (in.is_string) {
		if (in.dont_escape) {
			in.processed = true;
			return *p.qparms << in;
		}
		else {
			char *s = new char[in.size() * 2 + 1];
			mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
			SQLString in2 = s;
			in2.processed = true;
			*p.qparms << in2;
			delete[] s;
			return *p.qparms;
		}
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(escape_type1 o, const string& in)
{
	char *s = new char[in.size() * 2 + 1];
	mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
	*o.ostr << s;
	delete[] s;
	return *o.ostr;
}

template<>
ostream& operator<<(escape_type1 o, const char* const& in)
{
	unsigned int size;
	for (size = 0; in[size]; size++) ;
	char *s = new char[size * 2 + 1];
	mysql_escape_string(s, const_cast < char *>(in), size);
	*o.ostr << s;
	delete[] s;
	return *o.ostr;
}

template<class Str>
inline ostream& _manip(escape_type1 o, const ColData_Tmpl<Str>& in)
{
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), (unsigned long)in.size());
		delete[] s;
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(escape_type1 o, const ColData_Tmpl<string>& in)
{
	return _manip(o, in);
}

template<>
ostream& operator<<(escape_type1 o, const ColData_Tmpl<const_string>& in)
{
	return _manip(o, in);
}

} // end namespace mysqlpp

<commit_msg>Changed some C-style casts to static_casts to avoid GCC 4 warnings.<commit_after>#include "manip.h"

using namespace std;

// Manipulator stuff is _always_ in namespace mysqlpp.
namespace mysqlpp {

bool dont_quote_auto = false;

// quote manipulator

SQLQueryParms& operator <<(quote_type2 p, SQLString& in)
{
	if (in.is_string) {
		if (in.dont_escape) {
			SQLString in2 = "'" + in + "'";
			 in2.processed = true;
			 return *p.qparms << in2;
		}
		else {
			char *s = new char[in.size() * 2 + 1];
			mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
			SQLString in2 = SQLString("'") + s + "'";
			in2.processed = true;
			*p.qparms << in2;
			delete[]s;
			return *p.qparms;
		}
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(quote_type1 o, const string& in)
{
	char *s = new char[in.size() * 2 + 1];
	mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
	*o.ostr << "'" << s << "'";
	delete[] s;
	return *o.ostr;
}

template<>
ostream& operator<<(quote_type1 o, const char* const& in)
{
	unsigned int size;
	for (size = 0; in[size]; size++) ;
	char *s = new char[size * 2 + 1];
	mysql_escape_string(s, const_cast < char *>(in), size);
	*o.ostr << "'" << s << "'";
	delete[] s;
	return *o.ostr;
}

template<class Str>
inline ostream& _manip(quote_type1 o, const ColData_Tmpl<Str>& in)
{
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
		if (in.quote_q())
			*o.ostr << "'" << s << "'";
		else
			*o.ostr << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(quote_type1 o, const ColData_Tmpl<string>& in)
{
	return _manip(o, in);
}

template<>
ostream& operator<<(quote_type1 o, const ColData_Tmpl<const_string>& in)
{
	return _manip(o, in);
}

ostream& operator<<(ostream& o, const ColData_Tmpl<string>& in)
{
	if (dont_quote_auto || (o.rdbuf() == cout.rdbuf()) ||
			(o.rdbuf() == cerr.rdbuf())) {
		return o << in.get_string();
	}

	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
		if (in.quote_q())
			o << "'" << s << "'";
		else
			o << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		o << "'" << in.get_string() << "'";
	}
	else {
		o << in.get_string();
	}
	return o;
}

ostream& operator<<(ostream& o, const ColData_Tmpl<const_string>& in)
{
	if (dont_quote_auto || (o.rdbuf() == cout.rdbuf()) ||
			(o.rdbuf() == cerr.rdbuf())) {
		return o << in.get_string();
	}

	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, const_cast < char *>(in.c_str()),
							in.size());
		if (in.quote_q())
			o << "'" << s << "'";
		else
			o << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		o << "'" << in.get_string() << "'";
	}
	else {
		o << in.get_string();
	}
	return o;
}

SQLQuery& operator<<(SQLQuery& o, const ColData_Tmpl<string>& in)
{
	if (dont_quote_auto) {
		o << in.get_string();
		return o;
	}
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
		if (in.quote_q())
			static_cast<ostream &>(o) << "'" << s << "'";
		else
			static_cast<ostream &>(o) << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		static_cast<ostream &>(o) << "'" << in.get_string() << "'";
	}
	else {
		static_cast<ostream &>(o) << in.get_string();
	}
	return o;
}

SQLQuery& operator<<(SQLQuery& o, const ColData_Tmpl<const_string>& in)
{
	if (dont_quote_auto) {
		o << in.get_string();
		return o;
	}
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, const_cast < char *>(in.c_str()),
							in.size());
		if (in.quote_q())
			static_cast<ostream &>(o) << "'" << s << "'";
		else
			static_cast<ostream &>(o) << s;
		delete[] s;
	}
	else if (in.quote_q()) {
		static_cast<ostream &>(o) << "'" << in.get_string() << "'";
	}
	else {
		static_cast<ostream &>(o) << in.get_string();
	}
	return o;
}

// quote only manipulator

SQLQueryParms& operator<<(quote_only_type2 p, SQLString& in)
{
	if (in.is_string) {
		SQLString in2 = "'" + in + "'";
		in2.processed = true;
		return *p.qparms << in2;
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(quote_only_type1 o, const ColData_Tmpl<string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(quote_only_type1 o,
		const ColData_Tmpl<const_string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

// quote double only manipulator

SQLQueryParms& operator<<(quote_double_only_type2 p, SQLString& in)
{
	if (in.is_string) {
		SQLString in2 = "\"" + in + "\"";
		in2.processed = true;
		return *p.qparms << in2;
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(quote_double_only_type1 o,
		const ColData_Tmpl<string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(quote_double_only_type1 o,
		const ColData_Tmpl<const_string>& in)
{
	if (in.quote_q()) {
		*o.ostr << "'" << in << "'";
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

// escape manipulator

SQLQueryParms& operator<<(escape_type2 p, SQLString& in)
{
	if (in.is_string) {
		if (in.dont_escape) {
			in.processed = true;
			return *p.qparms << in;
		}
		else {
			char *s = new char[in.size() * 2 + 1];
			mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
			SQLString in2 = s;
			in2.processed = true;
			*p.qparms << in2;
			delete[] s;
			return *p.qparms;
		}
	}
	else {
		in.processed = true;
		return *p.qparms << in;
	}
}

template<>
ostream& operator<<(escape_type1 o, const string& in)
{
	char *s = new char[in.size() * 2 + 1];
	mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
	*o.ostr << s;
	delete[] s;
	return *o.ostr;
}

template<>
ostream& operator<<(escape_type1 o, const char* const& in)
{
	unsigned int size;
	for (size = 0; in[size]; size++) ;
	char *s = new char[size * 2 + 1];
	mysql_escape_string(s, const_cast < char *>(in), size);
	*o.ostr << s;
	delete[] s;
	return *o.ostr;
}

template<class Str>
inline ostream& _manip(escape_type1 o, const ColData_Tmpl<Str>& in)
{
	if (in.escape_q()) {
		char *s = new char[in.size() * 2 + 1];
		mysql_escape_string(s, in.c_str(), static_cast <unsigned long> (in.size()));
		delete[] s;
	}
	else {
		*o.ostr << in;
	}
	return *o.ostr;
}

template<>
ostream& operator<<(escape_type1 o, const ColData_Tmpl<string>& in)
{
	return _manip(o, in);
}

template<>
ostream& operator<<(escape_type1 o, const ColData_Tmpl<const_string>& in)
{
	return _manip(o, in);
}

} // end namespace mysqlpp

<|endoftext|>


<commit_before>#include "memory.h"
#include "../phasor-lua.hpp"
#include <cstdint>
#include <array>
#include <Windows.h>

#undef min
#undef max

void readData(lua_State* L, void* dest, void* src, size_t nbytes) {
    DWORD oldProtect = 0;
    if (VirtualProtect(src, nbytes, PAGE_EXECUTE_READ, &oldProtect)) {
        memcpy(dest, src, nbytes);
        VirtualProtect(src, nbytes, oldProtect, &oldProtect);
    } else {
        auto f = boost::format("invalid read: %u bytes from 0x%08X") % nbytes % src;
        luaL_error(L, "%s", f.str().c_str());
    }
}

void writeData(lua_State* L, void* dest, const void* src, size_t nbytes) {
    DWORD oldProtect = 0;
    if (VirtualProtect(dest, nbytes, PAGE_EXECUTE_READWRITE, &oldProtect)) {
        memcpy(dest, src, nbytes);
        VirtualProtect(dest, nbytes, oldProtect, &oldProtect);
    } else {
        auto f = boost::format("invalid write: %u bytes from 0x%08X") % nbytes % src;
        luaL_error(L, "%s", f.str().c_str());
    }
}

template <typename T>
bool checkLimits(double value, T& out) {
    static const T max_value = std::numeric_limits<T>::max();
    static const T min_value = std::numeric_limits<T>::lowest();
    if (value <= max_value && value >= min_value) {
        out = static_cast<T>(value);
        return true;
    } else {
        return false;
    }
}

size_t addBitOffset(size_t x, int& offset) {
    x += offset / 8;
    offset %= 8;
    return x;
}

// --------------------------------------------------------

int l_readbit(lua_State* L) {
    size_t address;
    int bitOffset;

    if (lua_gettop(L) == 3) {
        // legacy: three args mean address, address_offset, bit_offset
        int addrOffset;
        std::tie(address, addrOffset, bitOffset) = phlua::callback::getArguments<size_t, int, int>(L, __FUNCTION__);
        address += addrOffset;
    } else {
        std::tie(address, bitOffset) = phlua::callback::getArguments<size_t, int>(L, __FUNCTION__);
    }

    address = addBitOffset(address, bitOffset);

    std::uint8_t b;
    readData(L, &b, (void*)address, sizeof(b));
    bool bit = (b & (1 << bitOffset)) != 0;

    return phlua::callback::pushReturns(L, std::make_tuple(bit));
}

int l_writebit(lua_State* L) {
    size_t address;
    int bitOffset;
    bool value;

    if (lua_gettop(L) == 4) {
        int addrOffset;
        // legacy: four args mean address, address_offset, bit_offset, value
        std::tie(address, addrOffset, bitOffset, value) = phlua::callback::getArguments<size_t, int, int, bool>(L, __FUNCTION__);
        address += addrOffset;
    } else {
        std::tie(address, bitOffset, value) = phlua::callback::getArguments<size_t, int, bool>(L, __FUNCTION__);
    }

    address = addBitOffset(address, bitOffset);

    std::uint8_t b;
    readData(L, &b, (void*)address, sizeof(b));
    if (value) b |= 1 << bitOffset;
    else b &= ~(1 << bitOffset);
    writeData(L, (void*)address, &b, sizeof(b));

    return 0;
}

// --------------------------------------------------------

template <typename T>
int readNumber(lua_State* L, const char* f) {
    size_t address;
    boost::optional<size_t> offset; // backwards compatibility

    std::tie(address, offset) = phlua::callback::getArguments<size_t, decltype(offset)>(L, f);

    if (offset) address += *offset;

    T x;
    readData(L, &x, (void*)address, sizeof(T));

    return phlua::callback::pushReturns(L, std::make_tuple(x));
}

int l_readbyte(lua_State* L) {
    return readNumber<std::uint8_t>(L, __FUNCTION__);
}

int l_readchar(lua_State* L) {
    return readNumber<std::int8_t>(L, __FUNCTION__);
}

int l_readword(lua_State* L) {
    return readNumber<std::uint16_t>(L, __FUNCTION__);
}

int l_readshort(lua_State* L) {
    return readNumber<std::int16_t>(L, __FUNCTION__);
}

int l_readdword(lua_State* L) {
    return readNumber<std::uint32_t>(L, __FUNCTION__);
}

int l_readint(lua_State* L) {
    return readNumber<std::int32_t>(L, __FUNCTION__);
}

int l_readfloat(lua_State* L) {
    return readNumber<float>(L, __FUNCTION__);
}

int l_readdouble(lua_State* L) {
    return readNumber<double>(L, __FUNCTION__);
}

// --------------------------------------------------------

template <typename T>
int writeNumber(lua_State* L, const char* f) {
    size_t address;
    lua_Number value;

    if (lua_gettop(L) == 3) { // backwards compatibility
        // address, offset, value
        int offset;
        std::tie(address, offset, value) = phlua::callback::getArguments<size_t, int, lua_Number>(L, f);
        address += offset;
    } else {
        std::tie(address, value) = phlua::callback::getArguments<size_t, lua_Number>(L, f);
    }

    T x;
    if (!checkLimits<T>(value, x)) {
        auto f = boost::format("invalid write: value (%.0f) outside of type's range") % value;
        luaL_error(L, "%s", f.str().c_str());
    }

    writeData(L, (void*)address, &x, sizeof(T));
    return 0;
}

int l_writebyte(lua_State* L) {
    return writeNumber<std::uint8_t>(L, __FUNCTION__);
}

int l_writechar(lua_State* L) {
    return writeNumber<std::int8_t>(L, __FUNCTION__);
}

int l_writeword(lua_State* L) {
    return writeNumber<std::uint16_t>(L, __FUNCTION__);
}

int l_writeshort(lua_State* L) {
    return writeNumber<std::int16_t>(L, __FUNCTION__);
}

int l_writedword(lua_State* L) {
    return writeNumber<std::uint32_t>(L, __FUNCTION__);
}

int l_writeint(lua_State* L) {
    return writeNumber<std::int32_t>(L, __FUNCTION__);
}

int l_writefloat(lua_State* L) {
    return writeNumber<float>(L, __FUNCTION__);
}

int l_writedouble(lua_State* L) {
    return writeNumber<double>(L, __FUNCTION__);
}

// --------------------------------------------------------

static const size_t kMaxStringElements = 160;

template <typename T>
int readstring(lua_State* L, const char* f) {
    size_t address;
    boost::optional<unsigned int> length;
    std::array<T, kMaxStringElements+1> dest;

    std::tie(address, length) = phlua::callback::getArguments<size_t, decltype(length)>(L, f);

    size_t readLength = kMaxStringElements;
    if (length) {
        if (length > kMaxStringElements) {
            auto f = boost::format("can only read strings to a maximum size of %u characters") % kMaxStringElements;
            luaL_argerror(L, 2, f.str().c_str());
        }
        readLength = *length;
    }

    readData(L, dest.data(), (void*)address, readLength*sizeof(T));
    dest[readLength] = 0; // ensure it's null terminated

    return phlua::callback::pushReturns(L, std::make_tuple(dest.data()));
}

int l_readstring(lua_State* L) {
    return readstring<char>(L, __FUNCTION__);
}

int l_readwidestring(lua_State* L) {
    return readstring<wchar_t>(L, __FUNCTION__);
}

// --------------------------------------------------------

template <typename StrType>
int writestring(lua_State* L, const char* f) {
    typedef typename StrType::value_type char_type;
    size_t address;
    boost::optional<size_t> offset;
    StrType s;

    if (lua_gettop(L) == 3) { // backwards compatibility
        std::tie(address, offset, s) = phlua::callback::getArguments<size_t, decltype(offset), StrType>(L, f);
    } else {
        std::tie(address, s) = phlua::callback::getArguments<size_t, StrType>(L, f);
    }

    if (offset) address += *offset;

    size_t byteLength = s.size() * sizeof(char_type);
    writeData(L, (void*)address, s.c_str(), byteLength);
    char_type nullChar = 0;
    writeData(L, (void*)(address + byteLength), &nullChar, sizeof(nullChar));
    return 0;
}

int l_writestring(lua_State* L) {
    return writestring<std::string>(L, __FUNCTION__);
}

int l_writewidestring(lua_State* L) {
    return writestring<std::wstring>(L, __FUNCTION__);
}

struct SigUnit {
    uint8_t x;
    enum class Mode {
        NORMAL, WILDCARD, WILDCARD_HIGH, WILDCARD_LOW
    } mode;

};

uint8_t hex_to_int(char c) {
    c = tolower(c);
    if (c >= 'a' && c <= 'f') {
        return 10 + c - 'a';
    } else {
        return c - '0';
    }
}
// sig code in Addresses is really bad, so i'll just rewrite it...
// sig should conform to ([A-Fa-f0-9?][A-Fa-f0-9?])+
// returns absolute address
uint8_t* sigscan(const std::string& sig, int occurance) {
    // should refactor this, but for now a copy/paste works...
    uint8_t* module = (uint8_t*)GetModuleHandle(0);
    unsigned int OffsetToPE = *(unsigned int*)(module + 0x3C);
    unsigned int codeSize = *(unsigned int*)(module + OffsetToPE + 0x1C);
    unsigned int BaseOfCode = *(unsigned int*)(module + OffsetToPE + 0x2C);
    uint8_t* codeSection = (uint8_t*)(module + BaseOfCode);

    if (sig.size() % 2) return 0;

    // convert sig to byte values
    std::vector<SigUnit> bytes;
    bytes.reserve(sig.size() % 2);
    for (size_t x = 0; x < sig.size(); x += 2) {
        SigUnit unit;
        if (sig[x] == '?') {
            if (sig[x+1] == '?') {
                unit.mode = SigUnit::Mode::WILDCARD;
            } else {
                unit.mode = SigUnit::Mode::WILDCARD_HIGH;
                unit.x = hex_to_int(sig[x+1]);
            }
        } else if (sig[x+1] == '?') {
            unit.mode = SigUnit::Mode::WILDCARD_LOW;
            unit.x = hex_to_int(sig[x]);
        } else {
            unit.mode = SigUnit::Mode::NORMAL;
            unit.x = hex_to_int(sig[x]) << 4 | hex_to_int(sig[x+1]);
        }
        bytes.push_back(unit);
    }

    // todo: should probably use knp or something
    unsigned int found = 0;
    for (unsigned int x = 0; x < codeSize; x++) {
        unsigned int length = std::min(codeSize - x, bytes.size());
        for (unsigned int i = 0; i < length; i++) {
            uint8_t b = codeSection[x+i];
            bool match = true;

            switch (bytes[i].mode) {
            case SigUnit::Mode::WILDCARD:
                // nothing to do
                break;
            case SigUnit::Mode::WILDCARD_HIGH:
                // ?x
                match = (b & 0x0F) == bytes[i].x;
                break;
            case SigUnit::Mode::WILDCARD_LOW:
                // x?
                match = (b & 0xF0) == bytes[i].x;
                break;
            default:
                match = b == bytes[i].x;
                break;
            }

            if (match) {
                if (i + 1 == bytes.size()) {
                    if (found++ == occurance)
                        return codeSection + x;
                }
            } else
                break;
        }
    }

    return 0;
}

bool ishex(char c) {
    c = tolower(c);
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
}

int l_findsig(lua_State* L) {
    std::string sig;
    boost::optional<int> occurance;

    std::tie(sig, occurance) = phlua::callback::getArguments<std::string, decltype(occurance)>(L, __FUNCTION__);

    if (!occurance)
        occurance = 0;

    if (sig.length() == 0) {
        luaL_argerror(L, 1, "empty signature");
    }

    for (auto c : sig) {
        if (c != '?' && !ishex(c))
            luaL_argerror(L, 1, "signature can only contain hexadecimal or ? characters");
    }

    // If only part of a byte is specified, treat the next as a wildcard
    if (sig.length() % 2) {
        sig.append("?");
    }

    uint8_t* mem = sigscan(sig, *occurance);
    if (mem) {
        return phlua::callback::pushReturns(L, std::make_tuple((unsigned int)mem));
    } else {
        return phlua::callback::pushReturns(L, std::make_tuple(lua::types::Nil()));
    }
}<commit_msg>Basic caching for findsig<commit_after>#include "memory.h"
#include "../phasor-lua.hpp"
#include <cstdint>
#include <array>
#include <Windows.h>
#include <unordered_map>

#undef min
#undef max

void readData(lua_State* L, void* dest, void* src, size_t nbytes) {
    DWORD oldProtect = 0;
    if (VirtualProtect(src, nbytes, PAGE_EXECUTE_READ, &oldProtect)) {
        memcpy(dest, src, nbytes);
        VirtualProtect(src, nbytes, oldProtect, &oldProtect);
    } else {
        auto f = boost::format("invalid read: %u bytes from 0x%08X") % nbytes % src;
        luaL_error(L, "%s", f.str().c_str());
    }
}

void writeData(lua_State* L, void* dest, const void* src, size_t nbytes) {
    DWORD oldProtect = 0;
    if (VirtualProtect(dest, nbytes, PAGE_EXECUTE_READWRITE, &oldProtect)) {
        memcpy(dest, src, nbytes);
        VirtualProtect(dest, nbytes, oldProtect, &oldProtect);
    } else {
        auto f = boost::format("invalid write: %u bytes from 0x%08X") % nbytes % src;
        luaL_error(L, "%s", f.str().c_str());
    }
}

template <typename T>
bool checkLimits(double value, T& out) {
    static const T max_value = std::numeric_limits<T>::max();
    static const T min_value = std::numeric_limits<T>::lowest();
    if (value <= max_value && value >= min_value) {
        out = static_cast<T>(value);
        return true;
    } else {
        return false;
    }
}

size_t addBitOffset(size_t x, int& offset) {
    x += offset / 8;
    offset %= 8;
    return x;
}

// --------------------------------------------------------

int l_readbit(lua_State* L) {
    size_t address;
    int bitOffset;

    if (lua_gettop(L) == 3) {
        // legacy: three args mean address, address_offset, bit_offset
        int addrOffset;
        std::tie(address, addrOffset, bitOffset) = phlua::callback::getArguments<size_t, int, int>(L, __FUNCTION__);
        address += addrOffset;
    } else {
        std::tie(address, bitOffset) = phlua::callback::getArguments<size_t, int>(L, __FUNCTION__);
    }

    address = addBitOffset(address, bitOffset);

    std::uint8_t b;
    readData(L, &b, (void*)address, sizeof(b));
    bool bit = (b & (1 << bitOffset)) != 0;

    return phlua::callback::pushReturns(L, std::make_tuple(bit));
}

int l_writebit(lua_State* L) {
    size_t address;
    int bitOffset;
    bool value;

    if (lua_gettop(L) == 4) {
        int addrOffset;
        // legacy: four args mean address, address_offset, bit_offset, value
        std::tie(address, addrOffset, bitOffset, value) = phlua::callback::getArguments<size_t, int, int, bool>(L, __FUNCTION__);
        address += addrOffset;
    } else {
        std::tie(address, bitOffset, value) = phlua::callback::getArguments<size_t, int, bool>(L, __FUNCTION__);
    }

    address = addBitOffset(address, bitOffset);

    std::uint8_t b;
    readData(L, &b, (void*)address, sizeof(b));
    if (value) b |= 1 << bitOffset;
    else b &= ~(1 << bitOffset);
    writeData(L, (void*)address, &b, sizeof(b));

    return 0;
}

// --------------------------------------------------------

template <typename T>
int readNumber(lua_State* L, const char* f) {
    size_t address;
    boost::optional<size_t> offset; // backwards compatibility

    std::tie(address, offset) = phlua::callback::getArguments<size_t, decltype(offset)>(L, f);

    if (offset) address += *offset;

    T x;
    readData(L, &x, (void*)address, sizeof(T));

    return phlua::callback::pushReturns(L, std::make_tuple(x));
}

int l_readbyte(lua_State* L) {
    return readNumber<std::uint8_t>(L, __FUNCTION__);
}

int l_readchar(lua_State* L) {
    return readNumber<std::int8_t>(L, __FUNCTION__);
}

int l_readword(lua_State* L) {
    return readNumber<std::uint16_t>(L, __FUNCTION__);
}

int l_readshort(lua_State* L) {
    return readNumber<std::int16_t>(L, __FUNCTION__);
}

int l_readdword(lua_State* L) {
    return readNumber<std::uint32_t>(L, __FUNCTION__);
}

int l_readint(lua_State* L) {
    return readNumber<std::int32_t>(L, __FUNCTION__);
}

int l_readfloat(lua_State* L) {
    return readNumber<float>(L, __FUNCTION__);
}

int l_readdouble(lua_State* L) {
    return readNumber<double>(L, __FUNCTION__);
}

// --------------------------------------------------------

template <typename T>
int writeNumber(lua_State* L, const char* f) {
    size_t address;
    lua_Number value;

    if (lua_gettop(L) == 3) { // backwards compatibility
        // address, offset, value
        int offset;
        std::tie(address, offset, value) = phlua::callback::getArguments<size_t, int, lua_Number>(L, f);
        address += offset;
    } else {
        std::tie(address, value) = phlua::callback::getArguments<size_t, lua_Number>(L, f);
    }

    T x;
    if (!checkLimits<T>(value, x)) {
        auto f = boost::format("invalid write: value (%.0f) outside of type's range") % value;
        luaL_error(L, "%s", f.str().c_str());
    }

    writeData(L, (void*)address, &x, sizeof(T));
    return 0;
}

int l_writebyte(lua_State* L) {
    return writeNumber<std::uint8_t>(L, __FUNCTION__);
}

int l_writechar(lua_State* L) {
    return writeNumber<std::int8_t>(L, __FUNCTION__);
}

int l_writeword(lua_State* L) {
    return writeNumber<std::uint16_t>(L, __FUNCTION__);
}

int l_writeshort(lua_State* L) {
    return writeNumber<std::int16_t>(L, __FUNCTION__);
}

int l_writedword(lua_State* L) {
    return writeNumber<std::uint32_t>(L, __FUNCTION__);
}

int l_writeint(lua_State* L) {
    return writeNumber<std::int32_t>(L, __FUNCTION__);
}

int l_writefloat(lua_State* L) {
    return writeNumber<float>(L, __FUNCTION__);
}

int l_writedouble(lua_State* L) {
    return writeNumber<double>(L, __FUNCTION__);
}

// --------------------------------------------------------

static const size_t kMaxStringElements = 160;

template <typename T>
int readstring(lua_State* L, const char* f) {
    size_t address;
    boost::optional<unsigned int> length;
    std::array<T, kMaxStringElements+1> dest;

    std::tie(address, length) = phlua::callback::getArguments<size_t, decltype(length)>(L, f);

    size_t readLength = kMaxStringElements;
    if (length) {
        if (length > kMaxStringElements) {
            auto f = boost::format("can only read strings to a maximum size of %u characters") % kMaxStringElements;
            luaL_argerror(L, 2, f.str().c_str());
        }
        readLength = *length;
    }

    readData(L, dest.data(), (void*)address, readLength*sizeof(T));
    dest[readLength] = 0; // ensure it's null terminated

    return phlua::callback::pushReturns(L, std::make_tuple(dest.data()));
}

int l_readstring(lua_State* L) {
    return readstring<char>(L, __FUNCTION__);
}

int l_readwidestring(lua_State* L) {
    return readstring<wchar_t>(L, __FUNCTION__);
}

// --------------------------------------------------------

template <typename StrType>
int writestring(lua_State* L, const char* f) {
    typedef typename StrType::value_type char_type;
    size_t address;
    boost::optional<size_t> offset;
    StrType s;

    if (lua_gettop(L) == 3) { // backwards compatibility
        std::tie(address, offset, s) = phlua::callback::getArguments<size_t, decltype(offset), StrType>(L, f);
    } else {
        std::tie(address, s) = phlua::callback::getArguments<size_t, StrType>(L, f);
    }

    if (offset) address += *offset;

    size_t byteLength = s.size() * sizeof(char_type);
    writeData(L, (void*)address, s.c_str(), byteLength);
    char_type nullChar = 0;
    writeData(L, (void*)(address + byteLength), &nullChar, sizeof(nullChar));
    return 0;
}

int l_writestring(lua_State* L) {
    return writestring<std::string>(L, __FUNCTION__);
}

int l_writewidestring(lua_State* L) {
    return writestring<std::wstring>(L, __FUNCTION__);
}

struct SigUnit {
    uint8_t x;
    enum class Mode {
        NORMAL, WILDCARD, WILDCARD_HIGH, WILDCARD_LOW
    } mode;

};

uint8_t hex_to_int(char c) {
    c = tolower(c);
    if (c >= 'a' && c <= 'f') {
        return 10 + c - 'a';
    } else {
        return c - '0';
    }
}
// sig code in Addresses is really bad, so i'll just rewrite it...
// sig should conform to ([A-Fa-f0-9?][A-Fa-f0-9?])+
// returns absolute address
uint8_t* sigscan(const std::string& sig, int occurance) {
    // should refactor this, but for now a copy/paste works...
    uint8_t* module = (uint8_t*)GetModuleHandle(0);
    unsigned int OffsetToPE = *(unsigned int*)(module + 0x3C);
    unsigned int codeSize = *(unsigned int*)(module + OffsetToPE + 0x1C);
    unsigned int BaseOfCode = *(unsigned int*)(module + OffsetToPE + 0x2C);
    uint8_t* codeSection = (uint8_t*)(module + BaseOfCode);

    if (sig.size() % 2) return 0;

    // convert sig to byte values
    std::vector<SigUnit> bytes;
    bytes.reserve(sig.size() % 2);
    for (size_t x = 0; x < sig.size(); x += 2) {
        SigUnit unit;
        if (sig[x] == '?') {
            if (sig[x+1] == '?') {
                unit.mode = SigUnit::Mode::WILDCARD;
            } else {
                unit.mode = SigUnit::Mode::WILDCARD_HIGH;
                unit.x = hex_to_int(sig[x+1]);
            }
        } else if (sig[x+1] == '?') {
            unit.mode = SigUnit::Mode::WILDCARD_LOW;
            unit.x = hex_to_int(sig[x]);
        } else {
            unit.mode = SigUnit::Mode::NORMAL;
            unit.x = hex_to_int(sig[x]) << 4 | hex_to_int(sig[x+1]);
        }
        bytes.push_back(unit);
    }

    // todo: should probably use knp or something
    unsigned int found = 0;
    for (unsigned int x = 0; x < codeSize; x++) {
        unsigned int length = std::min(codeSize - x, bytes.size());
        for (unsigned int i = 0; i < length; i++) {
            uint8_t b = codeSection[x+i];
            bool match = true;

            switch (bytes[i].mode) {
            case SigUnit::Mode::WILDCARD:
                // nothing to do
                break;
            case SigUnit::Mode::WILDCARD_HIGH:
                // ?x
                match = (b & 0x0F) == bytes[i].x;
                break;
            case SigUnit::Mode::WILDCARD_LOW:
                // x?
                match = (b & 0xF0) == bytes[i].x;
                break;
            default:
                match = b == bytes[i].x;
                break;
            }

            if (match) {
                if (i + 1 == bytes.size()) {
                    if (found++ == occurance)
                        return codeSection + x;
                }
            } else
                break;
        }
    }

    return 0;
}

bool ishex(char c) {
    c = tolower(c);
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
}

std::unordered_map<std::string, unsigned int> sigMap;

int l_findsig(lua_State* L) {
    std::string sig;
    boost::optional<int> occurance;

    std::tie(sig, occurance) = phlua::callback::getArguments<std::string, decltype(occurance)>(L, __FUNCTION__);

    if (!occurance)
        occurance = 0;

    if (sig.length() == 0) {
        luaL_argerror(L, 1, "empty signature");
    }

    for (auto c : sig) {
        if (c != '?' && !ishex(c))
            luaL_argerror(L, 1, "signature can only contain hexadecimal or ? characters");
    }

    // If only part of a byte is specified, treat the next as a wildcard
    if (sig.length() % 2) {
        sig.append("?");
    }

    // Basic caching because sig searching is really slow...
    unsigned int mem;
    std::unordered_map<std::string, unsigned int>::iterator itr;
    char occuranceStr[9];
    static const std::string occ_key_header = "occ:";
    sprintf_s(occuranceStr, sizeof(occuranceStr), "%08x", *occurance);
    std::string map_key = sig + occ_key_header + occuranceStr;

    itr = sigMap.find(map_key);
    if (itr != sigMap.end())
        mem = itr->second;
    else {
        mem = (unsigned int)sigscan(sig, *occurance);
        sigMap.insert(std::make_pair(map_key, mem));
    }

    if (mem) {
        return phlua::callback::pushReturns(L, std::make_tuple(mem));
    } else {
        return phlua::callback::pushReturns(L, std::make_tuple(lua::types::Nil()));
    }
}<|endoftext|>


<commit_before>#include <libdariadb/storage/strategy.h>
#include <libdariadb/utils/strings.h>

std::istream &dariadb::storage::operator>>(std::istream &in, STRATEGY &strat) {
  std::string token;
  in >> token;

  token = utils::strings::to_upper(token);

  if (token == "FAST_WRITE") {
    strat = dariadb::storage::STRATEGY::FAST_WRITE;
  }
  if (token == "COMPRESSED") {
    strat = dariadb::storage::STRATEGY::COMPRESSED;
  }

  if (token == "MEMORY") {
    strat = dariadb::storage::STRATEGY::MEMORY;
  }

  if (token == "CACHE") {
    strat = dariadb::storage::STRATEGY::CACHE;
  }
  return in;
}

std::ostream &dariadb::storage::operator<<(std::ostream &stream, const STRATEGY &strat) {
  switch (strat) {
  case STRATEGY::COMPRESSED:
    stream << "COMPRESSED";
    break;
  case STRATEGY::FAST_WRITE:
    stream << "FAST_WRITE";
    break;
  case STRATEGY::MEMORY:
    stream << "MEMORY";
    break;
  case STRATEGY::CACHE:
    stream << "CACHE";
    break;
  default:
    stream << "UNKNOW: ui16=" << (uint16_t)strat;
    break;
  };
  return stream;
}
<commit_msg>throw exception if bad strategy name.<commit_after>#include <libdariadb/storage/strategy.h>
#include <libdariadb/utils/strings.h>
#include <libdariadb/utils/exception.h>

std::istream &dariadb::storage::operator>>(std::istream &in, STRATEGY &strat) {
  std::string token;
  in >> token;

  token = utils::strings::to_upper(token);

  if (token == "FAST_WRITE") {
    strat = dariadb::storage::STRATEGY::FAST_WRITE;
	return in;
  }
  if (token == "COMPRESSED") {
    strat = dariadb::storage::STRATEGY::COMPRESSED;
	return in;
  }

  if (token == "MEMORY") {
    strat = dariadb::storage::STRATEGY::MEMORY;
	return in;
  }

  if (token == "CACHE") {
    strat = dariadb::storage::STRATEGY::CACHE;
	return in;
  }
  THROW_EXCEPTION("engine: bad strategy name - ", token);
}

std::ostream &dariadb::storage::operator<<(std::ostream &stream, const STRATEGY &strat) {
  switch (strat) {
  case STRATEGY::COMPRESSED:
    stream << "COMPRESSED";
    break;
  case STRATEGY::FAST_WRITE:
    stream << "FAST_WRITE";
    break;
  case STRATEGY::MEMORY:
    stream << "MEMORY";
    break;
  case STRATEGY::CACHE:
    stream << "CACHE";
    break;
  default:
	THROW_EXCEPTION("engine: bad strategy - ", (uint16_t)strat);
    break;
  };
  return stream;
}
<|endoftext|>


<commit_before><commit_msg>createBillboard now uses the same lookAt transform (this is differs from view matrix)<commit_after><|endoftext|>