<commit_before>/*************************************************************************
 *
 *  $RCSfile: ZipFile.cxx,v $
 *
 *  $Revision: 1.21 $
 *
 *  last change: $Author: mtg $ $Date: 2001-04-30 18:19: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 WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES 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): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_FILE_HXX
#include <ZipFile.hxx>
#endif
#ifndef _ENTRY_INPUT_STREAM_HXX
#include <EntryInputStream.hxx>
#endif
#ifndef _ZIP_ENUMERATION_HXX
#include <ZipEnumeration.hxx>
#endif
#ifndef _VOS_DIAGNOSE_H_
#include <vos/diagnose.hxx>
#endif
#ifndef _COM_SUN_STAR_PACKAGES_ZIPCONSTANTS_HPP_
#include <com/sun/star/packages/ZipConstants.hpp>
#endif
#include <vector>

using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::packages;
using namespace com::sun::star::packages::ZipConstants;

/** This class is used to read entries from a zip file
 */
ZipFile::ZipFile( Reference < io::XInputStream > &xInput, sal_Bool bInitialise)
    throw(io::IOException, ZipException, RuntimeException)
: xStream(xInput)
, aGrabber(xInput)
, aInflater (sal_True)
{
    if (bInitialise)
        readCEN();
}
void ZipFile::setInputStream ( Reference < io::XInputStream > xNewStream )
{
    xStream = xNewStream;
    aGrabber.setInputStream ( xStream );
}

/*
void ZipFile::updateFromManList(std::vector < ManifestEntry * > &rManList)
{
    sal_Int32 i=0, nSize = rManList.size();
    aEntries.clear();

    // This is a bitwise copy, = is not an overloaded operator
    // I'm not sure how evil this is in this case...
    for (;i < nSize ; i++)
    {
        ZipEntry * pEntry = &rManList[i]->aEntry;
        aEntries[pEntry->sName] = *pEntry;
    }
}
*/
ZipFile::~ZipFile()
{
    aEntries.clear();
}

void SAL_CALL ZipFile::close(  )
    throw(io::IOException, RuntimeException)
{
}

ZipEnumeration * SAL_CALL ZipFile::entries(  )
{
    return new ZipEnumeration ( aEntries );
}

::rtl::OUString SAL_CALL ZipFile::getName(  )
    throw(RuntimeException)
{
    return sName;
}

sal_Int32 SAL_CALL ZipFile::getSize(  )
    throw(RuntimeException)
{
    return aEntries.size();
}

Type SAL_CALL ZipFile::getElementType(  )
    throw(RuntimeException)
{
    return ::getCppuType((ZipEntry *) 0);
}

sal_Bool SAL_CALL ZipFile::hasElements(  )
    throw(RuntimeException)
{
    return (aEntries.size()>0);
}

Any SAL_CALL ZipFile::getByName( const ::rtl::OUString& aName )
        throw(container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
{
    Any aAny;
    EntryHash::const_iterator aCI = aEntries.find(sName);
    if (aCI == aEntries.end())
        throw container::NoSuchElementException();
    aAny <<= (*aCI).second;
     return aAny;
}

Sequence< ::rtl::OUString > SAL_CALL ZipFile::getElementNames(  )
        throw(RuntimeException)
{
    sal_uInt32 i=0, nSize = aEntries.size();
    OUString *pNames = new OUString[aEntries.size()];
    for (EntryHash::const_iterator aIterator = aEntries.begin(); aIterator != aEntries.end(); aIterator++,i++)
        pNames[i] = (*aIterator).first;
    return Sequence<OUString> (pNames, nSize);
}

sal_Bool SAL_CALL ZipFile::hasByName( const ::rtl::OUString& aName )
        throw(RuntimeException)
{
    return aEntries.find(aName) != aEntries.end();
}

Reference< io::XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry,
        const vos::ORef < EncryptionData > &rData)
    throw(io::IOException, ZipException, RuntimeException)
{
    if (rEntry.nOffset <= 0)
        readLOC(rEntry);
    Reference< io::XInputStream > xStreamRef = new EntryInputStream(xStream, rEntry, rData, sal_False );
    return xStreamRef;
}

Reference< io::XInputStream > SAL_CALL ZipFile::getRawStream( ZipEntry& rEntry,
        const vos::ORef < EncryptionData > &rData)
    throw(io::IOException, ZipException, RuntimeException)
{
    if (rEntry.nOffset <= 0)
        readLOC(rEntry);
    Reference< io::XInputStream > xStreamRef = new EntryInputStream(xStream, rEntry, rData, sal_True );
    return xStreamRef;
}

sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
    throw(io::IOException, ZipException, RuntimeException)
{
    sal_uInt32 nTestSig, nTime, nCRC, nSize, nCompressedSize;
    sal_uInt16 nVersion, nFlag, nHow, nNameLen, nExtraLen;
    sal_Int32 nPos = -rEntry.nOffset;

    aGrabber.seek(nPos);
    aGrabber >> nTestSig;

    if (nTestSig != LOCSIG)
        throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid LOC header (bad signature") ), Reference < XInterface > () );
    aGrabber >> nVersion;
    aGrabber >> nFlag;
    aGrabber >> nHow;
    aGrabber >> nTime;
    aGrabber >> nCRC;
    aGrabber >> nCompressedSize;
    aGrabber >> nSize;
    aGrabber >> nNameLen;
    aGrabber >> nExtraLen;
    rEntry.nOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nNameLen + nExtraLen;
    return sal_True;
}

sal_Int32 ZipFile::findEND( )
    throw(io::IOException, ZipException, RuntimeException)
{
    sal_Int32 nLength=0, nPos=0;
    Sequence < sal_Int8 > aByteSeq;
    nLength = nPos = static_cast <sal_Int32 > (aGrabber.getLength());

    if (nLength == 0)
        return -1;
        //throw (ZipException( OUString::createFromAscii("Trying to find Zip END signature in a zero length file!"), Reference < XInterface> () ));

    aGrabber.seek( nLength );

    while (nLength - nPos < 0xFFFF)
    {
        sal_uInt32 nCount = 0xFFFF - ( nLength - nPos);
        if (nCount > ENDHDR)
            nCount = ENDHDR;
        nPos -= nCount;

        for (sal_uInt16 i=0; i <nCount;i++)
        {
            sal_uInt32 nTest=0, nFoo=ENDSIG;
            aGrabber.seek (nPos+i);
            aGrabber >> nTest;
            if (nTest == ENDSIG)
            {
                sal_uInt16 nCommentLength;
                sal_Int32 nEndPos = nPos + i;
                aGrabber.seek(nEndPos+ENDCOM);
                aGrabber >> nCommentLength;
                if (nEndPos + ENDHDR + nCommentLength == nLength)
                {
                    if (nCommentLength>0)
                    {
                        aByteSeq.realloc(nCommentLength+1);
                        aGrabber.readBytes(Sequence< sal_Int8>(aByteSeq.getArray(), nCommentLength), nCommentLength);
                        aByteSeq[nCommentLength]='\0';
                        sComment = OUString((sal_Char*)aByteSeq.getConstArray(), nCommentLength+1, RTL_TEXTENCODING_ASCII_US);

                    }
                    return nPos + i;
                }
            }
        }
    }
    throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface> () );
}

sal_Int32 ZipFile::readCEN()
    throw(io::IOException, ZipException, RuntimeException)
{
    sal_Int32 nEndPos, nLocPos;
    sal_Int16  nCount, nTotal;
    sal_Int32 nCenLen, nCenPos, nCenOff;

    nEndPos = findEND();
    if (nEndPos == -1)
        return -1;
    aGrabber.seek(nEndPos + ENDTOT);
    aGrabber >> nTotal;
    aGrabber >> nCenLen;
    aGrabber >> nCenOff;

    if (nTotal<0 || nTotal * CENHDR > nCenLen)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "invalid END header (bad entry count)") ), Reference < XInterface > ());

    if (nTotal > ZIP_MAXENTRIES)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "too many entries in ZIP File") ), Reference < XInterface > ());

    if (nCenLen < 0 || nCenLen > nEndPos)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), Reference < XInterface > ());

    nCenPos = nEndPos - nCenLen;

    if (nCenOff < 0 || nCenOff > nCenPos)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), Reference < XInterface > ());

    nLocPos = nCenPos - nCenOff;
    aGrabber.seek(nCenPos);

    ZipEntry *pEntry = new ZipEntry;
    for (nCount = 0 ; nCount < nTotal; nCount++)
    {
        sal_Int32 nTestSig, nCRC, nCompressedSize, nTime, nSize, nExtAttr, nOffset;
        sal_Int16 nVerMade, nVersion, nFlag, nHow, nNameLen, nExtraLen, nCommentLen;
        sal_Int16 nDisk, nIntAttr;

        if (aGrabber.getPosition() - nCenPos + CENHDR > nCenLen)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad header size check 1)") ), Reference < XInterface > ());

        aGrabber >> nTestSig;
        if (nTestSig != CENSIG)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), Reference < XInterface > ());

        aGrabber >> nVerMade;
        aGrabber >> nVersion;
        if ((nVersion & 1) == 1)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), Reference < XInterface > ());

        aGrabber >> nFlag;
        aGrabber >> nHow;
        if (nHow != STORED && nHow != DEFLATED)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), Reference < XInterface > ());

        aGrabber >> nTime;
        aGrabber >> nCRC;
        aGrabber >> nCompressedSize;
        aGrabber >> nSize;
        aGrabber >> nNameLen;
        aGrabber >> nExtraLen;
        aGrabber >> nCommentLen;
        aGrabber >> nDisk;
        aGrabber >> nIntAttr;
        aGrabber >> nExtAttr;
        aGrabber >> nOffset;

        if (aGrabber.getPosition() - nCenPos + nNameLen + nExtraLen + nCommentLen > nCenLen)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad header size check 2)") ), Reference < XInterface > ());

        if (nNameLen > ZIP_MAXNAMELEN)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "name length exceeds 512 bytes" ) ), Reference < XInterface > ());

        if (nExtraLen > ZIP_MAXEXTRA)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "extra header info exceeds 256 bytes") ), Reference < XInterface > ());

        pEntry->nTime   = nTime;
        pEntry->nCrc    = nCRC;
        pEntry->nSize   = nSize;
        pEntry->nCompressedSize = nCompressedSize;
        pEntry->nMethod = nHow;
        pEntry->nFlag   = nFlag;
        pEntry->nVersion= nVersion;
        pEntry->nOffset = nOffset + nLocPos;

        pEntry->nOffset *= -1;
        /*
        if (nHow == STORED)
            pEntry->nCompressedSize = 0;
        */
        Sequence < sal_Int8> aSequence (nNameLen);
        aGrabber.readBytes(aSequence, nNameLen);
        pEntry->sName = OUString((sal_Char*)aSequence.getConstArray(), nNameLen, RTL_TEXTENCODING_ASCII_US);

        aGrabber.seek(aGrabber.getPosition() + nExtraLen);
        if (nCommentLen>0)
        {
            Sequence < sal_Int8 > aCommentSeq( nCommentLen );
            aGrabber.readBytes(aCommentSeq, nCommentLen);
            pEntry->sComment = OUString((sal_Char*)aCommentSeq.getConstArray(), nNameLen, RTL_TEXTENCODING_ASCII_US);
        }
        aEntries[pEntry->sName] = *pEntry;
    }
    delete pEntry;

    if (nCount != nTotal)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), Reference < XInterface > ());

    return nCenPos;
}
<commit_msg>#87099# Remove unused method<commit_after>/*************************************************************************
 *
 *  $RCSfile: ZipFile.cxx,v $
 *
 *  $Revision: 1.22 $
 *
 *  last change: $Author: mtg $ $Date: 2001-05-31 09:48:20 $
 *
 *  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 WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES 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): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_FILE_HXX
#include <ZipFile.hxx>
#endif
#ifndef _ENTRY_INPUT_STREAM_HXX
#include <EntryInputStream.hxx>
#endif
#ifndef _ZIP_ENUMERATION_HXX
#include <ZipEnumeration.hxx>
#endif
#ifndef _VOS_DIAGNOSE_H_
#include <vos/diagnose.hxx>
#endif
#ifndef _COM_SUN_STAR_PACKAGES_ZIPCONSTANTS_HPP_
#include <com/sun/star/packages/ZipConstants.hpp>
#endif
#include <vector>

using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::packages;
using namespace com::sun::star::packages::ZipConstants;

/** This class is used to read entries from a zip file
 */
ZipFile::ZipFile( Reference < io::XInputStream > &xInput, sal_Bool bInitialise)
    throw(io::IOException, ZipException, RuntimeException)
: xStream(xInput)
, aGrabber(xInput)
, aInflater (sal_True)
{
    if (bInitialise)
        readCEN();
}
void ZipFile::setInputStream ( Reference < io::XInputStream > xNewStream )
{
    xStream = xNewStream;
    aGrabber.setInputStream ( xStream );
}

ZipFile::~ZipFile()
{
    aEntries.clear();
}

void SAL_CALL ZipFile::close(  )
    throw(io::IOException, RuntimeException)
{
}

ZipEnumeration * SAL_CALL ZipFile::entries(  )
{
    return new ZipEnumeration ( aEntries );
}

::rtl::OUString SAL_CALL ZipFile::getName(  )
    throw(RuntimeException)
{
    return sName;
}

sal_Int32 SAL_CALL ZipFile::getSize(  )
    throw(RuntimeException)
{
    return aEntries.size();
}

Type SAL_CALL ZipFile::getElementType(  )
    throw(RuntimeException)
{
    return ::getCppuType((ZipEntry *) 0);
}

sal_Bool SAL_CALL ZipFile::hasElements(  )
    throw(RuntimeException)
{
    return (aEntries.size()>0);
}

Any SAL_CALL ZipFile::getByName( const ::rtl::OUString& aName )
        throw(container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
{
    Any aAny;
    EntryHash::const_iterator aCI = aEntries.find(sName);
    if (aCI == aEntries.end())
        throw container::NoSuchElementException();
    aAny <<= (*aCI).second;
     return aAny;
}

Sequence< ::rtl::OUString > SAL_CALL ZipFile::getElementNames(  )
        throw(RuntimeException)
{
    sal_uInt32 i=0, nSize = aEntries.size();
    OUString *pNames = new OUString[aEntries.size()];
    for (EntryHash::const_iterator aIterator = aEntries.begin(); aIterator != aEntries.end(); aIterator++,i++)
        pNames[i] = (*aIterator).first;
    return Sequence<OUString> (pNames, nSize);
}

sal_Bool SAL_CALL ZipFile::hasByName( const ::rtl::OUString& aName )
        throw(RuntimeException)
{
    return aEntries.find(aName) != aEntries.end();
}

Reference< io::XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry,
        const vos::ORef < EncryptionData > &rData)
    throw(io::IOException, ZipException, RuntimeException)
{
    if (rEntry.nOffset <= 0)
        readLOC(rEntry);
    Reference< io::XInputStream > xStreamRef = new EntryInputStream(xStream, rEntry, rData, sal_False );
    return xStreamRef;
}

Reference< io::XInputStream > SAL_CALL ZipFile::getRawStream( ZipEntry& rEntry,
        const vos::ORef < EncryptionData > &rData)
    throw(io::IOException, ZipException, RuntimeException)
{
    if (rEntry.nOffset <= 0)
        readLOC(rEntry);
    Reference< io::XInputStream > xStreamRef = new EntryInputStream(xStream, rEntry, rData, sal_True );
    return xStreamRef;
}

sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
    throw(io::IOException, ZipException, RuntimeException)
{
    sal_uInt32 nTestSig, nTime, nCRC, nSize, nCompressedSize;
    sal_uInt16 nVersion, nFlag, nHow, nNameLen, nExtraLen;
    sal_Int32 nPos = -rEntry.nOffset;

    aGrabber.seek(nPos);
    aGrabber >> nTestSig;

    if (nTestSig != LOCSIG)
        throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid LOC header (bad signature") ), Reference < XInterface > () );
    aGrabber >> nVersion;
    aGrabber >> nFlag;
    aGrabber >> nHow;
    aGrabber >> nTime;
    aGrabber >> nCRC;
    aGrabber >> nCompressedSize;
    aGrabber >> nSize;
    aGrabber >> nNameLen;
    aGrabber >> nExtraLen;
    rEntry.nOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nNameLen + nExtraLen;
    return sal_True;
}

sal_Int32 ZipFile::findEND( )
    throw(io::IOException, ZipException, RuntimeException)
{
    sal_Int32 nLength=0, nPos=0;
    Sequence < sal_Int8 > aByteSeq;
    nLength = nPos = static_cast <sal_Int32 > (aGrabber.getLength());

    if (nLength == 0)
        return -1;
        //throw (ZipException( OUString::createFromAscii("Trying to find Zip END signature in a zero length file!"), Reference < XInterface> () ));

    aGrabber.seek( nLength );

    while (nLength - nPos < 0xFFFF)
    {
        sal_uInt32 nCount = 0xFFFF - ( nLength - nPos);
        if (nCount > ENDHDR)
            nCount = ENDHDR;
        nPos -= nCount;

        for (sal_uInt16 i=0; i <nCount;i++)
        {
            sal_uInt32 nTest=0, nFoo=ENDSIG;
            aGrabber.seek (nPos+i);
            aGrabber >> nTest;
            if (nTest == ENDSIG)
            {
                sal_uInt16 nCommentLength;
                sal_Int32 nEndPos = nPos + i;
                aGrabber.seek(nEndPos+ENDCOM);
                aGrabber >> nCommentLength;
                if (nEndPos + ENDHDR + nCommentLength == nLength)
                {
                    if (nCommentLength>0)
                    {
                        aByteSeq.realloc(nCommentLength+1);
                        aGrabber.readBytes(Sequence< sal_Int8>(aByteSeq.getArray(), nCommentLength), nCommentLength);
                        aByteSeq[nCommentLength]='\0';
                        sComment = OUString((sal_Char*)aByteSeq.getConstArray(), nCommentLength+1, RTL_TEXTENCODING_ASCII_US);

                    }
                    return nPos + i;
                }
            }
        }
    }
    throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface> () );
}

sal_Int32 ZipFile::readCEN()
    throw(io::IOException, ZipException, RuntimeException)
{
    sal_Int32 nEndPos, nLocPos;
    sal_Int16  nCount, nTotal;
    sal_Int32 nCenLen, nCenPos, nCenOff;

    nEndPos = findEND();
    if (nEndPos == -1)
        return -1;
    aGrabber.seek(nEndPos + ENDTOT);
    aGrabber >> nTotal;
    aGrabber >> nCenLen;
    aGrabber >> nCenOff;

    if (nTotal<0 || nTotal * CENHDR > nCenLen)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "invalid END header (bad entry count)") ), Reference < XInterface > ());

    if (nTotal > ZIP_MAXENTRIES)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "too many entries in ZIP File") ), Reference < XInterface > ());

    if (nCenLen < 0 || nCenLen > nEndPos)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), Reference < XInterface > ());

    nCenPos = nEndPos - nCenLen;

    if (nCenOff < 0 || nCenOff > nCenPos)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), Reference < XInterface > ());

    nLocPos = nCenPos - nCenOff;
    aGrabber.seek(nCenPos);

    ZipEntry *pEntry = new ZipEntry;
    for (nCount = 0 ; nCount < nTotal; nCount++)
    {
        sal_Int32 nTestSig, nCRC, nCompressedSize, nTime, nSize, nExtAttr, nOffset;
        sal_Int16 nVerMade, nVersion, nFlag, nHow, nNameLen, nExtraLen, nCommentLen;
        sal_Int16 nDisk, nIntAttr;

        if (aGrabber.getPosition() - nCenPos + CENHDR > nCenLen)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad header size check 1)") ), Reference < XInterface > ());

        aGrabber >> nTestSig;
        if (nTestSig != CENSIG)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), Reference < XInterface > ());

        aGrabber >> nVerMade;
        aGrabber >> nVersion;
        if ((nVersion & 1) == 1)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), Reference < XInterface > ());

        aGrabber >> nFlag;
        aGrabber >> nHow;
        if (nHow != STORED && nHow != DEFLATED)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), Reference < XInterface > ());

        aGrabber >> nTime;
        aGrabber >> nCRC;
        aGrabber >> nCompressedSize;
        aGrabber >> nSize;
        aGrabber >> nNameLen;
        aGrabber >> nExtraLen;
        aGrabber >> nCommentLen;
        aGrabber >> nDisk;
        aGrabber >> nIntAttr;
        aGrabber >> nExtAttr;
        aGrabber >> nOffset;

        if (aGrabber.getPosition() - nCenPos + nNameLen + nExtraLen + nCommentLen > nCenLen)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad header size check 2)") ), Reference < XInterface > ());

        if (nNameLen > ZIP_MAXNAMELEN)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "name length exceeds 512 bytes" ) ), Reference < XInterface > ());

        if (nExtraLen > ZIP_MAXEXTRA)
            throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "extra header info exceeds 256 bytes") ), Reference < XInterface > ());

        pEntry->nTime   = nTime;
        pEntry->nCrc    = nCRC;
        pEntry->nSize   = nSize;
        pEntry->nCompressedSize = nCompressedSize;
        pEntry->nMethod = nHow;
        pEntry->nFlag   = nFlag;
        pEntry->nVersion= nVersion;
        pEntry->nOffset = nOffset + nLocPos;

        pEntry->nOffset *= -1;
        /*
        if (nHow == STORED)
            pEntry->nCompressedSize = 0;
        */
        Sequence < sal_Int8> aSequence (nNameLen);
        aGrabber.readBytes(aSequence, nNameLen);
        pEntry->sName = OUString((sal_Char*)aSequence.getConstArray(), nNameLen, RTL_TEXTENCODING_ASCII_US);

        aGrabber.seek(aGrabber.getPosition() + nExtraLen);
        if (nCommentLen>0)
        {
            Sequence < sal_Int8 > aCommentSeq( nCommentLen );
            aGrabber.readBytes(aCommentSeq, nCommentLen);
            pEntry->sComment = OUString((sal_Char*)aCommentSeq.getConstArray(), nNameLen, RTL_TEXTENCODING_ASCII_US);
        }
        aEntries[pEntry->sName] = *pEntry;
    }
    delete pEntry;

    if (nCount != nTotal)
        throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), Reference < XInterface > ());

    return nCenPos;
}
<|endoftext|>


<commit_before>#include "gb-include.h"

#include "ip.h"

long atoip ( char *s , long slen ) {
	// point to it
	char *p = s;
	if ( s[slen] ) {
		// copy into buffer and NULL terminate
		char buf[1024];
		if ( slen >= 1024 ) slen = 1023;
		memcpy ( buf , s , slen );
		buf [ slen ] = '\0';
		// point to that
		p = buf;
	}
	// convert to int
	struct in_addr in;
	in.s_addr = 0;
	inet_aton ( p , &in );
	// ensure this really is a long before returning ip
	if ( sizeof(in_addr) == 4 ) return in.s_addr;
	// otherwise bitch and return 0
	log("ip:bad inet_aton");
	return 0;
}

long atoip ( char *s ) {
	// convert to int
	struct in_addr in;
	in.s_addr = 0;
	inet_aton ( s , &in );
	// ensure this really is a long before returning ip
	if ( sizeof(in_addr) == 4 ) return in.s_addr;
	// otherwise bitch and return 0
	log("ip:bad inet_aton");
	return 0;
}

char *iptoa ( long ip ) {
	static char s_buf [ 32 ];
	sprintf ( s_buf , "%hhu.%hhu.%hhu.%hhu",
		  (unsigned char)(ip >>  0)&0xff,
		  (unsigned char)(ip >>  8)&0xff,
		  (unsigned char)(ip >> 16)&0xff,
		  (unsigned char)(ip >> 24)&0xff);
	return s_buf;
	//struct in_addr in;
	//in.s_addr = ip;
	//return inet_ntoa ( in );
}

// . get domain of ip address
// . first byte is the host (little endian)
long  ipdom ( long ip ) { return ip & 0x00ffffff; };

// most significant 2 bytes of ip
long  iptop ( long ip ) { return ip & 0x0000ffff; };

// . is least significant byte a zero?
// . if it is then this ip is probably representing a whole ip domain
bool  isIpDom ( long ip ) { return ( (ip & 0xff000000) == 0 ); };

// are last 2 bytes 0's?
long  isIpTop ( long ip ) { return ( (ip & 0xffff0000) == 0 ); };

// returns number of top bytes in comon
long  ipCmp ( long ip1 , long ip2 ) {
	char *a = (char *)ip1;
	char *b = (char *)ip2;
	// little endian compare
	if ( a[3] != b[3] ) return 0;
	if ( a[2] != b[2] ) return 1;
	if ( a[1] != b[1] ) return 2;
	if ( a[0] != b[0] ) return 3;
	return 4; // exact match
}

<commit_msg>fix old bug.<commit_after>#include "gb-include.h"

#include "ip.h"

long atoip ( char *s , long slen ) {
	// point to it
	char *p = s;
	if ( s[slen] ) {
		// copy into buffer and NULL terminate
		char buf[1024];
		if ( slen >= 1024 ) slen = 1023;
		memcpy ( buf , s , slen );
		buf [ slen ] = '\0';
		// point to that
		p = buf;
	}
	// convert to int
	struct in_addr in;
	in.s_addr = 0;
	inet_aton ( p , &in );
	// ensure this really is a long before returning ip
	if ( sizeof(in_addr) == 4 ) return in.s_addr;
	// otherwise bitch and return 0
	log("ip:bad inet_aton");
	return 0;
}

long atoip ( char *s ) {
	// convert to int
	struct in_addr in;
	in.s_addr = 0;
	inet_aton ( s , &in );
	// ensure this really is a long before returning ip
	if ( sizeof(in_addr) == 4 ) return in.s_addr;
	// otherwise bitch and return 0
	log("ip:bad inet_aton");
	return 0;
}

char *iptoa ( long ip ) {
	static char s_buf [ 32 ];
	sprintf ( s_buf , "%hhu.%hhu.%hhu.%hhu",
		  (unsigned char)(ip >>  0)&0xff,
		  (unsigned char)(ip >>  8)&0xff,
		  (unsigned char)(ip >> 16)&0xff,
		  (unsigned char)(ip >> 24)&0xff);
	return s_buf;
	//struct in_addr in;
	//in.s_addr = ip;
	//return inet_ntoa ( in );
}

// . get domain of ip address
// . first byte is the host (little endian)
long  ipdom ( long ip ) { return ip & 0x00ffffff; };

// most significant 2 bytes of ip
long  iptop ( long ip ) { return ip & 0x0000ffff; };

// . is least significant byte a zero?
// . if it is then this ip is probably representing a whole ip domain
bool  isIpDom ( long ip ) { return ( (ip & 0xff000000) == 0 ); };

// are last 2 bytes 0's?
long  isIpTop ( long ip ) { return ( (ip & 0xffff0000) == 0 ); };

// returns number of top bytes in comon
long  ipCmp ( long ip1 , long ip2 ) {
	char *a = (char *)&ip1;
	char *b = (char *)&ip2;
	// little endian compare
	if ( a[3] != b[3] ) return 0;
	if ( a[2] != b[2] ) return 1;
	if ( a[1] != b[1] ) return 2;
	if ( a[0] != b[0] ) return 3;
	return 4; // exact match
}

<|endoftext|>


<commit_before>#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkImage.h"

int main( int argc, char ** argv )
{
  if( argc < 3 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " inputImageFile  outputImageFile " << std::endl;
    return EXIT_FAILURE;
    }

  typedef float      PixelType;
  const   unsigned int        Dimension = 3;
  typedef itk::Image< PixelType, Dimension >    ImageType;
  typedef itk::ImageFileReader< ImageType >  ReaderType;
  typedef itk::ImageFileWriter< ImageType >  WriterType;

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  const char * inputFilename  = argv[1];
  const char * outputFilename = argv[2];

  reader->SetFileName( inputFilename  );
  writer->SetFileName( outputFilename );

  writer->SetInput( reader->GetOutput() );

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<commit_msg>Usage spelling.<commit_after>#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkImage.h"

int main( int argc, char ** argv )
{
  if( argc < 3 )
    {
    std::cerr << "Usage:" << std::endl;
    std::cerr << argv[0] << " inputImageFile outputImageFile" << std::endl;
    return EXIT_FAILURE;
    }

  typedef float      PixelType;
  const   unsigned int        Dimension = 3;
  typedef itk::Image< PixelType, Dimension >    ImageType;
  typedef itk::ImageFileReader< ImageType >  ReaderType;
  typedef itk::ImageFileWriter< ImageType >  WriterType;

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  const char * inputFilename  = argv[1];
  const char * outputFilename = argv[2];

  reader->SetFileName( inputFilename  );
  writer->SetFileName( outputFilename );

  writer->SetInput( reader->GetOutput() );

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cerr << "ExceptionObject caught !" << std::endl;
    std::cerr << err << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "net/http_client.h"

#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#define closesocket close
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#include "base/logging.h"
#include "base/buffer.h"
#include "base/stringutil.h"
#include "data/compression.h"
#include "net/resolve.h"
#include "net/url.h"

// #include "strings/strutil.h"

namespace net {

Connection::Connection()
		: port_(-1), sock_(-1), resolved_(NULL) {
}

Connection::~Connection() {
	Disconnect();
	if (resolved_ != NULL)
		DNSResolveFree(resolved_);
}

// For whatever crazy reason, htons isn't available on android x86 on the build server. so here we go.

// TODO: Fix for big-endian
inline unsigned short myhtons(unsigned short x) {
	return (x >> 8) | (x << 8);
}

bool Connection::Resolve(const char *host, int port) {
	if ((intptr_t)sock_ != -1) {
		ELOG("Resolve: Already have a socket");
		return false;
	}

	host_ = host;
	port_ = port;

	char port_str[10];
	snprintf(port_str, sizeof(port_str), "%d", port);

	std::string err;
	if (!net::DNSResolve(host, port_str, &resolved_, err)) {
		ELOG("Failed to resolve host %s: %s", host, err.c_str());
		// So that future calls fail.
		port_ = 0;
		return false;
	}

	return true;
}

bool Connection::Connect() {
	if (port_ <= 0) {
		ELOG("Bad port");
		return false;
	}
	sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if ((intptr_t)sock_ == -1) {
		ELOG("Bad socket");
		return false;
	}

	for (int tries = 100; tries > 0; --tries) {
		for (addrinfo *possible = resolved_; possible != NULL; possible = possible->ai_next) {
			// TODO: Could support ipv6 without huge difficulty...
			if (possible->ai_family != AF_INET)
				continue;

			int retval = connect(sock_, possible->ai_addr, (int)possible->ai_addrlen);
			if (retval >= 0)
				return true;
		}
#ifdef _WIN32
		Sleep(1);
#else
		sleep(1);
#endif
	}

	// Let's not leak this socket.
	closesocket(sock_);
	sock_ = -1;
	return false;
}

void Connection::Disconnect() {
	if ((intptr_t)sock_ != -1) {
		closesocket(sock_);
		sock_ = -1;
	}
}

}	// net

namespace http {

Client::Client() {

}

Client::~Client() {
	Disconnect();
}

// TODO: do something sane here
#define USERAGENT "NATIVEAPP 1.0"

void DeChunk(Buffer *inbuffer, Buffer *outbuffer) {
	while (true) {
		std::string line;
		inbuffer->TakeLineCRLF(&line);
		if (!line.size())
			return;
		int chunkSize;
		sscanf(line.c_str(), "%x", &chunkSize);
		if (chunkSize) {
			std::string data;
			inbuffer->Take(chunkSize, &data);
			outbuffer->Append(data);
		} else {
			// a zero size chunk should mean the end.
			inbuffer->clear();
			return;
		}
		inbuffer->Skip(2);
	}
}

int Client::GET(const char *resource, Buffer *output) {
	Buffer buffer;
	const char *tpl =
		"GET %s HTTP/1.1\r\n"
		"Host: %s\r\n"
		"User-Agent: " USERAGENT "\r\n"
		"Accept: */*\r\n"
		"Accept-Encoding: gzip\r\n"
		"Connection: close\r\n"
		"\r\n";

	buffer.Printf(tpl, resource, host_.c_str());
	bool flushed = buffer.FlushSocket(sock());
	if (!flushed) {
		return -1;  // TODO error code.
	}

	Buffer readbuf;

	// Snarf all the data we can into RAM. A little unsafe but hey.
	if (!readbuf.ReadAll(sock()))
		return -1;

	// Grab the first header line that contains the http code.

	// Skip the header. TODO: read HTTP code and file size so we can make progress bars.

	std::string line;
	readbuf.TakeLineCRLF(&line);
	int code = atoi(&line[line.find(" ") + 1]);

	bool gzip = false;
	int contentLength = 0;
	while (true) {
		int sz = readbuf.TakeLineCRLF(&line);
		if (!sz)
			break;
		if (startsWith(line, "Content-Length:")) {
			contentLength = atoi(&line[16]);
		} else if (startsWith(line, "Content-Encoding:")) {
			if (line.find("gzip") != std::string::npos) {
				gzip = true;
			}
		}
	}

	// output now contains the rest of the reply. Dechunk it.
	DeChunk(&readbuf, output);

	// If it's gzipped, we decompress it and put it back in the buffer.
	if (gzip) {
		std::string compressed;
		output->TakeAll(&compressed);
		// What is this garbage?
		//if (compressed[0] == 0x8e)
//			compressed = compressed.substr(4);
		std::string decompressed;
		bool result = decompress_string(compressed, &decompressed);
		if (!result) {
			ELOG("Error decompressing using zlib");
			return -1;
		}
		output->Append(decompressed);
	}

	return code;
}

int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output) {
	Buffer buffer;
	const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\nContent-Length: %d\r\n";
	buffer.Printf(tpl, resource, host_.c_str(), (int)data.size());
	if (!mime.empty()) {
		buffer.Printf("Content-Type: %s\r\n", mime.c_str());
	}
	buffer.Append("\r\n");
	buffer.Append(data);
	if (!buffer.FlushSocket(sock())) {
		ELOG("Failed posting");
	}

	// I guess we could add a deadline here.
	output->ReadAll(sock());

	if (output->size() == 0) {
		// The connection was closed.
		ELOG("POST failed.");
		return -1;
	}

	std::string debug_data;
	output->PeekAll(&debug_data);

	//VLOG(1) << "Reply size (before stripping headers): " << debug_data.size();
	std::string debug_str;
	StringToHexString(debug_data, &debug_str);
	// Tear off the http headers, leaving the actual response data.
	std::string firstline;
	CHECK_GT(output->TakeLineCRLF(&firstline), 0);
	int code = atoi(&firstline[9]);
	//VLOG(1) << "HTTP result code: " << code;
	while (true) {
		int skipped = output->SkipLineCRLF();
		if (skipped == 0)
			break;
	}
	output->PeekAll(&debug_data);
	return code;
}

int Client::POST(const char *resource, const std::string &data, Buffer *output) {
	return POST(resource, data, "", output);
}

Download::Download(const std::string &url, const std::string &outfile)
	: url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0) {
	std::thread th(std::bind(&Download::Do, this));
	th.detach();
}

Download::~Download() {

}

void Download::Do() {
	resultCode_ = 0;

	Url fileUrl(url_);
	if (!fileUrl.Valid()) {
		failed_ = true;
		progress_ = 1.0f;
		return;
	}
	net::Init();

	http::Client client;
	if (!client.Resolve(fileUrl.Host().c_str(), 80)) {
		ELOG("Failed resolving %s", url_.c_str());
		failed_ = true;
		progress_ = 1.0f;
		net::Shutdown();
		return;
	}
	if (!client.Connect()) {
		ELOG("Failed connecting to server.");
		resultCode_ = -1;
		net::Shutdown();
		progress_ = 1.0f;
		return;
	}
	int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_);
	if (resultCode == 200) {
		ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str());
		if (!outfile_.empty() && !buffer_.FlushToFile(outfile_.c_str())) {
			ELOG("Failed writing download to %s", outfile_.c_str());
		}
	} else {
		ELOG("Error downloading %s to %s: %i", url_.c_str(), outfile_.c_str(), resultCode);
	}
	resultCode_ = resultCode;
	net::Shutdown();
	progress_ = 1.0f;
}

std::shared_ptr<Download> Downloader::StartDownload(const std::string &url, const std::string &outfile) {
	std::shared_ptr<Download> dl(new Download(url, outfile));
	downloads_.push_back(dl);
	return dl;
}

void Downloader::Update() {
	restart:
	for (size_t i = 0; i < downloads_.size(); i++) {
		if (downloads_[i]->Progress() == 1.0f || downloads_[i]->Failed()) {
			downloads_.erase(downloads_.begin() + i);
			goto restart;
		}
	}
}

}	// http
<commit_msg>Support non-chunked HTTP responses.<commit_after>#include "net/http_client.h"

#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#define closesocket close
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#include "base/logging.h"
#include "base/buffer.h"
#include "base/stringutil.h"
#include "data/compression.h"
#include "net/resolve.h"
#include "net/url.h"

// #include "strings/strutil.h"

namespace net {

Connection::Connection()
		: port_(-1), sock_(-1), resolved_(NULL) {
}

Connection::~Connection() {
	Disconnect();
	if (resolved_ != NULL)
		DNSResolveFree(resolved_);
}

// For whatever crazy reason, htons isn't available on android x86 on the build server. so here we go.

// TODO: Fix for big-endian
inline unsigned short myhtons(unsigned short x) {
	return (x >> 8) | (x << 8);
}

bool Connection::Resolve(const char *host, int port) {
	if ((intptr_t)sock_ != -1) {
		ELOG("Resolve: Already have a socket");
		return false;
	}

	host_ = host;
	port_ = port;

	char port_str[10];
	snprintf(port_str, sizeof(port_str), "%d", port);

	std::string err;
	if (!net::DNSResolve(host, port_str, &resolved_, err)) {
		ELOG("Failed to resolve host %s: %s", host, err.c_str());
		// So that future calls fail.
		port_ = 0;
		return false;
	}

	return true;
}

bool Connection::Connect() {
	if (port_ <= 0) {
		ELOG("Bad port");
		return false;
	}
	sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if ((intptr_t)sock_ == -1) {
		ELOG("Bad socket");
		return false;
	}

	for (int tries = 100; tries > 0; --tries) {
		for (addrinfo *possible = resolved_; possible != NULL; possible = possible->ai_next) {
			// TODO: Could support ipv6 without huge difficulty...
			if (possible->ai_family != AF_INET)
				continue;

			int retval = connect(sock_, possible->ai_addr, (int)possible->ai_addrlen);
			if (retval >= 0)
				return true;
		}
#ifdef _WIN32
		Sleep(1);
#else
		sleep(1);
#endif
	}

	// Let's not leak this socket.
	closesocket(sock_);
	sock_ = -1;
	return false;
}

void Connection::Disconnect() {
	if ((intptr_t)sock_ != -1) {
		closesocket(sock_);
		sock_ = -1;
	}
}

}	// net

namespace http {

Client::Client() {

}

Client::~Client() {
	Disconnect();
}

// TODO: do something sane here
#define USERAGENT "NATIVEAPP 1.0"

void DeChunk(Buffer *inbuffer, Buffer *outbuffer) {
	while (true) {
		std::string line;
		inbuffer->TakeLineCRLF(&line);
		if (!line.size())
			return;
		int chunkSize;
		sscanf(line.c_str(), "%x", &chunkSize);
		if (chunkSize) {
			std::string data;
			inbuffer->Take(chunkSize, &data);
			outbuffer->Append(data);
		} else {
			// a zero size chunk should mean the end.
			inbuffer->clear();
			return;
		}
		inbuffer->Skip(2);
	}
}

int Client::GET(const char *resource, Buffer *output) {
	Buffer buffer;
	const char *tpl =
		"GET %s HTTP/1.1\r\n"
		"Host: %s\r\n"
		"User-Agent: " USERAGENT "\r\n"
		"Accept: */*\r\n"
		"Accept-Encoding: gzip\r\n"
		"Connection: close\r\n"
		"\r\n";

	buffer.Printf(tpl, resource, host_.c_str());
	bool flushed = buffer.FlushSocket(sock());
	if (!flushed) {
		return -1;  // TODO error code.
	}

	Buffer readbuf;

	// Snarf all the data we can into RAM. A little unsafe but hey.
	if (!readbuf.ReadAll(sock()))
		return -1;

	// Grab the first header line that contains the http code.

	// Skip the header. TODO: read HTTP code and file size so we can make progress bars.

	std::string line;
	readbuf.TakeLineCRLF(&line);

	int code;
	size_t code_pos = line.find(' ');
	if (code_pos != line.npos) {
		code_pos = line.find_first_not_of(' ', code_pos);
	}
	if (code_pos != line.npos) {
		code = atoi(&line[code_pos]);
	} else {
		return -1;
	}

	bool gzip = false;
	bool chunked = false;
	int contentLength = 0;
	while (true) {
		int sz = readbuf.TakeLineCRLF(&line);
		if (!sz)
			break;
		// TODO: Case folding.
		if (startsWith(line, "Content-Length:")) {
			size_t size_pos = line.find_first_of(' ');
			if (size_pos != line.npos) {
				size_pos = line.find_first_not_of(' ', size_pos);
			}
			if (size_pos != line.npos) {
				contentLength = atoi(&line[size_pos]);
				chunked = false;
			}
		} else if (startsWith(line, "Content-Encoding:")) {
			if (line.find("gzip") != std::string::npos) {
				gzip = true;
			}
		} else if (startsWith(line, "Transfer-Encoding:")) {
			if (line.find("chunked") != std::string::npos) {
				chunked = true;
			}
		}
	}

	// output now contains the rest of the reply. Dechunk it.
	if (chunked) {
		DeChunk(&readbuf, output);
	} else {
		output->Append(readbuf);
	}

	// If it's gzipped, we decompress it and put it back in the buffer.
	if (gzip) {
		std::string compressed;
		output->TakeAll(&compressed);
		// What is this garbage?
		//if (compressed[0] == 0x8e)
//			compressed = compressed.substr(4);
		std::string decompressed;
		bool result = decompress_string(compressed, &decompressed);
		if (!result) {
			ELOG("Error decompressing using zlib");
			return -1;
		}
		output->Append(decompressed);
	}

	return code;
}

int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output) {
	Buffer buffer;
	const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\nContent-Length: %d\r\n";
	buffer.Printf(tpl, resource, host_.c_str(), (int)data.size());
	if (!mime.empty()) {
		buffer.Printf("Content-Type: %s\r\n", mime.c_str());
	}
	buffer.Append("\r\n");
	buffer.Append(data);
	if (!buffer.FlushSocket(sock())) {
		ELOG("Failed posting");
	}

	// I guess we could add a deadline here.
	output->ReadAll(sock());

	if (output->size() == 0) {
		// The connection was closed.
		ELOG("POST failed.");
		return -1;
	}

	std::string debug_data;
	output->PeekAll(&debug_data);

	//VLOG(1) << "Reply size (before stripping headers): " << debug_data.size();
	std::string debug_str;
	StringToHexString(debug_data, &debug_str);
	// Tear off the http headers, leaving the actual response data.
	std::string firstline;
	CHECK_GT(output->TakeLineCRLF(&firstline), 0);
	int code = atoi(&firstline[9]);
	//VLOG(1) << "HTTP result code: " << code;
	while (true) {
		int skipped = output->SkipLineCRLF();
		if (skipped == 0)
			break;
	}
	output->PeekAll(&debug_data);
	return code;
}

int Client::POST(const char *resource, const std::string &data, Buffer *output) {
	return POST(resource, data, "", output);
}

Download::Download(const std::string &url, const std::string &outfile)
	: url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0) {
	std::thread th(std::bind(&Download::Do, this));
	th.detach();
}

Download::~Download() {

}

void Download::Do() {
	resultCode_ = 0;

	Url fileUrl(url_);
	if (!fileUrl.Valid()) {
		failed_ = true;
		progress_ = 1.0f;
		return;
	}
	net::Init();

	http::Client client;
	if (!client.Resolve(fileUrl.Host().c_str(), 80)) {
		ELOG("Failed resolving %s", url_.c_str());
		failed_ = true;
		progress_ = 1.0f;
		net::Shutdown();
		return;
	}
	if (!client.Connect()) {
		ELOG("Failed connecting to server.");
		resultCode_ = -1;
		net::Shutdown();
		progress_ = 1.0f;
		return;
	}
	int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_);
	if (resultCode == 200) {
		ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str());
		if (!outfile_.empty() && !buffer_.FlushToFile(outfile_.c_str())) {
			ELOG("Failed writing download to %s", outfile_.c_str());
		}
	} else {
		ELOG("Error downloading %s to %s: %i", url_.c_str(), outfile_.c_str(), resultCode);
	}
	resultCode_ = resultCode;
	net::Shutdown();
	progress_ = 1.0f;
}

std::shared_ptr<Download> Downloader::StartDownload(const std::string &url, const std::string &outfile) {
	std::shared_ptr<Download> dl(new Download(url, outfile));
	downloads_.push_back(dl);
	return dl;
}

void Downloader::Update() {
	restart:
	for (size_t i = 0; i < downloads_.size(); i++) {
		if (downloads_[i]->Progress() == 1.0f || downloads_[i]->Failed()) {
			downloads_.erase(downloads_.begin() + i);
			goto restart;
		}
	}
}

}	// http
<|endoftext|>


<commit_before>#include "core/wordwrap.h"

namespace euphoria::core
{
    std::vector<std::string>
    word_wrap
    (
        const std::string& str,
        std::function<bool (const std::string&)> measure
    )
    {
        using I = std::string::size_type;
        if(measure(str)) { return {str}; }

        auto ret = std::vector<std::string>{};

        I start = 0;
        I last = 0;

        auto get_string = [&str, &start](I end)
        {
            if(end == std::string::npos)
            {
                return str.substr(start);
            }
            else
            {
                return str.substr(start, end - (start+1));
            }
        };

        for(int bulldog=0; bulldog<50; bulldog+=1)
        {
            if(last == std::string::npos)
            {
                return ret;
            }
            const auto first = str.find(' ', last);
            const auto s = get_string(first);
            const auto fit = measure(s);

            if(fit)
            {
                // fit.. continue
                last = (first != std::string::npos) ? first+1 : first;
            }
            if(!fit || last == std::string::npos)
            {
                // new doesn't fit, use last
                const auto p = last == start ? first : last;
                const auto pp = last == start && p != std::string::npos ? p+1 : p;
                ret.emplace_back(get_string(pp));
                if(p == std::string::npos)
                {
                    return ret;
                }
                if(last == start)
                {
                    start = p+1;
                    last = p;
                }
                else
                {
                    start = p;
                }
            }
        }

        return ret;
    }
}

<commit_msg>watchdog, not bulldog...<commit_after>#include "core/wordwrap.h"

namespace euphoria::core
{
    std::vector<std::string>
    word_wrap
    (
        const std::string& str,
        std::function<bool (const std::string&)> measure
    )
    {
        using I = std::string::size_type;
        if(measure(str)) { return {str}; }

        auto ret = std::vector<std::string>{};

        I start = 0;
        I last = 0;

        auto get_string = [&str, &start](I end)
        {
            if(end == std::string::npos)
            {
                return str.substr(start);
            }
            else
            {
                return str.substr(start, end - (start+1));
            }
        };

        for(int watchdog=0; watchdog<50; watchdog+=1)
        {
            if(last == std::string::npos)
            {
                return ret;
            }
            const auto first = str.find(' ', last);
            const auto s = get_string(first);
            const auto fit = measure(s);

            if(fit)
            {
                // fit.. continue
                last = (first != std::string::npos) ? first+1 : first;
            }
            if(!fit || last == std::string::npos)
            {
                // new doesn't fit, use last
                const auto p = last == start ? first : last;
                const auto pp = last == start && p != std::string::npos ? p+1 : p;
                ret.emplace_back(get_string(pp));
                if(p == std::string::npos)
                {
                    return ret;
                }
                if(last == start)
                {
                    start = p+1;
                    last = p;
                }
                else
                {
                    start = p;
                }
            }
        }

        return ret;
    }
}

<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <set>
#include "otbImage.h"

#include "itkImageRegionIterator.h"
#include "itkImageRegionReverseIterator.h"
#include "itkImageRandomIteratorWithIndex.h"
#include "itkImageScanlineIterator.h"
#include "itkImageRandomNonRepeatingIteratorWithIndex.h"
#include "otbSubsampledImageRegionIterator.h"

#include "otbMaskedIteratorDecorator.h"

// Generate a test image of specified size and value
template <typename ImageType>
typename ImageType::Pointer GetTestImage(itk::SizeValueType fillSize, const typename ImageType::PixelType& value)
{
  typename ImageType::Pointer image = ImageType::New();
  typename ImageType::SizeType size;
  size.Fill(fillSize);

  typename ImageType::RegionType region;
  region.SetSize(size);

  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(value);
  return image;
}

// Fill half of the pixels with a value
// Used for generating a test mask
template <typename ImageType>
void FillHalf(typename ImageType::Pointer image, const typename ImageType::RegionType& region, const typename ImageType::PixelType& value)
{
  itk::ImageRegionIterator<ImageType> it(image, region);
  unsigned int count = 0;
  for(it.GoToBegin(); !it.IsAtEnd(); ++it, ++count)
  {
    if (count % 2 == 0)
    {
      it.Set(value);
    }
  }
}

// Test template instanciation
int otbMaskedIteratorDecoratorNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);
  return EXIT_SUCCESS;
}

// Function to test the forward iteration interface
template <typename IteratorType>
int ForwardTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType> it(mask, image, region);

  it.GoToBegin();
  if (!it.IsAtBegin()) {return EXIT_FAILURE;}

  unsigned int loopCount = 0;
  for(; !it.IsAtEnd(); ++it)
  {
    if (loopCount != 0 && it.IsAtBegin()) {return EXIT_FAILURE;}
    if (it.IsAtEnd()) {return EXIT_FAILURE;}

    //it.Set(it.Value() * 0.42);

    loopCount += 1;
  }

  if(!it.IsAtEnd()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Test reverse iteration interface
template <typename IteratorType>
int ReverseTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType> it(mask, image, region);

  it.GoToEnd();
  if (!it.IsAtEnd()) {return EXIT_FAILURE;}

  bool beginReached = false;
  do
  {
    --it;

    if (it.IsAtEnd()) {return EXIT_FAILURE;}
    if (it.IsAtBegin())
    {
      if (beginReached)
      {
        return EXIT_FAILURE;
      }
      else {
        beginReached = true;
      }
    }

    //it.Set(it.Value() * 0.42);
  } while (!it.IsAtBegin());

  if(!it.IsAtBegin()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Check bijection between iterated and non masked
// i.e all locations where mask value != 0 are in the iteration (injection)
// and mask value != 0 at all iteration locations (surjection)
// Templated to test decoration of different iterator types
template <typename IteratorType>
int BijectiveTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType> itDecorated(mask, image, region);
  IteratorType it(image, region);

  it.GoToBegin();
  itDecorated.GoToBegin();

  // Find the non maked begin for the image iterator
  while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd())
  {
    ++it;
  }

  // Begins are the same
  if (!(it.GetIndex() == itDecorated.GetIndex()
     && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()
     && it.GetIndex() == itDecorated.GetMaskIterator().GetIndex()))
  {
    return EXIT_FAILURE;
  }

  // Advance both and check
  while (!it.IsAtEnd() && !itDecorated.IsAtEnd())
  {
    // Iteration locations are the same
    if (!(it.GetIndex() == itDecorated.GetIndex()
       && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()
       && it.GetIndex() == itDecorated.GetMaskIterator().GetIndex()))
    {
      return EXIT_FAILURE;
    }

    ++itDecorated;
    do
    {
      ++it;
    } while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd());
  }

  // Check IsAtEnd
  if (!(it.IsAtEnd() && itDecorated.IsAtEnd()))
  {
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

// Multiplex to forward, reverse and bijection test
template <typename IteratorType>
int TripleTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  int ret;
  int retGlobal = EXIT_SUCCESS;

  ret = ForwardTest<IteratorType>(mask, image, region);
  if (ret == EXIT_FAILURE)
    {
    std::cout << "Forward(FAILED) ";
    retGlobal = EXIT_FAILURE;
    }

  ret = ReverseTest<IteratorType>(mask, image, region);
  if (ret == EXIT_FAILURE)
    {
    std::cout << "Reverse(FAILED) ";
    retGlobal = EXIT_FAILURE;
    }

  ret = BijectiveTest<IteratorType>(mask, image, region);
  if (ret == EXIT_FAILURE)
    {
    std::cout << "Bijective(FAILED) ";
    retGlobal = EXIT_FAILURE;
    }

  if (retGlobal == EXIT_SUCCESS)
    {
    std::cout << "PASSED";
    }
  return retGlobal;
}

// Nominal case
int otbMaskedIteratorDecoratorNominal(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);
  int ret;
  int retGlobal = EXIT_SUCCESS;

  std::cout << std::endl << "itk::ImageRegionIterator : ";
  ret = TripleTest<itk::ImageRegionIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator : ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRandomConstIteratorWithIndex : ";
  ret = TripleTest< itk::ImageRandomConstIteratorWithIndex<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "otb::SubsampledImageRegionIterator : ";
  ret = TripleTest< otb::SubsampledImageRegionIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRandomIteratorWithIndex : ";
  ret = TripleTest< itk::ImageRandomIteratorWithIndex<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageScanlineIterator : ";
  ret = TripleTest< itk::ImageScanlineIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageScanlineConstIterator : ";
  ret = TripleTest< itk::ImageScanlineConstIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRandomNonRepeatingConstIteratorWithIndex : ";
  ret = TripleTest< itk::ImageRandomNonRepeatingConstIteratorWithIndex<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRandomNonRepeatingIteratorWithIndex : ";
  ret = TripleTest< itk::ImageRandomNonRepeatingIteratorWithIndex<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  return retGlobal;
}

// Degenerate cases
int otbMaskedIteratorDecoratorDegenerate(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  // Fully masked (0 everywhere) and image is smaller than mask
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(9, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(100, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  return TripleTest<itk::ImageRegionIterator<ImageType> >(image, mask, region);
}

/* Other iterators potentially compatible:

Different constructor arguments than (image, region)
itk::PathIterator
itk::LineIterator
itk::SliceIterator
itk::NeighborhoodIterator

GoToEnd is not implemented
itk::ImageLinearIteratorWithIndex
itk::ReflectiveImageRegionIterator
itk::ImageRegionExclusionConstIteratorWithIndex
itk::ImageRegionIteratorWithIndex

Other problem:
itk::ImageRegionReverseIterator>() // IsAtEnd not a const method
otb::PolyLineImageIterator>() // header not found
itk::ImageRandomConstIteratorWithOnlyIndex>() // no Value method
*/
<commit_msg>ENH: Update working iterators comments in MaskedIteratorDecorator<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <set>
#include "otbImage.h"

#include "itkImageRegionIterator.h"
#include "itkImageRegionReverseIterator.h"
#include "itkImageRandomIteratorWithIndex.h"
#include "itkImageScanlineIterator.h"
#include "itkImageRandomNonRepeatingIteratorWithIndex.h"
#include "otbSubsampledImageRegionIterator.h"

#include "otbMaskedIteratorDecorator.h"

// Generate a test image of specified size and value
template <typename ImageType>
typename ImageType::Pointer GetTestImage(itk::SizeValueType fillSize, const typename ImageType::PixelType& value)
{
  typename ImageType::Pointer image = ImageType::New();
  typename ImageType::SizeType size;
  size.Fill(fillSize);

  typename ImageType::RegionType region;
  region.SetSize(size);

  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(value);
  return image;
}

// Fill half of the pixels with a value
// Used for generating a test mask
template <typename ImageType>
void FillHalf(typename ImageType::Pointer image, const typename ImageType::RegionType& region, const typename ImageType::PixelType& value)
{
  itk::ImageRegionIterator<ImageType> it(image, region);
  unsigned int count = 0;
  for(it.GoToBegin(); !it.IsAtEnd(); ++it, ++count)
  {
    if (count % 2 == 0)
    {
      it.Set(value);
    }
  }
}

// Test template instanciation
int otbMaskedIteratorDecoratorNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);
  return EXIT_SUCCESS;
}

// Function to test the forward iteration interface
template <typename IteratorType>
int ForwardTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType> it(mask, image, region);

  it.GoToBegin();
  if (!it.IsAtBegin()) {return EXIT_FAILURE;}

  unsigned int loopCount = 0;
  for(; !it.IsAtEnd(); ++it)
  {
    if (loopCount != 0 && it.IsAtBegin()) {return EXIT_FAILURE;}
    if (it.IsAtEnd()) {return EXIT_FAILURE;}

    //it.Set(it.Value() * 0.42);

    loopCount += 1;
  }

  if(!it.IsAtEnd()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Test reverse iteration interface
template <typename IteratorType>
int ReverseTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType> it(mask, image, region);

  it.GoToEnd();
  if (!it.IsAtEnd()) {return EXIT_FAILURE;}

  bool beginReached = false;
  do
  {
    --it;

    if (it.IsAtEnd()) {return EXIT_FAILURE;}
    if (it.IsAtBegin())
    {
      if (beginReached)
      {
        return EXIT_FAILURE;
      }
      else {
        beginReached = true;
      }
    }

    //it.Set(it.Value() * 0.42);
  } while (!it.IsAtBegin());

  if(!it.IsAtBegin()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Check bijection between iterated and non masked
// i.e all locations where mask value != 0 are in the iteration (injection)
// and mask value != 0 at all iteration locations (surjection)
// Templated to test decoration of different iterator types
template <typename IteratorType>
int BijectiveTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType> itDecorated(mask, image, region);
  IteratorType it(image, region);

  it.GoToBegin();
  itDecorated.GoToBegin();

  // Find the non maked begin for the image iterator
  while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd())
  {
    ++it;
  }

  // Begins are the same
  if (!(it.GetIndex() == itDecorated.GetIndex()
     && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()
     && it.GetIndex() == itDecorated.GetMaskIterator().GetIndex()))
  {
    return EXIT_FAILURE;
  }

  // Advance both and check
  while (!it.IsAtEnd() && !itDecorated.IsAtEnd())
  {
    // Iteration locations are the same
    if (!(it.GetIndex() == itDecorated.GetIndex()
       && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()
       && it.GetIndex() == itDecorated.GetMaskIterator().GetIndex()))
    {
      return EXIT_FAILURE;
    }

    ++itDecorated;
    do
    {
      ++it;
    } while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd());
  }

  // Check IsAtEnd
  if (!(it.IsAtEnd() && itDecorated.IsAtEnd()))
  {
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

// Multiplex to forward, reverse and bijection test
template <typename IteratorType>
int TripleTest(typename IteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  int ret;
  int retGlobal = EXIT_SUCCESS;

  ret = ForwardTest<IteratorType>(mask, image, region);
  if (ret == EXIT_FAILURE)
    {
    std::cout << "Forward(FAILED) ";
    retGlobal = EXIT_FAILURE;
    }

  ret = ReverseTest<IteratorType>(mask, image, region);
  if (ret == EXIT_FAILURE)
    {
    std::cout << "Reverse(FAILED) ";
    retGlobal = EXIT_FAILURE;
    }

  ret = BijectiveTest<IteratorType>(mask, image, region);
  if (ret == EXIT_FAILURE)
    {
    std::cout << "Bijective(FAILED) ";
    retGlobal = EXIT_FAILURE;
    }

  if (retGlobal == EXIT_SUCCESS)
    {
    std::cout << "PASSED";
    }
  return retGlobal;
}

// Nominal case
int otbMaskedIteratorDecoratorNominal(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);
  int ret;
  int retGlobal = EXIT_SUCCESS;

  std::cout << std::endl << "itk::ImageRegionIterator : ";
  ret = TripleTest<itk::ImageRegionIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator : ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  return retGlobal;
}

// Degenerate cases
int otbMaskedIteratorDecoratorDegenerate(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  // Fully masked (0 everywhere) and image is smaller than mask
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(9, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(100, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  return TripleTest<itk::ImageRegionIterator<ImageType> >(image, mask, region);
}

/* Other iterators potentially compatible:

Different constructor arguments than (image, region)
itk::PathIterator
itk::LineIterator
itk::SliceIterator
itk::NeighborhoodIterator

Needs initialization code:
itk::ImageRandomConstIteratorWithIndex
otb::SubsampledImageRegionIterator
itk::ImageRandomIteratorWithIndex
itk::ImageRandomNonRepeatingConstIteratorWithIndex
itk::ImageRandomNonRepeatingIteratorWithIndex

Different iteration interface than normal iterators:
itk::ImageScanlineIterator
itk::ImageScanlineConstIterator

GoToEnd is not implemented
itk::ImageLinearIteratorWithIndex
itk::ReflectiveImageRegionIterator
itk::ImageRegionExclusionConstIteratorWithIndex
itk::ImageRegionIteratorWithIndex

Other problem:
itk::ImageRegionReverseIterator>() // IsAtEnd not a const method
otb::PolyLineImageIterator>() // header not found
itk::ImageRandomConstIteratorWithOnlyIndex>() // no Value method
*/
<|endoftext|>


<commit_before>/**
* @file Simulation.cpp
* @author Benjamin Schlotter
* Implementation of class Simulation
*/

#include "Simulation.h"

using namespace naoth;
using namespace std;

Simulation::Simulation()
{
  DEBUG_REQUEST_REGISTER("Simulation:draw_one_action_point:global","draw_one_action_point:global", false);
  DEBUG_REQUEST_REGISTER("Simulation:draw_ball","draw_ball", false);
  DEBUG_REQUEST_REGISTER("Simulation:ActionTarget","ActionTarget", false);
  DEBUG_REQUEST_REGISTER("Simulation:draw_best_action","best action",false);
  //DEBUG_REQUEST_REGISTER("Simulation:draw_pessimistic_best_action","best pessimistic action",false);
  DEBUG_REQUEST_REGISTER("Simulation:GoalLinePreview","GoalLinePreview",false);
  DEBUG_REQUEST_REGISTER("Simulation:draw_potential_field","Draw Potential Field",false);
  DEBUG_REQUEST_REGISTER("Simulation:use_Parameters","use_Parameters",false);

  getDebugParameterList().add(&theParameters);

  //calculate the actions
  action_local.reserve(KickActionModel::numOfActions);

  action_local.push_back(Action(KickActionModel::none, Vector2d()));
  action_local.push_back(Action(KickActionModel::kick_long, Vector2d(theParameters.action_long_kick_distance, 0))); // long
  action_local.push_back(Action(KickActionModel::kick_short, Vector2d(theParameters.action_short_kick_distance, 0))); // short
  action_local.push_back(Action(KickActionModel::sidekick_right, Vector2d(0, -theParameters.action_sidekick_distance))); // right
  action_local.push_back(Action(KickActionModel::sidekick_left, Vector2d(0, theParameters.action_sidekick_distance))); // left
}

Simulation::~Simulation(){}

void Simulation::execute()
{
  DEBUG_REQUEST("Simulation:use_Parameters",
    action_local.clear();
    action_local.reserve(KickActionModel::numOfActions);

    action_local.push_back(Action(KickActionModel::none, Vector2d()));
    action_local.push_back(Action(KickActionModel::kick_long, Vector2d(theParameters.action_long_kick_distance, 0))); // long
    action_local.push_back(Action(KickActionModel::kick_short, Vector2d(theParameters.action_short_kick_distance, 0))); // short
    action_local.push_back(Action(KickActionModel::sidekick_right, Vector2d(0, -theParameters.action_sidekick_distance))); // right
    action_local.push_back(Action(KickActionModel::sidekick_left, Vector2d(0, theParameters.action_sidekick_distance))); // left
  );

  if(!getBallModel().valid || getFrameInfo().getTimeInSeconds() >= getBallModel().frameInfoWhenBallWasSeen.getTimeInSeconds()+1)
  {
    return;
  }
  else
  {
    int best_action = 0;

    for(size_t i=0; i<action_local.size(); i++)
    {
      // physics simulator
      std::vector<Vector2d> ballPositionResults;
      // this size needs to be exposed
      for(size_t j=0; j<30; j++)
      {
        const Vector2d& ballRelativePreview = getBallModel().positionPreview;
        Vector2d ballPositionResult = action_local[i].predict(ballRelativePreview, theParameters.distance_variance, theParameters.angle_variance);

        DEBUG_REQUEST("Simulation:ActionTarget",
          FIELD_DRAWING_CONTEXT;
          PEN("0000FF", 1);
          Vector2d ball = getRobotPose() * ballPositionResult;
          CIRCLE( ball.x, ball.y, 50);
        );

        ballPositionResults.push_back(ballPositionResult);
      }

      // categorize positions
      std::vector<CategorizedBallPosition> categorizedBallPositionResults;
      categorizePosition(ballPositionResults, categorizedBallPositionResults);
    }

    getKickActionModel().myAction = action_local[best_action].id();

    DEBUG_REQUEST("Simulation:draw_best_action",
    {
      FIELD_DRAWING_CONTEXT;
      PEN("FF69B4", 7);
      Vector2d actionGlobal = action_local[best_action].target;
      FILLOVAL(actionGlobal.x, actionGlobal.y, 50,50);
    });

//  DEBUG_REQUEST("Simulation:draw_potential_field",
//     draw_potential_field();
//  );

  }
}//end execute

void Simulation::categorizePosition(
  const std::vector<Vector2d>& ballPositions,
  std::vector<CategorizedBallPosition>& categorizedBallPositions
  ) const
{
  // HINT: categorizedBallPositions is not necessarily empty here! Maybe we should clear it

  // calculate the opponent goal line
  GoalModel::Goal oppGoalModel = getSelfLocGoalModel().getOppGoal(getCompassDirection(), getFieldInfo());
  Vector2d oppGoalPostLeftPreview = getMotionStatus().plannedMotion.hip / oppGoalModel.leftPost;
  Vector2d oppGoalPostRightPreview = getMotionStatus().plannedMotion.hip / oppGoalModel.rightPost;

  Vector2d oppGoalDir = (oppGoalPostRightPreview - oppGoalPostLeftPreview).normalize();
  Vector2d oppLeftEndpoint = oppGoalPostLeftPreview + oppGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);
  Vector2d oppRightEndpoint = oppGoalPostRightPreview - oppGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);

  Math::LineSegment oppGoalLinePreview(oppLeftEndpoint, oppRightEndpoint);

  // calculate the own goal line
  GoalModel::Goal ownGoalModel = getSelfLocGoalModel().getOwnGoal(getCompassDirection(), getFieldInfo());
  Vector2d ownGoalPostLeftPreview = getMotionStatus().plannedMotion.hip / ownGoalModel.leftPost;
  Vector2d ownGoalPostRightPreview = getMotionStatus().plannedMotion.hip / ownGoalModel.rightPost;

  Vector2d ownGoalDir = (ownGoalPostRightPreview - ownGoalPostLeftPreview).normalize();
  Vector2d ownLeftEndpoint = ownGoalPostLeftPreview + ownGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);
  Vector2d ownRightEndpoint = ownGoalPostRightPreview - ownGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);

  Math::LineSegment ownGoalLinePreview(ownLeftEndpoint, ownRightEndpoint);

  // now loop through all positions
  for(std::vector<Vector2d>::const_iterator ballPosition = ballPositions.begin(); ballPosition != ballPositions.end(); ballPosition++)
  {
    //Schusslinie
    Math::LineSegment shootLine(getBallModel().positionPreview, *ballPosition);

    BallPositionCategory category = INFIELD;
    // inside field
    if(getFieldInfo().fieldRect.inside(*ballPosition))
    {
      category = INFIELD;
    }
    // goal!!
    else if(shootLine.intersect(oppGoalLinePreview) && oppGoalLinePreview.intersect(shootLine))
    {
      category = OPPGOAL;
    }
    // own goal
    else if(shootLine.intersect(ownGoalLinePreview) && ownGoalLinePreview.intersect(shootLine))
    {
      category = OWNGOAL;
    }
    //Opponent Groundline Out - Ball einen Meter hinter Roboter mind ansto hhe. jeweils seite wo ins ausgeht
    else if(ballPosition->x > getFieldInfo().xPosOpponentGroundline)
    {
      category = OPPOUT;
    }
    //Own Groundline out -  an der seite wo raus geht
    else if(ballPosition->x < getFieldInfo().xPosOwnGroundline)
    {
      category = OWNOUT;
    }
    //an der linken Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
    else if(ballPosition->y > getFieldInfo().yPosLeftSideline )
    {
      category = LEFTOUT;
    }
    //an der rechten Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
    else if(ballPosition->y < getFieldInfo().yPosRightSideline)
    {
      category = RIGHTOUT;
    }
    CategorizedBallPosition categorizedBallPosition = CategorizedBallPosition(*ballPosition, category);
    categorizedBallPositions.push_back(categorizedBallPosition);
  }
}

  //correction of distance in percentage, angle in degrees
  Vector2d Simulation::Action::predict(const Vector2d& ball, double distance_variance, double angle_variance) const
  {
  double random_length = 2.0*Math::random()-1.0;
  double random_angle = 2.0*Math::random()-1.0;

  Vector2d noisyAction = actionVector + actionVector*(distance_variance*random_length);
  noisyAction.rotate(angle_variance*random_angle);

  return ball + noisyAction;
  }

//calcualte according to the rules, without the roboter position, the ball position
//if it goes outside the field
Vector2d Simulation::outsideField(const Vector2d& globalPoint) const
{
  Vector2d point = globalPoint;

  //Schusslinie
  Math::LineSegment shootLine(getBallModel().positionPreview, globalPoint);

  if(getFieldInfo().fieldRect.inside(point)){
    return point;
  }
  else
      //Nach Prioritten geordnet - zuerst die Regeln mit dem mglichst schlimmsten Resultat
  {   //Opponent Groundline Out - Ball einen Meter hinter Roboter mind ansto hhe. jeweils seite wo ins ausgeht
      if(point.x > getFieldInfo().xPosOpponentGroundline)
      {
        Vector2d OppOutPoint = getFieldInfo().oppLineSegment.point(getFieldInfo().oppLineSegment.intersection(shootLine));
        if(OppOutPoint.y < 0)
        {
          return Vector2d(0, getFieldInfo().yThrowInLineRight);//range check
        } else
        {
          return Vector2d(0, getFieldInfo().yThrowInLineLeft);
        }
      }
      //Own Groundline out -  an der seite wo raus geht
      else if(point.x < getFieldInfo().xPosOwnGroundline)
      {
        Vector2d OwnOutPoint = getFieldInfo().ownLineSegment.point(getFieldInfo().ownLineSegment.intersection(shootLine));
        if(OwnOutPoint.y < 0)
        {
          return Vector2d(getFieldInfo().xThrowInLineOwn, getFieldInfo().yThrowInLineRight);//range check
        } else
        {
          return Vector2d(getFieldInfo().xThrowInLineOwn, getFieldInfo().yThrowInLineLeft);
        }
      }
      //an der linken Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
      else if(point.y > getFieldInfo().yPosLeftSideline )
      {
        Vector2d leftOutPoint = getFieldInfo().leftLineSegment.point(getFieldInfo().leftLineSegment.intersection(shootLine));
        point.x = min(leftOutPoint.x,getRobotPose().translation.x);

        if(point.x-1000 < getFieldInfo().xThrowInLineOwn)
        {
          point.x = getFieldInfo().xThrowInLineOwn;
        } else
        {
          point.x -= 1000;
        }
        return Vector2d(point.x, getFieldInfo().yThrowInLineLeft); //range check
      }
      //an der rechten Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
      else //(point.y < getFieldInfo().yPosRightSideline)
      {
        Vector2d rightOutPoint = getFieldInfo().rightLineSegment.point(getFieldInfo().rightLineSegment.intersection(shootLine));
        point.x = min(rightOutPoint.x,getRobotPose().translation.x);

        if(point.x-1000 < getFieldInfo().xThrowInLineOwn)
        {
        point.x = getFieldInfo().xThrowInLineOwn;
        } else
        {
         point.x -= 1000;
        }
      return Vector2d(point.x, getFieldInfo().yThrowInLineRight);//range check
      }
  }
}

double Simulation::evaluateAction(const Vector2d& a) const{
  Vector2d oppGoal(getFieldInfo().xPosOpponentGoal+200, 0.0);
  Vector2d oppDiff = oppGoal - a;

  double oppValueX = 0.1;
  double oppValueY = 1;
  MODIFY("Simulation:oppValueX", oppValueX);
  MODIFY("Simulation:oppValueY", oppValueY);
  double value_opp = oppValueX*oppDiff.x*oppDiff.x + oppValueY*oppDiff.y*oppDiff.y;

  //Vector2d ownGoal(getFieldInfo().xPosOwnGoal, 0.0);
  //Vector2d ownDiff = ownGoal - a;

  //double ownValueX = 0.01;
  //double ownValueY = 0.1;
  //MODIFY("Simulation:ownValueX", ownValueX);
  //MODIFY("Simulation:ownValueY", ownValueY);
  //double value_own = ownValueX*ownDiff.x*ownDiff.x + ownValueY*ownDiff.y*ownDiff.y;

  //return value_opp - value_own;
  return value_opp;
}

void Simulation::draw_potential_field() const
{
  static const int ySize = 20;
  static const int xSize = 30;
  double yWidth = 0.5*getFieldInfo().yFieldLength/(double)ySize;
  double xWidth = 0.5*getFieldInfo().xFieldLength/(double)xSize;

  FIELD_DRAWING_CONTEXT;
  Color white(0.0,0.0,1.0,0.5); // transparent
  Color black(1.0,0.0,0.0,0.5);

  // create new sample set
  std::vector<double> potential(xSize*ySize);
  int idx = 0;

  for (int x = 0; x < xSize; x++) {
    for (int y = 0; y < ySize; y++)
    {
      Vector2d point(xWidth*(2*x-xSize+1), yWidth*(2*y-ySize+1));
      potential[idx] = evaluateAction(point);
      idx++;
    }
  }

  double maxValue = 0;
  idx = 0;
  for (int x = 0; x < xSize; x++) {
    for (int y = 0; y < ySize; y++)
    {
      maxValue = max(maxValue, potential[idx++]);
    }
  }

  if(maxValue == 0) return;

  idx = 0;
  for (int x = 0; x < xSize; x++) {
    for (int y = 0; y < ySize; y++)
    {
      Vector2d point(xWidth*(2*x-xSize+1), yWidth*(2*y-ySize+1));

      double t = potential[idx++] / maxValue;
      Color color = black*t + white*(1-t);
      PEN(color, 20);
      FILLBOX(point.x - xWidth, point.y - yWidth, point.x+xWidth, point.y+yWidth);
    }
  }
}//end draw_closest_points
<commit_msg>Cleanup DebugRequest<commit_after>/**
* @file Simulation.cpp
* @author Benjamin Schlotter
* Implementation of class Simulation
*/

#include "Simulation.h"

using namespace naoth;
using namespace std;

Simulation::Simulation()
{
  DEBUG_REQUEST_REGISTER("Simulation:draw_ball","draw_ball", false);
  DEBUG_REQUEST_REGISTER("Simulation:ActionTarget","ActionTarget", false);
  DEBUG_REQUEST_REGISTER("Simulation:draw_best_action","best action",false);
  DEBUG_REQUEST_REGISTER("Simulation:draw_potential_field","Draw Potential Field",false);
  DEBUG_REQUEST_REGISTER("Simulation:use_Parameters","use_Parameters",false);

  getDebugParameterList().add(&theParameters);

  //calculate the actions
  action_local.reserve(KickActionModel::numOfActions);

  action_local.push_back(Action(KickActionModel::none, Vector2d()));
  action_local.push_back(Action(KickActionModel::kick_long, Vector2d(theParameters.action_long_kick_distance, 0))); // long
  action_local.push_back(Action(KickActionModel::kick_short, Vector2d(theParameters.action_short_kick_distance, 0))); // short
  action_local.push_back(Action(KickActionModel::sidekick_right, Vector2d(0, -theParameters.action_sidekick_distance))); // right
  action_local.push_back(Action(KickActionModel::sidekick_left, Vector2d(0, theParameters.action_sidekick_distance))); // left
}

Simulation::~Simulation(){}

void Simulation::execute()
{
  DEBUG_REQUEST("Simulation:use_Parameters",
    action_local.clear();
    action_local.reserve(KickActionModel::numOfActions);

    action_local.push_back(Action(KickActionModel::none, Vector2d()));
    action_local.push_back(Action(KickActionModel::kick_long, Vector2d(theParameters.action_long_kick_distance, 0))); // long
    action_local.push_back(Action(KickActionModel::kick_short, Vector2d(theParameters.action_short_kick_distance, 0))); // short
    action_local.push_back(Action(KickActionModel::sidekick_right, Vector2d(0, -theParameters.action_sidekick_distance))); // right
    action_local.push_back(Action(KickActionModel::sidekick_left, Vector2d(0, theParameters.action_sidekick_distance))); // left
  );

  if(!getBallModel().valid || getFrameInfo().getTimeInSeconds() >= getBallModel().frameInfoWhenBallWasSeen.getTimeInSeconds()+1)
  {
    return;
  }
  else
  {
    int best_action = 0;

    for(size_t i=0; i<action_local.size(); i++)
    {
      // physics simulator
      std::vector<Vector2d> ballPositionResults;
      // this size needs to be exposed
      for(size_t j=0; j<30; j++)
      {
        const Vector2d& ballRelativePreview = getBallModel().positionPreview;
        Vector2d ballPositionResult = action_local[i].predict(ballRelativePreview, theParameters.distance_variance, theParameters.angle_variance);

        DEBUG_REQUEST("Simulation:ActionTarget",
          FIELD_DRAWING_CONTEXT;
          PEN("0000FF", 1);
          Vector2d ball = getRobotPose() * ballPositionResult;
          CIRCLE( ball.x, ball.y, 50);
        );

        ballPositionResults.push_back(ballPositionResult);
      }

      // categorize positions
      std::vector<CategorizedBallPosition> categorizedBallPositionResults;
      categorizePosition(ballPositionResults, categorizedBallPositionResults);
    }

    getKickActionModel().myAction = action_local[best_action].id();

    DEBUG_REQUEST("Simulation:draw_best_action",
    {
      FIELD_DRAWING_CONTEXT;
      PEN("FF69B4", 7);
      Vector2d actionGlobal = action_local[best_action].target;
      FILLOVAL(actionGlobal.x, actionGlobal.y, 50,50);
    });

  DEBUG_REQUEST("Simulation:draw_potential_field",
     draw_potential_field();
  );

  }
}//end execute

void Simulation::categorizePosition(
  const std::vector<Vector2d>& ballPositions,
  std::vector<CategorizedBallPosition>& categorizedBallPositions
  ) const
{
  // HINT: categorizedBallPositions is not necessarily empty here! Maybe we should clear it

  // calculate the opponent goal line
  GoalModel::Goal oppGoalModel = getSelfLocGoalModel().getOppGoal(getCompassDirection(), getFieldInfo());
  Vector2d oppGoalPostLeftPreview = getMotionStatus().plannedMotion.hip / oppGoalModel.leftPost;
  Vector2d oppGoalPostRightPreview = getMotionStatus().plannedMotion.hip / oppGoalModel.rightPost;

  Vector2d oppGoalDir = (oppGoalPostRightPreview - oppGoalPostLeftPreview).normalize();
  Vector2d oppLeftEndpoint = oppGoalPostLeftPreview + oppGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);
  Vector2d oppRightEndpoint = oppGoalPostRightPreview - oppGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);

  Math::LineSegment oppGoalLinePreview(oppLeftEndpoint, oppRightEndpoint);

  // calculate the own goal line
  GoalModel::Goal ownGoalModel = getSelfLocGoalModel().getOwnGoal(getCompassDirection(), getFieldInfo());
  Vector2d ownGoalPostLeftPreview = getMotionStatus().plannedMotion.hip / ownGoalModel.leftPost;
  Vector2d ownGoalPostRightPreview = getMotionStatus().plannedMotion.hip / ownGoalModel.rightPost;

  Vector2d ownGoalDir = (ownGoalPostRightPreview - ownGoalPostLeftPreview).normalize();
  Vector2d ownLeftEndpoint = ownGoalPostLeftPreview + ownGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);
  Vector2d ownRightEndpoint = ownGoalPostRightPreview - ownGoalDir*(getFieldInfo().goalpostRadius + getFieldInfo().ballRadius);

  Math::LineSegment ownGoalLinePreview(ownLeftEndpoint, ownRightEndpoint);

  // now loop through all positions
  for(std::vector<Vector2d>::const_iterator ballPosition = ballPositions.begin(); ballPosition != ballPositions.end(); ballPosition++)
  {
    //Schusslinie
    Math::LineSegment shootLine(getBallModel().positionPreview, *ballPosition);

    BallPositionCategory category = INFIELD;
    // inside field
    if(getFieldInfo().fieldRect.inside(*ballPosition))
    {
      category = INFIELD;
    }
    // goal!!
    else if(shootLine.intersect(oppGoalLinePreview) && oppGoalLinePreview.intersect(shootLine))
    {
      category = OPPGOAL;
    }
    // own goal
    else if(shootLine.intersect(ownGoalLinePreview) && ownGoalLinePreview.intersect(shootLine))
    {
      category = OWNGOAL;
    }
    //Opponent Groundline Out - Ball einen Meter hinter Roboter mind ansto hhe. jeweils seite wo ins ausgeht
    else if(ballPosition->x > getFieldInfo().xPosOpponentGroundline)
    {
      category = OPPOUT;
    }
    //Own Groundline out -  an der seite wo raus geht
    else if(ballPosition->x < getFieldInfo().xPosOwnGroundline)
    {
      category = OWNOUT;
    }
    //an der linken Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
    else if(ballPosition->y > getFieldInfo().yPosLeftSideline )
    {
      category = LEFTOUT;
    }
    //an der rechten Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
    else if(ballPosition->y < getFieldInfo().yPosRightSideline)
    {
      category = RIGHTOUT;
    }
    CategorizedBallPosition categorizedBallPosition = CategorizedBallPosition(*ballPosition, category);
    categorizedBallPositions.push_back(categorizedBallPosition);
  }
}

  //correction of distance in percentage, angle in degrees
  Vector2d Simulation::Action::predict(const Vector2d& ball, double distance_variance, double angle_variance) const
  {
  double random_length = 2.0*Math::random()-1.0;
  double random_angle = 2.0*Math::random()-1.0;

  Vector2d noisyAction = actionVector + actionVector*(distance_variance*random_length);
  noisyAction.rotate(angle_variance*random_angle);

  return ball + noisyAction;
  }

//calcualte according to the rules, without the roboter position, the ball position
//if it goes outside the field
Vector2d Simulation::outsideField(const Vector2d& globalPoint) const
{
  Vector2d point = globalPoint;

  //Schusslinie
  Math::LineSegment shootLine(getBallModel().positionPreview, globalPoint);

  if(getFieldInfo().fieldRect.inside(point)){
    return point;
  }
  else
      //Nach Prioritten geordnet - zuerst die Regeln mit dem mglichst schlimmsten Resultat
  {   //Opponent Groundline Out - Ball einen Meter hinter Roboter mind ansto hhe. jeweils seite wo ins ausgeht
      if(point.x > getFieldInfo().xPosOpponentGroundline)
      {
        Vector2d OppOutPoint = getFieldInfo().oppLineSegment.point(getFieldInfo().oppLineSegment.intersection(shootLine));
        if(OppOutPoint.y < 0)
        {
          return Vector2d(0, getFieldInfo().yThrowInLineRight);//range check
        } else
        {
          return Vector2d(0, getFieldInfo().yThrowInLineLeft);
        }
      }
      //Own Groundline out -  an der seite wo raus geht
      else if(point.x < getFieldInfo().xPosOwnGroundline)
      {
        Vector2d OwnOutPoint = getFieldInfo().ownLineSegment.point(getFieldInfo().ownLineSegment.intersection(shootLine));
        if(OwnOutPoint.y < 0)
        {
          return Vector2d(getFieldInfo().xThrowInLineOwn, getFieldInfo().yThrowInLineRight);//range check
        } else
        {
          return Vector2d(getFieldInfo().xThrowInLineOwn, getFieldInfo().yThrowInLineLeft);
        }
      }
      //an der linken Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
      else if(point.y > getFieldInfo().yPosLeftSideline )
      {
        Vector2d leftOutPoint = getFieldInfo().leftLineSegment.point(getFieldInfo().leftLineSegment.intersection(shootLine));
        point.x = min(leftOutPoint.x,getRobotPose().translation.x);

        if(point.x-1000 < getFieldInfo().xThrowInLineOwn)
        {
          point.x = getFieldInfo().xThrowInLineOwn;
        } else
        {
          point.x -= 1000;
        }
        return Vector2d(point.x, getFieldInfo().yThrowInLineLeft); //range check
      }
      //an der rechten Seite raus -> ein meter hinter roboter oder wo ins ausgeht ein meter hinter
      else //(point.y < getFieldInfo().yPosRightSideline)
      {
        Vector2d rightOutPoint = getFieldInfo().rightLineSegment.point(getFieldInfo().rightLineSegment.intersection(shootLine));
        point.x = min(rightOutPoint.x,getRobotPose().translation.x);

        if(point.x-1000 < getFieldInfo().xThrowInLineOwn)
        {
        point.x = getFieldInfo().xThrowInLineOwn;
        } else
        {
         point.x -= 1000;
        }
      return Vector2d(point.x, getFieldInfo().yThrowInLineRight);//range check
      }
  }
}

double Simulation::evaluateAction(const Vector2d& a) const{
  Vector2d oppGoal(getFieldInfo().xPosOpponentGoal+200, 0.0);
  Vector2d oppDiff = oppGoal - a;

  double oppValueX = 0.1;
  double oppValueY = 1;
  MODIFY("Simulation:oppValueX", oppValueX);
  MODIFY("Simulation:oppValueY", oppValueY);
  double value_opp = oppValueX*oppDiff.x*oppDiff.x + oppValueY*oppDiff.y*oppDiff.y;

  //Vector2d ownGoal(getFieldInfo().xPosOwnGoal, 0.0);
  //Vector2d ownDiff = ownGoal - a;

  //double ownValueX = 0.01;
  //double ownValueY = 0.1;
  //MODIFY("Simulation:ownValueX", ownValueX);
  //MODIFY("Simulation:ownValueY", ownValueY);
  //double value_own = ownValueX*ownDiff.x*ownDiff.x + ownValueY*ownDiff.y*ownDiff.y;

  //return value_opp - value_own;
  return value_opp;
}

void Simulation::draw_potential_field() const
{
  static const int ySize = 20;
  static const int xSize = 30;
  double yWidth = 0.5*getFieldInfo().yFieldLength/(double)ySize;
  double xWidth = 0.5*getFieldInfo().xFieldLength/(double)xSize;

  FIELD_DRAWING_CONTEXT;
  Color white(0.0,0.0,1.0,0.5); // transparent
  Color black(1.0,0.0,0.0,0.5);

  // create new sample set
  std::vector<double> potential(xSize*ySize);
  int idx = 0;

  for (int x = 0; x < xSize; x++) {
    for (int y = 0; y < ySize; y++)
    {
      Vector2d point(xWidth*(2*x-xSize+1), yWidth*(2*y-ySize+1));
      potential[idx] = evaluateAction(point);
      idx++;
    }
  }

  double maxValue = 0;
  idx = 0;
  for (int x = 0; x < xSize; x++) {
    for (int y = 0; y < ySize; y++)
    {
      maxValue = max(maxValue, potential[idx++]);
    }
  }

  if(maxValue == 0) return;

  idx = 0;
  for (int x = 0; x < xSize; x++) {
    for (int y = 0; y < ySize; y++)
    {
      Vector2d point(xWidth*(2*x-xSize+1), yWidth*(2*y-ySize+1));

      double t = potential[idx++] / maxValue;
      Color color = black*t + white*(1-t);
      PEN(color, 20);
      FILLBOX(point.x - xWidth, point.y - yWidth, point.x+xWidth, point.y+yWidth);
    }
  }
}//end draw_closest_points
<|endoftext|>