<commit_before>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "ClTransposeConvolution2dWorkload.hpp"

#include "ClWorkloadUtils.hpp"

#include <cl/ClLayerSupport.hpp>
#include <cl/ClTensorHandle.hpp>
#include <cl/ClLayerSupport.hpp>

#include <aclCommon/ArmComputeUtils.hpp>
#include <aclCommon/ArmComputeTensorUtils.hpp>

#include <backendsCommon/CpuTensorHandle.hpp>

#include <arm_compute/runtime/CL/functions/CLDeconvolutionLayer.h>

namespace armnn
{

using namespace armcomputetensorutils;

arm_compute::Status ClTransposeConvolution2dWorkloadValidate(const TensorInfo& input,
                                                             const TensorInfo& output,
                                                             const TransposeConvolution2dDescriptor& descriptor,
                                                             const TensorInfo& weights,
                                                             const Optional<TensorInfo>& biases)
{
    arm_compute::TensorInfo aclInputInfo   = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
    arm_compute::TensorInfo aclOutputInfo  = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
    arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights, descriptor.m_DataLayout);

    arm_compute::TensorInfo aclBiasesInfo;
    arm_compute::TensorInfo *optionalAclBiasesInfo = nullptr;

    if (descriptor.m_BiasEnabled)
    {
        BOOST_ASSERT(biases.has_value());

        aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
        optionalAclBiasesInfo = &aclBiasesInfo;
    }

    arm_compute::PadStrideInfo padStrideInfo = BuildArmComputePadStrideInfo(descriptor);

    constexpr unsigned int innerBorderRight = 0u;
    constexpr unsigned int innerBorderTop   = 0u;

    return arm_compute::CLDeconvolutionLayer::validate(&aclInputInfo,
                                                       &aclWeightsInfo,
                                                       optionalAclBiasesInfo,
                                                       &aclOutputInfo,
                                                       padStrideInfo,
                                                       innerBorderRight,
                                                       innerBorderTop);
}

ClTransposeConvolution2dWorkload::ClTransposeConvolution2dWorkload(
    const TransposeConvolution2dQueueDescriptor& descriptor,
    const WorkloadInfo& info,
    std::shared_ptr<arm_compute::MemoryManagerOnDemand>& memoryManager) :
    BaseWorkload<TransposeConvolution2dQueueDescriptor>(descriptor, info),
    m_Layer(memoryManager)
{
    const TensorInfo& weightInfo = m_Data.m_Weight->GetTensorInfo();

    m_WeightsTensor = std::make_unique<arm_compute::CLTensor>();
    BuildArmComputeTensor(*m_WeightsTensor, weightInfo, m_Data.m_Parameters.m_DataLayout);

    arm_compute::PadStrideInfo padStrideInfo(m_Data.m_Parameters.m_StrideX,
                                             m_Data.m_Parameters.m_StrideY,
                                             m_Data.m_Parameters.m_PadLeft,
                                             m_Data.m_Parameters.m_PadRight,
                                             m_Data.m_Parameters.m_PadTop,
                                             m_Data.m_Parameters.m_PadBottom,
                                             arm_compute::DimensionRoundingType::FLOOR);

    if (m_Data.m_Parameters.m_BiasEnabled)
    {
        m_BiasesTensor = std::make_unique<arm_compute::CLTensor>();
        BuildArmComputeTensor(*m_BiasesTensor, m_Data.m_Bias->GetTensorInfo(), m_Data.m_Parameters.m_DataLayout);
    }

    m_Data.ValidateInputsOutputs("ClTransposeConvolution2dWorkload", 1, 1);

    arm_compute::ICLTensor& input  = static_cast<IClTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
    arm_compute::ICLTensor& output = static_cast<IClTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();

    arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout);

    input.info()->set_data_layout(aclDataLayout);
    output.info()->set_data_layout(aclDataLayout);

    m_Layer.configure(&input, m_WeightsTensor.get(), m_BiasesTensor.get(), &output, padStrideInfo);

    InitializeArmComputeClTensorData(*m_WeightsTensor, m_Data.m_Weight);
    if (m_BiasesTensor)
    {
        InitializeArmComputeClTensorData(*m_BiasesTensor, m_Data.m_Bias);
    }

    m_Layer.prepare();

    FreeUnusedTensors();
}

void ClTransposeConvolution2dWorkload::Execute() const
{
    ARMNN_SCOPED_PROFILING_EVENT_CL("ClTransposeConvolution2dWorkload_Execute");
    RunClFunction(m_Layer, CHECK_LOCATION());
}

void ClTransposeConvolution2dWorkload::FreeUnusedTensors()
{
    FreeTensorIfUnused(m_WeightsTensor);
    FreeTensorIfUnused(m_BiasesTensor);
}

} // namespace armnn
<commit_msg>IVGCVSW-3519 Refactor TransposeConvolution2dWorkload for CL backed<commit_after>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "ClTransposeConvolution2dWorkload.hpp"

#include "ClWorkloadUtils.hpp"

#include <cl/ClLayerSupport.hpp>
#include <cl/ClTensorHandle.hpp>
#include <cl/ClLayerSupport.hpp>

#include <aclCommon/ArmComputeUtils.hpp>
#include <aclCommon/ArmComputeTensorUtils.hpp>

#include <backendsCommon/CpuTensorHandle.hpp>

#include <arm_compute/runtime/CL/functions/CLDeconvolutionLayer.h>

namespace armnn
{

using namespace armcomputetensorutils;

arm_compute::Status ClTransposeConvolution2dWorkloadValidate(const TensorInfo& input,
                                                             const TensorInfo& output,
                                                             const TransposeConvolution2dDescriptor& descriptor,
                                                             const TensorInfo& weights,
                                                             const Optional<TensorInfo>& biases)
{
    arm_compute::TensorInfo aclInputInfo   = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout);
    arm_compute::TensorInfo aclOutputInfo  = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout);
    arm_compute::TensorInfo aclWeightsInfo = BuildArmComputeTensorInfo(weights, descriptor.m_DataLayout);

    arm_compute::TensorInfo aclBiasesInfo;
    arm_compute::TensorInfo *optionalAclBiasesInfo = nullptr;

    if (descriptor.m_BiasEnabled)
    {
        BOOST_ASSERT(biases.has_value());

        aclBiasesInfo = BuildArmComputeTensorInfo(biases.value(), descriptor.m_DataLayout);
        optionalAclBiasesInfo = &aclBiasesInfo;
    }

    arm_compute::PadStrideInfo padStrideInfo = BuildArmComputePadStrideInfo(descriptor);

    return arm_compute::CLDeconvolutionLayer::validate(&aclInputInfo,
                                                       &aclWeightsInfo,
                                                       optionalAclBiasesInfo,
                                                       &aclOutputInfo,
                                                       padStrideInfo);
}

ClTransposeConvolution2dWorkload::ClTransposeConvolution2dWorkload(
    const TransposeConvolution2dQueueDescriptor& descriptor,
    const WorkloadInfo& info,
    std::shared_ptr<arm_compute::MemoryManagerOnDemand>& memoryManager) :
    BaseWorkload<TransposeConvolution2dQueueDescriptor>(descriptor, info),
    m_Layer(memoryManager)
{
    const TensorInfo& weightInfo = m_Data.m_Weight->GetTensorInfo();

    m_WeightsTensor = std::make_unique<arm_compute::CLTensor>();
    BuildArmComputeTensor(*m_WeightsTensor, weightInfo, m_Data.m_Parameters.m_DataLayout);

    arm_compute::PadStrideInfo padStrideInfo(m_Data.m_Parameters.m_StrideX,
                                             m_Data.m_Parameters.m_StrideY,
                                             m_Data.m_Parameters.m_PadLeft,
                                             m_Data.m_Parameters.m_PadRight,
                                             m_Data.m_Parameters.m_PadTop,
                                             m_Data.m_Parameters.m_PadBottom,
                                             arm_compute::DimensionRoundingType::FLOOR);

    if (m_Data.m_Parameters.m_BiasEnabled)
    {
        m_BiasesTensor = std::make_unique<arm_compute::CLTensor>();
        BuildArmComputeTensor(*m_BiasesTensor, m_Data.m_Bias->GetTensorInfo(), m_Data.m_Parameters.m_DataLayout);
    }

    m_Data.ValidateInputsOutputs("ClTransposeConvolution2dWorkload", 1, 1);

    arm_compute::ICLTensor& input  = static_cast<IClTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
    arm_compute::ICLTensor& output = static_cast<IClTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();

    arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout);

    input.info()->set_data_layout(aclDataLayout);
    output.info()->set_data_layout(aclDataLayout);

    m_Layer.configure(&input, m_WeightsTensor.get(), m_BiasesTensor.get(), &output, padStrideInfo);

    InitializeArmComputeClTensorData(*m_WeightsTensor, m_Data.m_Weight);
    if (m_BiasesTensor)
    {
        InitializeArmComputeClTensorData(*m_BiasesTensor, m_Data.m_Bias);
    }

    m_Layer.prepare();

    FreeUnusedTensors();
}

void ClTransposeConvolution2dWorkload::Execute() const
{
    ARMNN_SCOPED_PROFILING_EVENT_CL("ClTransposeConvolution2dWorkload_Execute");
    RunClFunction(m_Layer, CHECK_LOCATION());
}

void ClTransposeConvolution2dWorkload::FreeUnusedTensors()
{
    FreeTensorIfUnused(m_WeightsTensor);
    FreeTensorIfUnused(m_BiasesTensor);
}

} // namespace armnn
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/optimization/Attic/COptFunction.cpp,v $
   $Revision: 1.14 $
   $Name:  $
   $Author: lixu1 $
   $Date: 2003/10/16 20:00:28 $
   End CVS Header */

#include <sstream>
#include "copasi.h"
#include "FlexLexer.h"
#include "function/CFunction.h"
#include "COptFunction.h"
#include "COptMethod.h"
#include "COptProblem.h"
#include "report/CKeyFactory.h"

COptFunction::COptFunction(const std::string & name, const CCopasiContainer * pParent)
    : CCopasiContainer(name, pParent, "OptFunction"),
    mKey(CKeyFactory::add("OptFunction", this)),
    mpMethod(new COptMethod),
    mpProblem(new COptProblem)
{
  mpMethod->setProblem(mpProblem);
  mParaList.clear();
  mMinFunctionList.clear();
  mMaxFunctionList.clear();
  mMinList.clear();
  mMaxList.clear();
  mMinOperList.clear();
  mMaxOperList.clear();
}

COptFunction::COptFunction(const COptFunction & src, CReadConfig * configBuffer, const CCopasiContainer * pParent)
    : CCopasiContainer(src, pParent),
    mKey(CKeyFactory::add("OptFunction", this)),
    mpMethod(src.mpMethod),
    mpProblem(src.mpProblem),
    mParaList(src.mParaList),
    mMinFunctionList(src.mMinFunctionList),
    mMaxFunctionList(src.mMaxFunctionList),
    mMinList(src.mMinList),
    mMaxList(src.mMaxList),
    mMinOperList(src.mMinOperList),
    mMaxOperList(src.mMaxOperList)
{
  mpMethod->setProblem(mpProblem);
}

COptFunction::~COptFunction()
{
  CKeyFactory::remove(mKey);
  cleanup();
}

void COptFunction::cleanup()
{
  //static members will be deleted during the deconstruction of COptFunction
  mParaList.clear();
  mMinFunctionList.clear();
  mMaxFunctionList.clear();
  mMinList.clear();
  mMaxList.clear();
  mMinOperList.clear();
  mMaxOperList.clear();
}

// check if a parameter already existing inside the mParaList
bool COptFunction::bExisted(const std::string & name)
{
  int i;
  for (i = 0; i < mParaList.size(); i++)
    if (mParaList[i]->getCN() == name)
      return true;
  return false;
}

// add a new item inside
int COptFunction::addItem(CCopasiObject* pObject)
{
  if (bExisted(pObject->getCN()))
    return - 1; //
  mParaList.push_back(pObject);
  mMinList.push_back("-inf");
  mMaxList.push_back("+inf");
  mMinFunctionList.push_back(NULL);
  mMaxFunctionList.push_back(NULL);
  return mParaList.size() - 1;
}

bool COptFunction::removeItem(const std::string & name)
{
  int i;
  for (i = 0; i < mParaList.size(); i++)
    {
      if (mParaList[i]->getCN() == name)
        {
          mParaList.erase(mParaList.begin() + i);
          mMinList.erase(mMinList.begin() + i);
          mMaxList.erase(mMaxList.begin() + i);
          mMinFunctionList.erase(mMinFunctionList.begin() + i);
          mMaxFunctionList.erase(mMaxFunctionList.begin() + i);
          return true;
        }
    }
  return false;
}

void COptFunction::connect()
{
  int i;
  CKinFunction* pMinFunc, * pMaxFunc;
  for (i = 0; i < mParaList.size(); i++)
    {
      //      pMinFunc = NULL;
      //      pMaxFunc = NULL;
      if (mMinList[i] != "-inf")
        {
          //          pMinFunc = new CKinFunction();
          //          pMinFunc->setDescription(mMinList[i].c_str());
          //          pMinFunc->compile();
          mMinFunctionList[i]->connect();
        }

      if (mMaxList[i] != "+inf")
        {
          //          pMaxFunc = new CKinFunction();
          //          pMaxFunc->setDescription(mMaxList[i].c_str());
          //          pMaxFunc->compile();
          mMaxFunctionList[i]->connect();
        }
      //      mMinFunctionList.push_back(pMinFunc);
      //      mMaxFunctionList.push_back(pMaxFunc);
    }
}
<commit_msg>change the compile function, to recompile everything, as ppl may use other way to change the formular,<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/optimization/Attic/COptFunction.cpp,v $
   $Revision: 1.15 $
   $Name:  $
   $Author: lixu1 $
   $Date: 2003/10/17 01:40:09 $
   End CVS Header */

#include <sstream>
#include "copasi.h"
#include "FlexLexer.h"
#include "function/CFunction.h"
#include "COptFunction.h"
#include "COptMethod.h"
#include "COptProblem.h"
#include "report/CKeyFactory.h"

COptFunction::COptFunction(const std::string & name, const CCopasiContainer * pParent)
    : CCopasiContainer(name, pParent, "OptFunction"),
    mKey(CKeyFactory::add("OptFunction", this)),
    mpMethod(new COptMethod),
    mpProblem(new COptProblem)
{
  mpMethod->setProblem(mpProblem);
  mParaList.clear();
  mMinFunctionList.clear();
  mMaxFunctionList.clear();
  mMinList.clear();
  mMaxList.clear();
  mMinOperList.clear();
  mMaxOperList.clear();
}

COptFunction::COptFunction(const COptFunction & src, CReadConfig * configBuffer, const CCopasiContainer * pParent)
    : CCopasiContainer(src, pParent),
    mKey(CKeyFactory::add("OptFunction", this)),
    mpMethod(src.mpMethod),
    mpProblem(src.mpProblem),
    mParaList(src.mParaList),
    mMinFunctionList(src.mMinFunctionList),
    mMaxFunctionList(src.mMaxFunctionList),
    mMinList(src.mMinList),
    mMaxList(src.mMaxList),
    mMinOperList(src.mMinOperList),
    mMaxOperList(src.mMaxOperList)
{
  mpMethod->setProblem(mpProblem);
}

COptFunction::~COptFunction()
{
  CKeyFactory::remove(mKey);
  cleanup();
}

void COptFunction::cleanup()
{
  //static members will be deleted during the deconstruction of COptFunction
  mParaList.clear();
  mMinFunctionList.clear();
  mMaxFunctionList.clear();
  mMinList.clear();
  mMaxList.clear();
  mMinOperList.clear();
  mMaxOperList.clear();
}

// check if a parameter already existing inside the mParaList
bool COptFunction::bExisted(const std::string & name)
{
  int i;
  for (i = 0; i < mParaList.size(); i++)
    if (mParaList[i]->getCN() == name)
      return true;
  return false;
}

// add a new item inside
int COptFunction::addItem(CCopasiObject* pObject)
{
  if (bExisted(pObject->getCN()))
    return - 1; //
  mParaList.push_back(pObject);
  mMinList.push_back("-inf");
  mMaxList.push_back("+inf");
  mMinFunctionList.push_back(NULL);
  mMaxFunctionList.push_back(NULL);
  return mParaList.size() - 1;
}

bool COptFunction::removeItem(const std::string & name)
{
  int i;
  for (i = 0; i < mParaList.size(); i++)
    {
      if (mParaList[i]->getCN() == name)
        {
          mParaList.erase(mParaList.begin() + i);
          mMinList.erase(mMinList.begin() + i);
          mMaxList.erase(mMaxList.begin() + i);
          mMinFunctionList.erase(mMinFunctionList.begin() + i);
          mMaxFunctionList.erase(mMaxFunctionList.begin() + i);
          return true;
        }
    }
  return false;
}

void COptFunction::connect()
{
  int i;
  for (i = 0; i < mParaList.size(); i++)
    {
      if (mMinList[i] != "-inf")
        {
          if (!mMinFunctionList[i])
            mMinFunctionList[i] = new CKinFunction();
          mMinFunctionList[i]->setDescription(mMinList[i].c_str());
          // will automatically call the compile function for CKinFunction
        }

      if (mMaxList[i] != "+inf")
        {
          if (!mMaxFunctionList[i])
            mMaxFunctionList[i] = new CKinFunction();
          mMaxFunctionList[i]->setDescription(mMaxList[i].c_str());
          // will automatically call the compile function for CKinFunction
        }
    }
}
<|endoftext|>


<commit_before>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file Triple.cpp
 * Three element double vectors, for use with geodetic coordinates
 */

#include "geometry.hpp"
#include "Triple.hpp"
#include <cmath>

namespace gpstk
{
   using namespace std;

   Triple :: Triple()
         : theArray(3)
   {
   }

   Triple :: Triple(const Triple& right)
      : theArray(right.theArray)
   {
   }

   Triple :: Triple(double a,
                    double b,
                    double c)
      : theArray(3)
   {
      theArray[0] = a;
      theArray[1] = b;
      theArray[2] = c;
   }

   Triple& Triple :: operator=(const Triple& right)
   {
      theArray = right.theArray;
      return *this;
   }

   Triple& Triple :: operator=(const valarray<double>& right)
      throw(GeometryException)
   {
      if (right.size() != 3)
      {
         GPSTK_THROW(GeometryException("Incorrect vector size"));
      }

      theArray = right;
      return *this;
   }

      // returns the dot product of the two vectors
   double Triple :: dot(const Triple& right) const
      throw()
   {
      Triple z;
      z = (this->theArray)*(right.theArray);
      double a = z.theArray.sum();
      return a;
   }

      // retuns v1 x v2 , vector cross product
   Triple Triple :: cross(const Triple& right) const
      throw()
   {
      Triple cp;
      cp[0] = (*this)[1] * right[2] - (*this)[2] * right[1];
      cp[1] = (*this)[2] * right[0] - (*this)[0] * right[2];
      cp[2] = (*this)[0] * right[1] - (*this)[1] * right[0];
      return cp;
   }

   double Triple :: mag() const throw()
   {
      return ::sqrt(dot(*this));
   }

   Triple Triple::unitVector() const
       throw(GeometryException)
   {
      double mag = sqrt(dot(*this));

      if (mag <= 1e-14)
      	GPSTK_THROW(GeometryException("Divide by Zero Error"));

      Triple retArg;
      retArg[0] = (*this)[0] / mag;
      retArg[1] = (*this)[1] / mag;
      retArg[2] = (*this)[2] / mag;
      return(retArg);
   }

      // function that returns the cosine of angle between this and right
   double Triple :: cosVector(const Triple& right) const
      throw(GeometryException)
   {
      double rx, ry, cosvects;

      rx = dot(*this);
      std::cout << "rx: " << rx << std::endl;
      ry = right.dot(right);
      std::cout << "ry: " << ry << std::endl;

      if (rx <= 1e-14 ||  ry <= 1e-14)
	{      std::cout << "gonna throw" << std::flush;
      	GPSTK_THROW(GeometryException("Divide by Zero Error"));
	}
      cosvects = dot(right) / ::sqrt(rx * ry);

      /* this if checks for and corrects round off error */
      if (fabs(cosvects) > 1.0e0)
      {
         cosvects = fabs(cosvects) / cosvects;
      }

      return cosvects;
   }

      // Computes the slant range between two vectors
   double Triple :: slantRange(const Triple& right) const
      throw()
   {
      Triple z;
      z = right.theArray - this->theArray;
      double r = z.mag();
      return r;
   }

      // Finds the elevation angle of the second point with respect to
      // the first point
   double Triple :: elvAngle(const Triple& right) const
      throw(GeometryException)
   {
      Triple z;
      z = right.theArray - this->theArray;
      double c = z.cosVector(*this);
      return 90.0 - ::acos(c) * RAD_TO_DEG;
   }

      //  Calculates a satellites azimuth from a station
   double Triple :: azAngle(const Triple& right) const
      throw(GeometryException)
   {
      double xy, xyz, cosl, sinl, sint, xn1, xn2, xn3, xe1, xe2;
      double z1, z2, z3, p1, p2, test, alpha;

      xy = (*this)[0] * (*this)[0] + (*this)[1] * (*this)[1] ;
      xyz = xy + (*this)[2] * (*this)[2] ;
      xy = ::sqrt(xy);
      xyz = ::sqrt(xyz);

      if (xy <= 1e-14 || xyz <=1e-14)
      	 GPSTK_THROW(GeometryException("Divide by Zero Error"))

      cosl = (*this)[0] / xy;
      sinl = (*this)[1] / xy;
      sint = (*this)[2] / xyz;

      xn1 = -sint * cosl;
      xn2 = -sint * sinl;
      xn3 = xy/xyz;

      xe1 = -sinl;
      xe2 = cosl;

      z1 = right[0] - (*this)[0];
      z2 = right[1] - (*this)[1];
      z3 = right[2] - (*this)[2];

      p1 = (xn1 * z1) + (xn2 * z2) + (xn3 * z3) ;
      p2 = (xe1 * z1) + (xe2 * z2) ;

      test = fabs(p1) + fabs(p2);

      if (test < 1.0e-16)
      {
         GPSTK_THROW(GeometryException("azAngle(), failed p1+p2 test."));
      }

      alpha = 90 - ::atan2(p1, p2) * RAD_TO_DEG;
      if (alpha < 0)
      {
         return alpha + 360;
      }
      else
      {
         return alpha;
      }
   }

   bool Triple :: operator== (const Triple& right) const
   {
     return (*this)[0]==right[0] && (*this)[1]==right[1] && (*this)[2]==right[2];
   }

   Triple Triple :: operator-(const Triple& right) const
   {
      Triple tmp;
      tmp.theArray = this->theArray - right.theArray;
      return tmp;
   }

   Triple Triple :: operator+(const Triple& right) const
   {
      Triple tmp;
      tmp.theArray = this->theArray + right.theArray;
      return tmp;
   }

   Triple operator*(double scale, const Triple& rhs)
   {
      Triple tmp;
      tmp.theArray = rhs.theArray * scale;
      return tmp;
   }

   std::ostream& operator<<(std::ostream& s,
                            const gpstk::Triple& v)
   {
      if (v.size() > 0)
      {
         s << "(" << v[0];
         for (int i = 1; i < v.size(); i++)
         {
            s << ", " << v[i];
         }
         s << ")";
      }

      return s;
   }

} // namespace gpstk

<commit_msg>Removing some debug code<commit_after>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file Triple.cpp
 * Three element double vectors, for use with geodetic coordinates
 */

#include "geometry.hpp"
#include "Triple.hpp"
#include <cmath>

namespace gpstk
{
   using namespace std;

   Triple :: Triple()
         : theArray(3)
   {
   }

   Triple :: Triple(const Triple& right)
      : theArray(right.theArray)
   {
   }

   Triple :: Triple(double a,
                    double b,
                    double c)
      : theArray(3)
   {
      theArray[0] = a;
      theArray[1] = b;
      theArray[2] = c;
   }

   Triple& Triple :: operator=(const Triple& right)
   {
      theArray = right.theArray;
      return *this;
   }

   Triple& Triple :: operator=(const valarray<double>& right)
      throw(GeometryException)
   {
      if (right.size() != 3)
      {
         GPSTK_THROW(GeometryException("Incorrect vector size"));
      }

      theArray = right;
      return *this;
   }

      // returns the dot product of the two vectors
   double Triple :: dot(const Triple& right) const
      throw()
   {
      Triple z;
      z = (this->theArray)*(right.theArray);
      double a = z.theArray.sum();
      return a;
   }

      // retuns v1 x v2 , vector cross product
   Triple Triple :: cross(const Triple& right) const
      throw()
   {
      Triple cp;
      cp[0] = (*this)[1] * right[2] - (*this)[2] * right[1];
      cp[1] = (*this)[2] * right[0] - (*this)[0] * right[2];
      cp[2] = (*this)[0] * right[1] - (*this)[1] * right[0];
      return cp;
   }

   double Triple :: mag() const throw()
   {
      return ::sqrt(dot(*this));
   }

   Triple Triple::unitVector() const
       throw(GeometryException)
   {
      double mag = sqrt(dot(*this));

      if (mag <= 1e-14)
      	GPSTK_THROW(GeometryException("Divide by Zero Error"));

      Triple retArg;
      retArg[0] = (*this)[0] / mag;
      retArg[1] = (*this)[1] / mag;
      retArg[2] = (*this)[2] / mag;
      return(retArg);
   }

      // function that returns the cosine of angle between this and right
   double Triple :: cosVector(const Triple& right) const
      throw(GeometryException)
   {
      double rx, ry, cosvects;

      rx = dot(*this);
      ry = right.dot(right);

      if (rx <= 1e-14 ||  ry <= 1e-14)
      {
         GPSTK_THROW(GeometryException("Divide by Zero Error"));
      }
      cosvects = dot(right) / ::sqrt(rx * ry);

      /* this if checks for and corrects round off error */
      if (fabs(cosvects) > 1.0e0)
      {
         cosvects = fabs(cosvects) / cosvects;
      }

      return cosvects;
   }

      // Computes the slant range between two vectors
   double Triple :: slantRange(const Triple& right) const
      throw()
   {
      Triple z;
      z = right.theArray - this->theArray;
      double r = z.mag();
      return r;
   }

      // Finds the elevation angle of the second point with respect to
      // the first point
   double Triple :: elvAngle(const Triple& right) const
      throw(GeometryException)
   {
      Triple z;
      z = right.theArray - this->theArray;
      double c = z.cosVector(*this);
      return 90.0 - ::acos(c) * RAD_TO_DEG;
   }

      //  Calculates a satellites azimuth from a station
   double Triple :: azAngle(const Triple& right) const
      throw(GeometryException)
   {
      double xy, xyz, cosl, sinl, sint, xn1, xn2, xn3, xe1, xe2;
      double z1, z2, z3, p1, p2, test, alpha;

      xy = (*this)[0] * (*this)[0] + (*this)[1] * (*this)[1] ;
      xyz = xy + (*this)[2] * (*this)[2] ;
      xy = ::sqrt(xy);
      xyz = ::sqrt(xyz);

      if (xy <= 1e-14 || xyz <=1e-14)
      	 GPSTK_THROW(GeometryException("Divide by Zero Error"))

      cosl = (*this)[0] / xy;
      sinl = (*this)[1] / xy;
      sint = (*this)[2] / xyz;

      xn1 = -sint * cosl;
      xn2 = -sint * sinl;
      xn3 = xy/xyz;

      xe1 = -sinl;
      xe2 = cosl;

      z1 = right[0] - (*this)[0];
      z2 = right[1] - (*this)[1];
      z3 = right[2] - (*this)[2];

      p1 = (xn1 * z1) + (xn2 * z2) + (xn3 * z3) ;
      p2 = (xe1 * z1) + (xe2 * z2) ;

      test = fabs(p1) + fabs(p2);

      if (test < 1.0e-16)
      {
         GPSTK_THROW(GeometryException("azAngle(), failed p1+p2 test."));
      }

      alpha = 90 - ::atan2(p1, p2) * RAD_TO_DEG;
      if (alpha < 0)
      {
         return alpha + 360;
      }
      else
      {
         return alpha;
      }
   }

   bool Triple :: operator== (const Triple& right) const
   {
     return (*this)[0]==right[0] && (*this)[1]==right[1] && (*this)[2]==right[2];
   }

   Triple Triple :: operator-(const Triple& right) const
   {
      Triple tmp;
      tmp.theArray = this->theArray - right.theArray;
      return tmp;
   }

   Triple Triple :: operator+(const Triple& right) const
   {
      Triple tmp;
      tmp.theArray = this->theArray + right.theArray;
      return tmp;
   }

   Triple operator*(double scale, const Triple& rhs)
   {
      Triple tmp;
      tmp.theArray = rhs.theArray * scale;
      return tmp;
   }

   std::ostream& operator<<(std::ostream& s,
                            const gpstk::Triple& v)
   {
      if (v.size() > 0)
      {
         s << "(" << v[0];
         for (int i = 1; i < v.size(); i++)
         {
            s << ", " << v[i];
         }
         s << ")";
      }

      return s;
   }

} // namespace gpstk

<|endoftext|>


<commit_before>#include "WideVM.hpp"
#include "VMOpcodes.hpp"
#include <fstream>
#include <cstring>
#include <cmath>

namespace wvm {

WideVM::WideVM()
{
    m_twister.seed(std::rand());
}

void WideVM::init(int size, int count, const float* initvals)
{
    particlesize = size;
    data.resize(size*count, 0.f);
    if(initvals)
    {
        for(int i = 0; i < particleCount(); ++i)
        {
            std::memcpy(getParticle(i), initvals, sizeof (float)* size);
        }
    }
}

void WideVM::runVmProgram(int subprog, int b, int e)
{
    begin = (b == -1)?0:b;
    end = (e == -1)?particleCount():e;

    pc = subprograms[subprog];
    while(pc < program.size())
    {
        startLoop(); //in case an opcode uses while loopParticle init counter for it
        const int opcode = fetch();
        switch(opcode)
        {
            case EVO_QUIT:
                opQuit();
                break;
            case EVO_SIN:
                opSin();
                break;
            case EVO_COS:
                opCos();
                break;
            case EVO_COPY:
                opCopy();
                break;
            case EVO_RAND2:
                opRand2();
                break;
            case EVO_MATH2:
                opMath2();
                break;
        } //switch opcodes pc
        ++pc;
    } //while pc < opcodes size
}

int WideVM::particleCount() const
{
    return data.size() / particlesize;
}

float* WideVM::getParticle(int index)
{
    return data.data() + index * particlesize;
}

void WideVM::findSubprograms()
{
    subprograms.clear();
    for(int i = 0; i < program.size(); ++i)
    {
        if(program[i] == EVO_SUBPROGRAM)
        {
            subprograms.push_back(i);
        }
        else
        {
            i += opcodeArgCount(static_cast<EVM_OPCODE>(program[i]));
        }
    }
}

//helpers for opcodes:

int WideVM::fetch()
{
    return program[pc++];
}

float WideVM::read(int index)
{
    if(index < 0)
    {
        index = -index - 1;
        return globals[index];
    }
    return getParticle(pindex)[index];
}

float& WideVM::write(int index)
{
    return getParticle(pindex)[index];
}

void WideVM::startLoop()
{
    pindex = begin - 1;
}

bool WideVM::loopParticles()
{
    ++pindex;
    if(pindex >= end) return false;
    return true;
}

//opcode calls:

void WideVM::opQuit()
{
    pc = program.size(); //trick program into thinking codes ran out
}

void WideVM::opSin()
{
    const int result = fetch();
    const int arg = fetch();

    while(loopParticles())
    {
        write(result) = std::sin(read(arg));
    }
}

void WideVM::opCos()
{
    const int result = fetch();
    const int arg = fetch();

    while(loopParticles())
    {
        write(result) = std::cos(read(arg));
    }
}

void WideVM::opCopy()
{
    const int to = fetch();
    const int from = fetch();

    while(loopParticles())
    {
        write(to) = read(from);
    }
}

void WideVM::opRand2()
{
    const int to = fetch();
    const int min = fetch();
    const int max = fetch();

    while(loopParticles())
    {
        std::uniform_real_distribution<float> distri(read(min), read(max));
        write(to) = distri(m_twister);
    }
}

void WideVM::opMath2()
{
    const int op = fetch();
    const int to = fetch();
    const int arg1 = fetch();
    const int arg2 = fetch();
    while(loopParticles())
    {
        switch(op)
        {
            case 1:
                write(to) = read(arg1) + read(arg2);
                break;
            case 2:
                write(to) = read(arg1) - read(arg2);
                break;
            case 3:
                write(to) = read(arg1) * read(arg2);
                break;
        }
    } //loopParticles
}

} //wvm
<commit_msg>Added divide arg(4) to math2 opcode<commit_after>#include "WideVM.hpp"
#include "VMOpcodes.hpp"
#include <fstream>
#include <cstring>
#include <cmath>

namespace wvm {

WideVM::WideVM()
{
    m_twister.seed(std::rand());
}

void WideVM::init(int size, int count, const float* initvals)
{
    particlesize = size;
    data.resize(size*count, 0.f);
    if(initvals)
    {
        for(int i = 0; i < particleCount(); ++i)
        {
            std::memcpy(getParticle(i), initvals, sizeof (float)* size);
        }
    }
}

void WideVM::runVmProgram(int subprog, int b, int e)
{
    begin = (b == -1)?0:b;
    end = (e == -1)?particleCount():e;

    pc = subprograms[subprog];
    while(pc < program.size())
    {
        startLoop(); //in case an opcode uses while loopParticle init counter for it
        const int opcode = fetch();
        switch(opcode)
        {
            case EVO_QUIT:
                opQuit();
                break;
            case EVO_SIN:
                opSin();
                break;
            case EVO_COS:
                opCos();
                break;
            case EVO_COPY:
                opCopy();
                break;
            case EVO_RAND2:
                opRand2();
                break;
            case EVO_MATH2:
                opMath2();
                break;
        } //switch opcodes pc
        ++pc;
    } //while pc < opcodes size
}

int WideVM::particleCount() const
{
    return data.size() / particlesize;
}

float* WideVM::getParticle(int index)
{
    return data.data() + index * particlesize;
}

void WideVM::findSubprograms()
{
    subprograms.clear();
    for(int i = 0; i < program.size(); ++i)
    {
        if(program[i] == EVO_SUBPROGRAM)
        {
            subprograms.push_back(i);
        }
        else
        {
            i += opcodeArgCount(static_cast<EVM_OPCODE>(program[i]));
        }
    }
}

//helpers for opcodes:

int WideVM::fetch()
{
    return program[pc++];
}

float WideVM::read(int index)
{
    if(index < 0)
    {
        index = -index - 1;
        return globals[index];
    }
    return getParticle(pindex)[index];
}

float& WideVM::write(int index)
{
    return getParticle(pindex)[index];
}

void WideVM::startLoop()
{
    pindex = begin - 1;
}

bool WideVM::loopParticles()
{
    ++pindex;
    if(pindex >= end) return false;
    return true;
}

//opcode calls:

void WideVM::opQuit()
{
    pc = program.size(); //trick program into thinking codes ran out
}

void WideVM::opSin()
{
    const int result = fetch();
    const int arg = fetch();

    while(loopParticles())
    {
        write(result) = std::sin(read(arg));
    }
}

void WideVM::opCos()
{
    const int result = fetch();
    const int arg = fetch();

    while(loopParticles())
    {
        write(result) = std::cos(read(arg));
    }
}

void WideVM::opCopy()
{
    const int to = fetch();
    const int from = fetch();

    while(loopParticles())
    {
        write(to) = read(from);
    }
}

void WideVM::opRand2()
{
    const int to = fetch();
    const int min = fetch();
    const int max = fetch();

    while(loopParticles())
    {
        std::uniform_real_distribution<float> distri(read(min), read(max));
        write(to) = distri(m_twister);
    }
}

void WideVM::opMath2()
{
    const int op = fetch();
    const int to = fetch();
    const int arg1 = fetch();
    const int arg2 = fetch();
    while(loopParticles())
    {
        switch(op)
        {
            case 1:
                write(to) = read(arg1) + read(arg2);
                break;
            case 2:
                write(to) = read(arg1) - read(arg2);
                break;
            case 3:
                write(to) = read(arg1) * read(arg2);
                break;
            case 4:
                write(to) = read(arg1) / read(arg2);
                break;
        }
    } //loopParticles
}

} //wvm
<|endoftext|>


<commit_before>#include <IOKit/IOLib.h>

#include "CommonData.hpp"
#include "EventInputQueue.hpp"
#include "IOLogWrapper.hpp"
#include "SimultaneousKeyPresses.hpp"

namespace org_pqrs_Karabiner {
namespace RemapFunc {
void SimultaneousKeyPresses::add(AddDataType datatype, AddValue newval) {
  switch (datatype) {
  case BRIDGE_DATATYPE_KEYCODE:
  case BRIDGE_DATATYPE_CONSUMERKEYCODE:
  case BRIDGE_DATATYPE_POINTINGBUTTON: {
    // ----------------------------------------
    // The first data is virtualkey_.
    if (index_ == 0) {
      if (datatype != BRIDGE_DATATYPE_KEYCODE) {
        IOLOG_ERROR("Invalid SimultaneousKeyPresses::add\n");
        return;
      }
      virtualkey_ = KeyCode(newval);
      keytokey_.add(virtualkey_);
      goto finish;
    }

    // ----------------------------------------
    // From keys
    if (!isFromInfoFull_) {
      fromInfo_.push_back(FromInfo(datatype, newval));

      if (isUseSeparator_ == false) {
        if (index_ == 2) {
          isFromInfoFull_ = true;
        }
      }
      goto finish;
    }

    // ----------------------------------------
    // To keys
    if (keytokey_.toKeysSize() == 0 &&
        datatype == BRIDGE_DATATYPE_KEYCODE) {
      toKey_raw_ = KeyCode(newval);
    }
    keytokey_.add(datatype, newval);

  finish:
    ++index_;

    break;
  }

  case BRIDGE_DATATYPE_MODIFIERFLAG:
  case BRIDGE_DATATYPE_MODIFIERFLAGS_END: {
    if (index_ < 2) {
      IOLOG_ERROR("Invalid SimultaneousKeyPresses::add\n");
      return;
    } else {
      if (keytokey_.toKeysSize() == 0) {
        fromModifierFlags_.push_back(ModifierFlag(datatype, newval));
      }
      keytokey_.add(datatype, newval);
    }
    break;
  }

  case BRIDGE_DATATYPE_OPTION: {
    Option option(newval);
    if (Option::SIMULTANEOUSKEYPRESSES_RAW == option) {
      isToRaw_ = true;
    } else if (Option::SIMULTANEOUSKEYPRESSES_POST_FROM_EVENTS_AS_RAW == option) {
      isPostFromEventsAsRaw_ = true;
    } else if (Option::SIMULTANEOUSKEYPRESSES_STRICT_KEY_ORDER == option) {
      isStrictKeyOrder_ = true;

    } else if (Option::USE_SEPARATOR == option) {
      isUseSeparator_ = true;

    } else if (Option::SEPARATOR == option) {
      isFromInfoFull_ = true;

    } else if (Option::NOREPEAT == option ||
               Option::KEYTOKEY_BEFORE_KEYDOWN == option ||
               Option::KEYTOKEY_AFTER_KEYUP == option) {
      keytokey_.add(option);

    } else {
      IOLOG_ERROR("SimultaneousKeyPresses::add unknown option:%u\n", static_cast<unsigned int>(newval));
    }
    break;
  }

  case BRIDGE_DATATYPE_DELAYUNTILREPEAT:
  case BRIDGE_DATATYPE_KEYREPEAT: {
    keytokey_.add(datatype, newval);
    break;
  }

  default:
    IOLOG_ERROR("SimultaneousKeyPresses::add invalid datatype:%u\n", static_cast<unsigned int>(datatype));
    break;
  }
}

RemapSimultaneousKeyPressesResult::Value
SimultaneousKeyPresses::remapSimultaneousKeyPresses(void) {
  // We consider "Shift_L+Shift_R to Space".
  // When we press keys by the following order.
  //
  // (1) Shift_L Down
  // (2) Shift_R Down
  // (3) Shift_L Up
  // (4) Shift_R Up
  //
  // First remap():
  //   (1) Shift_L Down -> to virtualkey_
  //   (2) Shift_R Down -> removed
  //   (3) Shift_L Up   -> no change
  //   (4) Shift_R Up   -> no change
  //
  // Second remap():
  //   (3) Shift_L Up   -> removed
  //   (4) Shift_R Up   -> no change
  // However, we need to remove (4) at the same time.
  // If (4) is alive, Shift_R Up event which we don't intend is fired in EventInputQueue.
  // So, we retry handling KeyUp event once more when we drop KeyUp event.

  auto front = static_cast<EventInputQueue::Item*>(EventInputQueue::queue_.safe_front());
  if (!front) {
    return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
  }

  if (!(front->isSimultaneousKeyPressesTarget)) {
    return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
  }

  // backup device information.
  DeviceIdentifier deviceIdentifier(front->deviceIdentifier);

  // ------------------------------------------------------------
  // fire KeyUp event if needed.
  for (size_t i = 0; i < fromInfo_.size(); ++i) {
    if (!fromInfo_[i].isActive()) continue;
    if (!fromInfo_[i].fromEvent().isTargetUpEvent(front->getParamsBase())) continue;

    // --------------------
    if (isPostFromEventsAsRaw_) {
      front->isSimultaneousKeyPressesTarget = false;
    } else {
      EventInputQueue::queue_.pop_front();
    }
    fromInfo_[i].deactivate();

    // --------------------
    // if all keys are released, fire KeyUp event.
    bool isAllDeactived = true;
    for (size_t j = 0; j < fromInfo_.size(); ++j) {
      if (fromInfo_[j].isActive()) {
        isAllDeactived = false;
      }
    }
    if (!isAllDeactived) {
      return RemapSimultaneousKeyPressesResult::QUEUE_CHANGED;
    }

    push_remapped(false, deviceIdentifier);
    return RemapSimultaneousKeyPressesResult::APPLIED;
  }

  // ------------------------------------------------------------
  // handle KeyDown event.
  if (!FlagStatus::globalFlagStatus().isOn(fromModifierFlags_)) return RemapSimultaneousKeyPressesResult::NOT_CHANGED;

  // Check the first item in queue_ is target.
  //
  // We need to skip when the first item is not target.
  // In this case:
  //   - shift+[a+s] to space
  //   - [a+s] to return
  // When queue_ is [shift, a, s], we need to change these events to space.
  // If we do not check the first item is target,
  // [shift, a, s] will be changed to [shift, return].
  // It's not intended.
  for (size_t i = 0; i < fromInfo_.size(); ++i) {
    if (fromInfo_[i].fromEvent().isTargetDownEvent(front->getParamsBase())) {
      goto scan;
    }
  }
  // skip
  return RemapSimultaneousKeyPressesResult::NOT_CHANGED;

scan:
  // --------------------
  // scan items in queue_.
  while (downKeys_.size() < fromInfo_.size()) {
    downKeys_.push_back(nullptr);
  }
  // Then, downKeys_.size() >= fromInfo_.size()

  for (size_t i = 0; i < fromInfo_.size(); ++i) {
    downKeys_[i].item = nullptr;
  }

  for (;;) {
    // We consider "Shift_L+Shift_R to Space".
    // When we press keys by the following order.
    //
    // (1) Shift_L Down
    // (2) Shift_L Up
    // (3) Shift_R Down
    // (4) Shift_R Up
    //
    // If fromKey was released before all keys are pressed,
    // we must not handle these keys as SimultaneousKeyPresses.
    //
    for (size_t i = 0; i < fromInfo_.size(); ++i) {
      if (fromInfo_[i].fromEvent().isTargetDownEvent(front->getParamsBase())) {
        downKeys_[i].item = front;
        break;
      } else if (fromInfo_[i].fromEvent().isTargetUpEvent(front->getParamsBase())) {
        return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
      }
    }

    // ----------------------------------------
    bool isAllKeysDown = true;
    for (size_t i = 0; i < fromInfo_.size(); ++i) {
      if (!downKeys_[i].item) {
        isAllKeysDown = false;
      } else {
        // Checking strict key order.
        //
        // If isStrictKeyOrder_ == true,
        // we must not handle the following state as SimultaneousKeyPresses.
        //
        // - downKeys_[0] == nullptr
        // - downKeys_[1] != nullptr
        //
        if (!isAllKeysDown && isStrictKeyOrder_) {
          return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
        }
      }
    }

    if (isAllKeysDown) {
      // We use the reverse iterator for isPostFromEventsAsRaw_.
      for (int i = static_cast<int>(fromInfo_.size()) - 1; i >= 0; --i) {
        fromInfo_[i].activate();

        if (! downKeys_[i].item) continue;

        if (isPostFromEventsAsRaw_) {
          bool retainFlagStatusTemporaryCount = false;
          bool push_back = false;
          bool isSimultaneousKeyPressesTarget = false;
          EventInputQueue::enqueue_((downKeys_[i].item)->getParamsBase(),
                                    retainFlagStatusTemporaryCount,
                                    deviceIdentifier,
                                    push_back,
                                    isSimultaneousKeyPressesTarget);
        }
        EventInputQueue::queue_.erase_and_delete(downKeys_[i].item);
      }
      push_remapped(true, deviceIdentifier);
      return RemapSimultaneousKeyPressesResult::APPLIED;
    }

    // ----------------------------------------
    // get next target item.
    for (;;) {
      front = static_cast<EventInputQueue::Item*>(front->getnext());
      if (!front) {
        return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
      }
      if (front->isSimultaneousKeyPressesTarget) {
        break;
      }
    }
  }

  return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
}

void SimultaneousKeyPresses::push_remapped(bool isKeyDown, const DeviceIdentifier& deviceIdentifier) {
  EventType eventType = isKeyDown ? EventType::DOWN : EventType::UP;

  KeyCode key = virtualkey_;
  if (isToRaw_) {
    key = toKey_raw_;
  }
  if (key == KeyCode::VK_NONE) return;

  Flags flags(0);
  if (isKeyDown) {
    flags.add(key.getModifierFlag());
  }

  // ----------------------------------------
  Params_KeyboardEventCallBack params(eventType, flags, key, CommonData::getcurrent_keyboardType(), false);

  bool retainFlagStatusTemporaryCount = false;
  bool push_back = false;
  bool isSimultaneousKeyPressesTarget = false;
  EventInputQueue::enqueue_(params, retainFlagStatusTemporaryCount, deviceIdentifier, push_back, isSimultaneousKeyPressesTarget);
}

bool SimultaneousKeyPresses::remap(RemapParams& remapParams) {
  return keytokey_.remap(remapParams);
}
}
}
<commit_msg>apply clang-format<commit_after>#include <IOKit/IOLib.h>

#include "CommonData.hpp"
#include "EventInputQueue.hpp"
#include "IOLogWrapper.hpp"
#include "SimultaneousKeyPresses.hpp"

namespace org_pqrs_Karabiner {
namespace RemapFunc {
void SimultaneousKeyPresses::add(AddDataType datatype, AddValue newval) {
  switch (datatype) {
  case BRIDGE_DATATYPE_KEYCODE:
  case BRIDGE_DATATYPE_CONSUMERKEYCODE:
  case BRIDGE_DATATYPE_POINTINGBUTTON: {
    // ----------------------------------------
    // The first data is virtualkey_.
    if (index_ == 0) {
      if (datatype != BRIDGE_DATATYPE_KEYCODE) {
        IOLOG_ERROR("Invalid SimultaneousKeyPresses::add\n");
        return;
      }
      virtualkey_ = KeyCode(newval);
      keytokey_.add(virtualkey_);
      goto finish;
    }

    // ----------------------------------------
    // From keys
    if (!isFromInfoFull_) {
      fromInfo_.push_back(FromInfo(datatype, newval));

      if (isUseSeparator_ == false) {
        if (index_ == 2) {
          isFromInfoFull_ = true;
        }
      }
      goto finish;
    }

    // ----------------------------------------
    // To keys
    if (keytokey_.toKeysSize() == 0 &&
        datatype == BRIDGE_DATATYPE_KEYCODE) {
      toKey_raw_ = KeyCode(newval);
    }
    keytokey_.add(datatype, newval);

  finish:
    ++index_;

    break;
  }

  case BRIDGE_DATATYPE_MODIFIERFLAG:
  case BRIDGE_DATATYPE_MODIFIERFLAGS_END: {
    if (index_ < 2) {
      IOLOG_ERROR("Invalid SimultaneousKeyPresses::add\n");
      return;
    } else {
      if (keytokey_.toKeysSize() == 0) {
        fromModifierFlags_.push_back(ModifierFlag(datatype, newval));
      }
      keytokey_.add(datatype, newval);
    }
    break;
  }

  case BRIDGE_DATATYPE_OPTION: {
    Option option(newval);
    if (Option::SIMULTANEOUSKEYPRESSES_RAW == option) {
      isToRaw_ = true;
    } else if (Option::SIMULTANEOUSKEYPRESSES_POST_FROM_EVENTS_AS_RAW == option) {
      isPostFromEventsAsRaw_ = true;
    } else if (Option::SIMULTANEOUSKEYPRESSES_STRICT_KEY_ORDER == option) {
      isStrictKeyOrder_ = true;

    } else if (Option::USE_SEPARATOR == option) {
      isUseSeparator_ = true;

    } else if (Option::SEPARATOR == option) {
      isFromInfoFull_ = true;

    } else if (Option::NOREPEAT == option ||
               Option::KEYTOKEY_BEFORE_KEYDOWN == option ||
               Option::KEYTOKEY_AFTER_KEYUP == option) {
      keytokey_.add(option);

    } else {
      IOLOG_ERROR("SimultaneousKeyPresses::add unknown option:%u\n", static_cast<unsigned int>(newval));
    }
    break;
  }

  case BRIDGE_DATATYPE_DELAYUNTILREPEAT:
  case BRIDGE_DATATYPE_KEYREPEAT: {
    keytokey_.add(datatype, newval);
    break;
  }

  default:
    IOLOG_ERROR("SimultaneousKeyPresses::add invalid datatype:%u\n", static_cast<unsigned int>(datatype));
    break;
  }
}

RemapSimultaneousKeyPressesResult::Value
SimultaneousKeyPresses::remapSimultaneousKeyPresses(void) {
  // We consider "Shift_L+Shift_R to Space".
  // When we press keys by the following order.
  //
  // (1) Shift_L Down
  // (2) Shift_R Down
  // (3) Shift_L Up
  // (4) Shift_R Up
  //
  // First remap():
  //   (1) Shift_L Down -> to virtualkey_
  //   (2) Shift_R Down -> removed
  //   (3) Shift_L Up   -> no change
  //   (4) Shift_R Up   -> no change
  //
  // Second remap():
  //   (3) Shift_L Up   -> removed
  //   (4) Shift_R Up   -> no change
  // However, we need to remove (4) at the same time.
  // If (4) is alive, Shift_R Up event which we don't intend is fired in EventInputQueue.
  // So, we retry handling KeyUp event once more when we drop KeyUp event.

  auto front = static_cast<EventInputQueue::Item*>(EventInputQueue::queue_.safe_front());
  if (!front) {
    return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
  }

  if (!(front->isSimultaneousKeyPressesTarget)) {
    return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
  }

  // backup device information.
  DeviceIdentifier deviceIdentifier(front->deviceIdentifier);

  // ------------------------------------------------------------
  // fire KeyUp event if needed.
  for (size_t i = 0; i < fromInfo_.size(); ++i) {
    if (!fromInfo_[i].isActive()) continue;
    if (!fromInfo_[i].fromEvent().isTargetUpEvent(front->getParamsBase())) continue;

    // --------------------
    if (isPostFromEventsAsRaw_) {
      front->isSimultaneousKeyPressesTarget = false;
    } else {
      EventInputQueue::queue_.pop_front();
    }
    fromInfo_[i].deactivate();

    // --------------------
    // if all keys are released, fire KeyUp event.
    bool isAllDeactived = true;
    for (size_t j = 0; j < fromInfo_.size(); ++j) {
      if (fromInfo_[j].isActive()) {
        isAllDeactived = false;
      }
    }
    if (!isAllDeactived) {
      return RemapSimultaneousKeyPressesResult::QUEUE_CHANGED;
    }

    push_remapped(false, deviceIdentifier);
    return RemapSimultaneousKeyPressesResult::APPLIED;
  }

  // ------------------------------------------------------------
  // handle KeyDown event.
  if (!FlagStatus::globalFlagStatus().isOn(fromModifierFlags_)) return RemapSimultaneousKeyPressesResult::NOT_CHANGED;

  // Check the first item in queue_ is target.
  //
  // We need to skip when the first item is not target.
  // In this case:
  //   - shift+[a+s] to space
  //   - [a+s] to return
  // When queue_ is [shift, a, s], we need to change these events to space.
  // If we do not check the first item is target,
  // [shift, a, s] will be changed to [shift, return].
  // It's not intended.
  for (size_t i = 0; i < fromInfo_.size(); ++i) {
    if (fromInfo_[i].fromEvent().isTargetDownEvent(front->getParamsBase())) {
      goto scan;
    }
  }
  // skip
  return RemapSimultaneousKeyPressesResult::NOT_CHANGED;

scan:
  // --------------------
  // scan items in queue_.
  while (downKeys_.size() < fromInfo_.size()) {
    downKeys_.push_back(nullptr);
  }
  // Then, downKeys_.size() >= fromInfo_.size()

  for (size_t i = 0; i < fromInfo_.size(); ++i) {
    downKeys_[i].item = nullptr;
  }

  for (;;) {
    // We consider "Shift_L+Shift_R to Space".
    // When we press keys by the following order.
    //
    // (1) Shift_L Down
    // (2) Shift_L Up
    // (3) Shift_R Down
    // (4) Shift_R Up
    //
    // If fromKey was released before all keys are pressed,
    // we must not handle these keys as SimultaneousKeyPresses.
    //
    for (size_t i = 0; i < fromInfo_.size(); ++i) {
      if (fromInfo_[i].fromEvent().isTargetDownEvent(front->getParamsBase())) {
        downKeys_[i].item = front;
        break;
      } else if (fromInfo_[i].fromEvent().isTargetUpEvent(front->getParamsBase())) {
        return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
      }
    }

    // ----------------------------------------
    bool isAllKeysDown = true;
    for (size_t i = 0; i < fromInfo_.size(); ++i) {
      if (!downKeys_[i].item) {
        isAllKeysDown = false;
      } else {
        // Checking strict key order.
        //
        // If isStrictKeyOrder_ == true,
        // we must not handle the following state as SimultaneousKeyPresses.
        //
        // - downKeys_[0] == nullptr
        // - downKeys_[1] != nullptr
        //
        if (!isAllKeysDown && isStrictKeyOrder_) {
          return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
        }
      }
    }

    if (isAllKeysDown) {
      // We use the reverse iterator for isPostFromEventsAsRaw_.
      for (int i = static_cast<int>(fromInfo_.size()) - 1; i >= 0; --i) {
        fromInfo_[i].activate();

        if (!downKeys_[i].item) continue;

        if (isPostFromEventsAsRaw_) {
          bool retainFlagStatusTemporaryCount = false;
          bool push_back = false;
          bool isSimultaneousKeyPressesTarget = false;
          EventInputQueue::enqueue_((downKeys_[i].item)->getParamsBase(),
                                    retainFlagStatusTemporaryCount,
                                    deviceIdentifier,
                                    push_back,
                                    isSimultaneousKeyPressesTarget);
        }
        EventInputQueue::queue_.erase_and_delete(downKeys_[i].item);
      }
      push_remapped(true, deviceIdentifier);
      return RemapSimultaneousKeyPressesResult::APPLIED;
    }

    // ----------------------------------------
    // get next target item.
    for (;;) {
      front = static_cast<EventInputQueue::Item*>(front->getnext());
      if (!front) {
        return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
      }
      if (front->isSimultaneousKeyPressesTarget) {
        break;
      }
    }
  }

  return RemapSimultaneousKeyPressesResult::NOT_CHANGED;
}

void SimultaneousKeyPresses::push_remapped(bool isKeyDown, const DeviceIdentifier& deviceIdentifier) {
  EventType eventType = isKeyDown ? EventType::DOWN : EventType::UP;

  KeyCode key = virtualkey_;
  if (isToRaw_) {
    key = toKey_raw_;
  }
  if (key == KeyCode::VK_NONE) return;

  Flags flags(0);
  if (isKeyDown) {
    flags.add(key.getModifierFlag());
  }

  // ----------------------------------------
  Params_KeyboardEventCallBack params(eventType, flags, key, CommonData::getcurrent_keyboardType(), false);

  bool retainFlagStatusTemporaryCount = false;
  bool push_back = false;
  bool isSimultaneousKeyPressesTarget = false;
  EventInputQueue::enqueue_(params, retainFlagStatusTemporaryCount, deviceIdentifier, push_back, isSimultaneousKeyPressesTarget);
}

bool SimultaneousKeyPresses::remap(RemapParams& remapParams) {
  return keytokey_.remap(remapParams);
}
}
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * interface_widgets.hpp : Custom widgets for the main interface
 ****************************************************************************
 * Copyright (C) 2006 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef _INTFWIDGETS_H_
#define _INTFWIDGETS_H_

#include <vlc/vlc.h>
#include <vlc_interface.h>

#include <vlc_aout.h>
#include "qt4.hpp"

#include <QWidget>
#include <QFrame>

class ResizeEvent;
class QPalette;
class QPixmap;
class QLabel;
class QHBoxLayout;

/******************** Video Widget ****************/
class VideoWidget : public QFrame
{
    Q_OBJECT
public:
    VideoWidget( intf_thread_t * );
    virtual ~VideoWidget();

    void *request( vout_thread_t *, int *, int *,
                   unsigned int *, unsigned int * );
    void release( void * );
    int control( void *, int, va_list );

    int i_video_height, i_video_width;
    vout_thread_t *p_vout;

    QSize widgetSize;
    virtual QSize sizeHint() const;
private:
    QWidget *frame;
    intf_thread_t *p_intf;
    vlc_mutex_t lock;
signals:
    void askResize();
private slots:
    void SetMinSize();
};

/******************** Background Widget ****************/
class BackgroundWidget : public QFrame
{
    Q_OBJECT
public:
    BackgroundWidget( intf_thread_t * );
    virtual ~BackgroundWidget();
    QSize widgetSize;
    virtual QSize sizeHint() const;
private:
    QPalette plt;
    QLabel *label;
    QHBoxLayout *backgroundLayout;
    virtual void resizeEvent( QResizeEvent *e );
    int DrawBackground();
    int CleanBackground();
    intf_thread_t *p_intf;
private slots:
    void setArt( QString );
};

class VisualSelector : public QFrame
{
    Q_OBJECT
public:
    VisualSelector( intf_thread_t *);
    virtual ~VisualSelector();
private:
    intf_thread_t *p_intf;
    QLabel *current;
private slots:
    void prev();
    void next();
};

class QPushButton;
class AdvControlsWidget : public QFrame
{
    Q_OBJECT
public:
    AdvControlsWidget( intf_thread_t *);
    virtual ~AdvControlsWidget();
    void enableInput( bool );
    void enableVideo( bool );
private:
    intf_thread_t *p_intf;
    QPushButton *normalButton, *recordButton, *ABButton;
    QPushButton *snapshotButton, *frameButton;
private slots:
    void normal();
    void snapshot();
    void frame();
    void fromAtoB();
    void record();
};

class InputSlider;
class QSlider;
class QGridLayout;
class VolumeClickHandler;
class ControlsWidget : public QFrame
{
    Q_OBJECT
public:
    ControlsWidget( intf_thread_t *, bool );
    virtual ~ControlsWidget();

    QPushButton *playlistButton;
    QSlider *volumeSlider;
    void setStatus( int );
    void enableInput( bool );
    void enableVideo( bool );
public slots:
    void setNavigation( int );
    void updateOnTimer();
protected:
    friend class MainInterface;
    friend class VolumeClickHandler;
private:
    intf_thread_t       *p_intf;
    QFrame              *discFrame;
    QGridLayout         *controlLayout;
    InputSlider         *slider;
    QPushButton         *prevSectionButton, *nextSectionButton, *menuButton;
    QPushButton         *playButton, *fullscreenButton;
    QPushButton         *slowerButton, *fasterButton;
    AdvControlsWidget   *advControls;
    QLabel              *volMuteLabel;

    bool                 b_advancedVisible;
private slots:
    void play();
    void stop();
    void prev();
    void next();
    void updateVolume( int );
    void fullscreen();
    void extSettings();
    void prefs();
    void faster();
    void slower();
    void toggleAdvanced();
signals:
    void advancedControlsToggled( bool );
};

class VolumeClickHandler : public QObject
{
public:
    VolumeClickHandler( intf_thread_t *_p_intf, ControlsWidget *_m ) :QObject(_m)
    {m = _m; p_intf = _p_intf; }
    virtual ~VolumeClickHandler() {};
    bool eventFilter( QObject *obj, QEvent *e )
    {
        if (e->type() == QEvent::MouseButtonPress )
        {
            aout_VolumeMute( p_intf, NULL );
            return true;
        }
        return false;
    }
private:
    ControlsWidget *m;
    intf_thread_t *p_intf;
};

/******************** Playlist Widgets ****************/
#include <QModelIndex>
#include <QSplitter>
class QSignalMapper;
class PLSelector;
class PLPanel;
class QPushButton;

class PlaylistWidget : public QSplitter
{
    Q_OBJECT;
public:
    PlaylistWidget( intf_thread_t *_p_i ) ;
    virtual ~PlaylistWidget();
    QSize widgetSize;
    virtual QSize sizeHint() const;
private:
    PLSelector *selector;
    PLPanel *rightPanel;
    QPushButton *addButton;
    QLabel *art;
    QString prevArt;
protected:
     intf_thread_t *p_intf;
private slots:
    void setArt( QString );
signals:
    void rootChanged( int );
    void artSet( QString );
};

#endif
<commit_msg>Qt4 - Volume, when clicked on the icon, mute and change the icon to the muted one.<commit_after>/*****************************************************************************
 * interface_widgets.hpp : Custom widgets for the main interface
 ****************************************************************************
 * Copyright (C) 2006 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef _INTFWIDGETS_H_
#define _INTFWIDGETS_H_

#include <vlc/vlc.h>
#include <vlc_interface.h>

#include <vlc_aout.h>
#include "qt4.hpp"

#include <QWidget>
#include <QFrame>

class ResizeEvent;
class QPalette;
class QPixmap;
class QLabel;
class QHBoxLayout;

/******************** Video Widget ****************/
class VideoWidget : public QFrame
{
    Q_OBJECT
public:
    VideoWidget( intf_thread_t * );
    virtual ~VideoWidget();

    void *request( vout_thread_t *, int *, int *,
                   unsigned int *, unsigned int * );
    void release( void * );
    int control( void *, int, va_list );

    int i_video_height, i_video_width;
    vout_thread_t *p_vout;

    QSize widgetSize;
    virtual QSize sizeHint() const;
private:
    QWidget *frame;
    intf_thread_t *p_intf;
    vlc_mutex_t lock;
signals:
    void askResize();
private slots:
    void SetMinSize();
};

/******************** Background Widget ****************/
class BackgroundWidget : public QFrame
{
    Q_OBJECT
public:
    BackgroundWidget( intf_thread_t * );
    virtual ~BackgroundWidget();
    QSize widgetSize;
    virtual QSize sizeHint() const;
private:
    QPalette plt;
    QLabel *label;
    QHBoxLayout *backgroundLayout;
    virtual void resizeEvent( QResizeEvent *e );
    int DrawBackground();
    int CleanBackground();
    intf_thread_t *p_intf;
private slots:
    void setArt( QString );
};

class VisualSelector : public QFrame
{
    Q_OBJECT
public:
    VisualSelector( intf_thread_t *);
    virtual ~VisualSelector();
private:
    intf_thread_t *p_intf;
    QLabel *current;
private slots:
    void prev();
    void next();
};

class QPushButton;
class AdvControlsWidget : public QFrame
{
    Q_OBJECT
public:
    AdvControlsWidget( intf_thread_t *);
    virtual ~AdvControlsWidget();
    void enableInput( bool );
    void enableVideo( bool );
private:
    intf_thread_t *p_intf;
    QPushButton *normalButton, *recordButton, *ABButton;
    QPushButton *snapshotButton, *frameButton;
private slots:
    void normal();
    void snapshot();
    void frame();
    void fromAtoB();
    void record();
};

class InputSlider;
class QSlider;
class QGridLayout;
class VolumeClickHandler;
class ControlsWidget : public QFrame
{
    Q_OBJECT
public:
    ControlsWidget( intf_thread_t *, bool );
    virtual ~ControlsWidget();

    QPushButton *playlistButton;
    QSlider *volumeSlider;
    void setStatus( int );
    void enableInput( bool );
    void enableVideo( bool );
public slots:
    void setNavigation( int );
    void updateOnTimer();
protected:
    friend class MainInterface;
    friend class VolumeClickHandler;
private:
    intf_thread_t       *p_intf;
    QFrame              *discFrame;
    QGridLayout         *controlLayout;
    InputSlider         *slider;
    QPushButton         *prevSectionButton, *nextSectionButton, *menuButton;
    QPushButton         *playButton, *fullscreenButton;
    QPushButton         *slowerButton, *fasterButton;
    AdvControlsWidget   *advControls;
    QLabel              *volMuteLabel;

    bool                 b_advancedVisible;
private slots:
    void play();
    void stop();
    void prev();
    void next();
    void updateVolume( int );
    void fullscreen();
    void extSettings();
    void prefs();
    void faster();
    void slower();
    void toggleAdvanced();
signals:
    void advancedControlsToggled( bool );
};

class VolumeClickHandler : public QObject
{
public:
    VolumeClickHandler( intf_thread_t *_p_intf, ControlsWidget *_m ) :QObject(_m)
    {m = _m; p_intf = _p_intf; }
    virtual ~VolumeClickHandler() {};
    bool eventFilter( QObject *obj, QEvent *e )
    {
        if (e->type() == QEvent::MouseButtonPress )
        {
            /* Mute it */
            aout_VolumeMute( p_intf, NULL );
            m->updateVolume( 0 );
            return true;
        }
        return false;
    }
private:
    ControlsWidget *m;
    intf_thread_t *p_intf;
};

/******************** Playlist Widgets ****************/
#include <QModelIndex>
#include <QSplitter>
class QSignalMapper;
class PLSelector;
class PLPanel;
class QPushButton;

class PlaylistWidget : public QSplitter
{
    Q_OBJECT;
public:
    PlaylistWidget( intf_thread_t *_p_i ) ;
    virtual ~PlaylistWidget();
    QSize widgetSize;
    virtual QSize sizeHint() const;
private:
    PLSelector *selector;
    PLPanel *rightPanel;
    QPushButton *addButton;
    QLabel *art;
    QString prevArt;
protected:
     intf_thread_t *p_intf;
private slots:
    void setArt( QString );
signals:
    void rootChanged( int );
    void artSet( QString );
};

#endif
<|endoftext|>


<commit_before>/*
** Copyright 2011-2012-2015 Centreon
**
** 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.
**
** For more information : contact@centreon.com
*/

#include <cstdlib>
#include <memory>
#include <QCoreApplication>
#include <QMutex>
#include <QMutexLocker>
#include "com/centreon/broker/config/applier/endpoint.hh"
#include "com/centreon/broker/config/applier/logger.hh"
#include "com/centreon/broker/config/applier/modules.hh"
#include "com/centreon/broker/config/applier/state.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/data.hh"
#include "com/centreon/broker/logging/file.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/engine.hh"
#include "com/centreon/broker/multiplexing/muxer.hh"
#include "com/centreon/broker/instance_broadcast.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::config::applier;

// Class instance.
static state* gl_state = NULL;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Destructor.
 */
state::~state() {}

/**
 *  Apply a configuration state.
 *
 *  @param[in] s       State to apply.
 *  @param[in] run_mux Set to true if multiplexing must be run.
 */
void state::apply(
              com::centreon::broker::config::state const& s,
              bool run_mux) {
  // Sanity checks.
  static char const* const
    allowed_chars("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
  if (!s.poller_id() || s.poller_name().empty())
    throw (exceptions::msg() << "state applier: poller information are "
           << "not set: please fill poller_id and poller_name");
  if (!s.broker_id() || s.broker_name().empty())
    throw (exceptions::msg() << "state applier: instance information "
           << "are not set: please fill broker_id and broker_name");
  for (std::string::const_iterator
         it(s.broker_name().begin()),
         end(s.broker_name().end());
       it != end;
       ++it)
    if (!strchr(allowed_chars, *it))
      throw (exceptions::msg() << "state applier: broker_name is not "
             << " valid: allowed characters are " << allowed_chars);
  for (std::list<config::endpoint>::const_iterator
         it(s.endpoints().begin()),
         end(s.endpoints().end());
       it != end;
       ++it) {
    if (it->name.empty())
      throw (exceptions::msg()
             << "state applier: endpoint name is not set: "
             << "please fill name of all endpoints");
    for (std::string::const_iterator
           it_name(it->name.begin()),
           end_name(it->name.end());
         it_name != end_name;
         ++it_name)
      if (!strchr(allowed_chars, *it_name))
        throw (exceptions::msg() << "state applier: endpoint name '"
               << *it_name << "' is not valid: allowed characters are "
               << allowed_chars);
  }

  // Set Broker instance ID.
  io::data::broker_id = s.broker_id();

  // Set poller instance.
  _poller_id = s.poller_id();
  _poller_name = s.poller_name();

  // Set cache directory.
  _cache_dir = s.cache_directory();
  if (!_cache_dir.empty())
    _cache_dir.append("/");
  _cache_dir.append(s.broker_name());

  // Apply logging configuration.
  logger::instance().apply(s.loggers());

  // Flush logs or not.
  com::centreon::broker::logging::file::with_flush(
    s.flush_logs());

  // Enable or not thread ID logging.
  com::centreon::broker::logging::file::with_thread_id(
    s.log_thread_id());

  // Enable or not timestamp logging.
  com::centreon::broker::logging::file::with_timestamp(
    s.log_timestamp());

  // Enable or not human readable timstamp logging.
  com::centreon::broker::logging::file::with_human_redable_timestamp(
    s.log_human_readable_timestamp());

  // Apply modules configuration.
  modules::instance().apply(
                        s.module_list(),
                        s.module_directory(),
                        &s);
  static bool first_application(true);
  if (first_application)
    first_application = false;
  else {
    unsigned int module_count(0);
    for (modules::iterator
           it(modules::instance().begin()),
           end(modules::instance().end());
         it != end;
         ++it)
      ++module_count;
    if (module_count)
      logging::config(logging::high) << "applier: " << module_count
        << " modules loaded";
    else
      logging::config(logging::high) << "applier: no module loaded, "
        "you might want to check the 'module_directory' directive";
  }

  // Event queue max size (used to limit memory consumption).
  com::centreon::broker::multiplexing::muxer::event_queue_max_size(
    s.event_queue_max_size());

  com::centreon::broker::config::state st = s;

  // Create command file input.
  if (!s.command_file().empty()) {
    config::endpoint ept;
    ept.name = "(external commands)";
    ept.type = "extcmd";
    ept.params.insert(
      "extcmd",
      QString::fromStdString(s.command_file()));
    ept.params.insert(
      "command_protocol",
      QString::fromStdString(s.command_protocol()));
    ept.read_filters.insert("all");
    st.endpoints().push_back(ept);
  }

  // Apply input and output configuration.
  endpoint::instance().apply(st.endpoints());

  // Create instance broadcast event.
  misc::shared_ptr<instance_broadcast> ib(new instance_broadcast);
  ib->broker_id = io::data::broker_id;
  ib->poller_id = _poller_id;
  ib->poller_name = _poller_name.c_str();
  ib->enabled = true;
  com::centreon::broker::multiplexing::engine::instance().publish(ib);

  // Enable multiplexing loop.
  if (run_mux)
    com::centreon::broker::multiplexing::engine::instance().start();

  return ;
}

/**
 *  Get applied cache directory.
 *
 *  @return Cache directory.
 */
std::string const& state::cache_dir() const throw () {
  return (_cache_dir);
}

/**
 *  Get the instance of this object.
 *
 *  @return Class instance.
 */
state& state::instance() {
  return (*gl_state);
}

/**
 *  Load singleton.
 */
void state::load() {
  if (!gl_state)
    gl_state = new state;
  return ;
}

/**
 *  Get the poller ID.
 *
 *  @return Poller ID of this Broker instance.
 */
unsigned int state::poller_id() const throw () {
  return (_poller_id);
}

/**
 *  Get the poller name.
 *
 *  @return Poller name of this Broker instance.
 */
std::string const& state::poller_name() const throw () {
  return (_poller_name);
}

/**
 *  Unload singleton.
 */
void state::unload() {
  delete gl_state;
  gl_state = NULL;
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
state::state() : _poller_id(0) {}
<commit_msg>core: allow spaces in configuration objects names.<commit_after>/*
** Copyright 2011-2013,2015-2016 Centreon
**
** 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.
**
** For more information : contact@centreon.com
*/

#include <cstdlib>
#include <memory>
#include <QCoreApplication>
#include <QMutex>
#include <QMutexLocker>
#include "com/centreon/broker/config/applier/endpoint.hh"
#include "com/centreon/broker/config/applier/logger.hh"
#include "com/centreon/broker/config/applier/modules.hh"
#include "com/centreon/broker/config/applier/state.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/data.hh"
#include "com/centreon/broker/logging/file.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/engine.hh"
#include "com/centreon/broker/multiplexing/muxer.hh"
#include "com/centreon/broker/instance_broadcast.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::config::applier;

// Class instance.
static state* gl_state = NULL;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Destructor.
 */
state::~state() {}

/**
 *  Apply a configuration state.
 *
 *  @param[in] s       State to apply.
 *  @param[in] run_mux Set to true if multiplexing must be run.
 */
void state::apply(
              com::centreon::broker::config::state const& s,
              bool run_mux) {
  // Sanity checks.
  static char const* const
    allowed_chars("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -_");
  if (!s.poller_id() || s.poller_name().empty())
    throw (exceptions::msg() << "state applier: poller information are "
           << "not set: please fill poller_id and poller_name");
  if (!s.broker_id() || s.broker_name().empty())
    throw (exceptions::msg() << "state applier: instance information "
           << "are not set: please fill broker_id and broker_name");
  for (std::string::const_iterator
         it(s.broker_name().begin()),
         end(s.broker_name().end());
       it != end;
       ++it)
    if (!strchr(allowed_chars, *it))
      throw (exceptions::msg() << "state applier: broker_name is not "
             << " valid: allowed characters are " << allowed_chars);
  for (std::list<config::endpoint>::const_iterator
         it(s.endpoints().begin()),
         end(s.endpoints().end());
       it != end;
       ++it) {
    if (it->name.empty())
      throw (exceptions::msg()
             << "state applier: endpoint name is not set: "
             << "please fill name of all endpoints");
    for (std::string::const_iterator
           it_name(it->name.begin()),
           end_name(it->name.end());
         it_name != end_name;
         ++it_name)
      if (!strchr(allowed_chars, *it_name))
        throw (exceptions::msg() << "state applier: endpoint name '"
               << *it_name << "' is not valid: allowed characters are "
               << allowed_chars);
  }

  // Set Broker instance ID.
  io::data::broker_id = s.broker_id();

  // Set poller instance.
  _poller_id = s.poller_id();
  _poller_name = s.poller_name();

  // Set cache directory.
  _cache_dir = s.cache_directory();
  if (!_cache_dir.empty())
    _cache_dir.append("/");
  _cache_dir.append(s.broker_name());

  // Apply logging configuration.
  logger::instance().apply(s.loggers());

  // Flush logs or not.
  com::centreon::broker::logging::file::with_flush(
    s.flush_logs());

  // Enable or not thread ID logging.
  com::centreon::broker::logging::file::with_thread_id(
    s.log_thread_id());

  // Enable or not timestamp logging.
  com::centreon::broker::logging::file::with_timestamp(
    s.log_timestamp());

  // Enable or not human readable timstamp logging.
  com::centreon::broker::logging::file::with_human_redable_timestamp(
    s.log_human_readable_timestamp());

  // Apply modules configuration.
  modules::instance().apply(
                        s.module_list(),
                        s.module_directory(),
                        &s);
  static bool first_application(true);
  if (first_application)
    first_application = false;
  else {
    unsigned int module_count(0);
    for (modules::iterator
           it(modules::instance().begin()),
           end(modules::instance().end());
         it != end;
         ++it)
      ++module_count;
    if (module_count)
      logging::config(logging::high) << "applier: " << module_count
        << " modules loaded";
    else
      logging::config(logging::high) << "applier: no module loaded, "
        "you might want to check the 'module_directory' directive";
  }

  // Event queue max size (used to limit memory consumption).
  com::centreon::broker::multiplexing::muxer::event_queue_max_size(
    s.event_queue_max_size());

  com::centreon::broker::config::state st = s;

  // Create command file input.
  if (!s.command_file().empty()) {
    config::endpoint ept;
    ept.name = "(external commands)";
    ept.type = "extcmd";
    ept.params.insert(
      "extcmd",
      QString::fromStdString(s.command_file()));
    ept.params.insert(
      "command_protocol",
      QString::fromStdString(s.command_protocol()));
    ept.read_filters.insert("all");
    st.endpoints().push_back(ept);
  }

  // Apply input and output configuration.
  endpoint::instance().apply(st.endpoints());

  // Create instance broadcast event.
  misc::shared_ptr<instance_broadcast> ib(new instance_broadcast);
  ib->broker_id = io::data::broker_id;
  ib->poller_id = _poller_id;
  ib->poller_name = _poller_name.c_str();
  ib->enabled = true;
  com::centreon::broker::multiplexing::engine::instance().publish(ib);

  // Enable multiplexing loop.
  if (run_mux)
    com::centreon::broker::multiplexing::engine::instance().start();

  return ;
}

/**
 *  Get applied cache directory.
 *
 *  @return Cache directory.
 */
std::string const& state::cache_dir() const throw () {
  return (_cache_dir);
}

/**
 *  Get the instance of this object.
 *
 *  @return Class instance.
 */
state& state::instance() {
  return (*gl_state);
}

/**
 *  Load singleton.
 */
void state::load() {
  if (!gl_state)
    gl_state = new state;
  return ;
}

/**
 *  Get the poller ID.
 *
 *  @return Poller ID of this Broker instance.
 */
unsigned int state::poller_id() const throw () {
  return (_poller_id);
}

/**
 *  Get the poller name.
 *
 *  @return Poller name of this Broker instance.
 */
std::string const& state::poller_name() const throw () {
  return (_poller_name);
}

/**
 *  Unload singleton.
 */
void state::unload() {
  delete gl_state;
  gl_state = NULL;
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
state::state() : _poller_id(0) {}
<|endoftext|>


<commit_before>// v8
#include <v8.h>

// node
#include <node.h>
#include <node_buffer.h>
#include <node_version.h>

/* dlopen(), dlsym() */
#include <dlfcn.h>

// boost
#include "utils.hpp"

// node-mapnik
#include "mapnik_map.hpp"
#include "mapnik_projection.hpp"
#include "mapnik_layer.hpp"
#include "mapnik_datasource.hpp"

// mapnik
#include <mapnik/version.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>

// boost
#include <boost/version.hpp>

// cairo

#if defined(HAVE_CAIRO)
#include <cairo-version.h>
#endif

using namespace node;
using namespace v8;

/**
 * Optional notification that the embedder is idle.
 * V8 uses the notification to reduce memory footprint.
 * This call can be used repeatedly if the embedder remains idle.
 * Returns true if the embedder should stop calling IdleNotification
 * until real work has been done.  This indicates that V8 has done
 * as much cleanup as it will be able to do.
 */
static Handle<Value> gc(const Arguments& args)
{
  HandleScope scope;
  return scope.Close(Boolean::New(V8::IdleNotification()));
}

static Handle<Value> make_mapnik_symbols_visible(const Arguments& args)
{
  HandleScope scope;
  if (args.Length() != 1 || !args[0]->IsString())
    return ThrowException(Exception::TypeError(
      String::New("first argument must be a path to a directory holding _mapnik.node")));
  String::Utf8Value filename(args[0]->ToString());
  void *handle = dlopen(*filename, RTLD_NOW|RTLD_GLOBAL);
  if (handle == NULL) {
      return False();
  }
  else
  {
      dlclose(handle);
      return True();
  }
}

static Handle<Value> register_datasources(const Arguments& args)
{
    HandleScope scope;
    if (args.Length() != 1 || !args[0]->IsString())
      return ThrowException(Exception::TypeError(
        String::New("first argument must be a path to a directory of mapnik input plugins")));

    std::vector<std::string> const names_before = mapnik::datasource_cache::plugin_names();
    std::string const& path = TOSTR(args[0]);
    mapnik::datasource_cache::instance()->register_datasources(path);
    std::vector<std::string> const& names_after = mapnik::datasource_cache::plugin_names();
    if (names_after.size() > names_before.size())
        return scope.Close(Boolean::New(true));
    return scope.Close(Boolean::New(false));
}

static Handle<Value> available_input_plugins(const Arguments& args)
{
    HandleScope scope;
    std::vector<std::string> const& names = mapnik::datasource_cache::plugin_names();
    Local<Array> a = Array::New(names.size());
    for (unsigned i = 0; i < names.size(); ++i)
    {
        a->Set(i, String::New(names[i].c_str()));
    }
    return scope.Close(a);
}

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

  if (!args.Length() >= 1 || !args[0]->IsString())
    return ThrowException(Exception::TypeError(
      String::New("first argument must be a path to a directory of fonts")));

  bool found = false;

  std::vector<std::string> const names_before = mapnik::freetype_engine::face_names();

  // option hash
  if (args.Length() == 2){
    if (!args[1]->IsObject())
      return ThrowException(Exception::TypeError(
        String::New("second argument is optional, but if provided must be an object, eg. { recurse:Boolean }")));

      Local<Object> options = args[1]->ToObject();
      if (options->Has(String::New("recurse")))
      {
          Local<Value> recurse_opt = options->Get(String::New("recurse"));
          if (!recurse_opt->IsBoolean())
            return ThrowException(Exception::TypeError(
              String::New("'recurse' must be a Boolean")));

          bool recurse = recurse_opt->BooleanValue();
          std::string const& path = TOSTR(args[0]);
          found = mapnik::freetype_engine::register_fonts(path,recurse);
      }
  }
  else
  {
      std::string const& path = TOSTR(args[0]);
      found = mapnik::freetype_engine::register_fonts(path);
  }

  std::vector<std::string> const& names_after = mapnik::freetype_engine::face_names();
  if (names_after.size() == names_before.size())
      found = false;

  return scope.Close(Boolean::New(found));
}

static Handle<Value> available_font_faces(const Arguments& args)
{
    HandleScope scope;
    std::vector<std::string> const& names = mapnik::freetype_engine::face_names();
    Local<Array> a = Array::New(names.size());
    for (unsigned i = 0; i < names.size(); ++i)
    {
        a->Set(i, String::New(names[i].c_str()));
    }
    return scope.Close(a);
}

static std::string format_version(int version)
{
    std::ostringstream s;
    s << version/100000 << "." << version/100 % 1000  << "." << version % 100;
    return s.str();
}

extern "C" {

  static void init (Handle<Object> target)
  {
    // module level functions
    NODE_SET_METHOD(target, "make_mapnik_symbols_visible", make_mapnik_symbols_visible);
    NODE_SET_METHOD(target, "register_datasources", register_datasources);
    NODE_SET_METHOD(target, "datasources", available_input_plugins);
    NODE_SET_METHOD(target, "register_fonts", register_fonts);
    NODE_SET_METHOD(target, "fonts", available_font_faces);
    NODE_SET_METHOD(target, "gc", gc);

    // Map
    Map::Initialize(target);

    // Projection
    Projection::Initialize(target);

    // Layer
    Layer::Initialize(target);

    // Datasource
    Datasource::Initialize(target);

    // node-mapnik version
    target->Set(String::NewSymbol("version"), String::New("0.2.2"));

    // versions of deps
    Local<Object> versions = Object::New();
    versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
    versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
    versions->Set(String::NewSymbol("boost"), String::New(format_version(BOOST_VERSION).c_str()));
    versions->Set(String::NewSymbol("boost_number"), Integer::New(BOOST_VERSION));
    versions->Set(String::NewSymbol("mapnik"), String::New(format_version(MAPNIK_VERSION).c_str()));
    versions->Set(String::NewSymbol("mapnik_number"), Integer::New(MAPNIK_VERSION));
    #if defined(HAVE_CAIRO)
      std::ostringstream s;
      s << CAIRO_VERSION_MAJOR << "." << CAIRO_VERSION_MINOR << "." << CAIRO_VERSION_MICRO;
      versions->Set(String::NewSymbol("cairo"), String::New(s.str().c_str()));
    #endif
    target->Set(String::NewSymbol("versions"), versions);

    // built in support
    Local<Object> supports = Object::New();
    #if defined(HAVE_CAIRO)
      supports->Set(String::NewSymbol("cairo"), Boolean::New(true));
    #else
      supports->Set(String::NewSymbol("cairo"), Boolean::New(false));
    #endif
    #if defined(HAVE_JPEG)
      supports->Set(String::NewSymbol("jpeg"), Boolean::New(true));
    #else
      supports->Set(String::NewSymbol("jpeg"), Boolean::New(false));
    #endif
    target->Set(String::NewSymbol("supports"), supports);

  }

  NODE_MODULE(_mapnik, init);
}
<commit_msg>pushing version 0.2.3<commit_after>// v8
#include <v8.h>

// node
#include <node.h>
#include <node_buffer.h>
#include <node_version.h>

/* dlopen(), dlsym() */
#include <dlfcn.h>

// boost
#include "utils.hpp"

// node-mapnik
#include "mapnik_map.hpp"
#include "mapnik_projection.hpp"
#include "mapnik_layer.hpp"
#include "mapnik_datasource.hpp"

// mapnik
#include <mapnik/version.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>

// boost
#include <boost/version.hpp>

// cairo

#if defined(HAVE_CAIRO)
#include <cairo-version.h>
#endif

using namespace node;
using namespace v8;

/**
 * Optional notification that the embedder is idle.
 * V8 uses the notification to reduce memory footprint.
 * This call can be used repeatedly if the embedder remains idle.
 * Returns true if the embedder should stop calling IdleNotification
 * until real work has been done.  This indicates that V8 has done
 * as much cleanup as it will be able to do.
 */
static Handle<Value> gc(const Arguments& args)
{
  HandleScope scope;
  return scope.Close(Boolean::New(V8::IdleNotification()));
}

static Handle<Value> make_mapnik_symbols_visible(const Arguments& args)
{
  HandleScope scope;
  if (args.Length() != 1 || !args[0]->IsString())
    return ThrowException(Exception::TypeError(
      String::New("first argument must be a path to a directory holding _mapnik.node")));
  String::Utf8Value filename(args[0]->ToString());
  void *handle = dlopen(*filename, RTLD_NOW|RTLD_GLOBAL);
  if (handle == NULL) {
      return False();
  }
  else
  {
      dlclose(handle);
      return True();
  }
}

static Handle<Value> register_datasources(const Arguments& args)
{
    HandleScope scope;
    if (args.Length() != 1 || !args[0]->IsString())
      return ThrowException(Exception::TypeError(
        String::New("first argument must be a path to a directory of mapnik input plugins")));

    std::vector<std::string> const names_before = mapnik::datasource_cache::plugin_names();
    std::string const& path = TOSTR(args[0]);
    mapnik::datasource_cache::instance()->register_datasources(path);
    std::vector<std::string> const& names_after = mapnik::datasource_cache::plugin_names();
    if (names_after.size() > names_before.size())
        return scope.Close(Boolean::New(true));
    return scope.Close(Boolean::New(false));
}

static Handle<Value> available_input_plugins(const Arguments& args)
{
    HandleScope scope;
    std::vector<std::string> const& names = mapnik::datasource_cache::plugin_names();
    Local<Array> a = Array::New(names.size());
    for (unsigned i = 0; i < names.size(); ++i)
    {
        a->Set(i, String::New(names[i].c_str()));
    }
    return scope.Close(a);
}

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

  if (!args.Length() >= 1 || !args[0]->IsString())
    return ThrowException(Exception::TypeError(
      String::New("first argument must be a path to a directory of fonts")));

  bool found = false;

  std::vector<std::string> const names_before = mapnik::freetype_engine::face_names();

  // option hash
  if (args.Length() == 2){
    if (!args[1]->IsObject())
      return ThrowException(Exception::TypeError(
        String::New("second argument is optional, but if provided must be an object, eg. { recurse:Boolean }")));

      Local<Object> options = args[1]->ToObject();
      if (options->Has(String::New("recurse")))
      {
          Local<Value> recurse_opt = options->Get(String::New("recurse"));
          if (!recurse_opt->IsBoolean())
            return ThrowException(Exception::TypeError(
              String::New("'recurse' must be a Boolean")));

          bool recurse = recurse_opt->BooleanValue();
          std::string const& path = TOSTR(args[0]);
          found = mapnik::freetype_engine::register_fonts(path,recurse);
      }
  }
  else
  {
      std::string const& path = TOSTR(args[0]);
      found = mapnik::freetype_engine::register_fonts(path);
  }

  std::vector<std::string> const& names_after = mapnik::freetype_engine::face_names();
  if (names_after.size() == names_before.size())
      found = false;

  return scope.Close(Boolean::New(found));
}

static Handle<Value> available_font_faces(const Arguments& args)
{
    HandleScope scope;
    std::vector<std::string> const& names = mapnik::freetype_engine::face_names();
    Local<Array> a = Array::New(names.size());
    for (unsigned i = 0; i < names.size(); ++i)
    {
        a->Set(i, String::New(names[i].c_str()));
    }
    return scope.Close(a);
}

static std::string format_version(int version)
{
    std::ostringstream s;
    s << version/100000 << "." << version/100 % 1000  << "." << version % 100;
    return s.str();
}

extern "C" {

  static void init (Handle<Object> target)
  {
    // module level functions
    NODE_SET_METHOD(target, "make_mapnik_symbols_visible", make_mapnik_symbols_visible);
    NODE_SET_METHOD(target, "register_datasources", register_datasources);
    NODE_SET_METHOD(target, "datasources", available_input_plugins);
    NODE_SET_METHOD(target, "register_fonts", register_fonts);
    NODE_SET_METHOD(target, "fonts", available_font_faces);
    NODE_SET_METHOD(target, "gc", gc);

    // Map
    Map::Initialize(target);

    // Projection
    Projection::Initialize(target);

    // Layer
    Layer::Initialize(target);

    // Datasource
    Datasource::Initialize(target);

    // node-mapnik version
    target->Set(String::NewSymbol("version"), String::New("0.2.3"));

    // versions of deps
    Local<Object> versions = Object::New();
    versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
    versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
    versions->Set(String::NewSymbol("boost"), String::New(format_version(BOOST_VERSION).c_str()));
    versions->Set(String::NewSymbol("boost_number"), Integer::New(BOOST_VERSION));
    versions->Set(String::NewSymbol("mapnik"), String::New(format_version(MAPNIK_VERSION).c_str()));
    versions->Set(String::NewSymbol("mapnik_number"), Integer::New(MAPNIK_VERSION));
    #if defined(HAVE_CAIRO)
      std::ostringstream s;
      s << CAIRO_VERSION_MAJOR << "." << CAIRO_VERSION_MINOR << "." << CAIRO_VERSION_MICRO;
      versions->Set(String::NewSymbol("cairo"), String::New(s.str().c_str()));
    #endif
    target->Set(String::NewSymbol("versions"), versions);

    // built in support
    Local<Object> supports = Object::New();
    #if defined(HAVE_CAIRO)
      supports->Set(String::NewSymbol("cairo"), Boolean::New(true));
    #else
      supports->Set(String::NewSymbol("cairo"), Boolean::New(false));
    #endif
    #if defined(HAVE_JPEG)
      supports->Set(String::NewSymbol("jpeg"), Boolean::New(true));
    #else
      supports->Set(String::NewSymbol("jpeg"), Boolean::New(false));
    #endif
    target->Set(String::NewSymbol("supports"), supports);

  }

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