<commit_before>/*************************************************************************
 *
 *  $RCSfile: prnmon.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: cd $ $Date: 2002-10-22 06:05:54 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif

#ifndef   SVTOOLS_ASYNCLINK_HXX
#include <svtools/asynclink.hxx>
#endif

#include <svtools/printwarningoptions.hxx>

#pragma hdrstop

#include "prnmon.hxx"
#include "viewsh.hxx"
#include "viewfrm.hxx"
#include "objsh.hxx"
#include "docfile.hxx"
#include "sfxtypes.hxx"
#include "progress.hxx"
#include "desrupt.hxx"
#include "bindings.hxx"
#include "sfxresid.hxx"

#include "view.hrc"

//------------------------------------------------------------------------

#define SFX_TITLE_MAXLEN_PRINTMONITOR   22

//------------------------------------------------------------------------

struct SfxPrintMonitor_Impl: public ModelessDialog
{
    SfxPrintMonitor_Impl( Window *pParent );

    FixedText               aDocName;
    FixedText               aPrinting;
    FixedText               aPrinter;
    FixedText               aPrintInfo;
    CancelButton            aCancel;
};

//-------------------------------------------------------------------------

struct SfxPrintProgress_Impl
{
    SfxPrintMonitor_Impl*   pMonitor;
    SfxViewShell*           pViewShell;
    SfxPrinter*             pPrinter;
    SfxPrinter*             pOldPrinter;
    USHORT                  nLastPage;
    BOOL                    bRunning;
    BOOL                    bCancel;
    BOOL                    bDeleteOnEndPrint;
    BOOL                    bShow;
    BOOL                    bCallbacks;
    BOOL                    bOldEnablePrintFile;
    BOOL                    bOldFlag;
    BOOL                    bRestoreFlag;
    svtools::AsynchronLink  aDeleteLink;
    Link                    aCancelHdl;

private:
    DECL_LINK( CancelHdl, Button * );
    DECL_STATIC_LINK( SfxPrintProgress_Impl, DeleteHdl, SfxPrintProgress * );

public:
    SfxPrintProgress_Impl( SfxViewShell* pTheViewShell, SfxPrinter* pThePrinter );
    ~SfxPrintProgress_Impl();

    void                    Delete( SfxPrintProgress* pAntiImpl ) { aDeleteLink.Call( pAntiImpl ); }
    SfxViewShell*           GetViewShell() const { return pViewShell; }
    BOOL                    SetPage( USHORT nPage, const String &rPage );
};

//------------------------------------------------------------------------

SfxPrintMonitor_Impl::SfxPrintMonitor_Impl( Window* pParent ) :

    ModelessDialog( pParent, SfxResId( DLG_PRINTMONITOR ) ),

    aDocName    ( this, ResId( FT_DOCNAME ) ),
    aPrinting   ( this, ResId( FT_PRINTING ) ),
    aPrinter    ( this, ResId( FT_PRINTER ) ),
    aPrintInfo  ( this, ResId( FT_PRINTINFO ) ),
    aCancel     ( this, ResId( PB_CANCELPRNMON ) )

{
    FreeResource();
}

//------------------------------------------------------------------------

IMPL_STATIC_LINK( SfxPrintProgress_Impl, DeleteHdl, SfxPrintProgress*, pAntiImpl )
{
    delete pAntiImpl;
    return 0;
}

//------------------------------------------------------------------------

SfxPrintProgress_Impl::SfxPrintProgress_Impl( SfxViewShell* pTheViewShell,
                                              SfxPrinter* pThePrinter ) :

    pViewShell          ( pTheViewShell ),
    pPrinter            ( pThePrinter ),
    pOldPrinter         ( NULL ),
    bRunning            ( TRUE ),
    bDeleteOnEndPrint   ( FALSE ),
    bCancel             ( FALSE ),
    bCallbacks          ( FALSE ),
    bOldEnablePrintFile ( FALSE ),
    bOldFlag            ( TRUE ),
    bRestoreFlag        ( FALSE ),
    nLastPage           ( 0 ),
    aDeleteLink         ( STATIC_LINK( this, SfxPrintProgress_Impl, DeleteHdl ) )

{
    Window* pParent =
        pTheViewShell->GetWindow()->IsReallyVisible() ? pTheViewShell->GetWindow() : NULL;
    pMonitor = new SfxPrintMonitor_Impl( pParent );
    pMonitor->aDocName.SetText(
        pViewShell->GetViewFrame()->GetObjectShell()->GetTitle( SFX_TITLE_MAXLEN_PRINTMONITOR ) );
    pMonitor->aPrinter.SetText( pViewShell->GetPrinter()->GetName() );
    pMonitor->aCancel.SetClickHdl( LINK( this, SfxPrintProgress_Impl, CancelHdl ) );
}

//------------------------------------------------------------------------

SfxPrintProgress_Impl::~SfxPrintProgress_Impl()
{
    if ( pMonitor )
    {
        pMonitor->Hide(); // sieht optisch besser aus, wenn alles auf einmal verschwindet
        delete pMonitor;
    }
}

//------------------------------------------------------------------------

BOOL SfxPrintProgress_Impl::SetPage( USHORT nPage, const String &rPage )
{
    // wurde der Druckauftrag abgebrochen?
    if ( bCancel || !pMonitor )
        return FALSE;

    nLastPage = nPage;
    String aStrPrintInfo = String( SfxResId( STR_PAGE ) );
    if ( !rPage.Len() )
        aStrPrintInfo += String::CreateFromInt32( nLastPage );
    else
        aStrPrintInfo += rPage;
    pMonitor->aPrintInfo.SetText( aStrPrintInfo );
    pMonitor->Update();
    return TRUE;
}

//------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxPrintProgress_Impl, CancelHdl, Button *, pButton )
{
    if ( pMonitor )
        pMonitor->Hide();
    pViewShell->GetPrinter()->AbortJob();
    bCancel = TRUE;

    if ( aCancelHdl.IsSet() )
        aCancelHdl.Call( this );

    return 0;
}
IMPL_LINK_INLINE_END( SfxPrintProgress_Impl, CancelHdl, Button *, pButton )

//--------------------------------------------------------------------

SfxPrintProgress::SfxPrintProgress( SfxViewShell* pViewSh, FASTBOOL bShow )
:   SfxProgress( pViewSh->GetViewFrame()->GetObjectShell(),
                 String(SfxResId(STR_PRINTING)), 1, FALSE ),
    pImp( new SfxPrintProgress_Impl( pViewSh, pViewSh->GetPrinter() ) )
{
    // Callback fuer Fehler und EndPrint setzen
    pImp->pPrinter->SetEndPrintHdl(
                LINK( this, SfxPrintProgress, EndPrintNotify ));
    pImp->pPrinter->SetErrorHdl(
                LINK( this, SfxPrintProgress, PrintErrorNotify ));
    pImp->bCallbacks = TRUE;

    pImp->pViewShell->GetViewFrame()->GetFrame()->Lock_Impl(TRUE);
    pImp->bShow = bShow;
    Lock();
    if ( !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
    {
        pImp->bRestoreFlag = TRUE;
        pImp->bOldFlag = pViewSh->GetObjectShell()->IsEnableSetModified();
        if ( pImp->bOldFlag )
            pViewSh->GetObjectShell()->EnableSetModified( FALSE );
    }
}

//--------------------------------------------------------------------

SfxPrintProgress::~SfxPrintProgress()
{
    // k"onnte auch schon weg sein (in EndPrintNotify)
    DELETEZ(pImp->pMonitor);

    // ggf. Callbacks entfermen
    if ( pImp->bCallbacks )
    {
        pImp->pPrinter->SetEndPrintHdl( Link() );
        pImp->pPrinter->SetErrorHdl( Link() );
        pImp->bCallbacks = FALSE;
    }

    // ggf. vorherigen Drucker wieder einsetzen
    if ( pImp->pOldPrinter )
        pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER );
    else
        // ggf. vorherigen Print-To-File-Status zuruecksetzen
        pImp->pViewShell->GetPrinter()->EnablePrintFile(
                pImp->bOldEnablePrintFile );

    // EndPrint-Notification an Frame
    pImp->pViewShell->GetViewFrame()->GetFrame()->Lock_Impl(FALSE);

    delete pImp;
}

//--------------------------------------------------------------------

BOOL SfxPrintProgress::SetState( ULONG nVal, ULONG nNewRange )
{
#ifndef MAC
    // auf dem MAC kommt einer vom Betriebssystem
    if ( pImp->bShow )
    {
        pImp->bShow = FALSE;
        pImp->pMonitor->Show();
        pImp->pMonitor->Update();
    }
#endif

    return pImp->SetPage( (USHORT)nVal, GetStateText_Impl() ) &&
           SfxProgress::SetState( nVal, nNewRange );
}

//--------------------------------------------------------------------

void SfxPrintProgress::SetText( const String& rText )
{
    if ( pImp->pMonitor )
    {
        pImp->pMonitor->SetText( rText );
        pImp->pMonitor->Update();
    }
    SfxProgress::SetText( rText );
}

//------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxPrintProgress, PrintErrorNotify, void *, pvoid )
{
    if ( pImp->pMonitor )
        pImp->pMonitor->Hide();
    pImp->pPrinter->AbortJob();
    InfoBox( pImp->GetViewShell()->GetWindow(),
             String( SfxResId(STR_ERROR_PRINT) ) ).Execute();
    if ( pImp->bRestoreFlag && pImp->pViewShell->GetObjectShell()->IsEnableSetModified() != pImp->bOldFlag )
        pImp->pViewShell->GetObjectShell()->EnableSetModified( pImp->bOldFlag );
    return 0;
}
IMPL_LINK_INLINE_END( SfxPrintProgress, PrintErrorNotify, void *, pvoid )

//------------------------------------------------------------------------

IMPL_LINK( SfxPrintProgress, EndPrintNotify, void *, pvoid )
{
    if ( pImp->pMonitor )
        pImp->pMonitor->Hide();

    // Slots enablen
    pImp->pViewShell->Invalidate( SID_PRINTDOC );
    pImp->pViewShell->Invalidate( SID_PRINTDOCDIRECT );
    pImp->pViewShell->Invalidate( SID_SETUPPRINTER );

    // . . . falls der Printer im System umgestellt wurde, hier Aenderung
    // nachziehen.
    //! if( pMDI->IsPrinterChanged() ) pMDI->Changed( 0L );

    // Callbacks rausnehmen
    pImp->pPrinter->SetEndPrintHdl( Link() );
    pImp->pPrinter->SetErrorHdl( Link() );
    pImp->bCallbacks = FALSE;

    // ggf. alten Printer wieder einsetzen
    if ( pImp->pOldPrinter )
    {
        // Fix #59613#: niemals den aktuellen Printer synchron abschiessen !
        // Da sowieso immer bDeleteOnEndPrint gesetzt wird, wird der der Drucker im
        // dtor vom Printprogress ( dann aber asynchron !! ) zur"uckgesetzt.
/*
        pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER );
        pImp->pOldPrinter = 0;
        pImp->pPrinter = 0;
 */
    }
    else
        // ggf. vorherigen Print-To-File-Status zuruecksetzen
        pImp->pViewShell->GetPrinter()->EnablePrintFile( pImp->bOldEnablePrintFile );

    // lief der Drucker im Thread?
    if ( pImp->bDeleteOnEndPrint )
    {
        // Dialog sofort l"oschen sonst wird ggf. das MDI vorher geschlossen
        DELETEZ(pImp->pMonitor);

        // Progress per PostMessage zerst"oren, nicht sofort sonst GPF
        pImp->Delete( this );
    }
    else
    {
        DBG_ASSERT( !pImp->pOldPrinter, "Printer konnte nicht korrekt restauriert werden!" );
        pImp->bRunning = FALSE;
    }

    if ( pImp->bRestoreFlag && pImp->pViewShell->GetObjectShell()->IsEnableSetModified() != pImp->bOldFlag )
        pImp->pViewShell->GetObjectShell()->EnableSetModified( TRUE );
    return 0;
}

//------------------------------------------------------------------------

void SfxPrintProgress::DeleteOnEndPrint()
{
    UnLock(); // jetzt schon, wg. Drucken im Thread
#ifndef WIN
    // da das Drucken im 'Thread' unter Windows zu undefiniert ist bleibt der
    // Print-Monitor dort stehen, auf den anderen Plattformen kann man dann
    // weiterarbeiten, also kommt das Teil weg
    DELETEZ( pImp->pMonitor );
#endif

    pImp->bDeleteOnEndPrint = TRUE;
    if ( !pImp->bRunning )
        delete this;
}

//------------------------------------------------------------------------

void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter *pOldPrinter,
                                          BOOL bOldEnablePrintFile )
{
    pImp->pOldPrinter = pOldPrinter;
    pImp->bOldEnablePrintFile = bOldEnablePrintFile;
}

//------------------------------------------------------------------------

void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter *pOldPrinter )
{
    RestoreOnEndPrint( pOldPrinter, FALSE );
}

//------------------------------------------------------------------------

void SfxPrintProgress::SetCancelHdl( const Link& aCancelHdl )
{
    pImp->aCancelHdl = aCancelHdl;
}
<commit_msg>#88560#: allow to close frame after printing if controller received a request for that<commit_after>/*************************************************************************
 *
 *  $RCSfile: prnmon.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: mba $ $Date: 2002-10-24 12:14:07 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
#include <com/sun/star/util/XCloseable.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_XCLOSEBROADCASTER_HPP_
#include <com/sun/star/util/XCloseBroadcaster.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_XCLOSELISTENER_HPP_
#include <com/sun/star/util/XCloseListener.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_CLOSEVETOEXCEPTION_HPP_
#include <com/sun/star/util/CloseVetoException.hpp>
#endif

#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif

#ifndef   SVTOOLS_ASYNCLINK_HXX
#include <svtools/asynclink.hxx>
#endif

#include <svtools/printwarningoptions.hxx>

#pragma hdrstop

#include "prnmon.hxx"
#include "viewsh.hxx"
#include "viewfrm.hxx"
#include "objsh.hxx"
#include "docfile.hxx"
#include "sfxtypes.hxx"
#include "progress.hxx"
#include "desrupt.hxx"
#include "bindings.hxx"
#include "sfxresid.hxx"

#include "view.hrc"

//------------------------------------------------------------------------

#define SFX_TITLE_MAXLEN_PRINTMONITOR   22

//------------------------------------------------------------------------

struct SfxPrintMonitor_Impl: public ModelessDialog
{
    SfxPrintMonitor_Impl( Window *pParent );

    FixedText               aDocName;
    FixedText               aPrinting;
    FixedText               aPrinter;
    FixedText               aPrintInfo;
    CancelButton            aCancel;
};

//-------------------------------------------------------------------------

struct SfxPrintProgress_Impl
{
    SfxPrintMonitor_Impl*   pMonitor;
    SfxViewShell*           pViewShell;
    SfxPrinter*             pPrinter;
    SfxPrinter*             pOldPrinter;
    USHORT                  nLastPage;
    BOOL                    bRunning;
    BOOL                    bCancel;
    BOOL                    bDeleteOnEndPrint;
    BOOL                    bShow;
    BOOL                    bCallbacks;
    BOOL                    bOldEnablePrintFile;
    BOOL                    bOldFlag;
    BOOL                    bRestoreFlag;
    svtools::AsynchronLink  aDeleteLink;
    Link                    aCancelHdl;

private:
    DECL_LINK( CancelHdl, Button * );
    DECL_STATIC_LINK( SfxPrintProgress_Impl, DeleteHdl, SfxPrintProgress * );

public:
    SfxPrintProgress_Impl( SfxViewShell* pTheViewShell, SfxPrinter* pThePrinter );
    ~SfxPrintProgress_Impl();

    void                    Delete( SfxPrintProgress* pAntiImpl ) { aDeleteLink.Call( pAntiImpl ); }
    SfxViewShell*           GetViewShell() const { return pViewShell; }
    BOOL                    SetPage( USHORT nPage, const String &rPage );
};

//------------------------------------------------------------------------

SfxPrintMonitor_Impl::SfxPrintMonitor_Impl( Window* pParent ) :

    ModelessDialog( pParent, SfxResId( DLG_PRINTMONITOR ) ),

    aDocName    ( this, ResId( FT_DOCNAME ) ),
    aPrinting   ( this, ResId( FT_PRINTING ) ),
    aPrinter    ( this, ResId( FT_PRINTER ) ),
    aPrintInfo  ( this, ResId( FT_PRINTINFO ) ),
    aCancel     ( this, ResId( PB_CANCELPRNMON ) )

{
    FreeResource();
}

//------------------------------------------------------------------------

IMPL_STATIC_LINK( SfxPrintProgress_Impl, DeleteHdl, SfxPrintProgress*, pAntiImpl )
{
    delete pAntiImpl;
    return 0;
}

//------------------------------------------------------------------------

SfxPrintProgress_Impl::SfxPrintProgress_Impl( SfxViewShell* pTheViewShell,
                                              SfxPrinter* pThePrinter ) :

    pViewShell          ( pTheViewShell ),
    pPrinter            ( pThePrinter ),
    pOldPrinter         ( NULL ),
    bRunning            ( TRUE ),
    bDeleteOnEndPrint   ( FALSE ),
    bCancel             ( FALSE ),
    bCallbacks          ( FALSE ),
    bOldEnablePrintFile ( FALSE ),
    bOldFlag            ( TRUE ),
    bRestoreFlag        ( FALSE ),
    nLastPage           ( 0 ),
    aDeleteLink         ( STATIC_LINK( this, SfxPrintProgress_Impl, DeleteHdl ) )

{
    Window* pParent =
        pTheViewShell->GetWindow()->IsReallyVisible() ? pTheViewShell->GetWindow() : NULL;
    pMonitor = new SfxPrintMonitor_Impl( pParent );
    pMonitor->aDocName.SetText(
        pViewShell->GetViewFrame()->GetObjectShell()->GetTitle( SFX_TITLE_MAXLEN_PRINTMONITOR ) );
    pMonitor->aPrinter.SetText( pViewShell->GetPrinter()->GetName() );
    pMonitor->aCancel.SetClickHdl( LINK( this, SfxPrintProgress_Impl, CancelHdl ) );
}

//------------------------------------------------------------------------

SfxPrintProgress_Impl::~SfxPrintProgress_Impl()
{
    if ( pMonitor )
    {
        pMonitor->Hide(); // sieht optisch besser aus, wenn alles auf einmal verschwindet
        delete pMonitor;
    }
}

//------------------------------------------------------------------------

BOOL SfxPrintProgress_Impl::SetPage( USHORT nPage, const String &rPage )
{
    // wurde der Druckauftrag abgebrochen?
    if ( bCancel || !pMonitor )
        return FALSE;

    nLastPage = nPage;
    String aStrPrintInfo = String( SfxResId( STR_PAGE ) );
    if ( !rPage.Len() )
        aStrPrintInfo += String::CreateFromInt32( nLastPage );
    else
        aStrPrintInfo += rPage;
    pMonitor->aPrintInfo.SetText( aStrPrintInfo );
    pMonitor->Update();
    return TRUE;
}

//------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxPrintProgress_Impl, CancelHdl, Button *, pButton )
{
    if ( pMonitor )
        pMonitor->Hide();
    pViewShell->GetPrinter()->AbortJob();
    bCancel = TRUE;

    if ( aCancelHdl.IsSet() )
        aCancelHdl.Call( this );

    return 0;
}
IMPL_LINK_INLINE_END( SfxPrintProgress_Impl, CancelHdl, Button *, pButton )

//--------------------------------------------------------------------

SfxPrintProgress::SfxPrintProgress( SfxViewShell* pViewSh, FASTBOOL bShow )
:   SfxProgress( pViewSh->GetViewFrame()->GetObjectShell(),
                 String(SfxResId(STR_PRINTING)), 1, FALSE ),
    pImp( new SfxPrintProgress_Impl( pViewSh, pViewSh->GetPrinter() ) )
{
    // Callback fuer Fehler und EndPrint setzen
    pImp->pPrinter->SetEndPrintHdl(
                LINK( this, SfxPrintProgress, EndPrintNotify ));
    pImp->pPrinter->SetErrorHdl(
                LINK( this, SfxPrintProgress, PrintErrorNotify ));
    pImp->bCallbacks = TRUE;

    //pImp->pViewShell->GetViewFrame()->GetFrame()->Lock_Impl(TRUE);
    pImp->bShow = bShow;
    Lock();
    if ( !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() )
    {
        pImp->bRestoreFlag = TRUE;
        pImp->bOldFlag = pViewSh->GetObjectShell()->IsEnableSetModified();
        if ( pImp->bOldFlag )
            pViewSh->GetObjectShell()->EnableSetModified( FALSE );
    }
}

//--------------------------------------------------------------------

SfxPrintProgress::~SfxPrintProgress()
{
    // k"onnte auch schon weg sein (in EndPrintNotify)
    DELETEZ(pImp->pMonitor);

    // ggf. Callbacks entfermen
    if ( pImp->bCallbacks )
    {
        pImp->pPrinter->SetEndPrintHdl( Link() );
        pImp->pPrinter->SetErrorHdl( Link() );
        pImp->bCallbacks = FALSE;
    }

    // ggf. vorherigen Drucker wieder einsetzen
    if ( pImp->pOldPrinter )
        pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER );
    else
        // ggf. vorherigen Print-To-File-Status zuruecksetzen
        pImp->pViewShell->GetPrinter()->EnablePrintFile(
                pImp->bOldEnablePrintFile );

    // EndPrint-Notification an Frame
    //pImp->pViewShell->GetViewFrame()->GetFrame()->Lock_Impl(FALSE);
    if ( pImp->pViewShell->GotOwnerShip_Impl() )
    {
        com::sun::star::uno::Reference < com::sun::star::util::XCloseable > xModel( pImp->pViewShell->GetObjectShell()->GetModel(), com::sun::star::uno::UNO_QUERY );
        if ( xModel.is() )
        {
            try
            {
                xModel->close( sal_True );
            }
            catch ( com::sun::star::util::CloseVetoException& )
            {
            }
        }
    }

    delete pImp;
}

//--------------------------------------------------------------------

BOOL SfxPrintProgress::SetState( ULONG nVal, ULONG nNewRange )
{
#ifndef MAC
    // auf dem MAC kommt einer vom Betriebssystem
    if ( pImp->bShow )
    {
        pImp->bShow = FALSE;
        pImp->pMonitor->Show();
        pImp->pMonitor->Update();
    }
#endif

    return pImp->SetPage( (USHORT)nVal, GetStateText_Impl() ) &&
           SfxProgress::SetState( nVal, nNewRange );
}

//--------------------------------------------------------------------

void SfxPrintProgress::SetText( const String& rText )
{
    if ( pImp->pMonitor )
    {
        pImp->pMonitor->SetText( rText );
        pImp->pMonitor->Update();
    }
    SfxProgress::SetText( rText );
}

//------------------------------------------------------------------------

IMPL_LINK_INLINE_START( SfxPrintProgress, PrintErrorNotify, void *, pvoid )
{
    if ( pImp->pMonitor )
        pImp->pMonitor->Hide();
    pImp->pPrinter->AbortJob();
    InfoBox( pImp->GetViewShell()->GetWindow(),
             String( SfxResId(STR_ERROR_PRINT) ) ).Execute();
    if ( pImp->bRestoreFlag && pImp->pViewShell->GetObjectShell()->IsEnableSetModified() != pImp->bOldFlag )
        pImp->pViewShell->GetObjectShell()->EnableSetModified( pImp->bOldFlag );
    return 0;
}
IMPL_LINK_INLINE_END( SfxPrintProgress, PrintErrorNotify, void *, pvoid )

//------------------------------------------------------------------------

IMPL_LINK( SfxPrintProgress, EndPrintNotify, void *, pvoid )
{
    if ( pImp->pMonitor )
        pImp->pMonitor->Hide();

    // Slots enablen
    pImp->pViewShell->Invalidate( SID_PRINTDOC );
    pImp->pViewShell->Invalidate( SID_PRINTDOCDIRECT );
    pImp->pViewShell->Invalidate( SID_SETUPPRINTER );

    // . . . falls der Printer im System umgestellt wurde, hier Aenderung
    // nachziehen.
    //! if( pMDI->IsPrinterChanged() ) pMDI->Changed( 0L );

    // Callbacks rausnehmen
    pImp->pPrinter->SetEndPrintHdl( Link() );
    pImp->pPrinter->SetErrorHdl( Link() );
    pImp->bCallbacks = FALSE;

    // ggf. alten Printer wieder einsetzen
    if ( pImp->pOldPrinter )
    {
        // Fix #59613#: niemals den aktuellen Printer synchron abschiessen !
        // Da sowieso immer bDeleteOnEndPrint gesetzt wird, wird der der Drucker im
        // dtor vom Printprogress ( dann aber asynchron !! ) zur"uckgesetzt.
/*
        pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER );
        pImp->pOldPrinter = 0;
        pImp->pPrinter = 0;
 */
    }
    else
        // ggf. vorherigen Print-To-File-Status zuruecksetzen
        pImp->pViewShell->GetPrinter()->EnablePrintFile( pImp->bOldEnablePrintFile );

    // lief der Drucker im Thread?
    if ( pImp->bDeleteOnEndPrint )
    {
        // Dialog sofort l"oschen sonst wird ggf. das MDI vorher geschlossen
        DELETEZ(pImp->pMonitor);

        // Progress per PostMessage zerst"oren, nicht sofort sonst GPF
        pImp->Delete( this );
    }
    else
    {
        DBG_ASSERT( !pImp->pOldPrinter, "Printer konnte nicht korrekt restauriert werden!" );
        pImp->bRunning = FALSE;
    }

    if ( pImp->bRestoreFlag && pImp->pViewShell->GetObjectShell()->IsEnableSetModified() != pImp->bOldFlag )
        pImp->pViewShell->GetObjectShell()->EnableSetModified( TRUE );
    return 0;
}

//------------------------------------------------------------------------

void SfxPrintProgress::DeleteOnEndPrint()
{
    UnLock(); // jetzt schon, wg. Drucken im Thread
#ifndef WIN
    // da das Drucken im 'Thread' unter Windows zu undefiniert ist bleibt der
    // Print-Monitor dort stehen, auf den anderen Plattformen kann man dann
    // weiterarbeiten, also kommt das Teil weg
    DELETEZ( pImp->pMonitor );
#endif

    pImp->bDeleteOnEndPrint = TRUE;
    if ( !pImp->bRunning )
        delete this;
}

//------------------------------------------------------------------------

void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter *pOldPrinter,
                                          BOOL bOldEnablePrintFile )
{
    pImp->pOldPrinter = pOldPrinter;
    pImp->bOldEnablePrintFile = bOldEnablePrintFile;
}

//------------------------------------------------------------------------

void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter *pOldPrinter )
{
    RestoreOnEndPrint( pOldPrinter, FALSE );
}

//------------------------------------------------------------------------

void SfxPrintProgress::SetCancelHdl( const Link& aCancelHdl )
{
    pImp->aCancelHdl = aCancelHdl;
}
<|endoftext|>


<commit_before>/**
 * \file dcs/testbed/rain_workload_driver.hpp
 *
 * \brief Workload driver based on the RAIN workload toolkit.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

 *
 * Copyright (C) 2012       Marco Guazzone
 *                          [Distributed Computing System (DCS) Group,
 *                           Computer Science Institute,
 *                           Department of Science and Technological Innovation,
 *                           University of Piemonte Orientale,
 *                           Alessandria (Italy)]
 *
 * This file is part of dcsxx-testbed.
 *
 * dcsxx-testbed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * dcsxx-testbed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with dcsxx-testbed. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
#define DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP

#include <boost/smart_ptr.hpp>
#include <cstdlib>
#include <dcs/exception.hpp>
#include <dcs/system/posix_process.hpp>
#include <dcs/system/process_status_category.hpp>
#include <dcs/testbed/base_workload_driver.hpp>
#include <istream>
extern "C" {
#include <pthread.h>
}
#include <string>
#include <vector>

namespace dcs { namespace testbed {

namespace detail {

namespace /*<unnamed>*/ {

inline
::std::string make_java_command(::std::string const& java_home)
{
	return java_home + "/bin/java";
}

inline
::std::string make_java_command()
{
	char* java_path = ::std::getenv("JAVA_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	java_path = ::std::getenv("JRE_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	return ::std::string("java");
}

/**
 * \brief Build arguments to pass to RAIN workload toolkit.
 *
 * The basic structure of the RAIN command is:
 *

 *  java [<java-arg1> ... <java-argN>] \
 *       -cp "rain.jar:<path to workload JAR>" \
 *       radlab.rain.Benchmark <path to Rain JSON configuration file>
 *

 */
template <typename FwdIterT>
inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home,
											  FwdIterT arg_first,
											  FwdIterT arg_last)
{
	::std::vector< ::std::string > args(arg_first, arg_last);

	args.push_back("-cp");
	args.push_back(rain_home + "/rain.jar:" + rain_home + "/workloads/" + workload + ".jar");
	args.push_back("radlab.rain.Benchmark");
	args.push_back(rain_home + "/config/rain.config." + workload + ".json");

	return args;
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home)
{
	::std::vector< ::std::string > java_args;
	java_args.push_back("-Xmx1g");
	java_args.push_back("-Xms256m");

	return make_rain_args(workload, rain_home, java_args.begin(), java_args.end());
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload)
{
	return make_rain_args(workload, ".");
}

} // Namespace <unnamed>

void* monitor_rain_rampup(void* arg);

} // Namespace detail

class rain_workload_driver: public base_workload_driver
{
	private: typedef ::dcs::system::posix_process sys_process_type;
	private: typedef ::boost::shared_ptr<sys_process_type> sys_process_pointer;

	friend void* detail::monitor_rain_rampup(void*);

	public: enum workload_category
	{
		olio_workload
	};

	public: rain_workload_driver()
	: p_thread_(0),
	  p_mutex_(0)
	{
	}

	public: ~rain_workload_driver()
	{
		if (p_thread_)
		{
			::pthread_join(*p_thread_, 0);
		}
	}

	public: rain_workload_driver(workload_category wkl_cat)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat))),
	  ready_(false)
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home)),
	  ready_(false)
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home)),
	  ready_(false)
	{
	}

	public: template <typename FwdIterT>
			rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home,
								 FwdIterT arg_first,
								 FwdIterT arg_last)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home, arg_first, arg_last)),
	  ready_(false)
	{
	}

	private: static ::std::string to_string(workload_category wkl_cat)
	{
		switch (wkl_cat)
		{
			case olio_workload:
				return "olio";
		}

		DCS_EXCEPTION_THROW(::std::invalid_argument,
							"Unknown workload category");
	}

	private: void ready(bool val)
	{
		::pthread_mutex_lock(p_mutex_);
			ready_ = val;
		::pthread_mutex_unlock(p_mutex_);
	}

	private: sys_process_pointer process()
	{
		return p_proc_;
	}

	private: sys_process_pointer process() const
	{
		return p_proc_;
	}

	private: void do_start()
	{
		if (p_proc_ && p_proc_->alive())
		{
			p_proc_->terminate();
		}

		ready_ = false;
		p_proc_ = ::boost::make_shared<sys_process_type>(cmd_);

		p_proc_->asynch(true);
		p_proc_->run(args_.begin(), args_.end(), false, false, true);

		if (p_proc_->status() != ::dcs::system::running_process_status)
		{
		   DCS_EXCEPTION_THROW(::std::runtime_error,
							   "Unable to start RAIN workload driver");
		}

		//TODO: create a thread that monitor the output of the process
		::pthread_create(p_thread_, 0, &detail::monitor_rain_rampup, this);
	}

	private: void do_stop()
	{
		p_proc_->terminate();

		if (::pthread_join(*p_thread_, 0) != 0)
		{
			DCS_EXCEPTION_THROW(::std::runtime_error,
								"Unable to join thread");
		}
		p_thread_ = 0;
	}

	private: bool do_alive() const
	{
		return p_proc_->alive();
	}

	private: bool do_ready() const
	{
		return ready_;
	}

	private: ::std::string cmd_;
	private: ::std::vector< ::std::string > args_;
	private: sys_process_pointer p_proc_;
	private: bool ready_;
	private: ::pthread_t* p_thread_;
	private: ::pthread_mutex_t* p_mutex_;
}; // rain_workload_driver

namespace detail {

inline
void* monitor_rain_rampup(void* arg)
{
	rain_workload_driver* p_driver = static_cast<rain_workload_driver*>(arg);

	::std::istream& eis = p_driver->process()->error_stream();

	while (eis.good())
	{
		::std::string line;

		::std::getline(eis, line);

		// Look for "Ramp up finished!" string
		if (line.find("Ramp up finished") != ::std::string::npos)
		{
			p_driver->ready(true);
			break;
		}
	}

	return 0;
}

} // Namespace detail

}} // Namespace dcs::testbed

#endif // DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
<commit_msg>(change:major) * Process and thread are not stored as pointers * Added thread clean-up code.<commit_after>/**
 * \file dcs/testbed/rain_workload_driver.hpp
 *
 * \brief Workload driver based on the RAIN workload toolkit.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

 *
 * Copyright (C) 2012       Marco Guazzone
 *                          [Distributed Computing System (DCS) Group,
 *                           Computer Science Institute,
 *                           Department of Science and Technological Innovation,
 *                           University of Piemonte Orientale,
 *                           Alessandria (Italy)]
 *
 * This file is part of dcsxx-testbed.
 *
 * dcsxx-testbed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * dcsxx-testbed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with dcsxx-testbed. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
#define DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP

#include <boost/smart_ptr.hpp>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <dcs/exception.hpp>
#include <dcs/system/posix_process.hpp>
#include <dcs/system/process_status_category.hpp>
#include <dcs/testbed/base_workload_driver.hpp>
#include <istream>
extern "C" {
#include <pthread.h>
}
#include <string>
#include <vector>

namespace dcs { namespace testbed {

namespace detail {

namespace /*<unnamed>*/ {

inline
::std::string make_java_command(::std::string const& java_home)
{
	return java_home + "/bin/java";
}

inline
::std::string make_java_command()
{
	char* java_path = ::std::getenv("JAVA_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	java_path = ::std::getenv("JRE_HOME");
	if (java_path)
	{
		return make_java_command(::std::string(java_path));
	}

	return ::std::string("java");
}

/**
 * \brief Build arguments to pass to RAIN workload toolkit.
 *
 * The basic structure of the RAIN command is:
 *

 *  java [<java-arg1> ... <java-argN>] \
 *       -cp "rain.jar:<path to workload JAR>" \
 *       radlab.rain.Benchmark <path to Rain JSON configuration file>
 *

 */
template <typename FwdIterT>
inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home,
											  FwdIterT arg_first,
											  FwdIterT arg_last)
{
	::std::vector< ::std::string > args(arg_first, arg_last);

	args.push_back("-cp");
	args.push_back(rain_home + "/rain.jar:" + rain_home + "/workloads/" + workload + ".jar");
	args.push_back("radlab.rain.Benchmark");
	args.push_back(rain_home + "/config/rain.config." + workload + ".json");

	return args;
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload,
											  ::std::string const& rain_home)
{
	::std::vector< ::std::string > java_args;
	java_args.push_back("-Xmx1g");
	java_args.push_back("-Xms256m");

	return make_rain_args(workload, rain_home, java_args.begin(), java_args.end());
}

inline
::std::vector< ::std::string > make_rain_args(::std::string const& workload)
{
	return make_rain_args(workload, ".");
}

} // Namespace <unnamed>

void* monitor_rain_rampup(void* arg);

} // Namespace detail

class rain_workload_driver: public base_workload_driver
{
	private: typedef ::dcs::system::posix_process sys_process_type;
	private: typedef ::boost::shared_ptr<sys_process_type> sys_process_pointer;

	friend void* detail::monitor_rain_rampup(void*);

	public: enum workload_category
	{
		olio_workload
	};

	public: rain_workload_driver(workload_category wkl_cat)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat))),
	  ready_(false)
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home)
	: cmd_(detail::make_java_command()),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home)),
	  ready_(false)
	{
	}

	public: rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home)),
	  ready_(false)
	{
	}

	public: template <typename FwdIterT>
			rain_workload_driver(workload_category wkl_cat,
								 ::std::string const& rain_home,
								 ::std::string const& java_home,
								 FwdIterT arg_first,
								 FwdIterT arg_last)
	: cmd_(detail::make_java_command(java_home)),
	  args_(detail::make_rain_args(to_string(wkl_cat), rain_home, arg_first, arg_last)),
	  ready_(false)
	{
	}

	public: ~rain_workload_driver()
	{
		try
		{
			proc_.terminate();
		}
		catch (...)
		{
			// empty
		}
		::pthread_cancel(thread_);
		::pthread_join(thread_, 0);
	}

	private: static ::std::string to_string(workload_category wkl_cat)
	{
		switch (wkl_cat)
		{
			case olio_workload:
				return "olio";
		}

		DCS_EXCEPTION_THROW(::std::invalid_argument,
							"Unknown workload category");
	}

	private: void ready(bool val)
	{
		::pthread_mutex_lock(&mutex_);
			ready_ = val;
		::pthread_mutex_unlock(&mutex_);
	}

	private: sys_process_type process()
	{
		return proc_;
	}

	private: sys_process_type process() const
	{
		return proc_;
	}

	private: void do_start()
	{
		// Stop previously running process and thread (if any)
		if (proc_.alive())
		{
			proc_.terminate();
		}
		pthread_cancel(thread_);
		pthread_join(thread_, 0);

		// Run a new process
		ready_ = false;
		proc_ = sys_process_type(cmd_);
		proc_.asynch(true);
		proc_.run(args_.begin(), args_.end(), false, false, true);
		if (proc_.status() != ::dcs::system::running_process_status)
		{
			::std::ostringstream oss;
			oss << "Unable to start RAIN workload driver: " << ::strerror(errno);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}

		// Run a thread to monitor RAIN ramp-up (transient) phase
		if (::pthread_create(&thread_, 0, &detail::monitor_rain_rampup, this) != 0)
		{
			::std::ostringstream oss;
			oss << "Unable to start transient phase monitor thread for the RAIN workload driver: " << ::strerror(errno);

			DCS_EXCEPTION_THROW(::std::runtime_error,
								"Unable to start transient phase monitor thread for the RAIN workload driver");
		}
	}

	private: void do_stop()
	{
		proc_.terminate();

		if (::pthread_cancel(thread_) != 0)
		{
			::std::ostringstream oss;
			oss << "Unable to cancel transient phase monitor thread for the RAIN workload driver: " << ::strerror(errno);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}
		if (::pthread_join(thread_, 0) != 0)
		{
			::std::ostringstream oss;
			oss << "Unable to join transient phase monitor thread for the RAIN workload driver: " << ::strerror(errno);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}
	}

	private: bool do_alive() const
	{
		return proc_.alive();
	}

	private: bool do_ready() const
	{
		return ready_;
	}

	private: ::std::string cmd_;
	private: ::std::vector< ::std::string > args_;
	private: bool ready_;
	private: sys_process_type proc_;
	private: ::pthread_t thread_;
	private: ::pthread_mutex_t mutex_;
}; // rain_workload_driver

namespace detail {

inline
void* monitor_rain_rampup(void* arg)
{
	rain_workload_driver* p_driver = static_cast<rain_workload_driver*>(arg);

	::std::istream& eis = p_driver->process().error_stream();

	while (eis.good())
	{
		::std::string line;

		::std::getline(eis, line);

		// Look for "Ramp up finished!" string
		if (line.find("Ramp up finished") != ::std::string::npos)
		{
			p_driver->ready(true);
			break;
		}
	}

	return 0;
}

} // Namespace detail

}} // Namespace dcs::testbed

#endif // DCS_TESTBED_RAIN_WORKLOAD_DRIVER_HPP
<|endoftext|>


<commit_before>#include "drawRule.h"

#include "tile/tile.h"
#include "scene/scene.h"
#include "scene/sceneLayer.h"
#include "scene/stops.h"
#include "scene/styleContext.h"
#include "style/style.h"
#include "platform.h"

#include <algorithm>

namespace Tangram {

DrawRuleData::DrawRuleData(std::string _name, int _id,
                               const std::vector<StyleParam>& _parameters) :
    parameters(_parameters),
    name(std::move(_name)),
    id(_id) {}

std::string DrawRuleData::toString() const {
    std::string str = "{\n";
    for (auto& p : parameters) {
         str += " { "
             + std::to_string(static_cast<int>(p.key))
             + ", "
             + p.toString()
             + " }\n";
    }
    str += "}\n";

    return str;
}

DrawRule::DrawRule(const DrawRuleData& _ruleData) :
    name(&_ruleData.name),
    id(_ruleData.id) {}

void DrawRule::merge(const DrawRuleData& _ruleData, const SceneLayer& _layer) {

    for (const auto& param : _ruleData.parameters) {

        auto key = static_cast<uint8_t>(param.key);

        const auto depthOld = depths[key];
        const auto depthNew = _layer.depth();
        const char* layerOld = layers[key];
        const char* layerNew = _layer.name().c_str();

        if (depthNew > depthOld || (depthNew == depthOld && strcmp(layerNew, layerOld) > 0)) {
            params[key] = &param;
            depths[key] = depthNew;
            layers[key] = layerNew;
        }

    }

}

bool DrawRule::isJSFunction(StyleParamKey _key) const {
    auto& param = findParameter(_key);
    if (!param) {
        return false;
    }
    return param.function >= 0;
}

bool DrawRule::contains(StyleParamKey _key) const {
    return findParameter(_key) != false;
}

const StyleParam& DrawRule::findParameter(StyleParamKey _key) const {
    static const StyleParam NONE;

    const auto* p = params[static_cast<uint8_t>(_key)];
    if (p) {
        return *p;
    }

    return NONE;
}

const std::string& DrawRule::getStyleName() const {

    const auto& style = findParameter(StyleParamKey::style);

    if (style) {
        return style.value.get<std::string>();
    } else {
        return *name;
    }
}

void DrawRule::logGetError(StyleParamKey _expectedKey, const StyleParam& _param) const {
    LOGE("wrong type '%d'for StyleParam '%d'", _param.value.which(), _expectedKey);
}

bool DrawRuleMergeSet::match(const Feature& _feature, const SceneLayer& _layer, StyleContext& _ctx) {

    _ctx.setFeature(_feature);
    matchedRules.clear();
    queuedLayers.clear();

    // If the first filter doesn't match, return immediately
    if (!_layer.filter().eval(_feature, _ctx)) { return false; }

    // Add the first layer to the stack
    queuedLayers.push_back(&_layer);

    // Iterate depth-first over the layer hierarchy
    while (!queuedLayers.empty()) {

        // Pop a layer off the top of the stack
        const auto& layer = *queuedLayers.back();
        queuedLayers.pop_back();

        // If the filter doesn't pass, move on to the next one
        if (!layer.filter().eval(_feature, _ctx)) { continue; }

        // Push each of the layer's sublayers onto the stack
        for (const auto& sublayer : layer.sublayers()) {
            queuedLayers.push_back(&sublayer);
        }

        // Merge rules from current layer into accumulated set
        mergeRules(layer);
    }
    return true;
}

void DrawRuleMergeSet::apply(const Feature& _feature, const Scene& _scene, const SceneLayer& _layer,
                    StyleContext& _ctx, Tile& _tile) {

    // If no rules matched the feature, return immediately
    if (!match(_feature, _layer, _ctx)) { return; }

    // For each matched rule, find the style to be used and build the feature with the rule's parameters
    for (auto& rule : matchedRules) {

        auto* style = _scene.findStyle(rule.getStyleName());

        if (!style) {
            LOGE("Invalid style %s", rule.getStyleName().c_str());
            continue;
        }

        // Evaluate JS functions and Stops
        bool valid = true;
        for (size_t i = 0; i < StyleParamKeySize; ++i) {

            auto* param = rule.params[i];
            if (!param) { continue; }

            if (param->function >= 0) {

                if (!_ctx.evalStyle(param->function, param->key, evaluated[i].value) && StyleParam::isRequired(param->key)) {
                    valid = false;
                    break;
                }

                evaluated[i].function = param->function;
                rule.params[i] = &evaluated[i];

            }
            if (param->stops) {

                evaluated[i].stops = param->stops;

                if (StyleParam::isColor(param->key)) {
                    evaluated[i].value = param->stops->evalColor(_ctx.getGlobalZoom());
                } else if (StyleParam::isWidth(param->key)) {
                    // FIXME width result is ignored from here
                    evaluated[i].value = param->stops->evalWidth(_ctx.getGlobalZoom());
                } else {
                    evaluated[i].value = param->stops->evalFloat(_ctx.getGlobalZoom());
                }

                rule.params[i] = &evaluated[i];

            }

        }

        if (valid) {
            style->buildFeature(_tile, _feature, rule);
        }
    }
}

void DrawRuleMergeSet::mergeRules(const SceneLayer& _layer) {

    for (const auto& rule : _layer.rules()) {

        auto it = std::find_if(matchedRules.begin(), matchedRules.end(),
                               [&](auto& m) { return rule.id == m.id; });

        if (it == matchedRules.end()) {
            it = matchedRules.insert(it, DrawRule(rule));
        }

        it->merge(rule, _layer);
    }

}

}
<commit_msg>Prevent potentially passing a null pointer to strcmp<commit_after>#include "drawRule.h"

#include "tile/tile.h"
#include "scene/scene.h"
#include "scene/sceneLayer.h"
#include "scene/stops.h"
#include "scene/styleContext.h"
#include "style/style.h"
#include "platform.h"

#include <algorithm>

namespace Tangram {

DrawRuleData::DrawRuleData(std::string _name, int _id,
                               const std::vector<StyleParam>& _parameters) :
    parameters(_parameters),
    name(std::move(_name)),
    id(_id) {}

std::string DrawRuleData::toString() const {
    std::string str = "{\n";
    for (auto& p : parameters) {
         str += " { "
             + std::to_string(static_cast<int>(p.key))
             + ", "
             + p.toString()
             + " }\n";
    }
    str += "}\n";

    return str;
}

DrawRule::DrawRule(const DrawRuleData& _ruleData) :
    name(&_ruleData.name),
    id(_ruleData.id) {

    const static char* empty = "";
    std::fill_n(layers, StyleParamKeySize, empty);

}

void DrawRule::merge(const DrawRuleData& _ruleData, const SceneLayer& _layer) {

    for (const auto& param : _ruleData.parameters) {

        auto key = static_cast<uint8_t>(param.key);

        const auto depthOld = depths[key];
        const auto depthNew = _layer.depth();
        const char* layerOld = layers[key];
        const char* layerNew = _layer.name().c_str();

        if (depthNew > depthOld || (depthNew == depthOld && strcmp(layerNew, layerOld) > 0)) {
            params[key] = &param;
            depths[key] = depthNew;
            layers[key] = layerNew;
        }

    }

}

bool DrawRule::isJSFunction(StyleParamKey _key) const {
    auto& param = findParameter(_key);
    if (!param) {
        return false;
    }
    return param.function >= 0;
}

bool DrawRule::contains(StyleParamKey _key) const {
    return findParameter(_key) != false;
}

const StyleParam& DrawRule::findParameter(StyleParamKey _key) const {
    static const StyleParam NONE;

    const auto* p = params[static_cast<uint8_t>(_key)];
    if (p) {
        return *p;
    }

    return NONE;
}

const std::string& DrawRule::getStyleName() const {

    const auto& style = findParameter(StyleParamKey::style);

    if (style) {
        return style.value.get<std::string>();
    } else {
        return *name;
    }
}

void DrawRule::logGetError(StyleParamKey _expectedKey, const StyleParam& _param) const {
    LOGE("wrong type '%d'for StyleParam '%d'", _param.value.which(), _expectedKey);
}

bool DrawRuleMergeSet::match(const Feature& _feature, const SceneLayer& _layer, StyleContext& _ctx) {

    _ctx.setFeature(_feature);
    matchedRules.clear();
    queuedLayers.clear();

    // If the first filter doesn't match, return immediately
    if (!_layer.filter().eval(_feature, _ctx)) { return false; }

    // Add the first layer to the stack
    queuedLayers.push_back(&_layer);

    // Iterate depth-first over the layer hierarchy
    while (!queuedLayers.empty()) {

        // Pop a layer off the top of the stack
        const auto& layer = *queuedLayers.back();
        queuedLayers.pop_back();

        // If the filter doesn't pass, move on to the next one
        if (!layer.filter().eval(_feature, _ctx)) { continue; }

        // Push each of the layer's sublayers onto the stack
        for (const auto& sublayer : layer.sublayers()) {
            queuedLayers.push_back(&sublayer);
        }

        // Merge rules from current layer into accumulated set
        mergeRules(layer);
    }
    return true;
}

void DrawRuleMergeSet::apply(const Feature& _feature, const Scene& _scene, const SceneLayer& _layer,
                    StyleContext& _ctx, Tile& _tile) {

    // If no rules matched the feature, return immediately
    if (!match(_feature, _layer, _ctx)) { return; }

    // For each matched rule, find the style to be used and build the feature with the rule's parameters
    for (auto& rule : matchedRules) {

        auto* style = _scene.findStyle(rule.getStyleName());

        if (!style) {
            LOGE("Invalid style %s", rule.getStyleName().c_str());
            continue;
        }

        // Evaluate JS functions and Stops
        bool valid = true;
        for (size_t i = 0; i < StyleParamKeySize; ++i) {

            auto* param = rule.params[i];
            if (!param) { continue; }

            if (param->function >= 0) {

                if (!_ctx.evalStyle(param->function, param->key, evaluated[i].value) && StyleParam::isRequired(param->key)) {
                    valid = false;
                    break;
                }

                evaluated[i].function = param->function;
                rule.params[i] = &evaluated[i];

            }
            if (param->stops) {

                evaluated[i].stops = param->stops;

                if (StyleParam::isColor(param->key)) {
                    evaluated[i].value = param->stops->evalColor(_ctx.getGlobalZoom());
                } else if (StyleParam::isWidth(param->key)) {
                    // FIXME width result is ignored from here
                    evaluated[i].value = param->stops->evalWidth(_ctx.getGlobalZoom());
                } else {
                    evaluated[i].value = param->stops->evalFloat(_ctx.getGlobalZoom());
                }

                rule.params[i] = &evaluated[i];

            }

        }

        if (valid) {
            style->buildFeature(_tile, _feature, rule);
        }
    }
}

void DrawRuleMergeSet::mergeRules(const SceneLayer& _layer) {

    for (const auto& rule : _layer.rules()) {

        auto it = std::find_if(matchedRules.begin(), matchedRules.end(),
                               [&](auto& m) { return rule.id == m.id; });

        if (it == matchedRules.end()) {
            it = matchedRules.insert(it, DrawRule(rule));
        }

        it->merge(rule, _layer);
    }

}

}
<|endoftext|>


<commit_before>#include <string>
#include "PointerSubgraphValidator.h"

namespace dg {
namespace analysis {
namespace pta {
namespace debug {

static void dumpNode(const PSNode *nd, std::string& errors) {
  errors +=  std::string(PSNodeTypeToCString(nd->getType())) + " with ID " +
             std::to_string(nd->getID()) + "\n  - operands: [";
    for (unsigned i = 0, e =  nd->getOperandsNum(); i < e; ++i) {
        const PSNode *op = nd->getOperand(i);
        errors += std::to_string(op->getID()) += " ";
        errors += std::string(PSNodeTypeToCString(op->getType()));
        if (i != e - 1)
            errors += ", ";
    }
    errors += "]\n";
}

bool PointerSubgraphValidator::reportInvalOperands(const PSNode *nd, const std::string& user_err) {
    errors += "Invalid operands:\n";
    dumpNode(nd, errors);

    if (!user_err.empty())
        errors += "(" + user_err + ")\n";

    return true;
}

bool PointerSubgraphValidator::reportInvalEdges(const PSNode *nd, const std::string& user_err) {
    errors += "Invalid number of edges:\n";
    dumpNode(nd, errors);

    if (!user_err.empty())
        errors += "(" + user_err + ")\n";
    return true;
}

bool PointerSubgraphValidator::reportInvalNode(const PSNode *nd, const std::string& user_err) {
    errors += "Invalid node:\n";
    dumpNode(nd, errors);
    if (!user_err.empty())
        errors += "(" + user_err + ")\n";
    return true;
}

bool PointerSubgraphValidator::reportUnreachableNode(const PSNode *nd) {
    errors += "Unreachable node:\n";
    dumpNode(nd, errors);
    return true;
}

static bool hasDuplicateOperand(const PSNode *nd)
{
    std::set<const PSNode *> ops;
    for (const PSNode *op : nd->getOperands()) {
        if (!ops.insert(op).second)
            return true;
    }

    return false;
}

bool PointerSubgraphValidator::checkOperands() {
    bool invalid = false;

    std::set<const PSNode *> known_nodes;
    const auto& nodes = PS->getNodes();

    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        if (!known_nodes.insert(nd).second)
            invalid |= reportInvalNode(nd, "Node multiple times in the graph");
    }

    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        for (const PSNode *op : nd->getOperands()) {
            if (op != NULLPTR && op != UNKNOWN_MEMORY && op != INVALIDATED &&
                known_nodes.count(op) == 0) {
                invalid |= reportInvalOperands(nd, "Node has unknown (maybe dangling) operand");
            }
        }

        switch (nd->getType()) {
            case PSNodeType::PHI:
                if (nd->getOperandsNum() == 0) {
                    invalid |= reportInvalOperands(nd, "Empty PHI");
                } else if (hasDuplicateOperand(nd)) {
                    invalid |= reportInvalOperands(nd, "PHI Node contains duplicated operand");
                }
                break;
            case PSNodeType::NULL_ADDR:
            case PSNodeType::UNKNOWN_MEM:
            case PSNodeType::NOOP:
            case PSNodeType::FUNCTION:
                if (nd->getOperandsNum() != 0) {
                    invalid |= reportInvalOperands(nd, "Should not have an operand");
                }
                break;
            case PSNodeType::GEP:
            case PSNodeType::LOAD:
            case PSNodeType::CAST:
            case PSNodeType::INVALIDATE_OBJECT:
            case PSNodeType::CONSTANT:
            case PSNodeType::FREE:
                if (nd->getOperandsNum() != 1) {
                    invalid |= reportInvalOperands(nd, "Should have exactly one operand");
                }
                break;
            case PSNodeType::STORE:
            case PSNodeType::MEMCPY:
                if (nd->getOperandsNum() != 2) {
                    invalid |= reportInvalOperands(nd, "Should have exactly two operands");
                }
                break;
        }
    }

    return invalid;
}

static inline bool isInPredecessors(const PSNode *nd, const PSNode *of) {
    for (const PSNode *pred: of->getPredecessors()) {
        if (pred == nd)
            return true;
    }

    return false;
}

static inline bool canBeOutsideGraph(const PSNode *nd) {
    return (nd->getType() == PSNodeType::FUNCTION ||
            nd->getType() == PSNodeType::CONSTANT ||
            nd->getType() == PSNodeType::UNKNOWN_MEM ||
            nd->getType() == PSNodeType::NULL_ADDR);
}

std::set<const PSNode *> reachableNodes(const PSNode *nd) {
    std::set<const PSNode *> reachable;
    reachable.insert(nd);

    std::vector<const PSNode *> to_process;
    to_process.reserve(4);
    to_process.push_back(nd);

    while (!to_process.empty()) {
        std::vector<const PSNode *> new_to_process;
        new_to_process.reserve(to_process.size());

        for (const PSNode *cur : to_process) {
            for (const PSNode *succ : cur->getSuccessors()) {
                if (reachable.insert(succ).second)
                    new_to_process.push_back(succ);
            }
        }

        new_to_process.swap(to_process);
    }

    return reachable;
}

bool PointerSubgraphValidator::checkEdges() {
    bool invalid = false;

    // check incoming/outcoming edges of all nodes
    auto nodes = PS->getNodes();
    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        if (nd->predecessorsNum() == 0 && nd != PS->getRoot() && !canBeOutsideGraph(nd)) {
            invalid |= reportInvalEdges(nd, "Non-root node has no predecessors");
        }

        for (const PSNode *succ : nd->getSuccessors()) {
            if (!isInPredecessors(nd, succ))
                invalid |= reportInvalEdges(nd, "Node not set as a predecessor of some of its successors");
        }
    }

    // check that the edges form valid CFG (all nodes are reachable)
    auto reachable = reachableNodes(PS->getRoot());
    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        if (reachable.count(nd) < 1 && !canBeOutsideGraph(nd)) {
                invalid |= reportUnreachableNode(nd);
        }
    }

    return invalid;
}

bool PointerSubgraphValidator::validate() {
    bool invalid = false;

    invalid |= checkOperands();
    invalid |= checkEdges();

    return invalid;
}

} // namespace debug
} // namespace pta
} // namespace analysis
} // namespace dg

<commit_msg>PTA validator: check the type of operands<commit_after>#include <string>
#include "PointerSubgraphValidator.h"

namespace dg {
namespace analysis {
namespace pta {
namespace debug {

static void dumpNode(const PSNode *nd, std::string& errors) {
  errors +=  std::string(PSNodeTypeToCString(nd->getType())) + " with ID " +
             std::to_string(nd->getID()) + "\n  - operands: [";
    for (unsigned i = 0, e =  nd->getOperandsNum(); i < e; ++i) {
        const PSNode *op = nd->getOperand(i);
        errors += std::to_string(op->getID()) += " ";
        errors += std::string(PSNodeTypeToCString(op->getType()));
        if (i != e - 1)
            errors += ", ";
    }
    errors += "]\n";
}

bool PointerSubgraphValidator::reportInvalOperands(const PSNode *nd, const std::string& user_err) {
    errors += "Invalid operands:\n";
    dumpNode(nd, errors);

    if (!user_err.empty())
        errors += "(" + user_err + ")\n";

    return true;
}

bool PointerSubgraphValidator::reportInvalEdges(const PSNode *nd, const std::string& user_err) {
    errors += "Invalid number of edges:\n";
    dumpNode(nd, errors);

    if (!user_err.empty())
        errors += "(" + user_err + ")\n";
    return true;
}

bool PointerSubgraphValidator::reportInvalNode(const PSNode *nd, const std::string& user_err) {
    errors += "Invalid node:\n";
    dumpNode(nd, errors);
    if (!user_err.empty())
        errors += "(" + user_err + ")\n";
    return true;
}

bool PointerSubgraphValidator::reportUnreachableNode(const PSNode *nd) {
    errors += "Unreachable node:\n";
    dumpNode(nd, errors);
    return true;
}

static bool hasDuplicateOperand(const PSNode *nd)
{
    std::set<const PSNode *> ops;
    for (const PSNode *op : nd->getOperands()) {
        if (!ops.insert(op).second)
            return true;
    }

    return false;
}

static bool hasNonpointerOperand(const PSNode *nd)
{
    for (const PSNode *op : nd->getOperands()) {
        if (op->getType() == PSNodeType::NOOP ||
            op->getType() == PSNodeType::FREE ||
            op->getType() == PSNodeType::ENTRY ||
            op->getType() == PSNodeType::INVALIDATE_LOCALS ||
            op->getType() == PSNodeType::INVALIDATE_OBJECT ||
            op->getType() == PSNodeType::MEMCPY ||
            op->getType() == PSNodeType::STORE)
            return true;
    }

    return false;
}

bool PointerSubgraphValidator::checkOperands() {
    bool invalid = false;

    std::set<const PSNode *> known_nodes;
    const auto& nodes = PS->getNodes();

    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        if (!known_nodes.insert(nd).second)
            invalid |= reportInvalNode(nd, "Node multiple times in the graph");
    }

    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        for (const PSNode *op : nd->getOperands()) {
            if (op != NULLPTR && op != UNKNOWN_MEMORY && op != INVALIDATED &&
                known_nodes.count(op) == 0) {
                invalid |= reportInvalOperands(nd, "Node has unknown (maybe dangling) operand");
            }
        }

        switch (nd->getType()) {
            case PSNodeType::PHI:
                if (nd->getOperandsNum() == 0) {
                    invalid |= reportInvalOperands(nd, "Empty PHI");
                } else if (hasDuplicateOperand(nd)) {
                    invalid |= reportInvalOperands(nd, "PHI Node contains duplicated operand");
                } else if (hasNonpointerOperand(nd)) {
                    invalid |= reportInvalOperands(nd, "PHI Node contains non-pointer operand");
                }
                break;
            case PSNodeType::NULL_ADDR:
            case PSNodeType::UNKNOWN_MEM:
            case PSNodeType::NOOP:
            case PSNodeType::FUNCTION:
                if (nd->getOperandsNum() != 0) {
                    invalid |= reportInvalOperands(nd, "Should not have an operand");
                }
                break;
            case PSNodeType::GEP:
            case PSNodeType::LOAD:
            case PSNodeType::CAST:
            case PSNodeType::INVALIDATE_OBJECT:
            case PSNodeType::CONSTANT:
            case PSNodeType::FREE:
                if (hasNonpointerOperand(nd)) {
                    invalid |= reportInvalOperands(nd, "Node has non-pointer operand");
                }
                if (nd->getOperandsNum() != 1) {
                    invalid |= reportInvalOperands(nd, "Should have exactly one operand");
                }
                break;
            case PSNodeType::STORE:
            case PSNodeType::MEMCPY:
                if (hasNonpointerOperand(nd)) {
                    invalid |= reportInvalOperands(nd, "Node has non-pointer operand");
                }
                if (nd->getOperandsNum() != 2) {
                    invalid |= reportInvalOperands(nd, "Should have exactly two operands");
                }
                break;
        }
    }

    return invalid;
}

static inline bool isInPredecessors(const PSNode *nd, const PSNode *of) {
    for (const PSNode *pred: of->getPredecessors()) {
        if (pred == nd)
            return true;
    }

    return false;
}

static inline bool canBeOutsideGraph(const PSNode *nd) {
    return (nd->getType() == PSNodeType::FUNCTION ||
            nd->getType() == PSNodeType::CONSTANT ||
            nd->getType() == PSNodeType::UNKNOWN_MEM ||
            nd->getType() == PSNodeType::NULL_ADDR);
}

std::set<const PSNode *> reachableNodes(const PSNode *nd) {
    std::set<const PSNode *> reachable;
    reachable.insert(nd);

    std::vector<const PSNode *> to_process;
    to_process.reserve(4);
    to_process.push_back(nd);

    while (!to_process.empty()) {
        std::vector<const PSNode *> new_to_process;
        new_to_process.reserve(to_process.size());

        for (const PSNode *cur : to_process) {
            for (const PSNode *succ : cur->getSuccessors()) {
                if (reachable.insert(succ).second)
                    new_to_process.push_back(succ);
            }
        }

        new_to_process.swap(to_process);
    }

    return reachable;
}

bool PointerSubgraphValidator::checkEdges() {
    bool invalid = false;

    // check incoming/outcoming edges of all nodes
    auto nodes = PS->getNodes();
    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        if (nd->predecessorsNum() == 0 && nd != PS->getRoot() && !canBeOutsideGraph(nd)) {
            invalid |= reportInvalEdges(nd, "Non-root node has no predecessors");
        }

        for (const PSNode *succ : nd->getSuccessors()) {
            if (!isInPredecessors(nd, succ))
                invalid |= reportInvalEdges(nd, "Node not set as a predecessor of some of its successors");
        }
    }

    // check that the edges form valid CFG (all nodes are reachable)
    auto reachable = reachableNodes(PS->getRoot());
    for (const PSNode *nd : nodes) {
        if (!nd)
            continue;

        if (reachable.count(nd) < 1 && !canBeOutsideGraph(nd)) {
                invalid |= reportUnreachableNode(nd);
        }
    }

    return invalid;
}

bool PointerSubgraphValidator::validate() {
    bool invalid = false;

    invalid |= checkOperands();
    invalid |= checkEdges();

    return invalid;
}

} // namespace debug
} // namespace pta
} // namespace analysis
} // namespace dg

<|endoftext|>


<commit_before>/***************************************************************************
 *  @file       main.cpp
 *  @author     Alan.W
 *  @date       07  JAN 2014
 *  @remark
 ***************************************************************************/
//!
//! Exercise 13.47:
//! Give the copy constructor and copy-assignment operator in your String class
//! from exercise 13.44 in § 13.5 (p. 531) a statement that prints a message
//! each time the function is executed.
//!
//! Exercise 13.48:
//! Define a vector<String> and call push_back several times on that vector.
//! Run your program and see how often Strings are copied.
//  times = 2i;///////error
//!
#include "string.h"
#include <vector>

int main()
{
    std::vector<String> v;

    String s("sssssss");

    for (unsigned i = 0; i != 3; ++i)
        v.push_back(s);

    return 0;
}
<commit_msg>update the ans to 13.48<commit_after>/***************************************************************************
 *  @file       main.cpp
 *  @author     Alan.W
 *  @date       07  JAN 2014
 *  @remark
 ***************************************************************************/
//!
//! Exercise 13.47:
//! Give the copy constructor and copy-assignment operator in your String class
//! from exercise 13.44 in § 13.5 (p. 531) a statement that prints a message
//! each time the function is executed.
//!
//! Exercise 13.48:
//! Define a vector<String> and call push_back several times on that vector.
//! Run your program and see how often Strings are copied.
//  Since no "move" members implemented, anytime when size() is equal to capacity(),
//  std::vector<T> performs reallocation by calling String's copy constructor.
//  In a word, it depends on the state of std::vector<String>.
//!
#include "string.h"
#include <vector>

int main()
{
    std::vector<String> v;

    String s("sssssss");

    for (unsigned i = 0; i != 3; ++i)
        v.push_back(s);

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>icoverity#705451: comparison of array against NULL<commit_after><|endoftext|>


<commit_before><commit_msg>coverity#735386 Copy-paste error<commit_after><|endoftext|>


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

#pragma hdrstop

#include "drawdoc.hxx"
#include "unoaprms.hxx"
#include "anminfo.hxx"

TYPEINIT1(SdAnimationPrmsUndoAction, SdUndoAction);

/*************************************************************************
|*
|* 2. Ctor, der den ersten (inline) nach der Version 4.0 einmal ersetzen
|* soll (mit 3. Parameter dann)
|* Hier werden die Member mit den Animations-Informationen vorbelegt,
|* um nicht immer alle inline-Methoden aufrufen zu muessen, auch im
|* Hinblick auf zukuenftige Erweiterungen (neue Member etc.)
|*
\************************************************************************/

SdAnimationPrmsUndoAction::SdAnimationPrmsUndoAction(
                                SdDrawDocument* pTheDoc,
                                SdrObject* pObj ) :
    SdUndoAction    ( pTheDoc ),
    pObject         ( pObj ),
    bInfoCreated    ( FALSE ) // Fuer Animationsreihenfolge existiert Info
{
    SdAnimationInfo* pInfo = pTheDoc->GetAnimationInfo( pObject );
    if( pInfo )
    {
        bNewActive      = bOldActive     = pInfo->bActive;
        eNewEffect      = eOldEffect     = pInfo->eEffect;
        eNewTextEffect  = eOldTextEffect = pInfo->eTextEffect;
        eNewSpeed       = eOldSpeed      = pInfo->eSpeed;
        bNewDimPrevious = bOldDimPrevious= pInfo->bDimPrevious;
        aNewDimColor    = aOldDimColor   = pInfo->aDimColor;
        bNewDimHide     = bOldDimHide    = pInfo->bDimHide;
        bNewSoundOn     = bOldSoundOn    = pInfo->bSoundOn;
        aNewSoundFile   = aOldSoundFile  = pInfo->aSoundFile;
        bNewPlayFull    = bOldPlayFull   = pInfo->bPlayFull;

        pNewPathObj     = pOldPathObj    = pInfo->pPathObj;

        eNewClickAction     = eOldClickAction    = pInfo->eClickAction;
        aNewBookmark        = aOldBookmark       = pInfo->aBookmark;
//      bNewInvisibleInPres = bOldInvisibleInPres= pInfo->bInvisibleInPresentation;
        nNewVerb            = nOldVerb           = pInfo->nVerb;
        nNewPresOrder       = nOldPresOrder      = pInfo->nPresOrder;

        eNewSecondEffect    = eOldSecondEffect   = pInfo->eSecondEffect;
        eNewSecondSpeed     = eOldSecondSpeed    = pInfo->eSecondSpeed;
        bNewSecondSoundOn   = bOldSecondSoundOn  = pInfo->bSecondSoundOn;
        bNewSecondPlayFull  = bOldSecondPlayFull = pInfo->bSecondPlayFull;
    }
}

/*************************************************************************
|*
|* Undo()
|*
\************************************************************************/

void SdAnimationPrmsUndoAction::Undo()
{
    // keine neu Info erzeugt: Daten restaurieren
    if (!bInfoCreated)
    {
        SdDrawDocument* pDoc   = (SdDrawDocument*)pObject->GetModel();
        if( pDoc )
        {
            SdAnimationInfo* pInfo = pDoc->GetAnimationInfo( pObject );
            // So nicht...
            //SdAnimationInfo* pInfo = (SdAnimationInfo*)pObject->GetUserData(0);
            pInfo->bActive      = bOldActive;
            pInfo->eEffect      = eOldEffect;
            pInfo->eTextEffect  = eOldTextEffect;
            pInfo->eSpeed       = eOldSpeed;
            pInfo->bDimPrevious = bOldDimPrevious;
            pInfo->aDimColor    = aOldDimColor;
            pInfo->bDimHide     = bOldDimHide;
            pInfo->bSoundOn     = bOldSoundOn;
            pInfo->aSoundFile   = aOldSoundFile;
            pInfo->bPlayFull    = bOldPlayFull;
//          pInfo->SetPath(pOldPathObj);
            pInfo->eClickAction = eOldClickAction;
            pInfo->aBookmark    = aOldBookmark;
//          pInfo->bInvisibleInPresentation = bOldInvisibleInPres;
            pInfo->nVerb        = nOldVerb;
            pInfo->nPresOrder   = nOldPresOrder;

            pInfo->eSecondEffect    = eOldSecondEffect;
            pInfo->eSecondSpeed     = eOldSecondSpeed;
            pInfo->bSecondSoundOn   = bOldSecondSoundOn;
            pInfo->bSecondPlayFull  = bOldSecondPlayFull;
        }
    }
    // Info wurde durch Aktion erzeugt: Info loeschen
    else
    {
        pObject->DeleteUserData(0);
    }
    // Damit ein ModelHasChanged() ausgeloest wird, um das Effekte-Window
    // auf Stand zu bringen (Animations-Reihenfolge)
    pObject->SetChanged();
    pObject->BroadcastObjectChange();
}

/*************************************************************************
|*
|* Redo()
|*
\************************************************************************/

void SdAnimationPrmsUndoAction::Redo()
{
    SdAnimationInfo* pInfo = NULL;

    pInfo = SdDrawDocument::GetShapeUserData(*pObject,true);

    pInfo->bActive      = bNewActive;
    pInfo->eEffect      = eNewEffect;
    pInfo->eTextEffect  = eNewTextEffect;
    pInfo->eSpeed       = eNewSpeed;
    pInfo->bDimPrevious = bNewDimPrevious;
    pInfo->aDimColor    = aNewDimColor;
    pInfo->bDimHide     = bNewDimHide;
    pInfo->bSoundOn     = bNewSoundOn;
    pInfo->aSoundFile   = aNewSoundFile;
    pInfo->bPlayFull    = bNewPlayFull;
//  pInfo->SetPath(pNewPathObj);
    pInfo->eClickAction = eNewClickAction;
    pInfo->aBookmark    = aNewBookmark;
//  pInfo->bInvisibleInPresentation = bNewInvisibleInPres;
    pInfo->nVerb        = nNewVerb;
    pInfo->nPresOrder   = nNewPresOrder;

    pInfo->eSecondEffect    = eNewSecondEffect;
    pInfo->eSecondSpeed     = eNewSecondSpeed;
    pInfo->bSecondSoundOn   = bNewSecondSoundOn;
    pInfo->bSecondPlayFull  = bNewSecondPlayFull;

    // Damit ein ModelHasChanged() ausgeloest wird, um das Effekte-Window
    // auf Stand zu bringen (Animations-Reihenfolge)
    pObject->SetChanged();
    pObject->BroadcastObjectChange();
}

/*************************************************************************
|*
|* Repeat()
|*
\************************************************************************/

void SdAnimationPrmsUndoAction::Repeat()
{
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

SdAnimationPrmsUndoAction::~SdAnimationPrmsUndoAction()
{
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.7.200); FILE MERGED 2006/09/01 17:37:13 kaib 1.7.200.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unoaprms.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 19:00:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "drawdoc.hxx"
#include "unoaprms.hxx"
#include "anminfo.hxx"

TYPEINIT1(SdAnimationPrmsUndoAction, SdUndoAction);

/*************************************************************************
|*
|* 2. Ctor, der den ersten (inline) nach der Version 4.0 einmal ersetzen
|* soll (mit 3. Parameter dann)
|* Hier werden die Member mit den Animations-Informationen vorbelegt,
|* um nicht immer alle inline-Methoden aufrufen zu muessen, auch im
|* Hinblick auf zukuenftige Erweiterungen (neue Member etc.)
|*
\************************************************************************/

SdAnimationPrmsUndoAction::SdAnimationPrmsUndoAction(
                                SdDrawDocument* pTheDoc,
                                SdrObject* pObj ) :
    SdUndoAction    ( pTheDoc ),
    pObject         ( pObj ),
    bInfoCreated    ( FALSE ) // Fuer Animationsreihenfolge existiert Info
{
    SdAnimationInfo* pInfo = pTheDoc->GetAnimationInfo( pObject );
    if( pInfo )
    {
        bNewActive      = bOldActive     = pInfo->bActive;
        eNewEffect      = eOldEffect     = pInfo->eEffect;
        eNewTextEffect  = eOldTextEffect = pInfo->eTextEffect;
        eNewSpeed       = eOldSpeed      = pInfo->eSpeed;
        bNewDimPrevious = bOldDimPrevious= pInfo->bDimPrevious;
        aNewDimColor    = aOldDimColor   = pInfo->aDimColor;
        bNewDimHide     = bOldDimHide    = pInfo->bDimHide;
        bNewSoundOn     = bOldSoundOn    = pInfo->bSoundOn;
        aNewSoundFile   = aOldSoundFile  = pInfo->aSoundFile;
        bNewPlayFull    = bOldPlayFull   = pInfo->bPlayFull;

        pNewPathObj     = pOldPathObj    = pInfo->pPathObj;

        eNewClickAction     = eOldClickAction    = pInfo->eClickAction;
        aNewBookmark        = aOldBookmark       = pInfo->aBookmark;
//      bNewInvisibleInPres = bOldInvisibleInPres= pInfo->bInvisibleInPresentation;
        nNewVerb            = nOldVerb           = pInfo->nVerb;
        nNewPresOrder       = nOldPresOrder      = pInfo->nPresOrder;

        eNewSecondEffect    = eOldSecondEffect   = pInfo->eSecondEffect;
        eNewSecondSpeed     = eOldSecondSpeed    = pInfo->eSecondSpeed;
        bNewSecondSoundOn   = bOldSecondSoundOn  = pInfo->bSecondSoundOn;
        bNewSecondPlayFull  = bOldSecondPlayFull = pInfo->bSecondPlayFull;
    }
}

/*************************************************************************
|*
|* Undo()
|*
\************************************************************************/

void SdAnimationPrmsUndoAction::Undo()
{
    // keine neu Info erzeugt: Daten restaurieren
    if (!bInfoCreated)
    {
        SdDrawDocument* pDoc   = (SdDrawDocument*)pObject->GetModel();
        if( pDoc )
        {
            SdAnimationInfo* pInfo = pDoc->GetAnimationInfo( pObject );
            // So nicht...
            //SdAnimationInfo* pInfo = (SdAnimationInfo*)pObject->GetUserData(0);
            pInfo->bActive      = bOldActive;
            pInfo->eEffect      = eOldEffect;
            pInfo->eTextEffect  = eOldTextEffect;
            pInfo->eSpeed       = eOldSpeed;
            pInfo->bDimPrevious = bOldDimPrevious;
            pInfo->aDimColor    = aOldDimColor;
            pInfo->bDimHide     = bOldDimHide;
            pInfo->bSoundOn     = bOldSoundOn;
            pInfo->aSoundFile   = aOldSoundFile;
            pInfo->bPlayFull    = bOldPlayFull;
//          pInfo->SetPath(pOldPathObj);
            pInfo->eClickAction = eOldClickAction;
            pInfo->aBookmark    = aOldBookmark;
//          pInfo->bInvisibleInPresentation = bOldInvisibleInPres;
            pInfo->nVerb        = nOldVerb;
            pInfo->nPresOrder   = nOldPresOrder;

            pInfo->eSecondEffect    = eOldSecondEffect;
            pInfo->eSecondSpeed     = eOldSecondSpeed;
            pInfo->bSecondSoundOn   = bOldSecondSoundOn;
            pInfo->bSecondPlayFull  = bOldSecondPlayFull;
        }
    }
    // Info wurde durch Aktion erzeugt: Info loeschen
    else
    {
        pObject->DeleteUserData(0);
    }
    // Damit ein ModelHasChanged() ausgeloest wird, um das Effekte-Window
    // auf Stand zu bringen (Animations-Reihenfolge)
    pObject->SetChanged();
    pObject->BroadcastObjectChange();
}

/*************************************************************************
|*
|* Redo()
|*
\************************************************************************/

void SdAnimationPrmsUndoAction::Redo()
{
    SdAnimationInfo* pInfo = NULL;

    pInfo = SdDrawDocument::GetShapeUserData(*pObject,true);

    pInfo->bActive      = bNewActive;
    pInfo->eEffect      = eNewEffect;
    pInfo->eTextEffect  = eNewTextEffect;
    pInfo->eSpeed       = eNewSpeed;
    pInfo->bDimPrevious = bNewDimPrevious;
    pInfo->aDimColor    = aNewDimColor;
    pInfo->bDimHide     = bNewDimHide;
    pInfo->bSoundOn     = bNewSoundOn;
    pInfo->aSoundFile   = aNewSoundFile;
    pInfo->bPlayFull    = bNewPlayFull;
//  pInfo->SetPath(pNewPathObj);
    pInfo->eClickAction = eNewClickAction;
    pInfo->aBookmark    = aNewBookmark;
//  pInfo->bInvisibleInPresentation = bNewInvisibleInPres;
    pInfo->nVerb        = nNewVerb;
    pInfo->nPresOrder   = nNewPresOrder;

    pInfo->eSecondEffect    = eNewSecondEffect;
    pInfo->eSecondSpeed     = eNewSecondSpeed;
    pInfo->bSecondSoundOn   = bNewSecondSoundOn;
    pInfo->bSecondPlayFull  = bNewSecondPlayFull;

    // Damit ein ModelHasChanged() ausgeloest wird, um das Effekte-Window
    // auf Stand zu bringen (Animations-Reihenfolge)
    pObject->SetChanged();
    pObject->BroadcastObjectChange();
}

/*************************************************************************
|*
|* Repeat()
|*
\************************************************************************/

void SdAnimationPrmsUndoAction::Repeat()
{
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

SdAnimationPrmsUndoAction::~SdAnimationPrmsUndoAction()
{
}

<|endoftext|>


<commit_before>#ifndef STAN__MATH__MATRIX__MULTIPLY_LOWER_TRI_SELF_HPP
#define STAN__MATH__MATRIX__MULTIPLY_LOWER_TRI_SELF_HPP

#include <stan/math/matrix/typedefs.hpp>

namespace stan {
  namespace math {

    /**
     * Returns the result of multiplying the lower triangular
     * portion of the input matrix by its own transpose.
     * @param L Matrix to multiply.
     * @return The lower triangular values in L times their own
     * transpose.
     * @throw std::domain_error If the input matrix is not square.
     */
    inline matrix_d
    multiply_lower_tri_self_transpose(const matrix_d& L) {
      if (L.rows() == 0)
        return matrix_d(0,0);
      if (L.rows() == 1) {
        matrix_d result(1,1);
        result(0,0) = L(0,0) * L(0,0);
        return result;
      }
      // FIXME:  write custom following agrad/matrix because can't get L_tri into
      // multiplication as no template support for tri * tri
      matrix_d L_tri = L.transpose().triangularView<Eigen::Upper>();
      return L.triangularView<Eigen::Lower>() * L_tri;
    }

  }
}
#endif
<commit_msg>Efficient implementation of multiply_lower_tri_self_transpose.hpp<commit_after>#ifndef STAN__MATH__MATRIX__MULTIPLY_LOWER_TRI_SELF_HPP
#define STAN__MATH__MATRIX__MULTIPLY_LOWER_TRI_SELF_HPP

#include <stan/math/matrix/typedefs.hpp>

namespace stan {
  namespace math {

    /**
     * Returns the result of multiplying the lower triangular
     * portion of the input matrix by its own transpose.
     * @param L Matrix to multiply.
     * @return The lower triangular values in L times their own
     * transpose.
     * @throw std::domain_error If the input matrix is not square.
     */
    inline matrix_d
    multiply_lower_tri_self_transpose(const matrix_d& L) {
      int K = L.rows();
      int J = L.cols();
      int k;
      matrix_d LLt(K,K);
      matrix_d Lt = L.transpose();

      if (K == 0)
        return matrix_d(0,0);
      if (K == 1) {
        matrix_d result(1,1);
        result(0,0) = L(0,0) * L(0,0);
        return result;
      }

      for (int m = 0; m < K; ++m) {
        k = (J < m + 1) ? J : m + 1;
        LLt(m,m) = Lt.col(m).head(k).squaredNorm();
        for (int n = (m + 1); n < K; ++n) {
          LLt(n,m) = LLt(m,n) = Lt.col(m).head(k).dot(Lt.col(n).head(k));
        }
      }
      return LLt;

      // FIXME:  write custom following agrad/matrix because can't get L_tri into
      // multiplication as no template support for tri * tri
      //matrix_d L_tri = L.transpose().triangularView<Eigen::Upper>();
      //return L.triangularView<Eigen::Lower>() * L_tri;
    }

  }
}
#endif
<|endoftext|>