<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: b2dhommatrix.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:42:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef _HOMMATRIX_TEMPLATE_HXX
#include <hommatrixtemplate.hxx>
#endif

#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX
#include <basegfx/matrix/b3dhommatrix.hxx>
#endif

#ifndef _BGFX_TUPLE_B3DTUPLE_HXX
#include <basegfx/tuple/b3dtuple.hxx>
#endif

#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif

namespace basegfx
{
    class Impl2DHomMatrix : public ::basegfx::internal::ImplHomMatrixTemplate< 3 >
    {
    };

    static Impl2DHomMatrix& get2DIdentityMatrix()
    {
        static Impl2DHomMatrix maStatic2DIdentityHomMatrix;
        return maStatic2DIdentityHomMatrix;
    }

    void B2DHomMatrix::implPrepareChange()
    {
        if(mpM->getRefCount())
        {
            mpM->decRefCount();
            mpM = new Impl2DHomMatrix(*mpM);
        }
    }

    B2DHomMatrix::B2DHomMatrix()
    :   mpM(&get2DIdentityMatrix())
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::B2DHomMatrix(const B2DHomMatrix& rMat)
    :   mpM(rMat.mpM)
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::~B2DHomMatrix()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;
    }

    B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix& rMat)
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = rMat.mpM;
        mpM->incRefCount();

        return *this;
    }

    double B2DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const
    {
        return mpM->get(nRow, nColumn);
    }

    void B2DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
    {
        implPrepareChange();
        mpM->set(nRow, nColumn, fValue);
    }

    bool B2DHomMatrix::isIdentity() const
    {
        if(mpM == &get2DIdentityMatrix())
            return true;

        return mpM->isIdentity();
    }

    void B2DHomMatrix::identity()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = &get2DIdentityMatrix();
        mpM->incRefCount();
    }

    bool B2DHomMatrix::isInvertible() const
    {
        return mpM->isInvertible();
    }

    bool B2DHomMatrix::invert()
    {
        Impl2DHomMatrix aWork(*mpM);
        sal_uInt16* pIndex = new sal_uInt16[mpM->getEdgeLength()];
        sal_Int16 nParity;

        if(aWork.ludcmp(pIndex, nParity))
        {
            implPrepareChange();
            mpM->doInvert(aWork, pIndex);
            delete[] pIndex;

            return true;
        }

        delete[] pIndex;
        return false;
    }

    bool B2DHomMatrix::isNormalized() const
    {
        return mpM->isNormalized();
    }

    void B2DHomMatrix::normalize()
    {
        if(!mpM->isNormalized())
        {
            implPrepareChange();
            mpM->doNormalize();
        }
    }

    double B2DHomMatrix::determinant() const
    {
        return mpM->doDeterminant();
    }

    double B2DHomMatrix::trace() const
    {
        return mpM->doTrace();
    }

    void B2DHomMatrix::transpose()
    {
        implPrepareChange();
        mpM->doTranspose();
    }

    B2DHomMatrix& B2DHomMatrix::operator+=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doAddMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator-=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doSubMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator/=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(1.0 / fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(const B2DHomMatrix& rMat)
    {
        if(!rMat.isIdentity())
        {
            implPrepareChange();
            mpM->doMulMatrix(*rMat.mpM);
        }

        return *this;
    }

    bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return true;

        return mpM->isEqual(*rMat.mpM);
    }

    bool B2DHomMatrix::operator!=(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return false;

        return !mpM->isEqual(*rMat.mpM);
    }

    void B2DHomMatrix::rotate(double fRadiant)
    {
        if(!::basegfx::fTools::equalZero(fRadiant))
        {
            double fSin;
            double fCos;

            // is the rotation angle an approximate multiple of pi/2?
            // If yes, force fSin/fCos to -1/0/1, to maintain
            // orthogonality (which might also be advantageous for the
            // other cases, but: for multiples of pi/2, the exact
            // values _can_ be attained. It would be largely
            // unintuitive, if a 180 degrees rotation would introduce
            // slight roundoff errors, instead of exactly mirroring
            // the coordinate system).
            if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
            {
                // determine quadrant
                const sal_Int32 nQuad(
                    (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
                switch( nQuad )
                {
                    case 0: // -2pi,0,2pi
                        fSin = 0.0;
                        fCos = 1.0;
                        break;

                    case 1: // -3/2pi,1/2pi
                        fSin = 1.0;
                        fCos = 0.0;
                        break;

                    case 2: // -pi,pi
                        fSin = 0.0;
                        fCos = -1.0;
                        break;

                    case 3: // -1/2pi,3/2pi
                        fSin = -1.0;
                        fCos = 0.0;
                        break;

                    default:
                        OSL_ENSURE( false,
                                    "B2DHomMatrix::rotate(): Impossible case reached" );
                }
            }
            else
            {
                fSin = sin(fRadiant);
                fCos = cos(fRadiant);
            }

            Impl2DHomMatrix aRotMat(get2DIdentityMatrix());

            aRotMat.set(0, 0, fCos);
            aRotMat.set(1, 1, fCos);
            aRotMat.set(1, 0, fSin);
            aRotMat.set(0, 1, -fSin);

            implPrepareChange();
            mpM->doMulMatrix(aRotMat);
        }
    }

    void B2DHomMatrix::translate(double fX, double fY)
    {
        if(!::basegfx::fTools::equalZero(fX) || !::basegfx::fTools::equalZero(fY))
        {
            Impl2DHomMatrix aTransMat(get2DIdentityMatrix());

            aTransMat.set(0, 2, fX);
            aTransMat.set(1, 2, fY);

            implPrepareChange();
            mpM->doMulMatrix(aTransMat);
        }
    }

    void B2DHomMatrix::scale(double fX, double fY)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fX) || !::basegfx::fTools::equal(fOne, fY))
        {
            Impl2DHomMatrix aScaleMat(get2DIdentityMatrix());

            aScaleMat.set(0, 0, fX);
            aScaleMat.set(1, 1, fY);

            implPrepareChange();
            mpM->doMulMatrix(aScaleMat);
        }
    }

    void B2DHomMatrix::shearX(double fSx)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSx))
        {
            Impl2DHomMatrix aShearXMat(get2DIdentityMatrix());

            aShearXMat.set(0, 1, fSx);

            implPrepareChange();
            mpM->doMulMatrix(aShearXMat);
        }
    }

    void B2DHomMatrix::shearY(double fSy)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSy))
        {
            Impl2DHomMatrix aShearYMat(get2DIdentityMatrix());

            aShearYMat.set(1, 0, fSy);

            implPrepareChange();
            mpM->doMulMatrix(aShearYMat);
        }
    }

    // Decomposition
    bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
    {
        // when perspective is used, decompose is not made here
        if(!mpM->isLastLineDefault())
            return false;

        // If determinant is zero, decomposition is not possible
        if(0.0 == mpM->doDeterminant())
            return false;

        // copy 2x2 matrix and translate vector to 3x3 matrix
        ::basegfx::B3DHomMatrix a3DHomMat;

        a3DHomMat.set(0, 0, get(0, 0));
        a3DHomMat.set(0, 1, get(0, 1));
        a3DHomMat.set(1, 0, get(1, 0));
        a3DHomMat.set(1, 1, get(1, 1));
        a3DHomMat.set(0, 3, get(0, 2));
        a3DHomMat.set(1, 3, get(1, 2));

        ::basegfx::B3DTuple r3DScale, r3DTranslate, r3DRotate, r3DShear;

        if(a3DHomMat.decompose(r3DScale, r3DTranslate, r3DRotate, r3DShear))
        {
            // copy scale values
            rScale.setX(r3DScale.getX());
            rScale.setY(r3DScale.getY());

            // copy shear
            rShearX = r3DShear.getX();

            // copy rotate
            rRotate = r3DRotate.getZ();

            // copy translate
            rTranslate.setX(r3DTranslate.getX());
            rTranslate.setY(r3DTranslate.getY());

            return true;
        }

        return false;
    }
} // end of namespace basegfx

// eof
<commit_msg>INTEGRATION: CWS canvas02 (1.9.2); FILE MERGED 2005/10/08 13:15:45 thb 1.9.2.3: RESYNC: (1.9-1.10); FILE MERGED 2005/08/22 15:30:17 thb 1.9.2.2: #i10000# Added comment string 2005/07/28 10:10:18 thb 1.9.2.1: Join from cws_src680_aw024: #i48939# and new rendering subsystem need AW's clipper changes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: b2dhommatrix.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2005-11-02 13:56:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef _HOMMATRIX_TEMPLATE_HXX
#include <hommatrixtemplate.hxx>
#endif

#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX
#include <basegfx/matrix/b3dhommatrix.hxx>
#endif

#ifndef _BGFX_TUPLE_B3DTUPLE_HXX
#include <basegfx/tuple/b3dtuple.hxx>
#endif

#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif

#ifndef _BGFX_VECTOR_B2DVECTOR_HXX
#include <basegfx/vector/b2dvector.hxx>
#endif

namespace basegfx
{
    class Impl2DHomMatrix : public ::basegfx::internal::ImplHomMatrixTemplate< 3 >
    {
    };

    static Impl2DHomMatrix& get2DIdentityMatrix()
    {
        static Impl2DHomMatrix maStatic2DIdentityHomMatrix;
        return maStatic2DIdentityHomMatrix;
    }

    void B2DHomMatrix::implPrepareChange()
    {
        if(mpM->getRefCount())
        {
            mpM->decRefCount();
            mpM = new Impl2DHomMatrix(*mpM);
        }
    }

    B2DHomMatrix::B2DHomMatrix()
    :   mpM(&get2DIdentityMatrix())
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::B2DHomMatrix(const B2DHomMatrix& rMat)
    :   mpM(rMat.mpM)
    {
        mpM->incRefCount();
    }

    B2DHomMatrix::~B2DHomMatrix()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;
    }

    B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix& rMat)
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = rMat.mpM;
        mpM->incRefCount();

        return *this;
    }

    double B2DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const
    {
        return mpM->get(nRow, nColumn);
    }

    void B2DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
    {
        implPrepareChange();
        mpM->set(nRow, nColumn, fValue);
    }

    bool B2DHomMatrix::isLastLineDefault() const
    {
        return mpM->isLastLineDefault();
    }

    bool B2DHomMatrix::isIdentity() const
    {
        if(mpM == &get2DIdentityMatrix())
            return true;

        return mpM->isIdentity();
    }

    void B2DHomMatrix::identity()
    {
        if(mpM->getRefCount())
            mpM->decRefCount();
        else
            delete mpM;

        mpM = &get2DIdentityMatrix();
        mpM->incRefCount();
    }

    bool B2DHomMatrix::isInvertible() const
    {
        return mpM->isInvertible();
    }

    bool B2DHomMatrix::invert()
    {
        Impl2DHomMatrix aWork(*mpM);
        sal_uInt16* pIndex = new sal_uInt16[mpM->getEdgeLength()];
        sal_Int16 nParity;

        if(aWork.ludcmp(pIndex, nParity))
        {
            implPrepareChange();
            mpM->doInvert(aWork, pIndex);
            delete[] pIndex;

            return true;
        }

        delete[] pIndex;
        return false;
    }

    bool B2DHomMatrix::isNormalized() const
    {
        return mpM->isNormalized();
    }

    void B2DHomMatrix::normalize()
    {
        if(!mpM->isNormalized())
        {
            implPrepareChange();
            mpM->doNormalize();
        }
    }

    double B2DHomMatrix::determinant() const
    {
        return mpM->doDeterminant();
    }

    double B2DHomMatrix::trace() const
    {
        return mpM->doTrace();
    }

    void B2DHomMatrix::transpose()
    {
        implPrepareChange();
        mpM->doTranspose();
    }

    B2DHomMatrix& B2DHomMatrix::operator+=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doAddMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator-=(const B2DHomMatrix& rMat)
    {
        implPrepareChange();
        mpM->doSubMatrix(*rMat.mpM);

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator/=(double fValue)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fValue))
        {
            implPrepareChange();
            mpM->doMulMatrix(1.0 / fValue);
        }

        return *this;
    }

    B2DHomMatrix& B2DHomMatrix::operator*=(const B2DHomMatrix& rMat)
    {
        if(!rMat.isIdentity())
        {
            implPrepareChange();
            mpM->doMulMatrix(*rMat.mpM);
        }

        return *this;
    }

    bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return true;

        return mpM->isEqual(*rMat.mpM);
    }

    bool B2DHomMatrix::operator!=(const B2DHomMatrix& rMat) const
    {
        if(mpM == rMat.mpM)
            return false;

        return !mpM->isEqual(*rMat.mpM);
    }

    void B2DHomMatrix::rotate(double fRadiant)
    {
        if(!::basegfx::fTools::equalZero(fRadiant))
        {
            double fSin;
            double fCos;

            // is the rotation angle an approximate multiple of pi/2?
            // If yes, force fSin/fCos to -1/0/1, to maintain
            // orthogonality (which might also be advantageous for the
            // other cases, but: for multiples of pi/2, the exact
            // values _can_ be attained. It would be largely
            // unintuitive, if a 180 degrees rotation would introduce
            // slight roundoff errors, instead of exactly mirroring
            // the coordinate system).
            if( fTools::equalZero( fmod( fRadiant, F_PI2 ) ) )
            {
                // determine quadrant
                const sal_Int32 nQuad(
                    (4 + fround( 4/F_2PI*fmod( fRadiant, F_2PI ) )) % 4 );
                switch( nQuad )
                {
                    case 0: // -2pi,0,2pi
                        fSin = 0.0;
                        fCos = 1.0;
                        break;

                    case 1: // -3/2pi,1/2pi
                        fSin = 1.0;
                        fCos = 0.0;
                        break;

                    case 2: // -pi,pi
                        fSin = 0.0;
                        fCos = -1.0;
                        break;

                    case 3: // -1/2pi,3/2pi
                        fSin = -1.0;
                        fCos = 0.0;
                        break;

                    default:
                        OSL_ENSURE( false,
                                    "B2DHomMatrix::rotate(): Impossible case reached" );
                }
            }
            else
            {
                // TODO(P1): Maybe use glibc's sincos here (though
                // that's kinda non-portable...)
                fSin = sin(fRadiant);
                fCos = cos(fRadiant);
            }

            Impl2DHomMatrix aRotMat(get2DIdentityMatrix());

            aRotMat.set(0, 0, fCos);
            aRotMat.set(1, 1, fCos);
            aRotMat.set(1, 0, fSin);
            aRotMat.set(0, 1, -fSin);

            implPrepareChange();
            mpM->doMulMatrix(aRotMat);
        }
    }

    void B2DHomMatrix::translate(double fX, double fY)
    {
        if(!::basegfx::fTools::equalZero(fX) || !::basegfx::fTools::equalZero(fY))
        {
            Impl2DHomMatrix aTransMat(get2DIdentityMatrix());

            aTransMat.set(0, 2, fX);
            aTransMat.set(1, 2, fY);

            implPrepareChange();
            mpM->doMulMatrix(aTransMat);
        }
    }

    void B2DHomMatrix::scale(double fX, double fY)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fX) || !::basegfx::fTools::equal(fOne, fY))
        {
            Impl2DHomMatrix aScaleMat(get2DIdentityMatrix());

            aScaleMat.set(0, 0, fX);
            aScaleMat.set(1, 1, fY);

            implPrepareChange();
            mpM->doMulMatrix(aScaleMat);
        }
    }

    void B2DHomMatrix::shearX(double fSx)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSx))
        {
            Impl2DHomMatrix aShearXMat(get2DIdentityMatrix());

            aShearXMat.set(0, 1, fSx);

            implPrepareChange();
            mpM->doMulMatrix(aShearXMat);
        }
    }

    void B2DHomMatrix::shearY(double fSy)
    {
        const double fOne(1.0);

        if(!::basegfx::fTools::equal(fOne, fSy))
        {
            Impl2DHomMatrix aShearYMat(get2DIdentityMatrix());

            aShearYMat.set(1, 0, fSy);

            implPrepareChange();
            mpM->doMulMatrix(aShearYMat);
        }
    }

    // Decomposition
    bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
    {
        // when perspective is used, decompose is not made here
        if(!mpM->isLastLineDefault())
            return false;

        // test for rotation and shear
        if(::basegfx::fTools::equalZero(get(0, 1)) && ::basegfx::fTools::equalZero(get(1, 0)))
        {
            // no rotation and shear, direct value extraction
            rRotate = rShearX = 0.0;

            // copy scale values
            rScale.setX(get(0, 0));
            rScale.setY(get(1, 1));

            // copy translation values
            rTranslate.setX(get(0, 2));
            rTranslate.setY(get(1, 2));

            return true;
        }
        else
        {
            // test if shear is zero. That's the case, if the unit vectors in the matrix
            // are perpendicular -> scalar is zero
            const ::basegfx::B2DVector aUnitVecX(get(0, 0), get(1, 0));
            const ::basegfx::B2DVector aUnitVecY(get(0, 1), get(1, 1));

            if(::basegfx::fTools::equalZero(aUnitVecX.scalar(aUnitVecY)))
            {
                // calculate rotation
                rRotate = atan2(aUnitVecX.getY(), aUnitVecX.getX());

                // calculate scale values
                rScale.setX(aUnitVecX.getLength());
                rScale.setY(aUnitVecY.getLength());

                // copy translation values
                rTranslate.setX(get(0, 2));
                rTranslate.setY(get(1, 2));

                return true;
            }
            else
            {
                // If determinant is zero, decomposition is not possible
                if(0.0 == mpM->doDeterminant())
                    return false;

                // copy 2x2 matrix and translate vector to 3x3 matrix
                ::basegfx::B3DHomMatrix a3DHomMat;

                a3DHomMat.set(0, 0, get(0, 0));
                a3DHomMat.set(0, 1, get(0, 1));
                a3DHomMat.set(1, 0, get(1, 0));
                a3DHomMat.set(1, 1, get(1, 1));
                a3DHomMat.set(0, 3, get(0, 2));
                a3DHomMat.set(1, 3, get(1, 2));

                ::basegfx::B3DTuple r3DScale, r3DTranslate, r3DRotate, r3DShear;

                if(a3DHomMat.decompose(r3DScale, r3DTranslate, r3DRotate, r3DShear))
                {
                    // copy scale values
                    rScale.setX(r3DScale.getX());
                    rScale.setY(r3DScale.getY());

                    // copy shear
                    rShearX = r3DShear.getX();

                    // copy rotate
                    rRotate = r3DRotate.getZ();

                    // copy translate
                    rTranslate.setX(r3DTranslate.getX());
                    rTranslate.setY(r3DTranslate.getY());

                    return true;
                }
            }
        }

        return false;
    }
} // end of namespace basegfx

// eof
<|endoftext|>


<commit_before>// Copyright (c) Facebook Inc. and Microsoft Corporation.
// Licensed under the MIT license.

#include "onnx/defs/schema.h"

using AttrType = onnx::OpSchema::AttrType;

OPERATOR_SCHEMA(Cast)
    .NumInputs(1)
    .NumOutputs(1)
    .SetDoc(R"DOC(
The operator casts the elements of a given input tensor to a data type
specified by the 'to' argument and returns an output tensor of the same size in
the converted type. The 'to' argument must be one of the data types specified
in the 'DataType' enum field in the TensorProto message. If the 'to' argument
is not provided or is not one of the enumerated types in DataType, Caffe2
throws an Enforce error.

NOTE: Casting to and from strings is not supported yet.
)DOC")
    .Attr(
          "to",
          "The data type to which the elements of the input tensor are cast."
          "Strictly must be one of the types from DataType enum in TensorProto",
          AttrType::STRING)
    .Input(0, "input", "Input tensor to be cast.")
    .Output(
        0,
        "output",
        "Output tensor with the same shape as input with type "
        "specified by the 'to' argument");

OPERATOR_SCHEMA(Reshape)
    .NumInputs(1)
    .NumOutputs(1)
    .AllowConsumed({{0, 0}})
    .SetDoc(R"DOC(
Reshape the input tensor similar to numpy.reshape.

It takes a tensor as input and an argument `shape`. It outputs the reshaped tensor.

At most one dimension of the new shape can be -1. In this case, the value is
inferred from the size of the tensor and the remaining dimensions. A dimension
could also be 0, in which case the actual dimension value is going to be copied
from the shape argument.)DOC")
    .Attr("shape", "New shape", AttrType::INTS)
    .Input(0, "data", "An input tensor.")
    .Output(0, "reshaped", "Reshaped data.");

OPERATOR_SCHEMA(Concat)
    .NumInputs(1, INT_MAX)
    .NumOutputs(2)
    .Attr("axis",
          "Which axis to concat on",
          AttrType::INT)
    .SetDoc("Concatenate a list of tensors into a single tensor")
    .Output(0, "concat_result", "Concatenated tensor");

OPERATOR_SCHEMA(Split)
    .NumInputs(1, 2)
    .NumOutputs(1, INT_MAX)
    .Input(0, "input", "The tensor to split")
    .Input(1, "split", "Optional list of output lengths (see also arg 'split')")
    .Attr("axis",
          "Which axis to split on",
          AttrType::INT)
    .Attr("split",
          "length of each output",
          AttrType::INTS)
    .SetDoc(R"DOC(Split a tensor into a list of tensors, along the specified
'axis'. The lengths of the split can be specified using argument 'axis' or
optional second input blob to the operator. Otherwise, the tensor is split
to equal sized parts.
)DOC");

OPERATOR_SCHEMA(Slice)
    .NumInputs(1, 3)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Produces a slice of the input tensor along multiple axes. Similar to numpy:
https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html

Slices are passed as two keyword argument lists with starting and end indices
for each dimension of the input `data` tensor. If a negative value is passed
for any of the start or end indices, it represent number of elements before
the end of that dimension.

`strides` is the  step sizes when applying slicing, negative value means in
reverse order.
)DOC")
    .Input(0, "data", "Tensor of data to extract slices from.")
    .Attr("starts",
          "List of starting indices",
          AttrType::INTS)
    .Attr("ends",
        "List of ending indices",
        AttrType::INTS)
    .Output(0, "output", "Sliced data tensor.");

OPERATOR_SCHEMA(Transpose)
    .NumInputs(1)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Transpose the input tensor similar to numpy.transpose. For example, when
axes=(1, 0, 2), given an input tensor of shape (1, 2, 3), the output shape
will be (2, 1, 3).
)DOC")
    .Attr("perm",
          "A list of integers. By default, reverse the dimensions, "
          "otherwise permute the axes according to the values given.",
          AttrType::INTS)
    .Input(0, "data", "An input tensor.")
    .Output(0, "transposed", "Transposed output.");

OPERATOR_SCHEMA(Gather)
    .NumInputs(2)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Given DATA tensor of rank r >= 1, and INDICES tensor of rank q, gather
entries of the outer-most dimension of DATA indexed by INDICES, and concatenate
them in an output tensor of rank q + (r - 1).

Example:
  DATA  = [
      [1.0, 1.2],
      [2.3, 3.4],
      [4.5, 5.7],
  ]
  INDICES = [
      [0, 1],
      [1, 2],
  ]
  OUTPUT = [
      [
          [1.0, 1.2],
          [2.3, 3.4],
      ],
      [
          [2.3, 3.4],
          [4.5, 5.7],
      ],
  ]
)DOC")
    .Input(0, "DATA", "Tensor of rank r >= 1.")
    .Input(1, "INDICES", "Tensor of int32/int64 indices, of any rank q.")
    .Output(0, "OUTPUT", "Tensor of rank q + (r - 1).");

OPERATOR_SCHEMA(Squeeze)
    .NumInputs(1)
    .NumOutputs(1)
    .Attr("axes",
          "List of positive integers, indicate the dimensions to squeeze.",
          AttrType::INTS,
          true)
    .SetDoc(R"DOC(
Remove single-dimensional entries from the shape of a tensor.
Takes a  parameter `axes` with a list of axes to squeeze.
)DOC")
    .Input(0, "data", "Tensors with at least max(dims) dimensions.")
    .Output(0, "squeezed", "Reshaped tensor with same data as input.");

OPERATOR_SCHEMA(Pad)
    .NumInputs(1)
    .NumOutputs(1)
    .Attr("paddings",
          "List of integers indicate the padding sizes, paddings's length"
          " should be the double of input's dimension. "
          "The order should be axis_0_begin, axis_0_end, axis_1_begin, ...,"
          " axis_n_begin, axis_n_end, n is input's dimension.",
          AttrType::INTS,
          true)
    .Attr("mode",
          "Three modes: constant(default), reflect, replicate",
          AttrType::STRING)
    .Attr("value",
          "One float, indicates the value to be filled, default is 0",
          AttrType::FLOAT)
    .SetDoc(R"DOC(
Given DATA tensor, paddings, mode, and value.

Example:
  Insert 0 paddings to the beginning of the second dimension.

  DATA  = [
      [1.0, 1.2],
      [2.3, 3.4],
      [4.5, 5.7],
  ]
  paddings = [0, 0, 2, 0]

  OUTPUT = [
      [
          [0.0, 0.0, 1.0, 1.2],
          [0.0, 0.0, 2.3, 3.4],
          [0.0, 0.0, 4.5, 5.7],
      ],
  ]
)DOC")
    .Input(0, "DATA", "Input tensor.")
    .Output(0, "OUTPUT", "Tensor after padding.");
<commit_msg>Change Pad mode name "replicate" to "edge" to match numpy convention<commit_after>// Copyright (c) Facebook Inc. and Microsoft Corporation.
// Licensed under the MIT license.

#include "onnx/defs/schema.h"

using AttrType = onnx::OpSchema::AttrType;

OPERATOR_SCHEMA(Cast)
    .NumInputs(1)
    .NumOutputs(1)
    .SetDoc(R"DOC(
The operator casts the elements of a given input tensor to a data type
specified by the 'to' argument and returns an output tensor of the same size in
the converted type. The 'to' argument must be one of the data types specified
in the 'DataType' enum field in the TensorProto message. If the 'to' argument
is not provided or is not one of the enumerated types in DataType, Caffe2
throws an Enforce error.

NOTE: Casting to and from strings is not supported yet.
)DOC")
    .Attr(
          "to",
          "The data type to which the elements of the input tensor are cast."
          "Strictly must be one of the types from DataType enum in TensorProto",
          AttrType::STRING)
    .Input(0, "input", "Input tensor to be cast.")
    .Output(
        0,
        "output",
        "Output tensor with the same shape as input with type "
        "specified by the 'to' argument");

OPERATOR_SCHEMA(Reshape)
    .NumInputs(1)
    .NumOutputs(1)
    .AllowConsumed({{0, 0}})
    .SetDoc(R"DOC(
Reshape the input tensor similar to numpy.reshape.

It takes a tensor as input and an argument `shape`. It outputs the reshaped tensor.

At most one dimension of the new shape can be -1. In this case, the value is
inferred from the size of the tensor and the remaining dimensions. A dimension
could also be 0, in which case the actual dimension value is going to be copied
from the shape argument.)DOC")
    .Attr("shape", "New shape", AttrType::INTS)
    .Input(0, "data", "An input tensor.")
    .Output(0, "reshaped", "Reshaped data.");

OPERATOR_SCHEMA(Concat)
    .NumInputs(1, INT_MAX)
    .NumOutputs(2)
    .Attr("axis",
          "Which axis to concat on",
          AttrType::INT)
    .SetDoc("Concatenate a list of tensors into a single tensor")
    .Output(0, "concat_result", "Concatenated tensor");

OPERATOR_SCHEMA(Split)
    .NumInputs(1, 2)
    .NumOutputs(1, INT_MAX)
    .Input(0, "input", "The tensor to split")
    .Input(1, "split", "Optional list of output lengths (see also arg 'split')")
    .Attr("axis",
          "Which axis to split on",
          AttrType::INT)
    .Attr("split",
          "length of each output",
          AttrType::INTS)
    .SetDoc(R"DOC(Split a tensor into a list of tensors, along the specified
'axis'. The lengths of the split can be specified using argument 'axis' or
optional second input blob to the operator. Otherwise, the tensor is split
to equal sized parts.
)DOC");

OPERATOR_SCHEMA(Slice)
    .NumInputs(1, 3)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Produces a slice of the input tensor along multiple axes. Similar to numpy:
https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html

Slices are passed as two keyword argument lists with starting and end indices
for each dimension of the input `data` tensor. If a negative value is passed
for any of the start or end indices, it represent number of elements before
the end of that dimension.

`strides` is the  step sizes when applying slicing, negative value means in
reverse order.
)DOC")
    .Input(0, "data", "Tensor of data to extract slices from.")
    .Attr("starts",
          "List of starting indices",
          AttrType::INTS)
    .Attr("ends",
        "List of ending indices",
        AttrType::INTS)
    .Output(0, "output", "Sliced data tensor.");

OPERATOR_SCHEMA(Transpose)
    .NumInputs(1)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Transpose the input tensor similar to numpy.transpose. For example, when
axes=(1, 0, 2), given an input tensor of shape (1, 2, 3), the output shape
will be (2, 1, 3).
)DOC")
    .Attr("perm",
          "A list of integers. By default, reverse the dimensions, "
          "otherwise permute the axes according to the values given.",
          AttrType::INTS)
    .Input(0, "data", "An input tensor.")
    .Output(0, "transposed", "Transposed output.");

OPERATOR_SCHEMA(Gather)
    .NumInputs(2)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Given DATA tensor of rank r >= 1, and INDICES tensor of rank q, gather
entries of the outer-most dimension of DATA indexed by INDICES, and concatenate
them in an output tensor of rank q + (r - 1).

Example:
  DATA  = [
      [1.0, 1.2],
      [2.3, 3.4],
      [4.5, 5.7],
  ]
  INDICES = [
      [0, 1],
      [1, 2],
  ]
  OUTPUT = [
      [
          [1.0, 1.2],
          [2.3, 3.4],
      ],
      [
          [2.3, 3.4],
          [4.5, 5.7],
      ],
  ]
)DOC")
    .Input(0, "DATA", "Tensor of rank r >= 1.")
    .Input(1, "INDICES", "Tensor of int32/int64 indices, of any rank q.")
    .Output(0, "OUTPUT", "Tensor of rank q + (r - 1).");

OPERATOR_SCHEMA(Squeeze)
    .NumInputs(1)
    .NumOutputs(1)
    .Attr("axes",
          "List of positive integers, indicate the dimensions to squeeze.",
          AttrType::INTS,
          true)
    .SetDoc(R"DOC(
Remove single-dimensional entries from the shape of a tensor.
Takes a  parameter `axes` with a list of axes to squeeze.
)DOC")
    .Input(0, "data", "Tensors with at least max(dims) dimensions.")
    .Output(0, "squeezed", "Reshaped tensor with same data as input.");

OPERATOR_SCHEMA(Pad)
    .NumInputs(1)
    .NumOutputs(1)
    .Attr("paddings",
          "List of integers indicate the padding sizes, paddings's length"
          " should be the double of input's dimension. "
          "The order should be axis_0_begin, axis_0_end, axis_1_begin, ...,"
          " axis_n_begin, axis_n_end, n is input's dimension.",
          AttrType::INTS,
          true)
    .Attr("mode",
          "Three modes: constant(default), reflect, edge",
          AttrType::STRING)
    .Attr("value",
          "One float, indicates the value to be filled, default is 0",
          AttrType::FLOAT)
    .SetDoc(R"DOC(
Given DATA tensor, paddings, mode, and value.

Example:
  Insert 0 paddings to the beginning of the second dimension.

  DATA  = [
      [1.0, 1.2],
      [2.3, 3.4],
      [4.5, 5.7],
  ]
  paddings = [0, 0, 2, 0]

  OUTPUT = [
      [
          [0.0, 0.0, 1.0, 1.2],
          [0.0, 0.0, 2.3, 3.4],
          [0.0, 0.0, 4.5, 5.7],
      ],
  ]
)DOC")
    .Input(0, "DATA", "Input tensor.")
    .Output(0, "OUTPUT", "Tensor after padding.");
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "heapdump.h"

#include "uv.h"
#include "node_version.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

namespace heapdump
{

uv_signal_t signal_handle;

void OnSignal(uv_signal_t* handle, int signo)
{
  assert(handle == &signal_handle);
  heapdump::WriteSnapshot();
}

void WriteSnapshot()
{
  if (fork() != 0) return;
  setsid();
  WriteSnapshotHelper();
  _exit(42);
}

void PlatformInit()
{
  uv_signal_init(uv_default_loop(), &signal_handle);
  uv_signal_start(&signal_handle, OnSignal, SIGUSR2);
  uv_unref(reinterpret_cast<uv_handle_t*>(&signal_handle));
}

} // namespace heapdump
<commit_msg>unix: reap child process<commit_after>/*
 * Copyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "heapdump.h"

#include "uv.h"
#include "node_version.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

namespace heapdump
{

uv_signal_t signal_handle;
uv_signal_t sigchld_handle;
pid_t child_pid = -1;

void OnSIGUSR2(uv_signal_t* handle, int signo)
{
  assert(handle == &signal_handle);
  heapdump::WriteSnapshot();
}

void OnSIGCHLD(uv_signal_t* handle, int signo)
{
  assert(handle == &sigchld_handle);
  int status;
  pid_t pid = waitpid(child_pid, &status, WNOHANG);
  assert(pid != -1);
  if (pid == 0) return;
  assert(pid == child_pid);
  uv_signal_stop(&sigchld_handle);
}

void WriteSnapshot()
{
  if (uv_is_active(reinterpret_cast<uv_handle_t*>(&sigchld_handle))) return;
  child_pid = fork();
  if (child_pid == -1) return;
  if (child_pid != 0) {
    uv_signal_start(&sigchld_handle, OnSIGCHLD, SIGCHLD);
    return;
  }
  setsid();
  WriteSnapshotHelper();
  _exit(42);
}

void PlatformInit()
{
  uv_signal_init(uv_default_loop(), &sigchld_handle);
  uv_signal_init(uv_default_loop(), &signal_handle);
  uv_signal_start(&signal_handle, OnSIGUSR2, SIGUSR2);
  uv_unref(reinterpret_cast<uv_handle_t*>(&signal_handle));
}

} // namespace heapdump
<|endoftext|>


<commit_before>// Copyright 2009 the V8 project authors. 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 Google Inc. 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
// OWNER 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.

// Platform specific code for POSIX goes here. This is not a platform on its
// own but contains the parts which are the same across POSIX platforms Linux,
// Mac OS, FreeBSD and OpenBSD.

#include <unistd.h>
#include <errno.h>
#include <time.h>

#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#if defined(ANDROID)
#define LOG_TAG "v8"
#include <utils/Log.h>  // LOG_PRI_VA
#endif

#include "v8.h"

#include "platform.h"

namespace v8 {
namespace internal {

// ----------------------------------------------------------------------------
// Math functions

double modulo(double x, double y) {
  return fmod(x, y);
}

double OS::nan_value() {
  // NAN from math.h is defined in C99 and not in POSIX.
  return NAN;
}

// ----------------------------------------------------------------------------
// POSIX date/time support.
//

int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
  struct rusage usage;

  if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
  *secs = usage.ru_utime.tv_sec;
  *usecs = usage.ru_utime.tv_usec;
  return 0;
}

double OS::TimeCurrentMillis() {
  struct timeval tv;
  if (gettimeofday(&tv, NULL) < 0) return 0.0;
  return (static_cast<double>(tv.tv_sec) * 1000) +
         (static_cast<double>(tv.tv_usec) / 1000);
}

int64_t OS::Ticks() {
  // gettimeofday has microsecond resolution.
  struct timeval tv;
  if (gettimeofday(&tv, NULL) < 0)
    return 0;
  return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
}

double OS::DaylightSavingsOffset(double time) {
  if (isnan(time)) return nan_value();
  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
  struct tm* t = localtime(&tv);
  if (NULL == t) return nan_value();
  return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
}

int OS::GetLastError() {
  return errno;
}

// ----------------------------------------------------------------------------
// POSIX stdio support.
//

FILE* OS::FOpen(const char* path, const char* mode) {
  return fopen(path, mode);
}

bool OS::Remove(const char* path) {
  return (remove(path) == 0);
}

const char* OS::LogFileOpenMode = "w";

void OS::Print(const char* format, ...) {
  va_list args;
  va_start(args, format);
  VPrint(format, args);
  va_end(args);
}

void OS::VPrint(const char* format, va_list args) {
#if defined(ANDROID)
  LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
#else
  vprintf(format, args);
#endif
}

void OS::FPrint(FILE* out, const char* format, ...) {
  va_list args;
  va_start(args, format);
  VFPrint(out, format, args);
  va_end(args);
}

void OS::VFPrint(FILE* out, const char* format, va_list args) {
#if defined(ANDROID)
  LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
#else
  vfprintf(out, format, args);
#endif
}

void OS::PrintError(const char* format, ...) {
  va_list args;
  va_start(args, format);
  VPrintError(format, args);
  va_end(args);
}

void OS::VPrintError(const char* format, va_list args) {
#if defined(ANDROID)
  LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
#else
  vfprintf(stderr, format, args);
#endif
}

int OS::SNPrintF(Vector<char> str, const char* format, ...) {
  va_list args;
  va_start(args, format);
  int result = VSNPrintF(str, format, args);
  va_end(args);
  return result;
}

int OS::VSNPrintF(Vector<char> str,
                  const char* format,
                  va_list args) {
  int n = vsnprintf(str.start(), str.length(), format, args);
  if (n < 0 || n >= str.length()) {
    // If the length is zero, the assignment fails.
    if (str.length() > 0)
      str[str.length() - 1] = '\0';
    return -1;
  } else {
    return n;
  }
}

// ----------------------------------------------------------------------------
// POSIX string support.
//

char* OS::StrChr(char* str, int c) {
  return strchr(str, c);
}

void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
  strncpy(dest.start(), src, n);
}

// ----------------------------------------------------------------------------
// POSIX socket support.
//

class POSIXSocket : public Socket {
 public:
  explicit POSIXSocket() {
    // Create the socket.
    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (IsValid()) {
      // Allow rapid reuse.
      static const int kOn = 1;
      int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
                           &kOn, sizeof(kOn));
      ASSERT(ret == 0);
      USE(ret);
    }
  }
  explicit POSIXSocket(int socket): socket_(socket) { }
  virtual ~POSIXSocket() { Shutdown(); }

  // Server initialization.
  bool Bind(const int port);
  bool Listen(int backlog) const;
  Socket* Accept() const;

  // Client initialization.
  bool Connect(const char* host, const char* port);

  // Shutdown socket for both read and write.
  bool Shutdown();

  // Data Transimission
  int Send(const char* data, int len) const;
  int Receive(char* data, int len) const;

  bool SetReuseAddress(bool reuse_address);

  bool IsValid() const { return socket_ != -1; }

 private:
  int socket_;
};

bool POSIXSocket::Bind(const int port) {
  if (!IsValid())  {
    return false;
  }

  sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  addr.sin_port = htons(port);
  int status = bind(socket_,
                    BitCast<struct sockaddr *>(&addr),
                    sizeof(addr));
  return status == 0;
}

bool POSIXSocket::Listen(int backlog) const {
  if (!IsValid()) {
    return false;
  }

  int status = listen(socket_, backlog);
  return status == 0;
}

Socket* POSIXSocket::Accept() const {
  if (!IsValid()) {
    return NULL;
  }

  int socket = accept(socket_, NULL, NULL);
  if (socket == -1) {
    return NULL;
  } else {
    return new POSIXSocket(socket);
  }
}

bool POSIXSocket::Connect(const char* host, const char* port) {
  if (!IsValid()) {
    return false;
  }

  // Lookup host and port.
  struct addrinfo *result = NULL;
  struct addrinfo hints;
  memset(&hints, 0, sizeof(addrinfo));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  int status = getaddrinfo(host, port, &hints, &result);
  if (status != 0) {
    return false;
  }

  // Connect.
  status = connect(socket_, result->ai_addr, result->ai_addrlen);
  freeaddrinfo(result);
  return status == 0;
}

bool POSIXSocket::Shutdown() {
  if (IsValid()) {
    // Shutdown socket for both read and write.
    int status = shutdown(socket_, SHUT_RDWR);
    close(socket_);
    socket_ = -1;
    return status == 0;
  }
  return true;
}

int POSIXSocket::Send(const char* data, int len) const {
  int status = send(socket_, data, len, 0);
  return status;
}

int POSIXSocket::Receive(char* data, int len) const {
  int status = recv(socket_, data, len, 0);
  return status;
}

bool POSIXSocket::SetReuseAddress(bool reuse_address) {
  int on = reuse_address ? 1 : 0;
  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  return status == 0;
}

bool Socket::Setup() {
  // Nothing to do on POSIX.
  return true;
}

int Socket::LastError() {
  return errno;
}

uint16_t Socket::HToN(uint16_t value) {
  return htons(value);
}

uint16_t Socket::NToH(uint16_t value) {
  return ntohs(value);
}

uint32_t Socket::HToN(uint32_t value) {
  return htonl(value);
}

uint32_t Socket::NToH(uint32_t value) {
  return ntohl(value);
}

Socket* OS::CreateSocket() {
  return new POSIXSocket();
}

} }  // namespace v8::internal
<commit_msg>Add a preprocessor symbol to have printing on Android use stdout instead of the system log<commit_after>// Copyright 2009 the V8 project authors. 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 Google Inc. 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
// OWNER 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.

// Platform specific code for POSIX goes here. This is not a platform on its
// own but contains the parts which are the same across POSIX platforms Linux,
// Mac OS, FreeBSD and OpenBSD.

#include <unistd.h>
#include <errno.h>
#include <time.h>

#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#if defined(ANDROID)
#define LOG_TAG "v8"
#include <utils/Log.h>  // LOG_PRI_VA
#endif

#include "v8.h"

#include "platform.h"

namespace v8 {
namespace internal {

// ----------------------------------------------------------------------------
// Math functions

double modulo(double x, double y) {
  return fmod(x, y);
}

double OS::nan_value() {
  // NAN from math.h is defined in C99 and not in POSIX.
  return NAN;
}

// ----------------------------------------------------------------------------
// POSIX date/time support.
//

int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
  struct rusage usage;

  if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
  *secs = usage.ru_utime.tv_sec;
  *usecs = usage.ru_utime.tv_usec;
  return 0;
}

double OS::TimeCurrentMillis() {
  struct timeval tv;
  if (gettimeofday(&tv, NULL) < 0) return 0.0;
  return (static_cast<double>(tv.tv_sec) * 1000) +
         (static_cast<double>(tv.tv_usec) / 1000);
}

int64_t OS::Ticks() {
  // gettimeofday has microsecond resolution.
  struct timeval tv;
  if (gettimeofday(&tv, NULL) < 0)
    return 0;
  return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
}

double OS::DaylightSavingsOffset(double time) {
  if (isnan(time)) return nan_value();
  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
  struct tm* t = localtime(&tv);
  if (NULL == t) return nan_value();
  return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
}

int OS::GetLastError() {
  return errno;
}

// ----------------------------------------------------------------------------
// POSIX stdio support.
//

FILE* OS::FOpen(const char* path, const char* mode) {
  return fopen(path, mode);
}

bool OS::Remove(const char* path) {
  return (remove(path) == 0);
}

const char* OS::LogFileOpenMode = "w";

void OS::Print(const char* format, ...) {
  va_list args;
  va_start(args, format);
  VPrint(format, args);
  va_end(args);
}

void OS::VPrint(const char* format, va_list args) {
#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
  LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
#else
  vprintf(format, args);
#endif
}

void OS::FPrint(FILE* out, const char* format, ...) {
  va_list args;
  va_start(args, format);
  VFPrint(out, format, args);
  va_end(args);
}

void OS::VFPrint(FILE* out, const char* format, va_list args) {
#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
  LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
#else
  vfprintf(out, format, args);
#endif
}

void OS::PrintError(const char* format, ...) {
  va_list args;
  va_start(args, format);
  VPrintError(format, args);
  va_end(args);
}

void OS::VPrintError(const char* format, va_list args) {
#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
  LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
#else
  vfprintf(stderr, format, args);
#endif
}

int OS::SNPrintF(Vector<char> str, const char* format, ...) {
  va_list args;
  va_start(args, format);
  int result = VSNPrintF(str, format, args);
  va_end(args);
  return result;
}

int OS::VSNPrintF(Vector<char> str,
                  const char* format,
                  va_list args) {
  int n = vsnprintf(str.start(), str.length(), format, args);
  if (n < 0 || n >= str.length()) {
    // If the length is zero, the assignment fails.
    if (str.length() > 0)
      str[str.length() - 1] = '\0';
    return -1;
  } else {
    return n;
  }
}

// ----------------------------------------------------------------------------
// POSIX string support.
//

char* OS::StrChr(char* str, int c) {
  return strchr(str, c);
}

void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
  strncpy(dest.start(), src, n);
}

// ----------------------------------------------------------------------------
// POSIX socket support.
//

class POSIXSocket : public Socket {
 public:
  explicit POSIXSocket() {
    // Create the socket.
    socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (IsValid()) {
      // Allow rapid reuse.
      static const int kOn = 1;
      int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
                           &kOn, sizeof(kOn));
      ASSERT(ret == 0);
      USE(ret);
    }
  }
  explicit POSIXSocket(int socket): socket_(socket) { }
  virtual ~POSIXSocket() { Shutdown(); }

  // Server initialization.
  bool Bind(const int port);
  bool Listen(int backlog) const;
  Socket* Accept() const;

  // Client initialization.
  bool Connect(const char* host, const char* port);

  // Shutdown socket for both read and write.
  bool Shutdown();

  // Data Transimission
  int Send(const char* data, int len) const;
  int Receive(char* data, int len) const;

  bool SetReuseAddress(bool reuse_address);

  bool IsValid() const { return socket_ != -1; }

 private:
  int socket_;
};

bool POSIXSocket::Bind(const int port) {
  if (!IsValid())  {
    return false;
  }

  sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  addr.sin_port = htons(port);
  int status = bind(socket_,
                    BitCast<struct sockaddr *>(&addr),
                    sizeof(addr));
  return status == 0;
}

bool POSIXSocket::Listen(int backlog) const {
  if (!IsValid()) {
    return false;
  }

  int status = listen(socket_, backlog);
  return status == 0;
}

Socket* POSIXSocket::Accept() const {
  if (!IsValid()) {
    return NULL;
  }

  int socket = accept(socket_, NULL, NULL);
  if (socket == -1) {
    return NULL;
  } else {
    return new POSIXSocket(socket);
  }
}

bool POSIXSocket::Connect(const char* host, const char* port) {
  if (!IsValid()) {
    return false;
  }

  // Lookup host and port.
  struct addrinfo *result = NULL;
  struct addrinfo hints;
  memset(&hints, 0, sizeof(addrinfo));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  int status = getaddrinfo(host, port, &hints, &result);
  if (status != 0) {
    return false;
  }

  // Connect.
  status = connect(socket_, result->ai_addr, result->ai_addrlen);
  freeaddrinfo(result);
  return status == 0;
}

bool POSIXSocket::Shutdown() {
  if (IsValid()) {
    // Shutdown socket for both read and write.
    int status = shutdown(socket_, SHUT_RDWR);
    close(socket_);
    socket_ = -1;
    return status == 0;
  }
  return true;
}

int POSIXSocket::Send(const char* data, int len) const {
  int status = send(socket_, data, len, 0);
  return status;
}

int POSIXSocket::Receive(char* data, int len) const {
  int status = recv(socket_, data, len, 0);
  return status;
}

bool POSIXSocket::SetReuseAddress(bool reuse_address) {
  int on = reuse_address ? 1 : 0;
  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  return status == 0;
}

bool Socket::Setup() {
  // Nothing to do on POSIX.
  return true;
}

int Socket::LastError() {
  return errno;
}

uint16_t Socket::HToN(uint16_t value) {
  return htons(value);
}

uint16_t Socket::NToH(uint16_t value) {
  return ntohs(value);
}

uint32_t Socket::HToN(uint32_t value) {
  return htonl(value);
}

uint32_t Socket::NToH(uint32_t value) {
  return ntohl(value);
}

Socket* OS::CreateSocket() {
  return new POSIXSocket();
}

} }  // namespace v8::internal
<|endoftext|>


<commit_before>#include <plugin/Plugin.hpp>
#include <plugin/Model.hpp>
#include <plugin.hpp>
#include <string.hpp>

namespace rack {
namespace plugin {

Plugin::~Plugin() {
	for (Model *model : models) {
		delete model;
	}
}

void Plugin::addModel(Model *model) {
	// Check that the model is not added to a plugin already
	assert(!model->plugin);
	model->plugin = this;
	models.push_back(model);
}

Model *Plugin::getModel(std::string slug) {
	slug = normalizeSlug(slug);
	for (Model *model : models) {
		if (model->slug == slug) {
			return model;
		}
	}
	return NULL;
}

void Plugin::fromJson(json_t *rootJ) {
	json_t *slugJ = json_object_get(rootJ, "slug");
	if (slugJ)
		slug = json_string_value(slugJ);

	json_t *versionJ = json_object_get(rootJ, "version");
	if (versionJ)
		version = json_string_value(versionJ);

	json_t *nameJ = json_object_get(rootJ, "name");
	if (nameJ)
		name = json_string_value(nameJ);

	json_t *brandJ = json_object_get(rootJ, "brand");
	if (brandJ)
		brand = json_string_value(brandJ);
	// Use name for brand name by default
	if (brand == "")
		brand = name;

	json_t *authorJ = json_object_get(rootJ, "author");
	if (authorJ)
		author = json_string_value(authorJ);

	json_t *licenseJ = json_object_get(rootJ, "license");
	if (licenseJ)
		license = json_string_value(licenseJ);

	json_t *authorEmailJ = json_object_get(rootJ, "authorEmail");
	if (authorEmailJ)
		authorEmail = json_string_value(authorEmailJ);

	json_t *pluginUrlJ = json_object_get(rootJ, "pluginUrl");
	if (pluginUrlJ)
		pluginUrl = json_string_value(pluginUrlJ);

	json_t *authorUrlJ = json_object_get(rootJ, "authorUrl");
	if (authorUrlJ)
		authorUrl = json_string_value(authorUrlJ);

	json_t *manualUrlJ = json_object_get(rootJ, "manualUrl");
	if (manualUrlJ)
		manualUrl = json_string_value(manualUrlJ);

	json_t *sourceUrlJ = json_object_get(rootJ, "sourceUrl");
	if (sourceUrlJ)
		sourceUrl = json_string_value(sourceUrlJ);

	json_t *donateUrlJ = json_object_get(rootJ, "donateUrl");
	if (donateUrlJ)
		donateUrl = json_string_value(donateUrlJ);

	json_t *modulesJ = json_object_get(rootJ, "modules");
	if (modulesJ) {
		size_t moduleId;
		json_t *moduleJ;
		json_array_foreach(modulesJ, moduleId, moduleJ) {
			json_t *modelSlugJ = json_object_get(moduleJ, "slug");
			if (!modelSlugJ) {
				throw UserException(string::f("No slug found for module entry %d", moduleId));
			}
			std::string modelSlug = json_string_value(modelSlugJ);

			// Check model slug
			if (!isSlugValid(modelSlug)) {
				throw UserException(string::f("Module slug \"%s\" is invalid", modelSlug.c_str()));
			}

			Model *model = getModel(modelSlug);
			if (!model) {
				throw UserException(string::f("Manifest contains module %s but it is not defined in the plugin", modelSlug.c_str()));
			}

			model->fromJson(moduleJ);
		}
	}
}

} // namespace plugin
} // namespace rack
<commit_msg>Add "disabled" property to module object in manifest.<commit_after>#include <plugin/Plugin.hpp>
#include <plugin/Model.hpp>
#include <plugin.hpp>
#include <string.hpp>

namespace rack {
namespace plugin {

Plugin::~Plugin() {
	for (Model *model : models) {
		delete model;
	}
}

void Plugin::addModel(Model *model) {
	// Check that the model is not added to a plugin already
	assert(!model->plugin);
	model->plugin = this;
	models.push_back(model);
}

Model *Plugin::getModel(std::string slug) {
	slug = normalizeSlug(slug);
	for (Model *model : models) {
		if (model->slug == slug) {
			return model;
		}
	}
	return NULL;
}

void Plugin::fromJson(json_t *rootJ) {
	json_t *slugJ = json_object_get(rootJ, "slug");
	if (slugJ)
		slug = json_string_value(slugJ);

	json_t *versionJ = json_object_get(rootJ, "version");
	if (versionJ)
		version = json_string_value(versionJ);

	json_t *nameJ = json_object_get(rootJ, "name");
	if (nameJ)
		name = json_string_value(nameJ);

	json_t *brandJ = json_object_get(rootJ, "brand");
	if (brandJ)
		brand = json_string_value(brandJ);
	// Use name for brand name by default
	if (brand == "")
		brand = name;

	json_t *authorJ = json_object_get(rootJ, "author");
	if (authorJ)
		author = json_string_value(authorJ);

	json_t *licenseJ = json_object_get(rootJ, "license");
	if (licenseJ)
		license = json_string_value(licenseJ);

	json_t *authorEmailJ = json_object_get(rootJ, "authorEmail");
	if (authorEmailJ)
		authorEmail = json_string_value(authorEmailJ);

	json_t *pluginUrlJ = json_object_get(rootJ, "pluginUrl");
	if (pluginUrlJ)
		pluginUrl = json_string_value(pluginUrlJ);

	json_t *authorUrlJ = json_object_get(rootJ, "authorUrl");
	if (authorUrlJ)
		authorUrl = json_string_value(authorUrlJ);

	json_t *manualUrlJ = json_object_get(rootJ, "manualUrl");
	if (manualUrlJ)
		manualUrl = json_string_value(manualUrlJ);

	json_t *sourceUrlJ = json_object_get(rootJ, "sourceUrl");
	if (sourceUrlJ)
		sourceUrl = json_string_value(sourceUrlJ);

	json_t *donateUrlJ = json_object_get(rootJ, "donateUrl");
	if (donateUrlJ)
		donateUrl = json_string_value(donateUrlJ);

	json_t *modulesJ = json_object_get(rootJ, "modules");
	if (modulesJ) {
		size_t moduleId;
		json_t *moduleJ;
		json_array_foreach(modulesJ, moduleId, moduleJ) {
			// Check if module is disabled
			json_t *disabledJ = json_object_get(moduleJ, "disabled");
			if (disabledJ) {
				if (json_boolean_value(disabledJ))
					continue;
			}

			// Get model slug
			json_t *modelSlugJ = json_object_get(moduleJ, "slug");
			if (!modelSlugJ) {
				throw UserException(string::f("No slug found for module entry %d", moduleId));
			}
			std::string modelSlug = json_string_value(modelSlugJ);

			// Check model slug
			if (!isSlugValid(modelSlug)) {
				throw UserException(string::f("Module slug \"%s\" is invalid", modelSlug.c_str()));
			}

			// Get model
			Model *model = getModel(modelSlug);
			if (!model) {
				throw UserException(string::f("Manifest contains module %s but it is not defined in the plugin", modelSlug.c_str()));
			}

			model->fromJson(moduleJ);
		}
	}
}

} // namespace plugin
} // namespace rack
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic

#include "policy/policy.h"

#include "main.h"
#include "tinyformat.h"
#include "util.h"
#include "utilstrencodings.h"

#include <boost/foreach.hpp>

    /**
     * Check transaction inputs to mitigate two
     * potential denial-of-service attacks:
     *
     * 1. scriptSigs with extra data stuffed into them,
     *    not consumed by scriptPubKey (or P2SH script)
     * 2. P2SH scripts with a crazy number of expensive
     *    CHECKSIG/CHECKMULTISIG operations
     *
     * Check transaction inputs, and make sure any
     * pay-to-script-hash transactions are evaluating IsStandard scripts
     *
     * Why bother? To avoid denial-of-service attacks; an attacker
     * can submit a standard HASH... OP_EQUAL transaction,
     * which will get accepted into blocks. The redemption
     * script can be anything; an attacker could use a very
     * expensive-to-check-upon-redemption script like:
     *   DUP CHECKSIG DROP ... repeated 100 times... OP_1
     */

bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
    std::vector<std::vector<unsigned char> > vSolutions;
    if (!Solver(scriptPubKey, whichType, vSolutions))
        return false;

    if (whichType == TX_MULTISIG)
    {
        unsigned char m = vSolutions.front()[0];
        unsigned char n = vSolutions.back()[0];
        // Support up to x-of-3 multisig txns as standard
        if (n < 1 || n > 3)
            return false;
        if (m < 1 || m > n)
            return false;
    } else if (whichType == TX_NULL_DATA &&
               (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
          return false;

    return whichType != TX_NONSTANDARD;
}

int64_t FutureDrift(int64_t nTime)
{
	// loose policy for FutureDrift in regtest mode
	if (Params().GetConsensus().fPowNoRetargeting && chainActive.Height() <= Params().GetConsensus().nLastPOWBlock) {
	         return nTime + 24 * 60 * 60;
	}
    return Params().GetConsensus().IsProtocolV2(nTime) ? nTime + 15 : nTime + 10 * 60;
}

bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
    if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
        reason = "version";
        return false;
    }

    // Extremely large transactions with lots of inputs can cost the network
    // almost as much to process as they cost the sender in fees, because
    // computing signature hashes is O(ninputs*txsize). Limiting transactions
    // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
    unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
    if (sz >= MAX_STANDARD_TX_SIZE) {
        reason = "tx-size";
        return false;
    }

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
        // keys. (remember the 520 byte limit on redeemScript size) That works
        // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
        // bytes of scriptSig, which we round off to 1650 bytes for some minor
        // future-proofing. That's also enough to spend a 20-of-20
        // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
        // considered standard)
        if (txin.scriptSig.size() > 1650) {
            reason = "scriptsig-size";
            return false;
        }
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    unsigned int nDataOut = 0;
    txnouttype whichType;
    BOOST_FOREACH(const CTxOut& txout, tx.vout) {
        if (!::IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }

        if (whichType == TX_NULL_DATA)
            nDataOut++;
        else if (txout.nValue == 0) {
        	reason = "dust";
            return false;
        }
        if (!txout.scriptPubKey.HasCanonicalPushes()) {
            reason = "scriptpubkey-non-canonical-push";
            return false;
        }
        else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
            reason = "bare-multisig";
            return false;
        } else if (txout.IsDust(::minRelayTxFee)) {
            reason = "dust";
            return false;
        }
    }

    // not more than one data txout per non-data txout is permitted
    // only one data txout is permitted too
    if (nDataOut > 1 && nDataOut > tx.vout.size()/2) {
        reason = "multi-op-return";
        return false;
    }

    return true;
}

bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
    if (tx.IsCoinBase())
        return true; // Coinbases don't use vin normally

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);

        std::vector<std::vector<unsigned char> > vSolutions;
        txnouttype whichType;
        // get the scriptPubKey corresponding to this input:
        const CScript& prevScript = prev.scriptPubKey;
        if (!Solver(prevScript, whichType, vSolutions))
            return false;

        if (whichType == TX_SCRIPTHASH)
        {
            std::vector<std::vector<unsigned char> > stack;
            // convert the scriptSig into a stack, so we can inspect the redeemScript
            if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
                return false;
            if (stack.empty())
                return false;
            CScript subscript(stack.back().begin(), stack.back().end());
            if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
                return false;
            }
        }
    }

    return true;
}
<commit_msg>dust fix<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic

#include "policy/policy.h"

#include "main.h"
#include "tinyformat.h"
#include "util.h"
#include "utilstrencodings.h"

#include <boost/foreach.hpp>

    /**
     * Check transaction inputs to mitigate two
     * potential denial-of-service attacks:
     *
     * 1. scriptSigs with extra data stuffed into them,
     *    not consumed by scriptPubKey (or P2SH script)
     * 2. P2SH scripts with a crazy number of expensive
     *    CHECKSIG/CHECKMULTISIG operations
     *
     * Check transaction inputs, and make sure any
     * pay-to-script-hash transactions are evaluating IsStandard scripts
     *
     * Why bother? To avoid denial-of-service attacks; an attacker
     * can submit a standard HASH... OP_EQUAL transaction,
     * which will get accepted into blocks. The redemption
     * script can be anything; an attacker could use a very
     * expensive-to-check-upon-redemption script like:
     *   DUP CHECKSIG DROP ... repeated 100 times... OP_1
     */

bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
    std::vector<std::vector<unsigned char> > vSolutions;
    if (!Solver(scriptPubKey, whichType, vSolutions))
        return false;

    if (whichType == TX_MULTISIG)
    {
        unsigned char m = vSolutions.front()[0];
        unsigned char n = vSolutions.back()[0];
        // Support up to x-of-3 multisig txns as standard
        if (n < 1 || n > 3)
            return false;
        if (m < 1 || m > n)
            return false;
    } else if (whichType == TX_NULL_DATA &&
               (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
          return false;

    return whichType != TX_NONSTANDARD;
}

int64_t FutureDrift(int64_t nTime)
{
	// loose policy for FutureDrift in regtest mode
	if (Params().GetConsensus().fPowNoRetargeting && chainActive.Height() <= Params().GetConsensus().nLastPOWBlock) {
	         return nTime + 24 * 60 * 60;
	}
    return Params().GetConsensus().IsProtocolV2(nTime) ? nTime + 15 : nTime + 10 * 60;
}

bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
    if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
        reason = "version";
        return false;
    }

    // Extremely large transactions with lots of inputs can cost the network
    // almost as much to process as they cost the sender in fees, because
    // computing signature hashes is O(ninputs*txsize). Limiting transactions
    // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
    unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
    if (sz >= MAX_STANDARD_TX_SIZE) {
        reason = "tx-size";
        return false;
    }

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
        // keys. (remember the 520 byte limit on redeemScript size) That works
        // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
        // bytes of scriptSig, which we round off to 1650 bytes for some minor
        // future-proofing. That's also enough to spend a 20-of-20
        // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
        // considered standard)
        if (txin.scriptSig.size() > 1650) {
            reason = "scriptsig-size";
            return false;
        }
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    unsigned int nDataOut = 0;
    txnouttype whichType;
    BOOST_FOREACH(const CTxOut& txout, tx.vout) {
        if (!::IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }

        if (whichType == TX_NULL_DATA)
            nDataOut++;
        else if (txout.nValue == 0) {
        	reason = "dust";
            return false;
        }
        if (!txout.scriptPubKey.HasCanonicalPushes()) {
            reason = "scriptpubkey-non-canonical-push";
            return false;
        }
        else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
            reason = "bare-multisig";
            return false;
        } else if (txout.nValue == 0) {
            reason = "dust";
            return false;
        }
    }

    // not more than one data txout per non-data txout is permitted
    // only one data txout is permitted too
    if (nDataOut > 1 && nDataOut > tx.vout.size()/2) {
        reason = "multi-op-return";
        return false;
    }

    return true;
}

bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
    if (tx.IsCoinBase())
        return true; // Coinbases don't use vin normally

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);

        std::vector<std::vector<unsigned char> > vSolutions;
        txnouttype whichType;
        // get the scriptPubKey corresponding to this input:
        const CScript& prevScript = prev.scriptPubKey;
        if (!Solver(prevScript, whichType, vSolutions))
            return false;

        if (whichType == TX_SCRIPTHASH)
        {
            std::vector<std::vector<unsigned char> > stack;
            // convert the scriptSig into a stack, so we can inspect the redeemScript
            if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
                return false;
            if (stack.empty())
                return false;
            CScript subscript(stack.back().begin(), stack.back().end());
            if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
                return false;
            }
        }
    }

    return true;
}
<|endoftext|>


<commit_before>#include "protob/protob.hpp"

#include "errors.hpp"
#include <boost/bind.hpp>
#include <google/protobuf/stubs/common.h>

#include "arch/arch.hpp"

template <class request_t, class response_t, class context_t>
protob_server_t<request_t, response_t, context_t>::protob_server_t(int port, int http_port, boost::function<response_t(request_t *, context_t *)> _f, response_t (*_on_unparsable_query)(request_t *), protob_server_callback_mode_t _cb_mode)
    : f(_f), on_unparsable_query(_on_unparsable_query), cb_mode(_cb_mode) {
    tcp_listener.init(new tcp_listener_t(port, boost::bind(&protob_server_t<request_t, response_t, context_t>::handle_conn, this, _1, auto_drainer_t::lock_t(&auto_drainer))));
    http_server.init(new http_server_t(http_port, this));
}

template <class request_t, class response_t, class context_t>
protob_server_t<request_t, response_t, context_t>::~protob_server_t() { }

template <class request_t, class response_t, class context_t>
void protob_server_t<request_t, response_t, context_t>::handle_conn(const scoped_ptr_t<nascent_tcp_conn_t> &nconn, auto_drainer_t::lock_t keepalive) {
    context_t ctx;
    scoped_ptr_t<tcp_conn_t> conn;
    nconn->ennervate(&conn);

    //TODO figure out how to do this with less copying
    for (;;) {
        request_t request;
        bool force_response = false;
        response_t forced_response;
        try {
            int32_t size;
            conn->read(&size, sizeof(int32_t), keepalive.get_drain_signal());

            scoped_array_t<char> data(size);
            conn->read(data.data(), size, keepalive.get_drain_signal());

            bool res = request.ParseFromArray(data.data(), size);
            if (!res) {
                forced_response = (*on_unparsable_query)(&request);
                force_response = true;
            }
        } catch (tcp_conn_read_closed_exc_t &) {
            //TODO need to figure out what blocks us up here in non inline cb
            //mode
            return;
        }

        try {
            switch (cb_mode) {
                case INLINE:
                    if (force_response) {
                        send(forced_response, conn.get(), keepalive.get_drain_signal());
                    } else {
                        send(f(&request, &ctx), conn.get(), keepalive.get_drain_signal());
                    }
                    break;
                case CORO_ORDERED:
                    crash("unimplemented");
                    break;
                case CORO_UNORDERED:
                    crash("unimplemented");
                    break;
                default:
                    crash("unreachable");
                    break;
            }
        } catch (tcp_conn_write_closed_exc_t &) {
            //TODO need to figure out what blocks us up here in non inline cb
            //mode
            return;
        }
    }
}

template <class request_t, class response_t, class context_t>
void protob_server_t<request_t, response_t, context_t>::send(const response_t &res, tcp_conn_t *conn, signal_t *closer) THROWS_ONLY(tcp_conn_write_closed_exc_t) {
    int size = res.ByteSize();
    conn->write(&size, sizeof(res.ByteSize()), closer);
    scoped_array_t<char> data(size);

    res.SerializeToArray(data.data(), size);
    conn->write(data.data(), size, closer);
}

template <class request_t, class response_t, class context_t>
http_res_t protob_server_t<request_t, response_t, context_t>::handle(const http_req_t &req) {

    // Extract protobuf from http request body
    const char *data = req.body.data();
    int32_t req_size = *((int32_t *)data);
    data += sizeof(req_size);

    context_t ctx;
    request_t request;
    bool parseFailed = request.ParseFromArray(data, req_size);

    response_t response;
    switch(cb_mode) {
    case INLINE:
        if (!parseFailed) {
            response = f(&request, &ctx);
        } else {
            response = on_unparsable_query(&request);
        }
        break;
    case CORO_ORDERED:
    case CORO_UNORDERED:
        crash("unimplemented");
    default:
        crash("unreachable");
        break;
    }

    int32_t res_size = response.ByteSize();
    scoped_array_t<char> res_data(sizeof(res_size) + res_size);
    *((int32_t *)res_data.data()) = res_size;
    response.SerializeToArray(res_data.data() + sizeof(res_size), res_size);

    http_res_t res(HTTP_OK);
    res.version = "HTTP/1.1";
    res.add_header_line("Access-Control-Allow-Origin", "*");

    std::string body_data;
    body_data.assign(res_data.data(), res_size + sizeof(res_size));
    res.set_body("application/octet-stream", body_data);

    return res;
}
<commit_msg>fixes problem in rdb http server<commit_after>#include "protob/protob.hpp"

#include "errors.hpp"
#include <boost/bind.hpp>
#include <google/protobuf/stubs/common.h>

#include "arch/arch.hpp"

template <class request_t, class response_t, class context_t>
protob_server_t<request_t, response_t, context_t>::protob_server_t(int port, int http_port, boost::function<response_t(request_t *, context_t *)> _f, response_t (*_on_unparsable_query)(request_t *), protob_server_callback_mode_t _cb_mode)
    : f(_f), on_unparsable_query(_on_unparsable_query), cb_mode(_cb_mode) {
    tcp_listener.init(new tcp_listener_t(port, boost::bind(&protob_server_t<request_t, response_t, context_t>::handle_conn, this, _1, auto_drainer_t::lock_t(&auto_drainer))));
    http_server.init(new http_server_t(http_port, this));
}

template <class request_t, class response_t, class context_t>
protob_server_t<request_t, response_t, context_t>::~protob_server_t() { }

template <class request_t, class response_t, class context_t>
void protob_server_t<request_t, response_t, context_t>::handle_conn(const scoped_ptr_t<nascent_tcp_conn_t> &nconn, auto_drainer_t::lock_t keepalive) {
    context_t ctx;
    scoped_ptr_t<tcp_conn_t> conn;
    nconn->ennervate(&conn);

    //TODO figure out how to do this with less copying
    for (;;) {
        request_t request;
        bool force_response = false;
        response_t forced_response;
        try {
            int32_t size;
            conn->read(&size, sizeof(int32_t), keepalive.get_drain_signal());

            scoped_array_t<char> data(size);
            conn->read(data.data(), size, keepalive.get_drain_signal());

            bool res = request.ParseFromArray(data.data(), size);
            if (!res) {
                forced_response = (*on_unparsable_query)(&request);
                force_response = true;
            }
        } catch (tcp_conn_read_closed_exc_t &) {
            //TODO need to figure out what blocks us up here in non inline cb
            //mode
            return;
        }

        try {
            switch (cb_mode) {
                case INLINE:
                    if (force_response) {
                        send(forced_response, conn.get(), keepalive.get_drain_signal());
                    } else {
                        send(f(&request, &ctx), conn.get(), keepalive.get_drain_signal());
                    }
                    break;
                case CORO_ORDERED:
                    crash("unimplemented");
                    break;
                case CORO_UNORDERED:
                    crash("unimplemented");
                    break;
                default:
                    crash("unreachable");
                    break;
            }
        } catch (tcp_conn_write_closed_exc_t &) {
            //TODO need to figure out what blocks us up here in non inline cb
            //mode
            return;
        }
    }
}

template <class request_t, class response_t, class context_t>
void protob_server_t<request_t, response_t, context_t>::send(const response_t &res, tcp_conn_t *conn, signal_t *closer) THROWS_ONLY(tcp_conn_write_closed_exc_t) {
    int size = res.ByteSize();
    conn->write(&size, sizeof(res.ByteSize()), closer);
    scoped_array_t<char> data(size);

    res.SerializeToArray(data.data(), size);
    conn->write(data.data(), size, closer);
}

template <class request_t, class response_t, class context_t>
http_res_t protob_server_t<request_t, response_t, context_t>::handle(const http_req_t &req) {

    // Extract protobuf from http request body
    const char *data = req.body.data();
    int32_t req_size = *((int32_t *)data);
    data += sizeof(req_size);

    context_t ctx;
    request_t request;
    bool parseSucceeded = request.ParseFromArray(data, req_size);

    response_t response;
    switch(cb_mode) {
    case INLINE:
        if (parseSucceeded) {
            response = f(&request, &ctx);
        } else {
            response = on_unparsable_query(&request);
        }
        break;
    case CORO_ORDERED:
    case CORO_UNORDERED:
        crash("unimplemented");
    default:
        crash("unreachable");
        break;
    }

    int32_t res_size = response.ByteSize();
    scoped_array_t<char> res_data(sizeof(res_size) + res_size);
    *((int32_t *)res_data.data()) = res_size;
    response.SerializeToArray(res_data.data() + sizeof(res_size), res_size);

    http_res_t res(HTTP_OK);
    res.version = "HTTP/1.1";
    res.add_header_line("Access-Control-Allow-Origin", "*");

    std::string body_data;
    body_data.assign(res_data.data(), res_size + sizeof(res_size));
    res.set_body("application/octet-stream", body_data);

    return res;
}
<|endoftext|>