<commit_before>/*************************************************************************
 *
 *  $RCSfile: xestream.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-26 18:04:35 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

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

#ifndef SC_XESTREAM_HXX
#include "xestream.hxx"
#endif

#ifndef SC_XEROOT_HXX
#include "xeroot.hxx"
#endif

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

XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt32 nMaxRecSize ) :
    mrStrm( rOutStrm ),
    mrRoot( rRoot ),
    mnMaxRecSize( nMaxRecSize ),
    mnCurrMaxSize( 0 ),
    mnMaxSliceSize( 0 ),
    mnCalcSize( 0 ),
    mnHeaderSize( 0 ),
    mnCurrSize( 0 ),
    mnSliceSize( 0 ),
    mnLastSizePos( 0 ),
    mbInRec( false )
{
    if( !mnMaxRecSize )
        mnMaxRecSize = (mrRoot.GetBiff() < xlBiff8) ? EXC_MAXRECSIZE_BIFF5 : EXC_MAXRECSIZE_BIFF8;
    mnMaxContSize = nMaxRecSize;
}

XclExpStream::~XclExpStream()
{
}

void XclExpStream::InitRecord( sal_uInt16 nRecId )
{
    mrStrm.Seek( STREAM_SEEK_TO_END );
    mrStrm << nRecId;

    mnLastSizePos = mrStrm.Tell();
    mnHeaderSize = ::std::min( mnCalcSize, mnCurrMaxSize );
    mrStrm << static_cast< sal_uInt16 >( mnHeaderSize );
    mnCurrSize = mnSliceSize = 0;
}

void XclExpStream::UpdateRecSize()
{
    if( mnCurrSize != mnHeaderSize )
    {
        mrStrm.Seek( mnLastSizePos );
        mrStrm << static_cast< sal_uInt16 >( mnCurrSize );
    }
}

void XclExpStream::UpdateSizeVars( sal_uInt32 nSize )
{
    mnCurrSize += nSize;

    if( mnMaxSliceSize )
    {
        mnSliceSize += nSize;
        DBG_ASSERT( mnSliceSize <= mnMaxSliceSize, "XclExpStream::UpdateSizeVars - slice overwritten" );
        if( mnSliceSize >= mnMaxSliceSize )
            mnSliceSize = 0;
    }
}

void XclExpStream::StartContinue()
{
    UpdateRecSize();
    mnCurrMaxSize = mnMaxContSize;
    mnCalcSize -= mnCurrSize;
    InitRecord( EXC_ID_CONT );
}

void XclExpStream::PrepareWrite( sal_uInt32 nSize )
{
    if( mbInRec )
    {
        if( (mnCurrSize + nSize > mnCurrMaxSize) ||
            (mnMaxSliceSize && !mnSliceSize && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
            StartContinue();
        UpdateSizeVars( nSize );
    }
}

sal_uInt32 XclExpStream::PrepareWrite()
{
    sal_uInt32 nRet = 0;
    if( mbInRec )
    {
        if( (mnCurrSize >= mnCurrMaxSize) ||
            (mnMaxSliceSize && !mnSliceSize && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
            StartContinue();
        UpdateSizeVars( 0 );

        nRet = mnMaxSliceSize ? mnMaxSliceSize - mnSliceSize : mnCurrMaxSize - mnCurrSize;
    }
    return nRet;
}

void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_uInt32 nRecSize )
{
    DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" );
    mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
    mnCalcSize = nRecSize;
    mbInRec = true;
    InitRecord( nRecId );
    SetSliceSize( 0 );
}

void XclExpStream::EndRecord()
{
    DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" );
    UpdateRecSize();
    mrStrm.Seek( STREAM_SEEK_TO_END );
    mbInRec = false;
}

void XclExpStream::SetSliceSize( sal_uInt32 nSize )
{
    mnMaxSliceSize = nSize;
    mnSliceSize = 0;
}

sal_uInt32 XclExpStream::Write( const void* pData, sal_uInt32 nBytes )
{
    sal_uInt32 nRet = 0;
    if( pData && nBytes )
    {
        if( mbInRec )
        {
            const sal_uInt8* pBuffer = reinterpret_cast< const sal_uInt8* >( pData );
            sal_uInt32 nBytesLeft = nBytes;
            bool bValid = true;

            while( bValid && nBytesLeft )
            {
                sal_uInt32 nWriteLen = ::std::min( PrepareWrite(), nBytesLeft );
                sal_uInt32 nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
                bValid = (nWriteLen == nWriteRet);
                DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" );
                pBuffer += nWriteRet;
                nRet += nWriteRet;
                nBytesLeft -= nWriteRet;
                UpdateSizeVars( nWriteRet );
            }
        }
        else
            nRet = mrStrm.Write( pData, nBytes );
    }
    return nRet;
}

void XclExpStream::WriteRawZeroBytes( sal_uInt32 nBytes )
{
    const sal_uInt32 nData = 0;
    sal_uInt32 nBytesLeft = nBytes;
    while( nBytesLeft >= sizeof( sal_uInt32 ) )
    {
        mrStrm << nData;
        nBytesLeft -= sizeof( sal_uInt32 );
    }
    if( nBytesLeft )
        mrStrm.Write( &nData, nBytesLeft );
}

void XclExpStream::WriteZeroBytes( sal_uInt32 nBytes )
{
    if( mbInRec )
    {
        sal_uInt32 nBytesLeft = nBytes;
        while( nBytesLeft )
        {
            sal_uInt32 nWriteLen = ::std::min( PrepareWrite(), nBytesLeft );
            WriteRawZeroBytes( nWriteLen );
            nBytesLeft -= nWriteLen;
            UpdateSizeVars( nWriteLen );
        }
    }
    else
        WriteRawZeroBytes( nBytes );
}

sal_uInt32 XclExpStream::CopyFromStream( SvStream& rInStrm, sal_uInt32 nBytes )
{
    sal_uInt32 nStreamPos = rInStrm.Tell();
    sal_uInt32 nStreamSize = rInStrm.Seek( STREAM_SEEK_TO_END );
    rInStrm.Seek( nStreamPos );

    sal_uInt32 nBytesLeft = ::std::min( nBytes, nStreamSize - nStreamPos );
    sal_uInt32 nRet = 0;
    if( nBytesLeft )
    {
        const sal_uInt32 nMaxBuffer = 0x00001000;
        sal_uInt8* pBuffer = new sal_uInt8[ ::std::min( nBytesLeft, nMaxBuffer ) ];
        bool bValid = true;

        while( bValid && nBytesLeft )
        {
            sal_uInt32 nWriteLen = ::std::min( nBytesLeft, nMaxBuffer );
            rInStrm.Read( pBuffer, nWriteLen );
            sal_uInt32 nWriteRet = Write( pBuffer, nWriteLen );
            bValid = (nWriteLen == nWriteRet);
            nRet += nWriteRet;
            nBytesLeft -= nWriteRet;
        }
        delete[] pBuffer;
    }
    return nRet;
}

void XclExpStream::WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_uInt32 nChars, sal_uInt8 nFlags )
{
    SetSliceSize( 0 );
    if( pBuffer && nChars )
    {
        sal_uInt32 nCharLen = (nFlags & EXC_STRF_16BIT) ? 2 : 1;
        for( sal_uInt32 nIndex = 0; nIndex < nChars; ++nIndex )
        {
            if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
            {
                StartContinue();
                // repeat only 16bit flag
                operator<<( static_cast< sal_uInt8 >( nFlags & EXC_STRF_16BIT ) );
            }
            if( nCharLen == 2 )
                operator<<( pBuffer[ nIndex ] );
            else
                operator<<( static_cast< sal_uInt8 >( pBuffer[ nIndex ] ) );
        }
    }
}

void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags )
{
    SetSliceSize( 0 );
    nFlags &= EXC_STRF_16BIT;   // repeat only 16bit flag
    sal_uInt32 nCharLen = nFlags ? 2 : 1;

    ScfUInt16Vec::const_iterator aEnd = rBuffer.end();
    for( ScfUInt16Vec::const_iterator aIter = rBuffer.begin(); aIter != aEnd; ++aIter )
    {
        if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
        {
            StartContinue();
            operator<<( nFlags );
        }
        if( nCharLen == 2 )
            operator<<( *aIter );
        else
            operator<<( static_cast< sal_uInt8 >( *aIter ) );
    }
}

void XclExpStream::WriteByteStringBuffer( const ByteString& rString, sal_uInt16 nMaxLen )
{
    SetSliceSize( 0 );
    Write( rString.GetBuffer(), ::std::min< xub_StrLen >( rString.Len(), nMaxLen ) );
}

// ER: #71367# Xcl has an obscure sense of whether starting a new record or not,
// and crashes if it encounters the string header at the very end of a record.
// Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
void XclExpStream::WriteByteString( const ByteString& rString, sal_uInt16 nMaxLen, bool b16BitCount )
{
    SetSliceSize( 0 );
    sal_uInt16 nLen = static_cast< sal_uInt16 >( ::std::min< xub_StrLen >( rString.Len(), nMaxLen ) );
    if( !b16BitCount )
        nLen = ::std::min< sal_uInt16 >( nLen, 0xFF );

    sal_uInt32 nLeft = PrepareWrite();
    if( mbInRec && (nLeft <= (b16BitCount ? 2UL : 1UL)) )
        StartContinue();

    if( b16BitCount )
        operator<<( nLen );
    else
        operator<<( static_cast< sal_uInt8 >( nLen ) );
    Write( rString.GetBuffer(), nLen );
}

void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer )
{
    SetSliceSize( 0 );
    Write( &rBuffer[ 0 ], rBuffer.size() );
}

sal_uInt32 XclExpStream::SetStreamPos( sal_uInt32 nPos )
{
    DBG_ASSERT( !mbInRec, "XclExpStream::SetStreamPos - not allowed inside of a record" );
    return mbInRec ? 0 : mrStrm.Seek( nPos );
}

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

<commit_msg>INTEGRATION: CWS dr8aig (1.3.104); FILE MERGED 2003/07/23 15:17:47 dr 1.3.104.1: #110947# export of form controls<commit_after>/*************************************************************************
 *
 *  $RCSfile: xestream.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2003-07-24 11:54:45 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

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

#ifndef SC_XESTREAM_HXX
#include "xestream.hxx"
#endif

#ifndef SC_XEROOT_HXX
#include "xeroot.hxx"
#endif

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

XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt32 nMaxRecSize ) :
    mrStrm( rOutStrm ),
    mrRoot( rRoot ),
    mnMaxRecSize( nMaxRecSize ),
    mnCurrMaxSize( 0 ),
    mnMaxSliceSize( 0 ),
    mnCalcSize( 0 ),
    mnHeaderSize( 0 ),
    mnCurrSize( 0 ),
    mnSliceSize( 0 ),
    mnLastSizePos( 0 ),
    mbInRec( false )
{
    if( !mnMaxRecSize )
        mnMaxRecSize = (mrRoot.GetBiff() < xlBiff8) ? EXC_MAXRECSIZE_BIFF5 : EXC_MAXRECSIZE_BIFF8;
    mnMaxContSize = nMaxRecSize;
}

XclExpStream::~XclExpStream()
{
    mrStrm.Flush();
}

void XclExpStream::InitRecord( sal_uInt16 nRecId )
{
    mrStrm.Seek( STREAM_SEEK_TO_END );
    mrStrm << nRecId;

    mnLastSizePos = mrStrm.Tell();
    mnHeaderSize = ::std::min( mnCalcSize, mnCurrMaxSize );
    mrStrm << static_cast< sal_uInt16 >( mnHeaderSize );
    mnCurrSize = mnSliceSize = 0;
}

void XclExpStream::UpdateRecSize()
{
    if( mnCurrSize != mnHeaderSize )
    {
        mrStrm.Seek( mnLastSizePos );
        mrStrm << static_cast< sal_uInt16 >( mnCurrSize );
    }
}

void XclExpStream::UpdateSizeVars( sal_uInt32 nSize )
{
    mnCurrSize += nSize;

    if( mnMaxSliceSize )
    {
        mnSliceSize += nSize;
        DBG_ASSERT( mnSliceSize <= mnMaxSliceSize, "XclExpStream::UpdateSizeVars - slice overwritten" );
        if( mnSliceSize >= mnMaxSliceSize )
            mnSliceSize = 0;
    }
}

void XclExpStream::StartContinue()
{
    UpdateRecSize();
    mnCurrMaxSize = mnMaxContSize;
    mnCalcSize -= mnCurrSize;
    InitRecord( EXC_ID_CONT );
}

void XclExpStream::PrepareWrite( sal_uInt32 nSize )
{
    if( mbInRec )
    {
        if( (mnCurrSize + nSize > mnCurrMaxSize) ||
            (mnMaxSliceSize && !mnSliceSize && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
            StartContinue();
        UpdateSizeVars( nSize );
    }
}

sal_uInt32 XclExpStream::PrepareWrite()
{
    sal_uInt32 nRet = 0;
    if( mbInRec )
    {
        if( (mnCurrSize >= mnCurrMaxSize) ||
            (mnMaxSliceSize && !mnSliceSize && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
            StartContinue();
        UpdateSizeVars( 0 );

        nRet = mnMaxSliceSize ? mnMaxSliceSize - mnSliceSize : mnCurrMaxSize - mnCurrSize;
    }
    return nRet;
}

void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_uInt32 nRecSize )
{
    DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" );
    mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
    mnCalcSize = nRecSize;
    mbInRec = true;
    InitRecord( nRecId );
    SetSliceSize( 0 );
}

void XclExpStream::EndRecord()
{
    DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" );
    UpdateRecSize();
    mrStrm.Seek( STREAM_SEEK_TO_END );
    mbInRec = false;
}

void XclExpStream::SetSliceSize( sal_uInt32 nSize )
{
    mnMaxSliceSize = nSize;
    mnSliceSize = 0;
}

sal_uInt32 XclExpStream::Write( const void* pData, sal_uInt32 nBytes )
{
    sal_uInt32 nRet = 0;
    if( pData && nBytes )
    {
        if( mbInRec )
        {
            const sal_uInt8* pBuffer = reinterpret_cast< const sal_uInt8* >( pData );
            sal_uInt32 nBytesLeft = nBytes;
            bool bValid = true;

            while( bValid && nBytesLeft )
            {
                sal_uInt32 nWriteLen = ::std::min( PrepareWrite(), nBytesLeft );
                sal_uInt32 nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
                bValid = (nWriteLen == nWriteRet);
                DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" );
                pBuffer += nWriteRet;
                nRet += nWriteRet;
                nBytesLeft -= nWriteRet;
                UpdateSizeVars( nWriteRet );
            }
        }
        else
            nRet = mrStrm.Write( pData, nBytes );
    }
    return nRet;
}

void XclExpStream::WriteRawZeroBytes( sal_uInt32 nBytes )
{
    const sal_uInt32 nData = 0;
    sal_uInt32 nBytesLeft = nBytes;
    while( nBytesLeft >= sizeof( sal_uInt32 ) )
    {
        mrStrm << nData;
        nBytesLeft -= sizeof( sal_uInt32 );
    }
    if( nBytesLeft )
        mrStrm.Write( &nData, nBytesLeft );
}

void XclExpStream::WriteZeroBytes( sal_uInt32 nBytes )
{
    if( mbInRec )
    {
        sal_uInt32 nBytesLeft = nBytes;
        while( nBytesLeft )
        {
            sal_uInt32 nWriteLen = ::std::min( PrepareWrite(), nBytesLeft );
            WriteRawZeroBytes( nWriteLen );
            nBytesLeft -= nWriteLen;
            UpdateSizeVars( nWriteLen );
        }
    }
    else
        WriteRawZeroBytes( nBytes );
}

sal_uInt32 XclExpStream::CopyFromStream( SvStream& rInStrm, sal_uInt32 nBytes )
{
    sal_uInt32 nStreamPos = rInStrm.Tell();
    sal_uInt32 nStreamSize = rInStrm.Seek( STREAM_SEEK_TO_END );
    rInStrm.Seek( nStreamPos );

    sal_uInt32 nBytesLeft = ::std::min( nBytes, nStreamSize - nStreamPos );
    sal_uInt32 nRet = 0;
    if( nBytesLeft )
    {
        const sal_uInt32 nMaxBuffer = 0x00001000;
        sal_uInt8* pBuffer = new sal_uInt8[ ::std::min( nBytesLeft, nMaxBuffer ) ];
        bool bValid = true;

        while( bValid && nBytesLeft )
        {
            sal_uInt32 nWriteLen = ::std::min( nBytesLeft, nMaxBuffer );
            rInStrm.Read( pBuffer, nWriteLen );
            sal_uInt32 nWriteRet = Write( pBuffer, nWriteLen );
            bValid = (nWriteLen == nWriteRet);
            nRet += nWriteRet;
            nBytesLeft -= nWriteRet;
        }
        delete[] pBuffer;
    }
    return nRet;
}

void XclExpStream::WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_uInt32 nChars, sal_uInt8 nFlags )
{
    SetSliceSize( 0 );
    if( pBuffer && nChars )
    {
        sal_uInt32 nCharLen = (nFlags & EXC_STRF_16BIT) ? 2 : 1;
        for( sal_uInt32 nIndex = 0; nIndex < nChars; ++nIndex )
        {
            if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
            {
                StartContinue();
                // repeat only 16bit flag
                operator<<( static_cast< sal_uInt8 >( nFlags & EXC_STRF_16BIT ) );
            }
            if( nCharLen == 2 )
                operator<<( pBuffer[ nIndex ] );
            else
                operator<<( static_cast< sal_uInt8 >( pBuffer[ nIndex ] ) );
        }
    }
}

void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags )
{
    SetSliceSize( 0 );
    nFlags &= EXC_STRF_16BIT;   // repeat only 16bit flag
    sal_uInt32 nCharLen = nFlags ? 2 : 1;

    ScfUInt16Vec::const_iterator aEnd = rBuffer.end();
    for( ScfUInt16Vec::const_iterator aIter = rBuffer.begin(); aIter != aEnd; ++aIter )
    {
        if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
        {
            StartContinue();
            operator<<( nFlags );
        }
        if( nCharLen == 2 )
            operator<<( *aIter );
        else
            operator<<( static_cast< sal_uInt8 >( *aIter ) );
    }
}

void XclExpStream::WriteByteStringBuffer( const ByteString& rString, sal_uInt16 nMaxLen )
{
    SetSliceSize( 0 );
    Write( rString.GetBuffer(), ::std::min< xub_StrLen >( rString.Len(), nMaxLen ) );
}

// ER: #71367# Xcl has an obscure sense of whether starting a new record or not,
// and crashes if it encounters the string header at the very end of a record.
// Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
void XclExpStream::WriteByteString( const ByteString& rString, sal_uInt16 nMaxLen, bool b16BitCount )
{
    SetSliceSize( 0 );
    sal_uInt16 nLen = static_cast< sal_uInt16 >( ::std::min< xub_StrLen >( rString.Len(), nMaxLen ) );
    if( !b16BitCount )
        nLen = ::std::min< sal_uInt16 >( nLen, 0xFF );

    sal_uInt32 nLeft = PrepareWrite();
    if( mbInRec && (nLeft <= (b16BitCount ? 2UL : 1UL)) )
        StartContinue();

    if( b16BitCount )
        operator<<( nLen );
    else
        operator<<( static_cast< sal_uInt8 >( nLen ) );
    Write( rString.GetBuffer(), nLen );
}

void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer )
{
    SetSliceSize( 0 );
    Write( &rBuffer[ 0 ], rBuffer.size() );
}

sal_uInt32 XclExpStream::SetStreamPos( sal_uInt32 nPos )
{
    DBG_ASSERT( !mbInRec, "XclExpStream::SetStreamPos - not allowed inside of a record" );
    return mbInRec ? 0 : mrStrm.Seek( nPos );
}

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

<|endoftext|>


<commit_before>#include "Game.h"
#include "GLWindowManager.h"

using namespace iceberg;

Game::Game(Backend backend)
    :stateMachine_(std::make_shared<StateMachine>())
{
    switch(backend)
    {
    case OPENGL:
        windowManager_ = std::make_shared<icebergGL::GLWindowManager>();
        break;

    default:
        throw std::runtime_error("Invalid backend specified");
    }

    // Begin the timer for delta time calculation
    previousTime_ = std::chrono::high_resolution_clock::now();
}

Game::~Game()
{
    glfwTerminate();
}

WindowManager* Game::window_manager() const
{
    return windowManager_.get();
}

void Game::change_state(GameState* state) const
{
    stateMachine_->change_state(state);
}

void Game::update()
{
    currentTime_ = std::chrono::high_resolution_clock::now();
    deltaTime_ = std::chrono::duration_cast<std::chrono::duration<float>>(currentTime_ - previousTime_).count();
    previousTime_ = std::chrono::high_resolution_clock::now();

    windowManager_->update();
    stateMachine_->update();
}

void Game::draw() const
{
    // Update the window
    stateMachine_->draw();
    windowManager_->refresh();
}

void Game::run()
{
    // TODO: Might be better to do this with an event
    while(windowManager_->has_active_windows())
    {
        update();
        draw();
    }
}

float Game::delta_time() const
{
   return deltaTime_;
}

void Game::handle_error(const std::string &errorMessage)
{
    boxer::show(errorMessage.c_str(), "Error", boxer::Style::Warning);
}
<commit_msg>Remove a missed glfw call from Game class.<commit_after>#include "Game.h"
#include "GLWindowManager.h"

using namespace iceberg;

Game::Game(Backend backend)
    :stateMachine_(std::make_shared<StateMachine>())
{
    switch(backend)
    {
    case OPENGL:
        windowManager_ = std::make_shared<icebergGL::GLWindowManager>();
        break;

    default:
        throw std::runtime_error("Invalid backend specified");
    }

    // Begin the timer for delta time calculation
    previousTime_ = std::chrono::high_resolution_clock::now();
}

Game::~Game()
{
}

WindowManager* Game::window_manager() const
{
    return windowManager_.get();
}

void Game::change_state(GameState* state) const
{
    stateMachine_->change_state(state);
}

void Game::update()
{
    currentTime_ = std::chrono::high_resolution_clock::now();
    deltaTime_ = std::chrono::duration_cast<std::chrono::duration<float>>(currentTime_ - previousTime_).count();
    previousTime_ = std::chrono::high_resolution_clock::now();

    windowManager_->update();
    stateMachine_->update();
}

void Game::draw() const
{
    // Update the window
    stateMachine_->draw();
    windowManager_->refresh();
}

void Game::run()
{
    // TODO: Might be better to do this with an event
    while(windowManager_->has_active_windows())
    {
        update();
        draw();
    }
}

float Game::delta_time() const
{
   return deltaTime_;
}

void Game::handle_error(const std::string &errorMessage)
{
    boxer::show(errorMessage.c_str(), "Error", boxer::Style::Warning);
}
<|endoftext|>


<commit_before>//===-- MallocHelper.cpp - Functions to identify malloc calls -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This family of functions identifies calls to malloc, bitcasts of malloc
// calls, and the types and array sizes associated with them.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/MallocHelper.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Analysis/ConstantFolding.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
//  malloc Call Utility Functions.
//

/// isMalloc - Returns true if the the value is either a malloc call or a
/// bitcast of the result of a malloc call.
bool llvm::isMalloc(const Value* I) {
  return extractMallocCall(I) || extractMallocCallFromBitCast(I);
}

static bool isMallocCall(const CallInst *CI) {
  if (!CI)
    return false;

  const Module* M = CI->getParent()->getParent()->getParent();
  Function *MallocFunc = M->getFunction("malloc");

  if (CI->getOperand(0) != MallocFunc)
    return false;

  // Check malloc prototype.
  // FIXME: this will be obsolete when nobuiltin attribute will exist.
  const FunctionType *FTy = MallocFunc->getFunctionType();
  if (FTy->getNumParams() != 1)
    return false;
  if (IntegerType *ITy = dyn_cast<IntegerType>(FTy->param_begin()->get())) {
    if (ITy->getBitWidth() != 32 && ITy->getBitWidth() != 64)
      return false;
    return true;
  }

  return false;
}

/// extractMallocCall - Returns the corresponding CallInst if the instruction
/// is a malloc call.  Since CallInst::CreateMalloc() only creates calls, we
/// ignore InvokeInst here.
const CallInst* llvm::extractMallocCall(const Value* I) {
  const CallInst *CI = dyn_cast<CallInst>(I);
  return (isMallocCall(CI)) ? CI : NULL;
}

CallInst* llvm::extractMallocCall(Value* I) {
  CallInst *CI = dyn_cast<CallInst>(I);
  return (isMallocCall(CI)) ? CI : NULL;
}

static bool isBitCastOfMallocCall(const BitCastInst* BCI) {
  if (!BCI)
    return false;

  return isMallocCall(dyn_cast<CallInst>(BCI->getOperand(0)));
}

/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the
/// instruction is a bitcast of the result of a malloc call.
CallInst* llvm::extractMallocCallFromBitCast(Value* I) {
  BitCastInst *BCI = dyn_cast<BitCastInst>(I);
  return (isBitCastOfMallocCall(BCI)) ? cast<CallInst>(BCI->getOperand(0))
                                      : NULL;
}

const CallInst* llvm::extractMallocCallFromBitCast(const Value* I) {
  const BitCastInst *BCI = dyn_cast<BitCastInst>(I);
  return (isBitCastOfMallocCall(BCI)) ? cast<CallInst>(BCI->getOperand(0))
                                      : NULL;
}

static bool isArrayMallocHelper(const CallInst *CI, LLVMContext &Context,
                                const TargetData* TD) {
  if (!CI)
    return false;

  const Type* T = getMallocAllocatedType(CI);

  // We can only indentify an array malloc if we know the type of the malloc
  // call.
  if (!T) return false;

  Value* MallocArg = CI->getOperand(1);
  Constant *ElementSize = ConstantExpr::getSizeOf(T);
  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize,
                                                MallocArg->getType());
  Constant *FoldedElementSize = ConstantFoldConstantExpression(
                                       cast<ConstantExpr>(ElementSize),
                                       Context, TD);

  if (isa<ConstantExpr>(MallocArg))
    return (MallocArg != ElementSize);

  BinaryOperator *BI = dyn_cast<BinaryOperator>(MallocArg);
  if (!BI)
    return false;

  if (BI->getOpcode() == Instruction::Mul)
    // ArraySize * ElementSize
    if (BI->getOperand(1) == ElementSize ||
        (FoldedElementSize && BI->getOperand(1) == FoldedElementSize))
      return true;

  // TODO: Detect case where MallocArg mul has been transformed to shl.

  return false;
}

/// isArrayMalloc - Returns the corresponding CallInst if the instruction
/// matches the malloc call IR generated by CallInst::CreateMalloc().  This
/// means that it is a malloc call with one bitcast use AND the malloc call's
/// size argument is:
///  1. a constant not equal to the malloc's allocated type
/// or
///  2. the result of a multiplication by the malloc's allocated type
/// Otherwise it returns NULL.
/// The unique bitcast is needed to determine the type/size of the array
/// allocation.
CallInst* llvm::isArrayMalloc(Value* I, LLVMContext &Context,
                              const TargetData* TD) {
  CallInst *CI = extractMallocCall(I);
  return (isArrayMallocHelper(CI, Context, TD)) ? CI : NULL;
}

const CallInst* llvm::isArrayMalloc(const Value* I, LLVMContext &Context,
                                    const TargetData* TD) {
  const CallInst *CI = extractMallocCall(I);
  return (isArrayMallocHelper(CI, Context, TD)) ? CI : NULL;
}

/// getMallocType - Returns the PointerType resulting from the malloc call.
/// This PointerType is the result type of the call's only bitcast use.
/// If there is no unique bitcast use, then return NULL.
const PointerType* llvm::getMallocType(const CallInst* CI) {
  assert(isMalloc(CI) && "GetMallocType and not malloc call");

  const BitCastInst* BCI = NULL;

  // Determine if CallInst has a bitcast use.
  for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end();
       UI != E; )
    if ((BCI = dyn_cast<BitCastInst>(cast<Instruction>(*UI++))))
      break;

  // Malloc call has 1 bitcast use and no other uses, so type is the bitcast's
  // destination type.
  if (BCI && CI->hasOneUse())
    return cast<PointerType>(BCI->getDestTy());

  // Malloc call was not bitcast, so type is the malloc function's return type.
  if (!BCI)
    return cast<PointerType>(CI->getType());

  // Type could not be determined.
  return NULL;
}

/// getMallocAllocatedType - Returns the Type allocated by malloc call. This
/// Type is the result type of the call's only bitcast use. If there is no
/// unique bitcast use, then return NULL.
const Type* llvm::getMallocAllocatedType(const CallInst* CI) {
  const PointerType* PT = getMallocType(CI);
  return PT ? PT->getElementType() : NULL;
}

/// isConstantOne - Return true only if val is constant int 1.
static bool isConstantOne(Value *val) {
  return isa<ConstantInt>(val) && cast<ConstantInt>(val)->isOne();
}

/// getMallocArraySize - Returns the array size of a malloc call.  The array
/// size is computated in 1 of 3 ways:
///  1. If the element type if of size 1, then array size is the argument to
///     malloc.
///  2. Else if the malloc's argument is a constant, the array size is that
///     argument divided by the element type's size.
///  3. Else the malloc argument must be a multiplication and the array size is
///     the first operand of the multiplication.
/// This function returns constant 1 if:
///  1. The malloc call's allocated type cannot be determined.
///  2. IR wasn't created by a call to CallInst::CreateMalloc() with a non-NULL
///     ArraySize.
Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context,
                                const TargetData* TD) {
  // Match CreateMalloc's use of constant 1 array-size for non-array mallocs.
  if (!isArrayMalloc(CI, Context, TD))
    return ConstantInt::get(CI->getOperand(1)->getType(), 1);

  Value* MallocArg = CI->getOperand(1);
  assert(getMallocAllocatedType(CI) && "getMallocArraySize and no type");
  Constant *ElementSize = ConstantExpr::getSizeOf(getMallocAllocatedType(CI));
  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize,
                                                MallocArg->getType());

  Constant* CO = dyn_cast<Constant>(MallocArg);
  BinaryOperator* BO = dyn_cast<BinaryOperator>(MallocArg);
  assert((isConstantOne(ElementSize) || CO || BO) &&
         "getMallocArraySize and malformed malloc IR");

  if (isConstantOne(ElementSize))
    return MallocArg;

  if (CO)
    return CO->getOperand(0);

  // TODO: Detect case where MallocArg mul has been transformed to shl.

  assert(BO && "getMallocArraySize not constant but not multiplication either");
  return BO->getOperand(0);
}
<commit_msg>Add PR to this FIXME, looks like I didn't commit this change after all.<commit_after>//===-- MallocHelper.cpp - Functions to identify malloc calls -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This family of functions identifies calls to malloc, bitcasts of malloc
// calls, and the types and array sizes associated with them.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/MallocHelper.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Analysis/ConstantFolding.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
//  malloc Call Utility Functions.
//

/// isMalloc - Returns true if the the value is either a malloc call or a
/// bitcast of the result of a malloc call.
bool llvm::isMalloc(const Value* I) {
  return extractMallocCall(I) || extractMallocCallFromBitCast(I);
}

static bool isMallocCall(const CallInst *CI) {
  if (!CI)
    return false;

  const Module* M = CI->getParent()->getParent()->getParent();
  Function *MallocFunc = M->getFunction("malloc");

  if (CI->getOperand(0) != MallocFunc)
    return false;

  // Check malloc prototype.
  // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
  // attribute will exist.
  const FunctionType *FTy = MallocFunc->getFunctionType();
  if (FTy->getNumParams() != 1)
    return false;
  if (IntegerType *ITy = dyn_cast<IntegerType>(FTy->param_begin()->get())) {
    if (ITy->getBitWidth() != 32 && ITy->getBitWidth() != 64)
      return false;
    return true;
  }

  return false;
}

/// extractMallocCall - Returns the corresponding CallInst if the instruction
/// is a malloc call.  Since CallInst::CreateMalloc() only creates calls, we
/// ignore InvokeInst here.
const CallInst* llvm::extractMallocCall(const Value* I) {
  const CallInst *CI = dyn_cast<CallInst>(I);
  return (isMallocCall(CI)) ? CI : NULL;
}

CallInst* llvm::extractMallocCall(Value* I) {
  CallInst *CI = dyn_cast<CallInst>(I);
  return (isMallocCall(CI)) ? CI : NULL;
}

static bool isBitCastOfMallocCall(const BitCastInst* BCI) {
  if (!BCI)
    return false;

  return isMallocCall(dyn_cast<CallInst>(BCI->getOperand(0)));
}

/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the
/// instruction is a bitcast of the result of a malloc call.
CallInst* llvm::extractMallocCallFromBitCast(Value* I) {
  BitCastInst *BCI = dyn_cast<BitCastInst>(I);
  return (isBitCastOfMallocCall(BCI)) ? cast<CallInst>(BCI->getOperand(0))
                                      : NULL;
}

const CallInst* llvm::extractMallocCallFromBitCast(const Value* I) {
  const BitCastInst *BCI = dyn_cast<BitCastInst>(I);
  return (isBitCastOfMallocCall(BCI)) ? cast<CallInst>(BCI->getOperand(0))
                                      : NULL;
}

static bool isArrayMallocHelper(const CallInst *CI, LLVMContext &Context,
                                const TargetData* TD) {
  if (!CI)
    return false;

  const Type* T = getMallocAllocatedType(CI);

  // We can only indentify an array malloc if we know the type of the malloc
  // call.
  if (!T) return false;

  Value* MallocArg = CI->getOperand(1);
  Constant *ElementSize = ConstantExpr::getSizeOf(T);
  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize,
                                                MallocArg->getType());
  Constant *FoldedElementSize = ConstantFoldConstantExpression(
                                       cast<ConstantExpr>(ElementSize),
                                       Context, TD);

  if (isa<ConstantExpr>(MallocArg))
    return (MallocArg != ElementSize);

  BinaryOperator *BI = dyn_cast<BinaryOperator>(MallocArg);
  if (!BI)
    return false;

  if (BI->getOpcode() == Instruction::Mul)
    // ArraySize * ElementSize
    if (BI->getOperand(1) == ElementSize ||
        (FoldedElementSize && BI->getOperand(1) == FoldedElementSize))
      return true;

  // TODO: Detect case where MallocArg mul has been transformed to shl.

  return false;
}

/// isArrayMalloc - Returns the corresponding CallInst if the instruction
/// matches the malloc call IR generated by CallInst::CreateMalloc().  This
/// means that it is a malloc call with one bitcast use AND the malloc call's
/// size argument is:
///  1. a constant not equal to the malloc's allocated type
/// or
///  2. the result of a multiplication by the malloc's allocated type
/// Otherwise it returns NULL.
/// The unique bitcast is needed to determine the type/size of the array
/// allocation.
CallInst* llvm::isArrayMalloc(Value* I, LLVMContext &Context,
                              const TargetData* TD) {
  CallInst *CI = extractMallocCall(I);
  return (isArrayMallocHelper(CI, Context, TD)) ? CI : NULL;
}

const CallInst* llvm::isArrayMalloc(const Value* I, LLVMContext &Context,
                                    const TargetData* TD) {
  const CallInst *CI = extractMallocCall(I);
  return (isArrayMallocHelper(CI, Context, TD)) ? CI : NULL;
}

/// getMallocType - Returns the PointerType resulting from the malloc call.
/// This PointerType is the result type of the call's only bitcast use.
/// If there is no unique bitcast use, then return NULL.
const PointerType* llvm::getMallocType(const CallInst* CI) {
  assert(isMalloc(CI) && "GetMallocType and not malloc call");

  const BitCastInst* BCI = NULL;

  // Determine if CallInst has a bitcast use.
  for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end();
       UI != E; )
    if ((BCI = dyn_cast<BitCastInst>(cast<Instruction>(*UI++))))
      break;

  // Malloc call has 1 bitcast use and no other uses, so type is the bitcast's
  // destination type.
  if (BCI && CI->hasOneUse())
    return cast<PointerType>(BCI->getDestTy());

  // Malloc call was not bitcast, so type is the malloc function's return type.
  if (!BCI)
    return cast<PointerType>(CI->getType());

  // Type could not be determined.
  return NULL;
}

/// getMallocAllocatedType - Returns the Type allocated by malloc call. This
/// Type is the result type of the call's only bitcast use. If there is no
/// unique bitcast use, then return NULL.
const Type* llvm::getMallocAllocatedType(const CallInst* CI) {
  const PointerType* PT = getMallocType(CI);
  return PT ? PT->getElementType() : NULL;
}

/// isConstantOne - Return true only if val is constant int 1.
static bool isConstantOne(Value *val) {
  return isa<ConstantInt>(val) && cast<ConstantInt>(val)->isOne();
}

/// getMallocArraySize - Returns the array size of a malloc call.  The array
/// size is computated in 1 of 3 ways:
///  1. If the element type if of size 1, then array size is the argument to
///     malloc.
///  2. Else if the malloc's argument is a constant, the array size is that
///     argument divided by the element type's size.
///  3. Else the malloc argument must be a multiplication and the array size is
///     the first operand of the multiplication.
/// This function returns constant 1 if:
///  1. The malloc call's allocated type cannot be determined.
///  2. IR wasn't created by a call to CallInst::CreateMalloc() with a non-NULL
///     ArraySize.
Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context,
                                const TargetData* TD) {
  // Match CreateMalloc's use of constant 1 array-size for non-array mallocs.
  if (!isArrayMalloc(CI, Context, TD))
    return ConstantInt::get(CI->getOperand(1)->getType(), 1);

  Value* MallocArg = CI->getOperand(1);
  assert(getMallocAllocatedType(CI) && "getMallocArraySize and no type");
  Constant *ElementSize = ConstantExpr::getSizeOf(getMallocAllocatedType(CI));
  ElementSize = ConstantExpr::getTruncOrBitCast(ElementSize,
                                                MallocArg->getType());

  Constant* CO = dyn_cast<Constant>(MallocArg);
  BinaryOperator* BO = dyn_cast<BinaryOperator>(MallocArg);
  assert((isConstantOne(ElementSize) || CO || BO) &&
         "getMallocArraySize and malformed malloc IR");

  if (isConstantOne(ElementSize))
    return MallocArg;

  if (CO)
    return CO->getOperand(0);

  // TODO: Detect case where MallocArg mul has been transformed to shl.

  assert(BO && "getMallocArraySize not constant but not multiplication either");
  return BO->getOperand(0);
}
<|endoftext|>


<commit_before>#include <SFCGAL/algorithm/triangulate.h>

#include <SFCGAL/Kernel.h>
#include <SFCGAL/all.h>
#include <SFCGAL/tools/Log.h>

#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
//#include <CGAL/Polygon_2.h>

#include <CGAL/Point_3.h>
#include <CGAL/Vector_3.h>
#include <CGAL/Line_3.h>

#include <SFCGAL/algorithm/plane.h>

#include <iostream>

namespace SFCGAL {
namespace algorithm {

/**
 * face information (depth)
 */
struct FaceInfo2 {
	FaceInfo2() {
	}
	int nesting_level;

	bool in_domain() {
		return nesting_level % 2 == 1;
	}
};

/**
 * vertex information with original coordinates
 */
struct VertexInfo2 {
	VertexInfo2() {
	}

	Point original ;
};

typedef CGAL::Triangulation_vertex_base_with_info_2< VertexInfo2, Kernel >            triangulation_vertex_base ;
typedef CGAL::Triangulation_face_base_with_info_2<FaceInfo2, Kernel>                  triangulation_face_base;
typedef CGAL::Constrained_triangulation_face_base_2<Kernel, triangulation_face_base>  constrained_triangulation_face_base;
typedef CGAL::Triangulation_data_structure_2<
		triangulation_vertex_base,
		constrained_triangulation_face_base >                                         triangulation_data_structure;

//typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<
			Kernel,
			triangulation_data_structure,
			CGAL::Exact_predicates_tag >                                              CDT;

typedef CDT::Point                                                                    triangulation_point;
typedef CGAL::Point_2<Kernel>                                                         Point_2;
//typedef CGAL::Polygon_2<Kernel>                                                       Polygon_2;

void mark_domains(CDT& ct, CDT::Face_handle start, int index, std::list<CDT::Edge>& border)
{
	if (start->info().nesting_level != -1) {
		return;
	}
	std::list<CDT::Face_handle> queue;
	queue.push_back(start);

	while (!queue.empty()) {
		CDT::Face_handle fh = queue.front();
		queue.pop_front();
		if (fh->info().nesting_level == -1) {
			fh->info().nesting_level = index;
			for (int i = 0; i < 3; i++) {
				CDT::Edge e(fh, i);
				CDT::Face_handle n = fh->neighbor(i);
				if (n->info().nesting_level == -1) {
					if (ct.is_constrained(e))
						border.push_back(e);
					else
						queue.push_back(n);
				}
			}
		}
	}
}

//explore set of facets connected with non constrained edges,
//and attribute to each such set a nesting level.
//We start from facets incident to the infinite vertex, with a nesting
//level of 0. Then we recursively consider the non-explored facets incident
//to constrained edges bounding the former set and increase the nesting level by 1.
//Facets in the domain are those with an odd nesting level.
void mark_domains(CDT& cdt) {
	for (CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it) {
		it->info().nesting_level = -1;
	}

	int index = 0;
	std::list<CDT::Edge> border;
	mark_domains(cdt, cdt.infinite_face(), index++, border);
	while (!border.empty()) {
		CDT::Edge e = border.front();
		border.pop_front();
		CDT::Face_handle n = e.first->neighbor(e.second);
		if (n->info().nesting_level == -1) {
			mark_domains(cdt, n, e.first->info().nesting_level + 1, border);
		}
	}
}

///
///
///
void triangulate( const Geometry & g, TriangulatedSurface & triangulatedSurface )
{
	switch ( g.geometryTypeId() ){
	case TYPE_POINT:
		return ;
	case TYPE_POLYGON:
		triangulate( g.as< Polygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOINT:
		triangulate( g.as< MultiPoint >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOLYGON:
		triangulate( g.as< MultiPolygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_TRIANGULATEDSURFACE:
		triangulatedSurface.addTriangles( g.as< TriangulatedSurface >() ) ;
		return ;
	case TYPE_POLYHEDRALSURFACE:
		triangulate( g.as< PolyhedralSurface >(), triangulatedSurface ) ;
		return ;
	case TYPE_SOLID:
		triangulate( g.as< Solid >().exteriorShell(), triangulatedSurface ) ;
		return ;
	}

	BOOST_THROW_EXCEPTION(
		Exception(
			( boost::format( "can't triangulate type '%1%'" ) % g.geometryType() ).str()
		)
	);
}

///
///
///
void triangulate2D( const Geometry & g, TriangulatedSurface & triangulatedSurface )
{
	switch ( g.geometryTypeId() ){
	case TYPE_POINT:
		return ;
	case TYPE_POLYGON:
		triangulate2D( g.as< Polygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOINT:
		triangulate( g.as< MultiPoint >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOLYGON:
		triangulate2D( g.as< MultiPolygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_TRIANGULATEDSURFACE:
		triangulatedSurface.addTriangles( g.as< TriangulatedSurface >() ) ;
		return ;
	case TYPE_POLYHEDRALSURFACE:
		triangulate2D( g.as< PolyhedralSurface >(), triangulatedSurface ) ;
		return ;
	}

	BOOST_THROW_EXCEPTION(
		Exception(
			( boost::format( "can't triangulate type '%1%'" ) % g.geometryType() ).str()
		)
	);
}

///
///
///
void triangulate( const MultiPoint & geometry, TriangulatedSurface & triangulatedSurface )
{
	/*
	 * filter empty geometry
	 */
	if ( geometry.isEmpty() )
		return ;

	/*
	 * prepare a Constraint Delaunay Triangulation
	 */
	CDT cdt;

	/*
	 * insert each vertex in the triangulation
	 */
	for ( size_t j = 0; j < geometry.numGeometries(); j++ ) {
		const Point & point = geometry.pointN( j );

		/*
		 * insert into triangulation
		 */
		CDT::Vertex_handle vh = cdt.insert( point.toPoint_2() );
		vh->info().original = point ;
	}

	/*
	 * Convert CDT to TriangulatedSurface
	 */
	for ( CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it )
	{
		//ignore holes
		if ( ! it->info().in_domain() ){
			continue ;
		}

		const Point & a = it->vertex(0)->info().original ;
		const Point & b = it->vertex(1)->info().original ;
		const Point & c = it->vertex(2)->info().original ;

		// check that vertex has an original vertex
		if ( a.isEmpty() || b.isEmpty() || c.isEmpty() ){
			BOOST_THROW_EXCEPTION( Exception(
				( boost::format("can't triangulate %1% without adding vertex (constraint intersection found)") % geometry.asText() ).str()
			) ) ;
		}

		triangulatedSurface.addTriangle( Triangle( a, b, c ) );
	}

}

///
///
///
void triangulate( const Polygon & polygon, TriangulatedSurface & triangulatedSurface )
{
	/*
	 * filter empty polygon
	 */
	if ( polygon.isEmpty() )
		return ;

	/*
	 * prepare a Constraint Delaunay Triangulation
	 */
	CDT cdt;

//	std::cout << "---------------------------------------------------------" << std::endl ;
//	std::cout << "triangulate polygon : " << polygon.asText() << std::endl;
	CGAL::Plane_3< Kernel > polygonPlane = plane3D< Kernel >( polygon, false ) ;
	if ( polygonPlane.is_degenerate() ){
		BOOST_THROW_EXCEPTION( Exception(
			( boost::format( "can't find plane for polygon %s" ) % polygon.asText() ).str()
		) );
	}

	/*
	 * insert each ring in the triangulation
	 */
	for ( size_t i = 0; i < polygon.numRings(); i++ ){
		const LineString & ring  = polygon.ringN( i );

		CDT::Vertex_handle v_prev ;
		for ( size_t j = 0; j < ring.numPoints(); j++ ) {
			const Point & point = ring.pointN( j );
			SFCGAL_DEBUG( boost::format( "insert point %s" ) % point.asText() );
			CGAL::Point_3< Kernel > p3d = point.toPoint_3();

			/*
			 * insert into triangulation
			 */
			CDT::Vertex_handle vh = cdt.insert( polygonPlane.to_2d( p3d ) );
			vh->info().original = point ;

			// filter first point
			if ( j != 0 ){
				if ( vh != v_prev ){
					cdt.insert_constraint(vh, v_prev);
				}else{
					//@todo log
				}
			}
			v_prev = vh;
		}
	}

	/*
	 * Mark facets that are inside the domain bounded by the polygon
	 */
	mark_domains(cdt);

	/*
	 * Convert CDT to triangulated surface
	 */
	for ( CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it )
	{
		//ignore holes
		if ( ! it->info().in_domain() ){
			continue ;
		}
//		assert( it->is_valid() );

		const Point & a = it->vertex(0)->info().original ;
		const Point & b = it->vertex(1)->info().original ;
		const Point & c = it->vertex(2)->info().original ;

		// check that vertex has an original vertex
		if ( a.isEmpty() || b.isEmpty() || c.isEmpty() ){
			BOOST_THROW_EXCEPTION( Exception(
				( boost::format("can't triangulate %1% without adding vertex (constraint intersection found)") % polygon.asText() ).str()
			) ) ;
		}
		triangulatedSurface.addTriangle( Triangle( a, b, c ) );
	}
}

///
///
///
void triangulate2D( const Polygon & polygon, TriangulatedSurface & triangulatedSurface )
{
	/*
	 * filter empty polygon
	 */
	if ( polygon.isEmpty() )
		return ;

	/*
	 * prepare a Constraint Delaunay Triangulation
	 */
	CDT cdt;

	/*
	 * insert each ring in the triangulation
	 */
	for ( size_t i = 0; i < polygon.numRings(); i++ ){
		const LineString & ring  = polygon.ringN( i );

		CDT::Vertex_handle v_prev ;
		for ( size_t j = 0; j < ring.numPoints(); j++ ) {
			const Point & point = ring.pointN( j );

			/*
			 * insert into triangulation
			 */
			CDT::Vertex_handle vh = cdt.insert( point.toPoint_2() );
			vh->info().original = point ;

			// filter first point
			if ( j != 0 ){
				if ( vh != v_prev ){
					cdt.insert_constraint(vh, v_prev);
				}else{
					//@todo log
				}
			}
			v_prev = vh;
		}
	}

	/*
	 * Mark facets that are inside the domain bounded by the polygon
	 */
	mark_domains(cdt);

	/*
	 * Convert CDT to triangulated surface
	 */
	for ( CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it )
	{
		//ignore holes
		if ( ! it->info().in_domain() ){
			continue ;
		}
//		assert( it->is_valid() );

		const Point & a = it->vertex(0)->info().original ;
		const Point & b = it->vertex(1)->info().original ;
		const Point & c = it->vertex(2)->info().original ;

		// check that vertex has an original vertex
		if ( a.isEmpty() || b.isEmpty() || c.isEmpty() ){
			BOOST_THROW_EXCEPTION( Exception(
				( boost::format("can't triangulate %1% without adding vertex (constraint intersection found)") % polygon.asText() ).str()
			) ) ;
		}
		triangulatedSurface.addTriangle( Triangle( a, b, c ) );
	}
}

///
///
///
void triangulate( const MultiPolygon & multiPolygon, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < multiPolygon.numGeometries(); i++ ){
		triangulate( multiPolygon.geometryN(i).as< Polygon >(), triangulatedSurface );
	}
}

///
///
///
void triangulate2D( const MultiPolygon & multiPolygon, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < multiPolygon.numGeometries(); i++ ){
		triangulate2D( multiPolygon.geometryN(i).as< Polygon >(), triangulatedSurface );
	}
}

///
///
///
void triangulate( const PolyhedralSurface & poly, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < poly.numPolygons(); i++ ){
		triangulate( poly.polygonN(i), triangulatedSurface );
	}
}

///
///
///
void triangulate2D( const PolyhedralSurface & poly, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < poly.numPolygons(); i++ ){
		triangulate2D( poly.polygonN(i), triangulatedSurface );
	}
}

}//algorithm
}//SFCGAL

<commit_msg>remove SFCGAL_DEBUG*<commit_after>#include <SFCGAL/algorithm/triangulate.h>

#include <SFCGAL/Kernel.h>
#include <SFCGAL/all.h>
#include <SFCGAL/tools/Log.h>

#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
//#include <CGAL/Polygon_2.h>

#include <CGAL/Point_3.h>
#include <CGAL/Vector_3.h>
#include <CGAL/Line_3.h>

#include <SFCGAL/algorithm/plane.h>

#include <iostream>

namespace SFCGAL {
namespace algorithm {

/**
 * face information (depth)
 */
struct FaceInfo2 {
	FaceInfo2() {
	}
	int nesting_level;

	bool in_domain() {
		return nesting_level % 2 == 1;
	}
};

/**
 * vertex information with original coordinates
 */
struct VertexInfo2 {
	VertexInfo2() {
	}

	Point original ;
};

typedef CGAL::Triangulation_vertex_base_with_info_2< VertexInfo2, Kernel >            triangulation_vertex_base ;
typedef CGAL::Triangulation_face_base_with_info_2<FaceInfo2, Kernel>                  triangulation_face_base;
typedef CGAL::Constrained_triangulation_face_base_2<Kernel, triangulation_face_base>  constrained_triangulation_face_base;
typedef CGAL::Triangulation_data_structure_2<
		triangulation_vertex_base,
		constrained_triangulation_face_base >                                         triangulation_data_structure;

//typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<
			Kernel,
			triangulation_data_structure,
			CGAL::Exact_predicates_tag >                                              CDT;

typedef CDT::Point                                                                    triangulation_point;
typedef CGAL::Point_2<Kernel>                                                         Point_2;
//typedef CGAL::Polygon_2<Kernel>                                                       Polygon_2;

void mark_domains(CDT& ct, CDT::Face_handle start, int index, std::list<CDT::Edge>& border)
{
	if (start->info().nesting_level != -1) {
		return;
	}
	std::list<CDT::Face_handle> queue;
	queue.push_back(start);

	while (!queue.empty()) {
		CDT::Face_handle fh = queue.front();
		queue.pop_front();
		if (fh->info().nesting_level == -1) {
			fh->info().nesting_level = index;
			for (int i = 0; i < 3; i++) {
				CDT::Edge e(fh, i);
				CDT::Face_handle n = fh->neighbor(i);
				if (n->info().nesting_level == -1) {
					if (ct.is_constrained(e))
						border.push_back(e);
					else
						queue.push_back(n);
				}
			}
		}
	}
}

//explore set of facets connected with non constrained edges,
//and attribute to each such set a nesting level.
//We start from facets incident to the infinite vertex, with a nesting
//level of 0. Then we recursively consider the non-explored facets incident
//to constrained edges bounding the former set and increase the nesting level by 1.
//Facets in the domain are those with an odd nesting level.
void mark_domains(CDT& cdt) {
	for (CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it) {
		it->info().nesting_level = -1;
	}

	int index = 0;
	std::list<CDT::Edge> border;
	mark_domains(cdt, cdt.infinite_face(), index++, border);
	while (!border.empty()) {
		CDT::Edge e = border.front();
		border.pop_front();
		CDT::Face_handle n = e.first->neighbor(e.second);
		if (n->info().nesting_level == -1) {
			mark_domains(cdt, n, e.first->info().nesting_level + 1, border);
		}
	}
}

///
///
///
void triangulate( const Geometry & g, TriangulatedSurface & triangulatedSurface )
{
	switch ( g.geometryTypeId() ){
	case TYPE_POINT:
		return ;
	case TYPE_POLYGON:
		triangulate( g.as< Polygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOINT:
		triangulate( g.as< MultiPoint >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOLYGON:
		triangulate( g.as< MultiPolygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_TRIANGULATEDSURFACE:
		triangulatedSurface.addTriangles( g.as< TriangulatedSurface >() ) ;
		return ;
	case TYPE_POLYHEDRALSURFACE:
		triangulate( g.as< PolyhedralSurface >(), triangulatedSurface ) ;
		return ;
	case TYPE_SOLID:
		triangulate( g.as< Solid >().exteriorShell(), triangulatedSurface ) ;
		return ;
	}

	BOOST_THROW_EXCEPTION(
		Exception(
			( boost::format( "can't triangulate type '%1%'" ) % g.geometryType() ).str()
		)
	);
}

///
///
///
void triangulate2D( const Geometry & g, TriangulatedSurface & triangulatedSurface )
{
	switch ( g.geometryTypeId() ){
	case TYPE_POINT:
		return ;
	case TYPE_POLYGON:
		triangulate2D( g.as< Polygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOINT:
		triangulate( g.as< MultiPoint >(), triangulatedSurface ) ;
		return ;
	case TYPE_MULTIPOLYGON:
		triangulate2D( g.as< MultiPolygon >(), triangulatedSurface ) ;
		return ;
	case TYPE_TRIANGULATEDSURFACE:
		triangulatedSurface.addTriangles( g.as< TriangulatedSurface >() ) ;
		return ;
	case TYPE_POLYHEDRALSURFACE:
		triangulate2D( g.as< PolyhedralSurface >(), triangulatedSurface ) ;
		return ;
	}

	BOOST_THROW_EXCEPTION(
		Exception(
			( boost::format( "can't triangulate type '%1%'" ) % g.geometryType() ).str()
		)
	);
}

///
///
///
void triangulate( const MultiPoint & geometry, TriangulatedSurface & triangulatedSurface )
{
	/*
	 * filter empty geometry
	 */
	if ( geometry.isEmpty() )
		return ;

	/*
	 * prepare a Constraint Delaunay Triangulation
	 */
	CDT cdt;

	/*
	 * insert each vertex in the triangulation
	 */
	for ( size_t j = 0; j < geometry.numGeometries(); j++ ) {
		const Point & point = geometry.pointN( j );

		/*
		 * insert into triangulation
		 */
		CDT::Vertex_handle vh = cdt.insert( point.toPoint_2() );
		vh->info().original = point ;
	}

	/*
	 * Convert CDT to TriangulatedSurface
	 */
	for ( CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it )
	{
		//ignore holes
		if ( ! it->info().in_domain() ){
			continue ;
		}

		const Point & a = it->vertex(0)->info().original ;
		const Point & b = it->vertex(1)->info().original ;
		const Point & c = it->vertex(2)->info().original ;

		// check that vertex has an original vertex
		if ( a.isEmpty() || b.isEmpty() || c.isEmpty() ){
			BOOST_THROW_EXCEPTION( Exception(
				( boost::format("can't triangulate %1% without adding vertex (constraint intersection found)") % geometry.asText() ).str()
			) ) ;
		}

		triangulatedSurface.addTriangle( Triangle( a, b, c ) );
	}

}

///
///
///
void triangulate( const Polygon & polygon, TriangulatedSurface & triangulatedSurface )
{
	/*
	 * filter empty polygon
	 */
	if ( polygon.isEmpty() )
		return ;

	/*
	 * prepare a Constraint Delaunay Triangulation
	 */
	CDT cdt;

//	std::cout << "---------------------------------------------------------" << std::endl ;
//	std::cout << "triangulate polygon : " << polygon.asText() << std::endl;
	CGAL::Plane_3< Kernel > polygonPlane = plane3D< Kernel >( polygon, false ) ;
	if ( polygonPlane.is_degenerate() ){
		BOOST_THROW_EXCEPTION( Exception(
			( boost::format( "can't find plane for polygon %s" ) % polygon.asText() ).str()
		) );
	}

	/*
	 * insert each ring in the triangulation
	 */
	for ( size_t i = 0; i < polygon.numRings(); i++ ){
		const LineString & ring  = polygon.ringN( i );

		CDT::Vertex_handle v_prev ;
		for ( size_t j = 0; j < ring.numPoints(); j++ ) {
			const Point & point = ring.pointN( j );
			CGAL::Point_3< Kernel > p3d = point.toPoint_3();

			/*
			 * insert into triangulation
			 */
			CDT::Vertex_handle vh = cdt.insert( polygonPlane.to_2d( p3d ) );
			vh->info().original = point ;

			// filter first point
			if ( j != 0 ){
				if ( vh != v_prev ){
					cdt.insert_constraint(vh, v_prev);
				}else{
					//@todo log
				}
			}
			v_prev = vh;
		}
	}

	/*
	 * Mark facets that are inside the domain bounded by the polygon
	 */
	mark_domains(cdt);

	/*
	 * Convert CDT to triangulated surface
	 */
	for ( CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it )
	{
		//ignore holes
		if ( ! it->info().in_domain() ){
			continue ;
		}

		const Point & a = it->vertex(0)->info().original ;
		const Point & b = it->vertex(1)->info().original ;
		const Point & c = it->vertex(2)->info().original ;

		// check that vertex has an original vertex
		if ( a.isEmpty() || b.isEmpty() || c.isEmpty() ){
			BOOST_THROW_EXCEPTION( Exception(
				( boost::format("can't triangulate %1% without adding vertex (constraint intersection found)") % polygon.asText() ).str()
			) ) ;
		}
		triangulatedSurface.addTriangle( Triangle( a, b, c ) );
	}
}

///
///
///
void triangulate2D( const Polygon & polygon, TriangulatedSurface & triangulatedSurface )
{
	/*
	 * filter empty polygon
	 */
	if ( polygon.isEmpty() )
		return ;

	/*
	 * prepare a Constraint Delaunay Triangulation
	 */
	CDT cdt;

	/*
	 * insert each ring in the triangulation
	 */
	for ( size_t i = 0; i < polygon.numRings(); i++ ){
		const LineString & ring  = polygon.ringN( i );

		CDT::Vertex_handle v_prev ;
		for ( size_t j = 0; j < ring.numPoints(); j++ ) {
			const Point & point = ring.pointN( j );

			/*
			 * insert into triangulation
			 */
			CDT::Vertex_handle vh = cdt.insert( point.toPoint_2() );
			vh->info().original = point ;

			// filter first point
			if ( j != 0 ){
				if ( vh != v_prev ){
					cdt.insert_constraint(vh, v_prev);
				}else{
					//@todo log
				}
			}
			v_prev = vh;
		}
	}

	/*
	 * Mark facets that are inside the domain bounded by the polygon
	 */
	mark_domains(cdt);

	/*
	 * Convert CDT to triangulated surface
	 */
	for ( CDT::Finite_faces_iterator it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); ++it )
	{
		//ignore holes
		if ( ! it->info().in_domain() ){
			continue ;
		}
//		assert( it->is_valid() );

		const Point & a = it->vertex(0)->info().original ;
		const Point & b = it->vertex(1)->info().original ;
		const Point & c = it->vertex(2)->info().original ;

		// check that vertex has an original vertex
		if ( a.isEmpty() || b.isEmpty() || c.isEmpty() ){
			BOOST_THROW_EXCEPTION( Exception(
				( boost::format("can't triangulate %1% without adding vertex (constraint intersection found)") % polygon.asText() ).str()
			) ) ;
		}
		triangulatedSurface.addTriangle( Triangle( a, b, c ) );
	}
}

///
///
///
void triangulate( const MultiPolygon & multiPolygon, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < multiPolygon.numGeometries(); i++ ){
		triangulate( multiPolygon.geometryN(i).as< Polygon >(), triangulatedSurface );
	}
}

///
///
///
void triangulate2D( const MultiPolygon & multiPolygon, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < multiPolygon.numGeometries(); i++ ){
		triangulate2D( multiPolygon.geometryN(i).as< Polygon >(), triangulatedSurface );
	}
}

///
///
///
void triangulate( const PolyhedralSurface & poly, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < poly.numPolygons(); i++ ){
		triangulate( poly.polygonN(i), triangulatedSurface );
	}
}

///
///
///
void triangulate2D( const PolyhedralSurface & poly, TriangulatedSurface & triangulatedSurface )
{
	for ( size_t i = 0; i < poly.numPolygons(); i++ ){
		triangulate2D( poly.polygonN(i), triangulatedSurface );
	}
}

}//algorithm
}//SFCGAL

<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node),
//                     Adrian Stoewer (adrian.stoewer@rz.ifi.lmu.de),
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

/**
 * @file pandora.hpp
 * @brief Main header for the public API.
 *
 * @namespace pandora
 * @brief This namespace contains all declarations of the public API.
 */

#include <pandora/Group.hpp>
#include <pandora/File.hpp>
#include <pandora/Block.hpp>
<commit_msg>pandora.hpp: updated copyright notice<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node),
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

/**
 * @file pandora.hpp
 * @brief Main header for the public API.
 *
 * @namespace pandora
 * @brief This namespace contains all declarations of the public API.
 */

#include <pandora/Group.hpp>
#include <pandora/File.hpp>
#include <pandora/Block.hpp>
<|endoftext|>


<commit_before>/*-
 * This file is part of CXX Experiments.
 *
 * CXX Experiments is free software. See AUTHORS and LICENSE for more
 * information on the copying conditions.
 */
#ifndef POINTER_HPP
#define POINTER_HPP

///
/// \file include/pointer.hpp
/// \brief Smart pointer
///

#include <memory>
#include <stdexcept>

namespace cxx_experiments {

template <typename T> class Pointer : public std::shared_ptr<T> {

  using std::shared_ptr<T>::shared_ptr;

public:
  T *operator->() {
    if (std::shared_ptr<T>::get() == nullptr) {
      throw std::runtime_error("Null pointer deference");
    }
    return std::shared_ptr<T>::operator->();
  }

  typename std::add_lvalue_reference<T>::type operator*() {
    if (std::shared_ptr<T>::get() == nullptr) {
      throw std::runtime_error("Null pointer deference");
    }
    return std::shared_ptr<T>::operator*();
  }
};

template <typename T, typename... A> Pointer<T> make(A&&... args) {
  return Pointer<T>(new T(std::forward<A>(args)...));
}

}
#endif
<commit_msg>Make operators as const<commit_after>/*-
 * This file is part of CXX Experiments.
 *
 * CXX Experiments is free software. See AUTHORS and LICENSE for more
 * information on the copying conditions.
 */
#ifndef POINTER_HPP
#define POINTER_HPP

///
/// \file include/pointer.hpp
/// \brief Smart pointer
///

#include <memory>
#include <stdexcept>

namespace cxx_experiments {

template <typename T> class Pointer : public std::shared_ptr<T> {

  using std::shared_ptr<T>::shared_ptr;

public:
  T *operator->() const {
    if (std::shared_ptr<T>::get() == nullptr) {
      throw std::runtime_error("Null pointer deference");
    }
    return std::shared_ptr<T>::operator->();
  }

  typename std::add_lvalue_reference<T>::type operator*() const {
    if (std::shared_ptr<T>::get() == nullptr) {
      throw std::runtime_error("Null pointer deference");
    }
    return std::shared_ptr<T>::operator*();
  }
};

template <typename T, typename... A> Pointer<T> make(A&&... args) {
  return Pointer<T>(new T(std::forward<A>(args)...));
}

}
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2017 Benno Straub, licensed under the MIT license. (A copy can be found at the end of this file)

// TODO: xml::node::m_value also contains the content of comments etc. how do we make this clear to library users?

#ifndef STX_XML_HPP_INCLUDED
#define STX_XML_HPP_INCLUDED

#pragma once

#include "dlist.hpp"
#include "allocator.hpp"

#include <exception>
#include <string_view>
#include <string>

#include <iosfwd>

#include <cassert>

namespace stx {
namespace xml {

class attribute;
class node;

class node_iterator;

constexpr inline
size_t name_hash(std::string_view sv) noexcept;

class attribute : public dlist_element<attribute> {
public:
	std::string_view const& name() const noexcept { return m_name; }

	template<class T = std::string_view>
	T value() const { return m_value; }

	using dlist_element::next;
	using dlist_element::prev;
	attribute* next(std::string_view const& name) noexcept;
	attribute* prev(std::string_view const& name) noexcept;
	attribute& req_next(std::string_view const& name);
	attribute& req_prev(std::string_view const& name);

	const char* parse(arena_allocator& alloc, const char* s);
private:
	std::string_view m_name;
	std::string_view m_value;
};

class node : public dlist_element<node> {
public:
	enum node_type {
		unassigned,
		doctype,
		cdata, // TODO: should those be regular content nodes? (Annoying for serialization)
		regular,
		content,
		comment
	};

	node_type               type() const noexcept { return m_type; }
	std::string_view const& name()          const noexcept { assert(type() == node_type::regular);return m_value; }
	std::string_view const& cdata_value()   const noexcept { assert(type() == node_type::cdata);  return m_value; }
	std::string_view const& comment_value() const noexcept { assert(type() == node_type::comment);return m_value; }
	std::string_view const& content_value() const noexcept { assert(type() == node_type::content);return m_value; }

	node* parent() const noexcept { return m_parent; }

	// Sibling accessors
	using dlist_element::next;
	using dlist_element::prev;

	node* next(std::string_view const& name) noexcept;
	node* prev(std::string_view const& name) noexcept;
	node& req_next(std::string_view const& name);
	node& req_prev(std::string_view const& name);

	node* next(node_type type) noexcept;
	node* prev(node_type type) noexcept;
	node& req_next(node_type type);
	node& req_prev(node_type type);

	// Child accessors
	node* children() const noexcept { return m_children; }

	node* child(std::string_view const& name) noexcept;
	node* child(node_type type) noexcept;

	node& req_child(std::string_view const& name);
	node& req_child(node_type type);

	// Attribute accessors
	attribute* attributes() const noexcept { return m_attributes; }
	attribute* attrib(std::string_view const& name) noexcept;
	attribute& req_attrib(std::string_view const& name);
	template<class T>
	T attrib(std::string_view const& name, T alternative) noexcept;
	template<class T>
	T req_attrib(std::string_view const& name);

	// Iterator
	using iterator = node_iterator;
	iterator begin();
	iterator end();

	// Name hash for switch(node) { case stx::xml::name_hash("thing"): break; }
	constexpr inline operator size_t() const noexcept { return name_hash(m_value); }

	// Comparisons
	constexpr inline bool operator==(std::string_view const& other) const noexcept { return m_value == other; }
	constexpr inline bool operator!=(std::string_view const& other) const noexcept { return m_value != other; }

	// ostream
	void print(std::ostream& stream, unsigned indent = 0);

	// Parsing
	const char* parse_document(arena_allocator&, const char* cstr);
	const char* parse_regular(arena_allocator&, const char*);
	const char* parse_doctype(arena_allocator&, const char*);
	const char* parse_comment(arena_allocator&, const char*);
	const char* parse_content(arena_allocator&, const char*);
	const char* parse_attributes(arena_allocator&, const char*);
	const char* parse_children(arena_allocator&, const char*);
	const char* parse_node(arena_allocator&, const char*);
private:
	node_type        m_type = node_type::unassigned;
	std::string_view m_value;
	attribute*       m_attributes = nullptr;
	node*            m_parent     = nullptr;
	node*            m_children   = nullptr;
};

std::string load_document(std::string_view path);

struct cursor_location {
	unsigned         line;
	unsigned         column;
	std::string_view line_content;

	cursor_location(unsigned line, unsigned column);
	cursor_location(const char* start, const char* location);
};

namespace errors {
	class error : public std::exception {
		std::string m_message;
		const char* m_location;
		std::string_view m_location2;
	public:
		error(std::string message, const char* location = nullptr, std::string_view location2 = {}) :
			m_message(std::move(message)),
			m_location(location), m_location2(location2)
		{}

		const char* what() const noexcept override { return m_message.c_str(); }
		const char* location() const noexcept { return m_location; }
		std::string_view location2() const noexcept { return m_location2; }

		void diagnose(
			const char* sourcefile,
			const char* source,
			std::ostream& printTo);
		void diagnose(
			const char* sourcefile,
			const char* source);
	};

	class parsing_error : public error {
	public: using error::error;
	};

	class attribute_not_found : public error {
	public: using error::error;
	};

	class node_not_found : public error {
	public: using error::error;
	};
} // namespace errors

} // namespace xml
} // namespace stx

// =============================================================
// == Inline implementation =============================================
// =============================================================

namespace stx {
namespace xml {

constexpr inline
size_t name_hash(std::string_view sv) noexcept {
	// FNV 1a hash
	if constexpr(sizeof(size_t) == 4) {
		size_t result = 2166136261ul;
		for(auto& c : sv) {
			result ^= c;
			result *= 16777619ul;
		}
		return result;
	}
	else if constexpr(sizeof(size_t) == 8) {
		size_t result = 14695981039346656037ul;
		for(auto& c : sv) {
			result ^= c;
			result *= 1099511628211ul;
		}
		return result;
	}
}

// ** attribute *******************************************************

template<>
bool attribute::value<bool>() const;
template<>
int attribute::value<int>() const;
template<>
float attribute::value<float>() const;
template<>
double attribute::value<double>() const;

// ** node *******************************************************

template<class T>
T node::attrib(std::string_view const& name, T alternative) noexcept {
	auto* atb = attrib(name);
	return atb ? atb->value<T>() : alternative;
}
template<class T>
T node::req_attrib(std::string_view const& name) {
	return req_attrib(name).value<T>();
}

class node_iterator {
	node* m_current;
public:
	node_iterator(node* n = nullptr) : m_current(n) {}

	node& operator*() noexcept { return *m_current; }
	node* operator->() noexcept { return m_current; }
	node const& operator*() const noexcept { return *m_current; }
	node const* operator->() const noexcept { return m_current; }
	node_iterator& operator++() { m_current = m_current->next(); return *this; }
	node_iterator  operator++(int) { auto copy = *this; return ++copy; }
	operator bool() const noexcept { return m_current != nullptr; }
};

inline node_iterator node::begin() { return node_iterator(children()); }
inline node_iterator node::end() { return node_iterator(); }

} // namespace xml
} // namespace stx

#endif // header guard STX_XML_HPP_INCLUDED

/*
 Copyright (c) 2018 Benno Straub

 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
<commit_msg>Comments<commit_after>// Copyright (c) 2017 Benno Straub, licensed under the MIT license. (A copy can be found at the end of this file)

// TODO: xml::node::m_value also contains the content of comments etc. how do we make this clear to library users?

#ifndef STX_XML_HPP_INCLUDED
#define STX_XML_HPP_INCLUDED

#pragma once

#include "dlist.hpp"
#include "allocator.hpp"

#include <exception>
#include <string_view>
#include <string>

#include <iosfwd>

#include <cassert>

namespace stx {
namespace xml {

class attribute;
class node;

class node_iterator;

constexpr inline
size_t name_hash(std::string_view sv) noexcept;

class attribute : public dlist_element<attribute> {
public:
	std::string_view const& name() const noexcept { return m_name; }

	template<class T = std::string_view>
	T value() const { return m_value; }

	using dlist_element::next;
	using dlist_element::prev;
	attribute* next(std::string_view const& name) noexcept;
	attribute* prev(std::string_view const& name) noexcept;
	attribute& req_next(std::string_view const& name);
	attribute& req_prev(std::string_view const& name);

	const char* parse(arena_allocator& alloc, const char* s);
private:
	std::string_view m_name;
	std::string_view m_value;
};

class node : public dlist_element<node> {
public:
	enum node_type {
		unassigned,
		doctype,
		cdata, // TODO: should those be regular content nodes? (Annoying for serialization)
		regular,
		content,
		comment
	};

	node_type               type() const noexcept { return m_type; }
	std::string_view const& name()          const noexcept { assert(type() == node_type::regular);return m_value; }
	std::string_view const& cdata_value()   const noexcept { assert(type() == node_type::cdata);  return m_value; }
	std::string_view const& comment_value() const noexcept { assert(type() == node_type::comment);return m_value; }
	std::string_view const& content_value() const noexcept { assert(type() == node_type::content);return m_value; }

	node* parent() const noexcept { return m_parent; }

	// Sibling accessors
	using dlist_element::next;
	using dlist_element::prev;

	node* next(std::string_view const& name) noexcept;
	node* prev(std::string_view const& name) noexcept;
	node& req_next(std::string_view const& name);
	node& req_prev(std::string_view const& name);

	node* next(node_type type) noexcept;
	node* prev(node_type type) noexcept;
	node& req_next(node_type type);
	node& req_prev(node_type type);

	// Child accessors
	node* children() const noexcept { return m_children; }

	node* child(std::string_view const& name) noexcept;
	node* child(node_type type) noexcept;

	node& req_child(std::string_view const& name);
	node& req_child(node_type type);

	// Attribute accessors
	attribute* attributes() const noexcept { return m_attributes; }
	attribute* attrib(std::string_view const& name) noexcept;
	attribute& req_attrib(std::string_view const& name);
	template<class T>
	T attrib(std::string_view const& name, T alternative) noexcept;
	template<class T>
	T req_attrib(std::string_view const& name);

	// Iterator
	using iterator = node_iterator;
	iterator begin(); //<! Iterate over children
	iterator end();

	// Name hash for switch(node) { case stx::xml::name_hash("thing"): break; }
	constexpr inline operator size_t() const noexcept { return name_hash(m_value); }

	// Comparisons
	constexpr inline bool operator==(std::string_view const& other) const noexcept { return m_value == other; }
	constexpr inline bool operator!=(std::string_view const& other) const noexcept { return m_value != other; }

	// ostream
	void print(std::ostream& stream, unsigned indent = 0);

	// Parsing
	const char* parse_document(arena_allocator&, const char* cstr);
	const char* parse_regular(arena_allocator&, const char*);
	const char* parse_doctype(arena_allocator&, const char*);
	const char* parse_comment(arena_allocator&, const char*);
	const char* parse_content(arena_allocator&, const char*);
	const char* parse_attributes(arena_allocator&, const char*);
	const char* parse_children(arena_allocator&, const char*);
	const char* parse_node(arena_allocator&, const char*);
private:
	node_type        m_type = node_type::unassigned;
	std::string_view m_value;
	attribute*       m_attributes = nullptr;
	node*            m_parent     = nullptr;
	node*            m_children   = nullptr;
};

std::string load_document(std::string_view path);

struct cursor_location {
	unsigned         line;
	unsigned         column;
	std::string_view line_content;

	cursor_location(unsigned line, unsigned column);
	cursor_location(const char* start, const char* location);
};

namespace errors {
	class error : public std::exception {
		std::string m_message;
		const char* m_location;
		std::string_view m_location2;
	public:
		error(std::string message, const char* location = nullptr, std::string_view location2 = {}) :
			m_message(std::move(message)),
			m_location(location), m_location2(location2)
		{}

		const char* what() const noexcept override { return m_message.c_str(); }
		const char* location() const noexcept { return m_location; }
		std::string_view location2() const noexcept { return m_location2; }

		void diagnose(
			const char* sourcefile,
			const char* source,
			std::ostream& printTo);
		void diagnose(
			const char* sourcefile,
			const char* source);
	};

	class parsing_error : public error {
	public: using error::error;
	};

	class attribute_not_found : public error {
	public: using error::error;
	};

	class node_not_found : public error {
	public: using error::error;
	};
} // namespace errors

} // namespace xml
} // namespace stx

// =============================================================
// == Inline implementation =============================================
// =============================================================

namespace stx {
namespace xml {

constexpr inline
size_t name_hash(std::string_view sv) noexcept {
	// FNV 1a hash
	if constexpr(sizeof(size_t) == 4) {
		size_t result = 2166136261ul;
		for(auto& c : sv) {
			result ^= c;
			result *= 16777619ul;
		}
		return result;
	}
	else if constexpr(sizeof(size_t) == 8) {
		size_t result = 14695981039346656037ul;
		for(auto& c : sv) {
			result ^= c;
			result *= 1099511628211ul;
		}
		return result;
	}
}

// ** attribute *******************************************************

template<>
bool attribute::value<bool>() const;
template<>
int attribute::value<int>() const;
template<>
float attribute::value<float>() const;
template<>
double attribute::value<double>() const;

// ** node *******************************************************

template<class T>
T node::attrib(std::string_view const& name, T alternative) noexcept {
	auto* atb = attrib(name);
	return atb ? atb->value<T>() : alternative;
}
template<class T>
T node::req_attrib(std::string_view const& name) {
	return req_attrib(name).value<T>();
}

class node_iterator {
	node* m_current;
public:
	node_iterator(node* n = nullptr) : m_current(n) {}

	node& operator*() noexcept { return *m_current; }
	node* operator->() noexcept { return m_current; }
	node const& operator*() const noexcept { return *m_current; }
	node const* operator->() const noexcept { return m_current; }
	node_iterator& operator++() { m_current = m_current->next(); return *this; }
	node_iterator  operator++(int) { auto copy = *this; return ++copy; }
	operator bool() const noexcept { return m_current != nullptr; }
};

inline node_iterator node::begin() { return node_iterator(children()); }
inline node_iterator node::end() { return node_iterator(); }

} // namespace xml
} // namespace stx

#endif // header guard STX_XML_HPP_INCLUDED

/*
 Copyright (c) 2018 Benno Straub

 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
<|endoftext|>


<commit_before>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 *Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 *contact: immarespond at gmail dot com
 *
 */

#include "PluginMemory.h"

#include <stdexcept>
#include <QMutex>

PluginMemory::PluginMemory(Natron::EffectInstance* effect)
: _ptr(0)
, _locked(0)
, _nBytes(0)
, _mutex(new QMutex)
, _effect(effect)
{
}

PluginMemory::~PluginMemory() {
    delete [] _ptr;
}

bool PluginMemory::alloc(size_t nBytes) {
    QMutexLocker l(_mutex);

    if(!_locked){
        _nBytes = nBytes;
        if(_ptr)
            freeMem();
        _ptr = new char[nBytes];
        if (!_ptr) {
            throw std::bad_alloc();
        }
        return true;
    } else {
        return false;
    }
}

void PluginMemory::freeMem() {
    QMutexLocker l(_mutex);
    _nBytes = 0;
    delete [] _ptr;
    _ptr = 0;
    _locked = 0;
}

void* PluginMemory::getPtr() {
    QMutexLocker l(_mutex);
    return _ptr;
}

void PluginMemory::lock() {
    QMutexLocker l(_mutex);
    ++_locked;
}

void PluginMemory::unlock() {
    QMutexLocker l(_mutex);
    --_locked;
}<commit_msg>Fix missing call<commit_after>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 *Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 *contact: immarespond at gmail dot com
 *
 */

#include "PluginMemory.h"

#include <stdexcept>
#include <QMutex>
#include "Engine/EffectInstance.h"

PluginMemory::PluginMemory(Natron::EffectInstance* effect)
: _ptr(0)
, _locked(0)
, _nBytes(0)
, _mutex(new QMutex)
, _effect(effect)
{
}

PluginMemory::~PluginMemory() {
    delete [] _ptr;
}

bool PluginMemory::alloc(size_t nBytes) {
    QMutexLocker l(_mutex);
    if(!_locked){
        _nBytes = nBytes;
        if(_ptr)
            freeMem();
        _ptr = new char[nBytes];
        if (!_ptr) {
            throw std::bad_alloc();
        }

        _effect->registerPluginMemory(nBytes);

        return true;
    } else {
        return false;
    }
}

void PluginMemory::freeMem() {
    QMutexLocker l(_mutex);
    _effect->unregisterPluginMemory(_nBytes);
    _nBytes = 0;
    delete [] _ptr;
    _ptr = 0;
    _locked = 0;
}

void* PluginMemory::getPtr() {
    QMutexLocker l(_mutex);
    return _ptr;
}

void PluginMemory::lock() {
    QMutexLocker l(_mutex);
    ++_locked;
}

void PluginMemory::unlock() {
    QMutexLocker l(_mutex);
    --_locked;
}<|endoftext|>