<commit_before>/*************************************************************************
 *
 *  $RCSfile: X11_transferable.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: pl $ $Date: 2001-02-07 17:59:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <X11_transferable.hxx>
#include <X11/Xatom.h>

#ifndef _COM_SUN_STAR_IO_IOEXCEPTION_HPP_
#include <com/sun/star/io/IOException.hpp>
#endif

using namespace com::sun::star::datatransfer;
using namespace com::sun::star::lang;
using namespace com::sun::star::io;
using namespace com::sun::star::uno;
using namespace cppu;
using namespace osl;
using namespace rtl;

using namespace x11;

X11Transferable::X11Transferable(
    SelectionManager& rManager,
    const Reference< XInterface >& xCreator,
    Atom selection
    ) :
        m_rManager( rManager ),
        m_xCreator( xCreator ),
        m_aSelection( selection )
{
}

//==================================================================================================

X11Transferable::~X11Transferable()
{
}

//==================================================================================================

Any SAL_CALL X11Transferable::getTransferData( const DataFlavor& rFlavor )
    throw(UnsupportedFlavorException, IOException, RuntimeException)
{
    Any aRet;
    Sequence< sal_Int8 > aData;
    bool bSuccess = m_rManager.getPasteData( m_aSelection ? m_aSelection : XA_PRIMARY, rFlavor.MimeType, aData );
    if( ! bSuccess && m_aSelection == 0 )
        bSuccess = m_rManager.getPasteData( m_rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), rFlavor.MimeType, aData );

    if( ! bSuccess )
    {
        throw UnsupportedFlavorException( rFlavor.MimeType, static_cast < XTransferable * > ( this ) );
    }
    if( rFlavor.MimeType.equalsIgnoreCase( OUString::createFromAscii( "text/plain;charset=utf-16" ) ) )
    {
        OUString aString( (sal_Unicode*)aData.getConstArray(), aData.getLength()/sizeof( sal_Unicode ) );
        aRet <<= aString;
    }
    else
        aRet <<= aData;
    return aRet;
}

//==================================================================================================

Sequence< DataFlavor > SAL_CALL X11Transferable::getTransferDataFlavors()
    throw(RuntimeException)
{
    Sequence< DataFlavor > aFlavorList;
    bool bSuccess = m_rManager.getPasteDataTypes( m_aSelection ? m_aSelection : XA_PRIMARY, aFlavorList );
    if( ! bSuccess && m_aSelection == 0 )
        bSuccess = m_rManager.getPasteDataTypes( m_rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), aFlavorList );

    return aFlavorList;
}

//==================================================================================================

sal_Bool SAL_CALL X11Transferable::isDataFlavorSupported( const DataFlavor& aFlavor )
    throw(RuntimeException)
{
    if( aFlavor.DataType != getCppuType( (Sequence< sal_Int8 >*)0 ) )
    {
        if( ! aFlavor.MimeType.equalsIgnoreCase( OUString::createFromAscii( "text/plain;charset=utf-16" ) ) &&
            aFlavor.DataType == getCppuType( (OUString*)0 ) )
            return false;
    }

    Sequence< DataFlavor > aFlavors( getTransferDataFlavors() );
    for( int i = 0; i < aFlavors.getLength(); i++ )
        if( aFlavor.MimeType.equalsIgnoreCase( aFlavors.getConstArray()[i].MimeType ) &&
            aFlavor.DataType == aFlavors.getConstArray()[i].DataType )
            return sal_True;

    return sal_False;
}

<commit_msg>handle terminated strings as well as unterminated<commit_after>/*************************************************************************
 *
 *  $RCSfile: X11_transferable.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: pl $ $Date: 2001-02-21 16:34:09 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <X11_transferable.hxx>
#include <X11/Xatom.h>

#ifndef _COM_SUN_STAR_IO_IOEXCEPTION_HPP_
#include <com/sun/star/io/IOException.hpp>
#endif

using namespace com::sun::star::datatransfer;
using namespace com::sun::star::lang;
using namespace com::sun::star::io;
using namespace com::sun::star::uno;
using namespace cppu;
using namespace osl;
using namespace rtl;

using namespace x11;

X11Transferable::X11Transferable(
    SelectionManager& rManager,
    const Reference< XInterface >& xCreator,
    Atom selection
    ) :
        m_rManager( rManager ),
        m_xCreator( xCreator ),
        m_aSelection( selection )
{
}

//==================================================================================================

X11Transferable::~X11Transferable()
{
}

//==================================================================================================

Any SAL_CALL X11Transferable::getTransferData( const DataFlavor& rFlavor )
    throw(UnsupportedFlavorException, IOException, RuntimeException)
{
    Any aRet;
    Sequence< sal_Int8 > aData;
    bool bSuccess = m_rManager.getPasteData( m_aSelection ? m_aSelection : XA_PRIMARY, rFlavor.MimeType, aData );
    if( ! bSuccess && m_aSelection == 0 )
        bSuccess = m_rManager.getPasteData( m_rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), rFlavor.MimeType, aData );

    if( ! bSuccess )
    {
        throw UnsupportedFlavorException( rFlavor.MimeType, static_cast < XTransferable * > ( this ) );
    }
    if( rFlavor.MimeType.equalsIgnoreCase( OUString::createFromAscii( "text/plain;charset=utf-16" ) ) )
    {
        int nLen = aData.getLength()/2;
        if( ((sal_Unicode*)aData.getConstArray())[nLen-1] == 0 )
            nLen--;
        OUString aString( (sal_Unicode*)aData.getConstArray(), nLen );
#ifdef DEBUG
    fprintf( stderr, "X11Transferable::getTransferData( \"%s\" )\n -> \"%s\"\n",
             OUStringToOString( rFlavor.MimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
             OUStringToOString( aString, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
#endif
        aRet <<= aString;
    }
    else
        aRet <<= aData;
    return aRet;
}

//==================================================================================================

Sequence< DataFlavor > SAL_CALL X11Transferable::getTransferDataFlavors()
    throw(RuntimeException)
{
    Sequence< DataFlavor > aFlavorList;
    bool bSuccess = m_rManager.getPasteDataTypes( m_aSelection ? m_aSelection : XA_PRIMARY, aFlavorList );
    if( ! bSuccess && m_aSelection == 0 )
        bSuccess = m_rManager.getPasteDataTypes( m_rManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), aFlavorList );

    return aFlavorList;
}

//==================================================================================================

sal_Bool SAL_CALL X11Transferable::isDataFlavorSupported( const DataFlavor& aFlavor )
    throw(RuntimeException)
{
    if( aFlavor.DataType != getCppuType( (Sequence< sal_Int8 >*)0 ) )
    {
        if( ! aFlavor.MimeType.equalsIgnoreCase( OUString::createFromAscii( "text/plain;charset=utf-16" ) ) &&
            aFlavor.DataType == getCppuType( (OUString*)0 ) )
            return false;
    }

    Sequence< DataFlavor > aFlavors( getTransferDataFlavors() );
    for( int i = 0; i < aFlavors.getLength(); i++ )
        if( aFlavor.MimeType.equalsIgnoreCase( aFlavors.getConstArray()[i].MimeType ) &&
            aFlavor.DataType == aFlavors.getConstArray()[i].DataType )
            return sal_True;

    return sal_False;
}

<|endoftext|>


<commit_before>#ifndef DUNE_FUNCTIONALS_COMMON_LOCALVECTOR_HH
#define DUNE_FUNCTIONALS_COMMON_LOCALVECTOR_HH

namespace Dune {

namespace Functionals {

namespace Common {

/**
  * \brief  This class represents a local DoF vector.
  *         It is based upon std::vector and should be replaced by something clever in the future!
  *
  * \tparam ElementType
  *         Type of one element, usually double or RangeFieldType.
  **/
template <class ElementType>
class LocalVector
{
public:
  /**
    * \brief      Initializes an empty vector, according to the given size.
    *
    * \param[in]  size
    *             Size, the vector should have, usually the number of local DoFs.
    **/
  LocalVector(const unsigned int size)
  {
    // resize
    storage_.resize(size, 0.0);
  }

  /**
    * \brief      Initializes a DoF vector and sets its entries to the
    *             corresponding entries of the given localFunction.
    *
    * \tparam     LocalFunctionType
    *             Type of the given local function, usually something that fulfills the Dune::LocalFunction interface.
    *
    * \param[in]  localFunction
    *             Local function, whose DoFs are going to be assigned to the vector. Has to provide the method
    *             numDofs() and read access via an operator[].
    **/
  template <class LocalFunctionType>
  LocalVector(const LocalFunctionType& localFunction)
  {
    // resize
    storage_.resize(localFunction.numDofs(), 0.0);

    // copy entries
    for (int i = 0; i < localFunction.numDofs(); ++i) {
      storage_[i] = localFunction[i];
    }
  }

  /**
    * \brief      Returns the size.
    *
    * \param[out] const unsigned int
    *             Number of entries.
    */
  const unsigned int size() const
  {
    return storage_.size();
  }

  /**
    * \brief      Random read and write access.
    *
    * \param[in]  i
    *             Number of the element.
    *
    * \param[out] ElementType&
    *             Reference to the element at position i, writable.
    **/
  ElementType& operator[](const unsigned int i)
  {
    return storage_[i];
  }

  /**
    * \brief      Random read access.
    * \param[in]  i
    *             Number of the element.
    *
    * \param[out] const ElementType
    *             Reference to the element at position i, readable only.
    **/
  const ElementType operator[](const unsigned int i) const
  {
    return storage_[i];
  }

  /**
    * \brief      Scalar product of two local vectors of same type.
    *
    * \param[in]  other
    *             The LocalVector, that will be multiplied with from the right.
    *
    * \param[out] ElementType
    *             Result of the scalar product.
    **/
  ElementType operator*(const LocalVector<ElementType>& other) const
  {
    assert(storage_.size() == other.size());
    ElementType result = 0.0;

    for (unsigned ii = 0; ii < storage_.size(); ++ii) {
      result += storage_[ii] * other[ii];
    }

    return result;
  }

private:
  std::vector<ElementType> storage_;

}; // end of class LocalVector

} // end of namespace Common

} // end of namespace Functionals

} // end of namespace Dune

#endif // end DUNE_FUNCTIONALS_COMMON_LOCALVECTOR_HH
<commit_msg>added another constructor to Common::LocalVector<commit_after>#ifndef DUNE_FUNCTIONALS_COMMON_LOCALVECTOR_HH
#define DUNE_FUNCTIONALS_COMMON_LOCALVECTOR_HH

namespace Dune {

namespace Functionals {

namespace Common {

/**
  * \brief  This class represents a local DoF vector.
  *         It is based upon std::vector and should be replaced by something clever in the future!
  *
  * \tparam ElementType
  *         Type of one element, usually double or RangeFieldType.
  **/
template <class ElementType>
class LocalVector
{
public:
  /**
    * \brief      Initializes an empty vector, according to the given size.
    *
    * \param[in]  size
    *             Size, the vector should have, usually the number of local DoFs.
    **/
  LocalVector(const unsigned int size)
  {
    // resize
    storage_.resize(size, 0.0);
  }

  LocalVector(const int size)
  {
    // resize
    storage_.resize(size, 0.0);
  }

  /**
    * \brief      Initializes a DoF vector and sets its entries to the
    *             corresponding entries of the given localFunction.
    *
    * \tparam     LocalFunctionType
    *             Type of the given local function, usually something that fulfills the Dune::LocalFunction interface.
    *
    * \param[in]  localFunction
    *             Local function, whose DoFs are going to be assigned to the vector. Has to provide the method
    *             numDofs() and read access via an operator[].
    **/
  template <class LocalFunctionType>
  LocalVector(const LocalFunctionType& localFunction)
  {
    // resize
    storage_.resize(localFunction.numDofs(), 0.0);

    // copy entries
    for (int i = 0; i < localFunction.numDofs(); ++i) {
      storage_[i] = localFunction[i];
    }
  }

  /**
    * \brief      Returns the size.
    *
    * \param[out] const unsigned int
    *             Number of entries.
    */
  const unsigned int size() const
  {
    return storage_.size();
  }

  /**
    * \brief      Random read and write access.
    *
    * \param[in]  i
    *             Number of the element.
    *
    * \param[out] ElementType&
    *             Reference to the element at position i, writable.
    **/
  ElementType& operator[](const unsigned int i)
  {
    return storage_[i];
  }

  /**
    * \brief      Random read access.
    * \param[in]  i
    *             Number of the element.
    *
    * \param[out] const ElementType
    *             Reference to the element at position i, readable only.
    **/
  const ElementType operator[](const unsigned int i) const
  {
    return storage_[i];
  }

  /**
    * \brief      Scalar product of two local vectors of same type.
    *
    * \param[in]  other
    *             The LocalVector, that will be multiplied with from the right.
    *
    * \param[out] ElementType
    *             Result of the scalar product.
    **/
  ElementType operator*(const LocalVector<ElementType>& other) const
  {
    assert(storage_.size() == other.size());
    ElementType result = 0.0;

    for (unsigned ii = 0; ii < storage_.size(); ++ii) {
      result += storage_[ii] * other[ii];
    }

    return result;
  }

private:
  std::vector<ElementType> storage_;

}; // end of class LocalVector

} // end of namespace Common

} // end of namespace Functionals

} // end of namespace Dune

#endif // end DUNE_FUNCTIONALS_COMMON_LOCALVECTOR_HH
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_FUNCTION_EXPRESSION_BASE_HH
#define DUNE_STUFF_FUNCTION_EXPRESSION_BASE_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <sstream>
#include <vector>

//#if HAVE_EIGEN
//  #include <Eigen/Core>
//#endif // HAVE_EIGEN

#include <dune/common/fvector.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/static_assert.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/color.hh>

#include "mathexpr.hh"

namespace Dune {
namespace Stuff {
namespace Function {

///**
//  \brief  Provides a function which evaluates a given mathematical expression at runtime.

//          Given a mathematical expression as a string, a domain \f$ K_d^{m \geq 1} \f$ and a range \f$ K_r^{n \geq 1}
//          \f$ this function represents the map
//          \f{eqnarray}
//            f:K_d^m \to K_r^n\\
//            x = (x_1, \dots, x_m)' \mapsto (f_1(x), \dots f_n(x))',
//          \f}
//          where \f$ K_d \f$ is the DomainType and \f$ K_r \f$ is the RangeType, usually a power of \f$ \mathcal{R} \f$.
//          The name of the variable as well as the \f$ n \f$ expressions of \f$f_1, \dots, f_n\f$ have to be given in a
//          Dune::ParameterTree in the following form:
//\code variable: x
//expression.0: 2*x[0]
//expression.1: sin(x[1])*x[0]\endcode
//          There have to exist at least \f$n\f$ expressions; the entries of the variable are indexed by \f$[i]\f$ for
//          \f$ 0 \leq i \leq m - 1 \f$.
// **/
/**
 *  \brief base class that wraps makes a function out of the stuff from mathexpr.hh
 *  \attention  Most surely you do not want to use this class directly!
 */
template< class DomainFieldImp, int domainDim,
          class RangeFieldImp, int rangeDim >
class ExpressionBase
{
public:
  typedef ExpressionBase< DomainFieldImp, domainDim, RangeFieldImp, rangeDim > ThisType;

  typedef DomainFieldImp  DomainFieldType;
  static const int        dimDomain = domainDim;

  typedef RangeFieldImp   RangeFieldType;
  static const int        dimRange = rangeDim;

  ExpressionBase(const std::string _variable, const std::string _expression)
  {
    const std::vector< std::string > expressions(1, _expression);
    setup(_variable, expressions);
  } // NonparametricExpression(const std::string variable, const std::string expression)

  ExpressionBase(const std::string _variable, const std::vector< std::string > _expressions)
  {
    setup(_variable, _expressions);
  } // NonparametricExpression(const std::string variable, const std::vector< std::string >& expressions)

  ExpressionBase(const ThisType& _other)
  {
    setup(_other.variable(), _other.expression());
  } // NonparametricExpression(const ThisType& other)

  ThisType& operator=(const ThisType& _other)
  {
    if (this != &_other) {
      cleanup();
      variable_ = "";
      variables_ = std::vector< std::string >();
      expressions_ = std::vector< std::string >();
      setup(_other.variable(), _other.expression());
    }
    return this;
  } // ThisType& operator=(const ThisType& other)

  ~ExpressionBase()
  {
    cleanup();
  } // ~NonparametricExpression()

  std::string variable() const
  {
    return variable_;
  }

  const std::vector< std::string >& expression() const
  {
    return expressions_;
  }

  void evaluate(const Dune::FieldVector< DomainFieldType, dimDomain >& _arg,
                Dune::FieldVector< RangeFieldType, dimRange >& _ret) const
  {
    // copy arg
    for (typename Dune::FieldVector< DomainFieldType, dimDomain >::size_type ii = 0; ii < dimDomain; ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    for (typename Dune::FieldVector< RangeFieldType, dimRange >::size_type ii = 0; ii < dimRange; ++ii)
      _ret[ii] = op_[ii]->Val();
  }

  /**
   *  \attention  _arg will be used up to its size, _ret will be resized!
   */
  void evaluate(const Dune::DynamicVector< DomainFieldType >& _arg,
                Dune::DynamicVector< RangeFieldType >& _ret) const
  {
    // check for sizes
    if (_ret.size() != dimRange)
      _ret = Dune::DynamicVector< RangeFieldType >(dimRange);
    // copy arg
    for (int ii = 0; ii < std::min(domainDim, int(_arg.size())); ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    for (int ii = 0; ii < dimRange; ++ii)
      _ret[ii] = op_[ii]->Val();
  }

  /**
   *  \attention  _arg will be used up to its size
   */
  void evaluate(const Dune::DynamicVector< DomainFieldType >& _arg,
                Dune::FieldVector< RangeFieldType, dimRange >& _ret) const
  {
    // copy arg
    for (int ii = 0; ii < std::min(domainDim, int(_arg.size())); ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    for (int ii = 0; ii < dimRange; ++ii)
      _ret[ii] = op_[ii]->Val();
  }

//#if HAVE_EIGEN
//  void evaluate(const Eigen::Matrix< Eigen::Dynamic, 1, DomainFieldType >& _arg,
//                Eigen::Matrix< Eigen::Dynamic, 1, RangeFieldType >& _ret)
//  {
//    // check for sizes
//    assert(_arg.size() <= dimDomain);
//    if (_ret.size != dimRange)
//      _ret.resize(dimRange);
//    // copy arg
//    for (typename Dune::DynamicVector< DomainFieldType >::size_type ii = 0; ii < dimDomain; ++ii)
//      *(arg_[ii]) = arg[ii];
//    // copy ret
//    for (typename RangeType::size_type ii = 0; ii < ret.size(); ++ii)
//      ret[ii] = op_[ii]->Val();
//  }
//#endif // HAVE_EIGEN

  void report(const std::string _name = "function.nonparametric.expression",
              std::ostream& _stream = std::cout,
              const std::string& _prefix = "") const
  {
    const std::string tmp = _name + "(" + variable() + ") = ";
    _stream << _prefix << tmp;
    if (expression().size() == 1)
        _stream << expression()[0] << std::endl;
    else {
      _stream << "[ " << expression()[0] << ";" << std::endl;
      const std::string whitespace = Dune::Stuff::Common::whitespaceify(tmp + "[ ");
      for (unsigned int i = 1; i < expression().size() - 1; ++i)
        _stream << _prefix << whitespace << expression()[i] << ";" << std::endl;
      _stream << _prefix << whitespace << expression()[expression().size() -1] << " ]" << std::endl;
    }
  } // void report(const std::string, std::ostream&, const std::string&) const

private:
  void setup(const std::string& _variable, const std::vector< std::string >& _expression)
  {
    dune_static_assert((dimDomain > 0), "Really?");
    dune_static_assert((dimRange > 0), "Really?");
    // set expressions
    if (_expression.size() < dimRange)
      DUNE_THROW(Dune::InvalidStateException,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " '_expression' too short (is " << _expression.size()
                 << ", should be " << dimRange << ")!");
    for (int ii = 0; ii < dimRange; ++ii)
      expressions_.push_back(_expression[ii]);
    // set variable (i.e. "x")
    variable_ = _variable;
    // fill variables (i.e. "x[0]", "x[1]", ...)
    for (int ii = 0; ii < dimDomain; ++ii) {
      std::stringstream variableStream;
      variableStream << variable_ << "[" << ii << "]";
      variables_.push_back(variableStream.str());
    }
    // create epressions
    for (int ii = 0; ii < dimDomain; ++ii) {
      arg_[ii] = new DomainFieldType(0.0);
      var_arg_[ii] = new RVar(variables_[ii].c_str(), arg_[ii]);
      vararray_[ii] = var_arg_[ii];
    }
    for (int ii = 0; ii < dimRange; ++ ii) {
      op_[ii] = new ROperation(expressions_[ii].c_str(), dimDomain, vararray_);
    }
  } // void setup(const std::string& variable, const std::vector< std::string >& expressions)

  void cleanup()
  {
    for (int ii = 0; ii < dimRange; ++ii) {
      delete op_[ii];
    }
    for (int ii = 0; ii < dimDomain; ++ii) {
      delete var_arg_[ii];
      delete arg_[ii];
    }
  } // void cleanup()

  std::string                variable_;
  std::vector< std::string > variables_;
  std::vector< std::string > expressions_;
  unsigned int actualDimRange_;
  mutable DomainFieldType* arg_[dimDomain];
  RVar* var_arg_[dimDomain];
  RVar* vararray_[dimDomain];
  ROperation* op_[dimRange];
}; // class ExpressionBase

//template< class DomainFieldImp, int domainDim,
//          class RangeFieldImp, int rangeDim >
//const int ExpressionBase< DomainFieldImp, domainDim, RangeFieldImp, rangeDim >::dimDomain = domainDim;

} // namespace Function
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTION_EXPRESSION_BASE_HH
<commit_msg>[function.expression.base] added a private evaluate() for my friend, the coefficient class<commit_after>#ifndef DUNE_STUFF_FUNCTION_EXPRESSION_BASE_HH
#define DUNE_STUFF_FUNCTION_EXPRESSION_BASE_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <sstream>
#include <vector>

//#if HAVE_EIGEN
//  #include <Eigen/Core>
//#endif // HAVE_EIGEN

#include <dune/common/fvector.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/static_assert.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/color.hh>

#include "mathexpr.hh"

namespace Dune {
namespace Stuff {
namespace Function {

// forward
template< class RangeFieldImp >
class Coefficient;

///**
//  \brief  Provides a function which evaluates a given mathematical expression at runtime.

//          Given a mathematical expression as a string, a domain \f$ K_d^{m \geq 1} \f$ and a range \f$ K_r^{n \geq 1}
//          \f$ this function represents the map
//          \f{eqnarray}
//            f:K_d^m \to K_r^n\\
//            x = (x_1, \dots, x_m)' \mapsto (f_1(x), \dots f_n(x))',
//          \f}
//          where \f$ K_d \f$ is the DomainType and \f$ K_r \f$ is the RangeType, usually a power of \f$ \mathcal{R} \f$.
//          The name of the variable as well as the \f$ n \f$ expressions of \f$f_1, \dots, f_n\f$ have to be given in a
//          Dune::ParameterTree in the following form:
//\code variable: x
//expression.0: 2*x[0]
//expression.1: sin(x[1])*x[0]\endcode
//          There have to exist at least \f$n\f$ expressions; the entries of the variable are indexed by \f$[i]\f$ for
//          \f$ 0 \leq i \leq m - 1 \f$.
// **/
/**
 *  \brief base class that wraps makes a function out of the stuff from mathexpr.hh
 *  \attention  Most surely you do not want to use this class directly!
 */
template< class DomainFieldImp, int domainDim,
          class RangeFieldImp, int rangeDim >
class ExpressionBase
{
public:
  typedef ExpressionBase< DomainFieldImp, domainDim, RangeFieldImp, rangeDim > ThisType;

  typedef DomainFieldImp  DomainFieldType;
  static const int        dimDomain = domainDim;

  typedef RangeFieldImp   RangeFieldType;
  static const int        dimRange = rangeDim;

  ExpressionBase(const std::string _variable, const std::string _expression)
  {
    const std::vector< std::string > expressions(1, _expression);
    setup(_variable, expressions);
  } // NonparametricExpression(const std::string variable, const std::string expression)

  ExpressionBase(const std::string _variable, const std::vector< std::string > _expressions)
  {
    setup(_variable, _expressions);
  } // NonparametricExpression(const std::string variable, const std::vector< std::string >& expressions)

  ExpressionBase(const ThisType& _other)
  {
    setup(_other.variable(), _other.expression());
  } // NonparametricExpression(const ThisType& other)

  ThisType& operator=(const ThisType& _other)
  {
    if (this != &_other) {
      cleanup();
      variable_ = "";
      variables_ = std::vector< std::string >();
      expressions_ = std::vector< std::string >();
      setup(_other.variable(), _other.expression());
    }
    return this;
  } // ThisType& operator=(const ThisType& other)

  ~ExpressionBase()
  {
    cleanup();
  } // ~NonparametricExpression()

  std::string variable() const
  {
    return variable_;
  }

  const std::vector< std::string >& expression() const
  {
    return expressions_;
  }

  void evaluate(const Dune::FieldVector< DomainFieldType, dimDomain >& _arg,
                Dune::FieldVector< RangeFieldType, dimRange >& _ret) const
  {
    // copy arg
    for (typename Dune::FieldVector< DomainFieldType, dimDomain >::size_type ii = 0; ii < dimDomain; ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    for (typename Dune::FieldVector< RangeFieldType, dimRange >::size_type ii = 0; ii < dimRange; ++ii)
      _ret[ii] = op_[ii]->Val();
  }

  /**
   *  \attention  _arg will be used up to its size, _ret will be resized!
   */
  void evaluate(const Dune::DynamicVector< DomainFieldType >& _arg,
                Dune::DynamicVector< RangeFieldType >& _ret) const
  {
    // check for sizes
    if (_ret.size() != dimRange)
      _ret = Dune::DynamicVector< RangeFieldType >(dimRange);
    // copy arg
    for (int ii = 0; ii < std::min(domainDim, int(_arg.size())); ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    for (int ii = 0; ii < dimRange; ++ii)
      _ret[ii] = op_[ii]->Val();
  }

  /**
   *  \attention  _arg will be used up to its size
   */
  void evaluate(const Dune::DynamicVector< DomainFieldType >& _arg,
                Dune::FieldVector< RangeFieldType, dimRange >& _ret) const
  {
    // copy arg
    for (int ii = 0; ii < std::min(domainDim, int(_arg.size())); ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    for (int ii = 0; ii < dimRange; ++ii)
      _ret[ii] = op_[ii]->Val();
  }

//#if HAVE_EIGEN
//  void evaluate(const Eigen::Matrix< Eigen::Dynamic, 1, DomainFieldType >& _arg,
//                Eigen::Matrix< Eigen::Dynamic, 1, RangeFieldType >& _ret)
//  {
//    // check for sizes
//    assert(_arg.size() <= dimDomain);
//    if (_ret.size != dimRange)
//      _ret.resize(dimRange);
//    // copy arg
//    for (typename Dune::DynamicVector< DomainFieldType >::size_type ii = 0; ii < dimDomain; ++ii)
//      *(arg_[ii]) = arg[ii];
//    // copy ret
//    for (typename RangeType::size_type ii = 0; ii < ret.size(); ++ii)
//      ret[ii] = op_[ii]->Val();
//  }
//#endif // HAVE_EIGEN

  void report(const std::string _name = "function.nonparametric.expression",
              std::ostream& _stream = std::cout,
              const std::string& _prefix = "") const
  {
    const std::string tmp = _name + "(" + variable() + ") = ";
    _stream << _prefix << tmp;
    if (expression().size() == 1)
        _stream << expression()[0] << std::endl;
    else {
      _stream << "[ " << expression()[0] << ";" << std::endl;
      const std::string whitespace = Dune::Stuff::Common::whitespaceify(tmp + "[ ");
      for (unsigned int i = 1; i < expression().size() - 1; ++i)
        _stream << _prefix << whitespace << expression()[i] << ";" << std::endl;
      _stream << _prefix << whitespace << expression()[expression().size() -1] << " ]" << std::endl;
    }
  } // void report(const std::string, std::ostream&, const std::string&) const

private:
  friend class Coefficient< RangeFieldType >;

  void evaluate(const Dune::DynamicVector< DomainFieldType >& _arg, RangeFieldType& _ret) const
  {
    assert(dimRange == 1 && "I'm only here to be used by Function::Parametric::Coefficient, which has dimrange == 1");
    // copy arg
    for (int ii = 0; ii < std::min(domainDim, int(_arg.size())); ++ii)
      *(arg_[ii]) = _arg[ii];
    // copy ret
    _ret = op_[0]->Val();
  }

  void setup(const std::string& _variable, const std::vector< std::string >& _expression)
  {
    dune_static_assert((dimDomain > 0), "Really?");
    dune_static_assert((dimRange > 0), "Really?");
    // set expressions
    if (_expression.size() < dimRange)
      DUNE_THROW(Dune::InvalidStateException,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " '_expression' too short (is " << _expression.size()
                 << ", should be " << dimRange << ")!");
    for (int ii = 0; ii < dimRange; ++ii)
      expressions_.push_back(_expression[ii]);
    // set variable (i.e. "x")
    variable_ = _variable;
    // fill variables (i.e. "x[0]", "x[1]", ...)
    for (int ii = 0; ii < dimDomain; ++ii) {
      std::stringstream variableStream;
      variableStream << variable_ << "[" << ii << "]";
      variables_.push_back(variableStream.str());
    }
    // create epressions
    for (int ii = 0; ii < dimDomain; ++ii) {
      arg_[ii] = new DomainFieldType(0.0);
      var_arg_[ii] = new RVar(variables_[ii].c_str(), arg_[ii]);
      vararray_[ii] = var_arg_[ii];
    }
    for (int ii = 0; ii < dimRange; ++ ii) {
      op_[ii] = new ROperation(expressions_[ii].c_str(), dimDomain, vararray_);
    }
  } // void setup(const std::string& variable, const std::vector< std::string >& expressions)

  void cleanup()
  {
    for (int ii = 0; ii < dimRange; ++ii) {
      delete op_[ii];
    }
    for (int ii = 0; ii < dimDomain; ++ii) {
      delete var_arg_[ii];
      delete arg_[ii];
    }
  } // void cleanup()

  std::string                variable_;
  std::vector< std::string > variables_;
  std::vector< std::string > expressions_;
  unsigned int actualDimRange_;
  mutable DomainFieldType* arg_[dimDomain];
  RVar* var_arg_[dimDomain];
  RVar* vararray_[dimDomain];
  ROperation* op_[dimRange];
}; // class ExpressionBase

//template< class DomainFieldImp, int domainDim,
//          class RangeFieldImp, int rangeDim >
//const int ExpressionBase< DomainFieldImp, domainDim, RangeFieldImp, rangeDim >::dimDomain = domainDim;

} // namespace Function
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTION_EXPRESSION_BASE_HH
<|endoftext|>


<commit_before>#include "estimation/jet/fiducial_measurement.hh"

namespace estimation {
namespace jet_filter {

const SE3 fiducial_1_from_world;

FiducialMeasurement observe_fiducial(const State& x, const Parameters& p) {
  FiducialMeasurement meas;
  // const SE3 T_camera_from_world = p.T_camera_from_body * x.T_body_from_world;
  const SE3 T_camera_from_body = SE3();
  const SE3 T_camera_from_world = T_camera_from_body * x.T_body_from_world;

  meas.T_fiducial_from_camera = fiducial_1_from_world * T_camera_from_world.inverse();
  return meas;
}

VecNd<6> fiducial_error_model(const State& x,
                              const FiducialMeasurement& z,
                              const Parameters& p) {
  /*  const SE3 measured_body_from_fiducial =
        (z.T_fiducial_from_camera * p.T_camera_from_body).inverse();
    const SE3 expected_body_from_fiducial =
        x.T_body_from_world * fiducial_1_from_world.inverse();
    const SE3 error = measured_body_from_fiducial * expected_body_from_fiducial;
  */

  const auto expected_fiducial = observe_fiducial(x, p);
  const SE3 error =
      z.T_fiducial_from_camera * expected_fiducial.T_fiducial_from_camera.inverse();

  return SE3::log(error);
}
}  // namespace jet_filter
}  // namespace estimation<commit_msg>Use camera-from-camera for fiducial measurement<commit_after>#include "estimation/jet/fiducial_measurement.hh"

namespace estimation {
namespace jet_filter {

FiducialMeasurement observe_fiducial(const State& x, const Parameters& p) {
  const SE3 fiducial_1_from_world;

  FiducialMeasurement meas;
  // const SE3 T_camera_from_world = p.T_camera_from_body * x.T_body_from_world;
  const SE3 T_camera_from_body = SE3();

  const SE3 T_world_from_body = SE3(x.R_world_from_body, x.x_world);

  const SE3 T_camera_from_world = T_camera_from_body * T_world_from_body.inverse();

  meas.T_fiducial_from_camera = fiducial_1_from_world * T_camera_from_world.inverse();
  return meas;
}

VecNd<6> fiducial_error_model(const State& x,
                              const FiducialMeasurement& z,
                              const Parameters& p) {
  /*  const SE3 measured_body_from_fiducial =
        (z.T_fiducial_from_camera * p.T_camera_from_body).inverse();
    const SE3 expected_body_from_fiducial =
        x.T_body_from_world * fiducial_1_from_world.inverse();
    const SE3 error = measured_body_from_fiducial * expected_body_from_fiducial;
  */

  const auto expected_fiducial = observe_fiducial(x, p);
  // const SE3 error =
  // z.T_fiducial_from_camera * expected_fiducial.T_fiducial_from_camera.inverse();
  const SE3 error =
      z.T_fiducial_from_camera * expected_fiducial.T_fiducial_from_camera.inverse();

  return SE3::log(error);
}
}  // namespace jet_filter
}  // namespace estimation<|endoftext|>


<commit_before>/*

 Copyright (c) 2013, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include "application_manager/commands/mobile/unsubscribe_vehicle_data_request.h"
#include "application_manager/commands/command_impl.h"

#include "application_manager/application_impl.h"
#include "application_manager/message_helper.h"
#include "interfaces/MOBILE_API.h"
#include "interfaces/HMI_API.h"
#include "application_manager/smart_object_keys.h"
#include "utils/helpers.h"

namespace application_manager {
namespace commands {

UnsubscribeVehicleDataRequest::UnsubscribeVehicleDataRequest(
    const MessageSharedPtr& message, ApplicationManager& application_manager)
    : CommandRequestImpl(message, application_manager) {}

UnsubscribeVehicleDataRequest::~UnsubscribeVehicleDataRequest() {}

#ifdef HMI_DBUS_API
namespace {
struct Subrequest {
  hmi_apis::FunctionID::eType func_id;
  const char* str;
};
Subrequest subrequests[] = {
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeGps, strings::gps},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeSpeed, strings::speed},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeRpm, strings::rpm},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeFuelLevel,
     strings::fuel_level},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeFuelLevel_State,
     strings::fuel_level_state},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeInstantFuelConsumption,
     strings::instant_fuel_consumption},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeExternalTemperature,
     strings::external_temp},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeVin, strings::vin},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribePrndl, strings::prndl},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeTirePressure,
     strings::tire_pressure},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeOdometer, strings::odometer},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeBeltStatus,
     strings::belt_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeBodyInformation,
     strings::body_information},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeDeviceStatus,
     strings::device_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeDriverBraking,
     strings::driver_braking},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeWiperStatus,
     strings::wiper_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeHeadLampStatus,
     strings::head_lamp_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeEngineTorque,
     strings::engine_torque},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeAccPedalPosition,
     strings::acc_pedal_pos},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeSteeringWheelAngle,
     strings::steering_wheel_angle},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeECallInfo,
     strings::e_call_info},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeAirbagStatus,
     strings::airbag_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeEmergencyEvent,
     strings::emergency_event},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeClusterModeStatus,
     strings::cluster_mode_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeMyKey, strings::my_key},
};
}
#endif  // #ifdef HMI_DBUS_API

void UnsubscribeVehicleDataRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationSharedPtr app = application_manager_.application(connection_key());

  if (!app) {
    LOG4CXX_ERROR(logger_, "NULL pointer");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  int32_t items_to_unsubscribe = 0;
  int32_t unsubscribed_items = 0;

  const VehicleData& vehicle_data = MessageHelper::vehicle_data();
  VehicleData::const_iterator it = vehicle_data.begin();

  smart_objects::SmartObject msg_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);

  smart_objects::SmartObject response_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);

  for (; vehicle_data.end() != it; ++it) {
    const std::string& key_name = it->first;
    if ((*message_)[strings::msg_params].keyExists(key_name)) {
      bool is_key_enabled = (*message_)[strings::msg_params][key_name].asBool();
      if (is_key_enabled) {
        ++items_to_unsubscribe;

        VehicleDataType key_type = it->second;
        if (!app->IsSubscribedToIVI(key_type)) {
          ++unsubscribed_items;
          vi_already_unsubscribed_by_this_app_.insert(key_type);
          response_params[key_name][strings::data_type] = key_type;
          response_params[key_name][strings::result_code] =
              mobile_apis::VehicleDataResultCode::VDRC_DATA_NOT_SUBSCRIBED;
          continue;
        }

        if (!app->UnsubscribeFromIVI(static_cast<uint32_t>(key_type))) {
          LOG4CXX_ERROR(logger_,
                        "Unable to unsubscribe from "
                        "VehicleDataType: "
                            << key_type);
          continue;
        }

        LOG4CXX_DEBUG(logger_,
                      "Unsubscribed app with connection key "
                          << connection_key()
                          << " from VehicleDataType: " << key_type);

        ++unsubscribed_items;

        if (IsSomeoneSubscribedFor(key_type)) {
          LOG4CXX_DEBUG(logger_,
                        "There are another apps still subscribed for "
                        "VehicleDataType: "
                            << key_type);

          vi_still_subscribed_by_another_apps_.insert(key_type);
          response_params[key_name][strings::data_type] = key_type;
          response_params[key_name][strings::result_code] =
              mobile_apis::VehicleDataResultCode::VDRC_SUCCESS;
          continue;
        }

        msg_params[key_name] = is_key_enabled;
      }
    }
  }

  bool is_everything_already_unsubscribed =
      static_cast<uint32_t>(items_to_unsubscribe) ==
      vi_still_subscribed_by_another_apps_.size() +
          vi_already_unsubscribed_by_this_app_.size();

  if (0 == items_to_unsubscribe) {
    if (HasDisallowedParams()) {
      SendResponse(false, mobile_apis::Result::DISALLOWED);
    } else {
      SendResponse(
          false, mobile_apis::Result::INVALID_DATA, "No data in the request.");
    }
    return;
  }

  if (0 == unsubscribed_items) {
    SendResponse(false,
                 mobile_apis::Result::IGNORED,
                 "Was not subscribed on any VehicleData.",
                 &response_params);
    return;
  }

  if (is_everything_already_unsubscribed) {
    mobile_apis::Result::eType result_code =
        vi_already_unsubscribed_by_this_app_.size()
            ? mobile_apis::Result::IGNORED
            : mobile_apis::Result::SUCCESS;

    const char* info = vi_already_unsubscribed_by_this_app_.size()
                           ? "Already subscribed on some provided VehicleData."
                           : NULL;

    SendResponse(true, result_code, info, &response_params);
    return;
  }

#ifdef HMI_DBUS_API
  // Generate list of subrequests
  for (size_t i = 0; i < sizeof(subrequests) / sizeof(subrequests[0]); ++i) {
    const Subrequest& sr = subrequests[i];
    if (true == (*message_)[strings::msg_params].keyExists(sr.str) &&
        true == (*message_)[strings::msg_params][sr.str].asBool()) {
      HmiRequest hmi_request;
      hmi_request.str = sr.str;
      hmi_request.func_id = sr.func_id;
      hmi_request.complete = false;
      hmi_requests_.push_back(hmi_request);
    }
  }
  LOG4CXX_INFO(logger_,
               hmi_requests_.size() << " requests are going to be sent to HMI");

  // Send subrequests
  for (HmiRequests::const_iterator it = hmi_requests_.begin();
       it != hmi_requests_.end();
       ++it)
    SendHMIRequest(it->func_id, &msg_params, true);
#else
  SendHMIRequest(hmi_apis::FunctionID::VehicleInfo_UnsubscribeVehicleData,
                 &msg_params,
                 true);
#endif  // #ifdef HMI_DBUS_API
}

void UnsubscribeVehicleDataRequest::on_event(const event_engine::Event& event) {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace helpers;

  const smart_objects::SmartObject& message = event.smart_object();

  if (hmi_apis::FunctionID::VehicleInfo_UnsubscribeVehicleData != event.id()) {
    LOG4CXX_ERROR(logger_, "Received unknown event.");
    return;
  }

#ifdef HMI_DBUS_API
  for (HmiRequests::iterator it = hmi_requests_.begin();
       it != hmi_requests_.end();
       ++it) {
    HmiRequest& hmi_request = *it;
    if (hmi_request.func_id == event.id()) {
      hmi_request.status = static_cast<hmi_apis::Common_Result::eType>(
          message[strings::params][hmi_response::code].asInt());
      if (hmi_apis::Common_Result::SUCCESS == hmi_request.status)
        hmi_request.value = message[strings::msg_params][hmi_request.str];
      hmi_request.complete = true;
      break;
    }
  }
  bool all_complete = true;
  bool any_arg_success = false;
  mobile_api::Result::eType status = mobile_api::Result::eType::SUCCESS;
  for (HmiRequests::const_iterator it = hmi_requests_.begin();
       it != hmi_requests_.end();
       ++it) {
    if (!it->complete) {
      all_complete = false;
      break;
    }
    if (hmi_apis::Common_Result::SUCCESS != it->status) {
      if (mobile_api::Result::SUCCESS == status) {
        status = static_cast<mobile_apis::Result::eType>(it->status);
      } else if (status !=
                 static_cast<mobile_apis::Result::eType>(it->status)) {
        status = mobile_api::Result::eType::GENERIC_ERROR;
      }
      LOG4CXX_TRACE(logger_,
                    "Status from HMI: " << it->status
                                        << ", so response status become "
                                        << status);
    } else {
      any_arg_success = true;
    }
  }
  if (all_complete) {
    smart_objects::SmartObject response_params(smart_objects::SmartType_Map);
    if (any_arg_success) {
      for (HmiRequests::const_iterator it = hmi_requests_.begin();
           it != hmi_requests_.end();
           ++it) {
        response_params[it->str] = it->value;
      }
    }

    LOG4CXX_INFO(logger_, "All HMI requests are complete");
    if (true == any_arg_success) {
      SetAllowedToTerminate(false);
    }
    SendResponse(any_arg_success, status, NULL, &response_params);
    if (true == any_arg_success) {
      UpdateHash();
    }
  }
#else
  hmi_apis::Common_Result::eType hmi_result =
      static_cast<hmi_apis::Common_Result::eType>(
          message[strings::params][hmi_response::code].asInt());
  std::string response_info;
  GetInfo(message, response_info);
  const bool result = PrepareResultForMobileResponse(
      hmi_result, HmiInterfaces::HMI_INTERFACE_VehicleInfo);

  mobile_apis::Result::eType result_code =
      MessageHelper::HMIToMobileResult(hmi_result);

  if (result) {
    if (vi_already_unsubscribed_by_this_app_.size()) {
      result_code = mobile_apis::Result::IGNORED;
      response_info = "Some provided VehicleData was not subscribed.";
    }
  }

  if (!vi_still_subscribed_by_another_apps_.empty() ||
      !vi_already_unsubscribed_by_this_app_.empty()) {
    AddAlreadyUnsubscribedVI(
        const_cast<smart_objects::SmartObject&>(message[strings::msg_params]));
  }

  if (result) {
    SetAllowedToTerminate(false);
  }
  SendResponse(result,
               result_code,
               response_info.empty() ? NULL : response_info.c_str(),
               &(message[strings::msg_params]));
  if (result) {
    UpdateHash();
  }
#endif  // #ifdef HMI_DBUS_API
}

struct SubscribedToIVIPredicate {
  int32_t vehicle_info_;
  SubscribedToIVIPredicate(int32_t vehicle_info)
      : vehicle_info_(vehicle_info) {}
  bool operator()(const ApplicationSharedPtr app) const {
    return app ? app->IsSubscribedToIVI(vehicle_info_) : false;
  }
};

bool UnsubscribeVehicleDataRequest::IsSomeoneSubscribedFor(
    const uint32_t param_id) const {
  LOG4CXX_AUTO_TRACE(logger_);
  SubscribedToIVIPredicate finder(param_id);
  DataAccessor<ApplicationSet> accessor = application_manager_.applications();
  ApplicationSetConstIt it = std::find_if(
      accessor.GetData().begin(), accessor.GetData().end(), finder);
  return it != accessor.GetData().end();
}

void UnsubscribeVehicleDataRequest::AddAlreadyUnsubscribedVI(
    smart_objects::SmartObject& response) const {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace mobile_apis;
  VehicleInfoSubscriptions::const_iterator it_same_app =
      vi_already_unsubscribed_by_this_app_.begin();
  for (; vi_already_unsubscribed_by_this_app_.end() != it_same_app;
       ++it_same_app) {
    response[*it_same_app][strings::result_code] =
        VehicleDataResultCode::VDRC_DATA_NOT_SUBSCRIBED;
  }

  VehicleInfoSubscriptions::const_iterator it_another_app =
      vi_still_subscribed_by_another_apps_.begin();
  for (; vi_still_subscribed_by_another_apps_.end() != it_another_app;
       ++it_another_app) {
    response[*it_another_app][strings::result_code] =
        VehicleDataResultCode::VDRC_SUCCESS;
  }
}

void UnsubscribeVehicleDataRequest::UpdateHash() const {
  LOG4CXX_AUTO_TRACE(logger_);
  ApplicationSharedPtr application =
      application_manager_.application(connection_key());
  if (application) {
    application->UpdateHash();
  } else {
    LOG4CXX_ERROR(logger_,
                  "Application with connection_key = " << connection_key()
                                                       << " doesn't exist.");
  }
  application_manager_.TerminateRequest(
      connection_key(), correlation_id(), function_id());
}

}  // namespace commands
}  // namespace application_manager
<commit_msg>Correct response params in UnSubscribeVehicleData<commit_after>/*

 Copyright (c) 2017, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include "application_manager/commands/mobile/unsubscribe_vehicle_data_request.h"
#include "application_manager/commands/command_impl.h"

#include "application_manager/application_impl.h"
#include "application_manager/message_helper.h"
#include "interfaces/MOBILE_API.h"
#include "interfaces/HMI_API.h"
#include "application_manager/smart_object_keys.h"
#include "utils/helpers.h"

namespace application_manager {
namespace commands {

UnsubscribeVehicleDataRequest::UnsubscribeVehicleDataRequest(
    const MessageSharedPtr& message, ApplicationManager& application_manager)
    : CommandRequestImpl(message, application_manager) {}

UnsubscribeVehicleDataRequest::~UnsubscribeVehicleDataRequest() {}

#ifdef HMI_DBUS_API
namespace {
struct Subrequest {
  hmi_apis::FunctionID::eType func_id;
  const char* str;
};
Subrequest subrequests[] = {
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeGps, strings::gps},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeSpeed, strings::speed},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeRpm, strings::rpm},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeFuelLevel,
     strings::fuel_level},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeFuelLevel_State,
     strings::fuel_level_state},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeInstantFuelConsumption,
     strings::instant_fuel_consumption},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeExternalTemperature,
     strings::external_temp},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeVin, strings::vin},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribePrndl, strings::prndl},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeTirePressure,
     strings::tire_pressure},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeOdometer, strings::odometer},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeBeltStatus,
     strings::belt_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeBodyInformation,
     strings::body_information},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeDeviceStatus,
     strings::device_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeDriverBraking,
     strings::driver_braking},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeWiperStatus,
     strings::wiper_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeHeadLampStatus,
     strings::head_lamp_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeEngineTorque,
     strings::engine_torque},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeAccPedalPosition,
     strings::acc_pedal_pos},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeSteeringWheelAngle,
     strings::steering_wheel_angle},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeECallInfo,
     strings::e_call_info},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeAirbagStatus,
     strings::airbag_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeEmergencyEvent,
     strings::emergency_event},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeClusterModeStatus,
     strings::cluster_mode_status},
    {hmi_apis::FunctionID::VehicleInfo_UnsubscribeMyKey, strings::my_key},
};
}
#endif  // #ifdef HMI_DBUS_API

void UnsubscribeVehicleDataRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationSharedPtr app = application_manager_.application(connection_key());

  if (!app) {
    LOG4CXX_ERROR(logger_, "NULL pointer");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  int32_t items_to_unsubscribe = 0;
  int32_t unsubscribed_items = 0;

  const VehicleData& vehicle_data = MessageHelper::vehicle_data();
  VehicleData::const_iterator it = vehicle_data.begin();

  smart_objects::SmartObject msg_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);

  smart_objects::SmartObject response_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);

  for (; vehicle_data.end() != it; ++it) {
    const std::string& key_name = it->first;
    if ((*message_)[strings::msg_params].keyExists(key_name)) {
      bool is_key_enabled = (*message_)[strings::msg_params][key_name].asBool();
      if (is_key_enabled) {
        ++items_to_unsubscribe;

        VehicleDataType key_type = it->second;
        if (!app->IsSubscribedToIVI(key_type)) {
          ++unsubscribed_items;
          vi_already_unsubscribed_by_this_app_.insert(key_type);
          response_params[key_name][strings::data_type] = key_type;
          response_params[key_name][strings::result_code] =
              mobile_apis::VehicleDataResultCode::VDRC_DATA_NOT_SUBSCRIBED;
          continue;
        }

        if (!app->UnsubscribeFromIVI(static_cast<uint32_t>(key_type))) {
          LOG4CXX_ERROR(logger_,
                        "Unable to unsubscribe from "
                        "VehicleDataType: "
                            << key_type);
          continue;
        }

        LOG4CXX_DEBUG(logger_,
                      "Unsubscribed app with connection key "
                          << connection_key()
                          << " from VehicleDataType: " << key_type);

        ++unsubscribed_items;

        if (IsSomeoneSubscribedFor(key_type)) {
          LOG4CXX_DEBUG(logger_,
                        "There are another apps still subscribed for "
                        "VehicleDataType: "
                            << key_type);

          vi_still_subscribed_by_another_apps_.insert(key_type);
          response_params[key_name][strings::data_type] = key_type;
          response_params[key_name][strings::result_code] =
              mobile_apis::VehicleDataResultCode::VDRC_SUCCESS;
          continue;
        }

        msg_params[key_name] = is_key_enabled;
      }
    }
  }

  bool is_everything_already_unsubscribed =
      static_cast<uint32_t>(items_to_unsubscribe) ==
      vi_still_subscribed_by_another_apps_.size() +
          vi_already_unsubscribed_by_this_app_.size();

  if (0 == items_to_unsubscribe) {
    if (HasDisallowedParams()) {
      SendResponse(false, mobile_apis::Result::DISALLOWED);
    } else {
      SendResponse(
          false, mobile_apis::Result::INVALID_DATA, "No data in the request.");
    }
    return;
  }

  if (0 == unsubscribed_items) {
    SendResponse(false,
                 mobile_apis::Result::IGNORED,
                 "Was not subscribed on any VehicleData.",
                 &response_params);
    return;
  }

  if (is_everything_already_unsubscribed) {
    if (!vi_already_unsubscribed_by_this_app_.empty()) {
      SendResponse(false,
                   mobile_apis::Result::IGNORED,
                   "Some provided VehicleData was not subscribed.",
                   &response_params);
    } else {
      SendResponse(true, mobile_apis::Result::SUCCESS, NULL, &response_params);
    }
    return;
  }

#ifdef HMI_DBUS_API
  // Generate list of subrequests
  for (size_t i = 0; i < sizeof(subrequests) / sizeof(subrequests[0]); ++i) {
    const Subrequest& sr = subrequests[i];
    if (true == (*message_)[strings::msg_params].keyExists(sr.str) &&
        true == (*message_)[strings::msg_params][sr.str].asBool()) {
      HmiRequest hmi_request;
      hmi_request.str = sr.str;
      hmi_request.func_id = sr.func_id;
      hmi_request.complete = false;
      hmi_requests_.push_back(hmi_request);
    }
  }
  LOG4CXX_INFO(logger_,
               hmi_requests_.size() << " requests are going to be sent to HMI");

  // Send subrequests
  for (HmiRequests::const_iterator it = hmi_requests_.begin();
       it != hmi_requests_.end();
       ++it)
    SendHMIRequest(it->func_id, &msg_params, true);
#else
  SendHMIRequest(hmi_apis::FunctionID::VehicleInfo_UnsubscribeVehicleData,
                 &msg_params,
                 true);
#endif  // #ifdef HMI_DBUS_API
}

void UnsubscribeVehicleDataRequest::on_event(const event_engine::Event& event) {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace helpers;

  const smart_objects::SmartObject& message = event.smart_object();

  if (hmi_apis::FunctionID::VehicleInfo_UnsubscribeVehicleData != event.id()) {
    LOG4CXX_ERROR(logger_, "Received unknown event.");
    return;
  }

#ifdef HMI_DBUS_API
  for (HmiRequests::iterator it = hmi_requests_.begin();
       it != hmi_requests_.end();
       ++it) {
    HmiRequest& hmi_request = *it;
    if (hmi_request.func_id == event.id()) {
      hmi_request.status = static_cast<hmi_apis::Common_Result::eType>(
          message[strings::params][hmi_response::code].asInt());
      if (hmi_apis::Common_Result::SUCCESS == hmi_request.status)
        hmi_request.value = message[strings::msg_params][hmi_request.str];
      hmi_request.complete = true;
      break;
    }
  }
  bool all_complete = true;
  bool any_arg_success = false;
  mobile_api::Result::eType status = mobile_api::Result::eType::SUCCESS;
  for (HmiRequests::const_iterator it = hmi_requests_.begin();
       it != hmi_requests_.end();
       ++it) {
    if (!it->complete) {
      all_complete = false;
      break;
    }
    if (hmi_apis::Common_Result::SUCCESS != it->status) {
      if (mobile_api::Result::SUCCESS == status) {
        status = static_cast<mobile_apis::Result::eType>(it->status);
      } else if (status !=
                 static_cast<mobile_apis::Result::eType>(it->status)) {
        status = mobile_api::Result::eType::GENERIC_ERROR;
      }
      LOG4CXX_TRACE(logger_,
                    "Status from HMI: " << it->status
                                        << ", so response status become "
                                        << status);
    } else {
      any_arg_success = true;
    }
  }
  if (all_complete) {
    smart_objects::SmartObject response_params(smart_objects::SmartType_Map);
    if (any_arg_success) {
      for (HmiRequests::const_iterator it = hmi_requests_.begin();
           it != hmi_requests_.end();
           ++it) {
        response_params[it->str] = it->value;
      }
    }

    LOG4CXX_INFO(logger_, "All HMI requests are complete");
    if (true == any_arg_success) {
      SetAllowedToTerminate(false);
    }
    SendResponse(any_arg_success, status, NULL, &response_params);
    if (true == any_arg_success) {
      UpdateHash();
    }
  }
#else
  hmi_apis::Common_Result::eType hmi_result =
      static_cast<hmi_apis::Common_Result::eType>(
          message[strings::params][hmi_response::code].asInt());
  std::string response_info;
  GetInfo(message, response_info);
  const bool result = PrepareResultForMobileResponse(
      hmi_result, HmiInterfaces::HMI_INTERFACE_VehicleInfo);

  mobile_apis::Result::eType result_code =
      MessageHelper::HMIToMobileResult(hmi_result);

  if (result) {
    if (vi_already_unsubscribed_by_this_app_.size()) {
      result_code = mobile_apis::Result::IGNORED;
      response_info = "Some provided VehicleData was not subscribed.";
    }
  }

  if (!vi_still_subscribed_by_another_apps_.empty() ||
      !vi_already_unsubscribed_by_this_app_.empty()) {
    AddAlreadyUnsubscribedVI(
        const_cast<smart_objects::SmartObject&>(message[strings::msg_params]));
  }

  if (result) {
    SetAllowedToTerminate(false);
  }
  SendResponse(result,
               result_code,
               response_info.empty() ? NULL : response_info.c_str(),
               &(message[strings::msg_params]));
  if (result) {
    UpdateHash();
  }
#endif  // #ifdef HMI_DBUS_API
}

struct SubscribedToIVIPredicate {
  int32_t vehicle_info_;
  SubscribedToIVIPredicate(int32_t vehicle_info)
      : vehicle_info_(vehicle_info) {}
  bool operator()(const ApplicationSharedPtr app) const {
    return app ? app->IsSubscribedToIVI(vehicle_info_) : false;
  }
};

bool UnsubscribeVehicleDataRequest::IsSomeoneSubscribedFor(
    const uint32_t param_id) const {
  LOG4CXX_AUTO_TRACE(logger_);
  SubscribedToIVIPredicate finder(param_id);
  DataAccessor<ApplicationSet> accessor = application_manager_.applications();
  ApplicationSetConstIt it = std::find_if(
      accessor.GetData().begin(), accessor.GetData().end(), finder);
  return it != accessor.GetData().end();
}

void UnsubscribeVehicleDataRequest::AddAlreadyUnsubscribedVI(
    smart_objects::SmartObject& response) const {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace mobile_apis;
  VehicleInfoSubscriptions::const_iterator it_same_app =
      vi_already_unsubscribed_by_this_app_.begin();
  for (; vi_already_unsubscribed_by_this_app_.end() != it_same_app;
       ++it_same_app) {
    response[*it_same_app][strings::result_code] =
        VehicleDataResultCode::VDRC_DATA_NOT_SUBSCRIBED;
  }

  VehicleInfoSubscriptions::const_iterator it_another_app =
      vi_still_subscribed_by_another_apps_.begin();
  for (; vi_still_subscribed_by_another_apps_.end() != it_another_app;
       ++it_another_app) {
    response[*it_another_app][strings::result_code] =
        VehicleDataResultCode::VDRC_SUCCESS;
  }
}

void UnsubscribeVehicleDataRequest::UpdateHash() const {
  LOG4CXX_AUTO_TRACE(logger_);
  ApplicationSharedPtr application =
      application_manager_.application(connection_key());
  if (application) {
    application->UpdateHash();
  } else {
    LOG4CXX_ERROR(logger_,
                  "Application with connection_key = " << connection_key()
                                                       << " doesn't exist.");
  }
  application_manager_.TerminateRequest(
      connection_key(), correlation_id(), function_id());
}

}  // namespace commands
}  // namespace application_manager
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
// Copyright (C) 2002-2006 Marcin Kalicinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// ----------------------------------------------------------------------------
#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED

#include <boost/property_tree/ptree.hpp>
#include <boost/next_prior.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <string>
#include <ostream>
#include <iomanip>

namespace boost { namespace property_tree { namespace json_parser
{

    // Create necessary escape sequences from illegal characters
    template<class Ch>
    std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
    {
        std::basic_string<Ch> result;
        typename std::basic_string<Ch>::const_iterator b = s.begin();
        typename std::basic_string<Ch>::const_iterator e = s.end();
        while (b != e)
        {
            // This assumes an ASCII superset. But so does everything in PTree.
            // We escape everything outside ASCII, because this code can't
            // handle high unicode characters.
            if (*b == 0x20 || *b == 0x21 || (*b >= 0x23 && *b <= 0x2E) ||
                (*b >= 0x30 && *b <= 0x5B) || (*b >= 0x5D && *b <= 0xFF))
                result += *b;
            else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
            else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
            else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
            else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
            else if (*b == Ch('\t')) result += Ch('\\'), result += Ch('t');
            else if (*b == Ch('/')) result += Ch('\\'), result += Ch('/');
            else if (*b == Ch('"'))  result += Ch('\\'), result += Ch('"');
            else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
            else
            {
                const char *hexdigits = "0123456789ABCDEF";
                typedef typename make_unsigned<Ch>::type UCh;
                unsigned long u = (std::min)(static_cast<unsigned long>(
                                                 static_cast<UCh>(*b)),
                                             0xFFFFul);
                int d1 = u / 4096; u -= d1 * 4096;
                int d2 = u / 256; u -= d2 * 256;
                int d3 = u / 16; u -= d3 * 16;
                int d4 = u;
                result += Ch('\\'); result += Ch('u');
                result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
                result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
            }
            ++b;
        }
        return result;
    }

    template<class Ptree>
    void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
                           const Ptree &pt,
                           int indent, bool pretty)
    {

        typedef typename Ptree::key_type::value_type Ch;
        typedef typename std::basic_string<Ch> Str;

        // Value or object or array
        if (indent > 0 && pt.empty())
        {
            // Write value
            Str data = create_escapes(pt.template get_value<Str>());
            stream << Ch('"') << data << Ch('"');

        }
        else if (indent > 0 && pt.count(Str()) == pt.size())
        {
            // Write array
            stream << Ch('[');
            if (pretty) stream << Ch('\n');
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {
                if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
                write_json_helper(stream, it->second, indent + 1, pretty);
                if (boost::next(it) != pt.end())
                    stream << Ch(',');
                if (pretty) stream << Ch('\n');
            }
            if (pretty) stream << Str(4 * indent, Ch(' '));
            stream << Ch(']');

        }
        else
        {
            // Write object
            stream << Ch('{');
            if (pretty) stream << Ch('\n');
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {
                if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
                stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
                if (pretty) stream << Ch(' ');
                write_json_helper(stream, it->second, indent + 1, pretty);
                if (boost::next(it) != pt.end())
                    stream << Ch(',');
                if (pretty) stream << Ch('\n');
            }
            if (pretty) stream << Str(4 * indent, Ch(' '));
            stream << Ch('}');
        }

    }

    // Verify if ptree does not contain information that cannot be written to json
    template<class Ptree>
    bool verify_json(const Ptree &pt, int depth)
    {

        typedef typename Ptree::key_type::value_type Ch;
        typedef typename std::basic_string<Ch> Str;

        // Root ptree cannot have data
        if (depth == 0 && !pt.template get_value<Str>().empty())
            return false;

        // Ptree cannot have both children and data
        if (!pt.template get_value<Str>().empty() && !pt.empty())
            return false;

        // Check children
        typename Ptree::const_iterator it = pt.begin();
        for (; it != pt.end(); ++it)
            if (!verify_json(it->second, depth + 1))
                return false;

        // Success
        return true;

    }

    // Write ptree to json stream
    template<class Ptree>
    void write_json_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
                             const Ptree &pt,
                             const std::string &filename,
                             bool pretty)
    {
        if (!verify_json(pt, 0))
            BOOST_PROPERTY_TREE_THROW(json_parser_error("ptree contains data that cannot be represented in JSON format", filename, 0));
        write_json_helper(stream, pt, 0, pretty);
        stream << std::endl;
        if (!stream.good())
            BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0));
    }

} } }

#endif
<commit_msg>Suppress a warning inside boost.<commit_after>// ----------------------------------------------------------------------------
// Copyright (C) 2002-2006 Marcin Kalicinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see www.boost.org
// ----------------------------------------------------------------------------
#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED
#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WRITE_HPP_INCLUDED

#include <boost/property_tree/ptree.hpp>
#include <boost/next_prior.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <string>
#include <ostream>
#include <iomanip>

namespace boost { namespace property_tree { namespace json_parser
{
  inline bool is_ascii (char)
  {
    return true;
  }

  template <class Ch>
  inline bool is_ascii (Ch b)
  {
    return b <= 0xFF;
  }

    // Create necessary escape sequences from illegal characters
    template<class Ch>
    std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
    {
        std::basic_string<Ch> result;
        typename std::basic_string<Ch>::const_iterator b = s.begin();
        typename std::basic_string<Ch>::const_iterator e = s.end();
        while (b != e)
        {
            // This assumes an ASCII superset. But so does everything in PTree.
            // We escape everything outside ASCII, because this code can't
            // handle high unicode characters.
            if (*b == 0x20 || *b == 0x21 || (*b >= 0x23 && *b <= 0x2E) ||
                (*b >= 0x30 && *b <= 0x5B) || (*b >= 0x5D && is_ascii(*b)))
                result += *b;
            else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
            else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
            else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
            else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
            else if (*b == Ch('\t')) result += Ch('\\'), result += Ch('t');
            else if (*b == Ch('/')) result += Ch('\\'), result += Ch('/');
            else if (*b == Ch('"'))  result += Ch('\\'), result += Ch('"');
            else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
            else
            {
                const char *hexdigits = "0123456789ABCDEF";
                typedef typename make_unsigned<Ch>::type UCh;
                unsigned long u = (std::min)(static_cast<unsigned long>(
                                                 static_cast<UCh>(*b)),
                                             0xFFFFul);
                int d1 = u / 4096; u -= d1 * 4096;
                int d2 = u / 256; u -= d2 * 256;
                int d3 = u / 16; u -= d3 * 16;
                int d4 = u;
                result += Ch('\\'); result += Ch('u');
                result += Ch(hexdigits[d1]); result += Ch(hexdigits[d2]);
                result += Ch(hexdigits[d3]); result += Ch(hexdigits[d4]);
            }
            ++b;
        }
        return result;
    }

    template<class Ptree>
    void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
                           const Ptree &pt,
                           int indent, bool pretty)
    {

        typedef typename Ptree::key_type::value_type Ch;
        typedef typename std::basic_string<Ch> Str;

        // Value or object or array
        if (indent > 0 && pt.empty())
        {
            // Write value
            Str data = create_escapes(pt.template get_value<Str>());
            stream << Ch('"') << data << Ch('"');

        }
        else if (indent > 0 && pt.count(Str()) == pt.size())
        {
            // Write array
            stream << Ch('[');
            if (pretty) stream << Ch('\n');
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {
                if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
                write_json_helper(stream, it->second, indent + 1, pretty);
                if (boost::next(it) != pt.end())
                    stream << Ch(',');
                if (pretty) stream << Ch('\n');
            }
            if (pretty) stream << Str(4 * indent, Ch(' '));
            stream << Ch(']');

        }
        else
        {
            // Write object
            stream << Ch('{');
            if (pretty) stream << Ch('\n');
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {
                if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
                stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
                if (pretty) stream << Ch(' ');
                write_json_helper(stream, it->second, indent + 1, pretty);
                if (boost::next(it) != pt.end())
                    stream << Ch(',');
                if (pretty) stream << Ch('\n');
            }
            if (pretty) stream << Str(4 * indent, Ch(' '));
            stream << Ch('}');
        }

    }

    // Verify if ptree does not contain information that cannot be written to json
    template<class Ptree>
    bool verify_json(const Ptree &pt, int depth)
    {

        typedef typename Ptree::key_type::value_type Ch;
        typedef typename std::basic_string<Ch> Str;

        // Root ptree cannot have data
        if (depth == 0 && !pt.template get_value<Str>().empty())
            return false;

        // Ptree cannot have both children and data
        if (!pt.template get_value<Str>().empty() && !pt.empty())
            return false;

        // Check children
        typename Ptree::const_iterator it = pt.begin();
        for (; it != pt.end(); ++it)
            if (!verify_json(it->second, depth + 1))
                return false;

        // Success
        return true;

    }

    // Write ptree to json stream
    template<class Ptree>
    void write_json_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
                             const Ptree &pt,
                             const std::string &filename,
                             bool pretty)
    {
        if (!verify_json(pt, 0))
            BOOST_PROPERTY_TREE_THROW(json_parser_error("ptree contains data that cannot be represented in JSON format", filename, 0));
        write_json_helper(stream, pt, 0, pretty);
        stream << std::endl;
        if (!stream.good())
            BOOST_PROPERTY_TREE_THROW(json_parser_error("write error", filename, 0));
    }

} } }

#endif
<|endoftext|>