<commit_before>/*************************************************************************
 *
 *  $RCSfile: canvascustomsprite.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: thb $ $Date: 2004-03-18 10:38:40 $
 *
 *  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 _VCLCANVAS_CANVASCUSTOMSPRITE_HXX
#define _VCLCANVAS_CANVASCUSTOMSPRITE_HXX

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase3.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XCUSTOMSPRITE_HPP_
#include <drafts/com/sun/star/rendering/XCustomSprite.hpp>
#endif

#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif

#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif

#include <canvas/vclwrapper.hxx>

#include "outdevprovider.hxx"
#include "spritecanvas.hxx"
#include "bitmapcanvas.hxx"
#include "sprite.hxx"

#define CANVASCUSTOMSPRITE_IMPLEMENTATION_NAME "VCLCanvas::CanvasCustomSprite"

namespace vclcanvas
{
    typedef ::cppu::WeakImplHelper3< ::drafts::com::sun::star::rendering::XCustomSprite,
                                     ::drafts::com::sun::star::rendering::XBitmapCanvas,
                                      ::com::sun::star::lang::XServiceInfo >  CanvasCustomSprite_Base;

    /* Definition of CanvasCustomSprite class */

    class CanvasCustomSprite : public Sprite,
                               public OutDevProvider,
                               public CanvasCustomSprite_Base
    {
    public:
        CanvasCustomSprite( const ::drafts::com::sun::star::geometry::RealSize2D&   rSpriteSize,
                            const SpriteCanvas::ImplRef&                        rSpriteCanvas );

        // XInterface

        // Need to implement that, because Sprite and OutDevProvider
        // both come with an unimplemented version of XInterface.

        // Forwarding the XInterface implementation to the
        // cppu::ImplHelper templated base, which does the refcounting and
        // queryInterface for us:  Classname     Base doing refcount and handling queryInterface
        //                             |                 |
        //                             V                 V
        DECLARE_UNO3_AGG_DEFAULTS( CanvasCustomSprite, CanvasCustomSprite_Base );

        // XCanvas
        virtual void SAL_CALL drawPoint( const ::drafts::com::sun::star::geometry::RealPoint2D&     aPoint,
                                         const ::drafts::com::sun::star::rendering::ViewState&      viewState,
                                         const ::drafts::com::sun::star::rendering::RenderState&    renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL drawLine( const ::drafts::com::sun::star::geometry::RealPoint2D&  aStartPoint,
                                        const ::drafts::com::sun::star::geometry::RealPoint2D&  aEndPoint,
                                        const ::drafts::com::sun::star::rendering::ViewState&   viewState,
                                        const ::drafts::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL drawBezier( const ::drafts::com::sun::star::geometry::RealBezierSegment2D&    aBezierSegment,
                                          const ::drafts::com::sun::star::geometry::RealPoint2D&            aEndPoint,
                                          const ::drafts::com::sun::star::rendering::ViewState&             viewState,
                                          const ::drafts::com::sun::star::rendering::RenderState&           renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            drawPolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
                             const ::drafts::com::sun::star::rendering::ViewState&                                          viewState,
                             const ::drafts::com::sun::star::rendering::RenderState&                                        renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            strokePolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >&   xPolyPolygon,
                               const ::drafts::com::sun::star::rendering::ViewState&                                            viewState,
                               const ::drafts::com::sun::star::rendering::RenderState&                                          renderState,
                               const ::drafts::com::sun::star::rendering::StrokeAttributes&                                     strokeAttributes ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            strokeTexturedPolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >&   xPolyPolygon,
                                       const ::drafts::com::sun::star::rendering::ViewState&                                            viewState,
                                       const ::drafts::com::sun::star::rendering::RenderState&                                          renderState,
                                       const ::com::sun::star::uno::Sequence< ::drafts::com::sun::star::rendering::Texture >&           textures,
                                       const ::drafts::com::sun::star::rendering::StrokeAttributes&                                     strokeAttributes ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            strokeTextureMappedPolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >&  xPolyPolygon,
                                            const ::drafts::com::sun::star::rendering::ViewState&                                           viewState,
                                            const ::drafts::com::sun::star::rendering::RenderState&                                         renderState,
                                            const ::com::sun::star::uno::Sequence< ::drafts::com::sun::star::rendering::Texture >&          textures,
                                            const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::geometry::XMapping2D >&       xMapping,
                                            const ::drafts::com::sun::star::rendering::StrokeAttributes&                                    strokeAttributes ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >   SAL_CALL
            queryStrokeShapes( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >&   xPolyPolygon,
                               const ::drafts::com::sun::star::rendering::ViewState&                                            viewState,
                               const ::drafts::com::sun::star::rendering::RenderState&                                          renderState,
                               const ::drafts::com::sun::star::rendering::StrokeAttributes&                                     strokeAttributes ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            fillPolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
                             const ::drafts::com::sun::star::rendering::ViewState&                                          viewState,
                             const ::drafts::com::sun::star::rendering::RenderState&                                        renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            fillTexturedPolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
                                     const ::drafts::com::sun::star::rendering::ViewState&                                          viewState,
                                     const ::drafts::com::sun::star::rendering::RenderState&                                        renderState,
                                     const ::com::sun::star::uno::Sequence< ::drafts::com::sun::star::rendering::Texture >&         textures ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            fillTextureMappedPolyPolygon( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >&    xPolyPolygon,
                                          const ::drafts::com::sun::star::rendering::ViewState&                                             viewState,
                                          const ::drafts::com::sun::star::rendering::RenderState&                                           renderState,
                                          const ::com::sun::star::uno::Sequence< ::drafts::com::sun::star::rendering::Texture >&            textures,
                                          const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::geometry::XMapping2D >&         xMapping ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCanvasFont >      SAL_CALL
            queryFont( const ::drafts::com::sun::star::rendering::FontRequest&  fontRequest ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            drawText( const ::drafts::com::sun::star::rendering::StringContext&                                     text,
                      const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCanvasFont >&   xFont,
                      const ::drafts::com::sun::star::rendering::ViewState&                                         viewState,
                      const ::drafts::com::sun::star::rendering::RenderState&                                       renderState,
                      sal_Int8                                                                                textDirection ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            drawOffsettedText( const ::drafts::com::sun::star::rendering::StringContext&                                    text,
                               const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCanvasFont >&  xFont,
                               const ::com::sun::star::uno::Sequence< double >&                                             offsets,
                               const ::drafts::com::sun::star::rendering::ViewState&                                        viewState,
                               const ::drafts::com::sun::star::rendering::RenderState&                                      renderState,
                               sal_Int8                                                                                textDirection ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCachedPrimitive > SAL_CALL
            drawBitmap( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XBitmap >& xBitmap,
                        const ::drafts::com::sun::star::rendering::ViewState&                                   viewState,
                        const ::drafts::com::sun::star::rendering::RenderState&                                 renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XGraphicDevice >   SAL_CALL
            getDevice() throw (::com::sun::star::uno::RuntimeException);

        // XBitmapCanvas (only providing, not implementing the
        // interface. Also note subtle method parameter differences)
        virtual void SAL_CALL copyRect( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XBitmapCanvas >&   sourceCanvas,
                                        const ::drafts::com::sun::star::geometry::RealRectangle2D&                                      sourceRect,
                                        const ::drafts::com::sun::star::rendering::ViewState&                                           sourceViewState,
                                        const ::drafts::com::sun::star::rendering::RenderState&                                         sourceRenderState,
                                        const ::drafts::com::sun::star::geometry::RealRectangle2D&                                      destRect,
                                        const ::drafts::com::sun::star::rendering::ViewState&                                           destViewState,
                                        const ::drafts::com::sun::star::rendering::RenderState&                                         destRenderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);

        // XSprite
        virtual void SAL_CALL setAlpha( double alpha ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL move( const ::drafts::com::sun::star::geometry::RealPoint2D& aNewPos, const ::drafts::com::sun::star::rendering::ViewState& viewState, const ::drafts::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL transform( const ::drafts::com::sun::star::geometry::AffineMatrix2D& aTransformation ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL clip( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >& aClip, const ::drafts::com::sun::star::rendering::ViewState& viewState, const ::drafts::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL show(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL hide(  ) throw (::com::sun::star::uno::RuntimeException);

        // XCustomSprite
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCanvas > SAL_CALL
            getContentCanvas(  ) throw (::com::sun::star::uno::RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
        virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()  throw( ::com::sun::star::uno::RuntimeException );

        // OutDevProvider
        virtual OutputDevice&       getOutDev();
        virtual const OutputDevice& getOutDev() const;

        // Sprite
        virtual void redraw( OutputDevice& rTargetSurface ) const;
        virtual void redraw( OutputDevice& rTargetSurface, const Point& rOutputPosition ) const;
        virtual ::basegfx::B2DSize getSize() const;

    protected:
        ~CanvasCustomSprite(); // we're a ref-counted UNO class. _We_ destroy ourselves.

    private:
        // default: disabled copy/assignment
        CanvasCustomSprite(const CanvasCustomSprite&);
        CanvasCustomSprite& operator=( const CanvasCustomSprite& );

        OutDevProvider::ImplRef             getImplRef();

        // for the integrated bitmap canvas implementation
        ::canvas::vcltools::VCLObject<VirtualDevice>        maVDev;
        ::canvas::vcltools::VCLObject<VirtualDevice>        maMaskVDev;
        CanvasBase                                          maCanvasHelper;

        SpriteCanvas::ImplRef                               mpSpriteCanvas;

        // sprite state
        ::basegfx::B2DPoint                                 maPosition;
        Size                                                maSize;
        double                                              mfAlpha;
        bool                                                mbActive;
    };
}

#endif /* _VCLCANVAS_CANVASCUSTOMSPRITE_HXX */
<commit_msg>INTEGRATION: CWS presentationengine01 (1.2.2); FILE MERGED 2004/11/17 17:00:28 thb 1.2.2.9: #118514# Canvas module reorg 2004/09/01 10:50:36 thb 1.2.2.8: #110496# Optimized sprite repaint (for static sprite content) 2004/08/06 14:00:09 thb 1.2.2.7: #110496# Adapted XSprite API to match reality (the way it was simply wasn't logical). Implemented sprite clipping 2004/08/02 17:50:59 thb 1.2.2.6: #110496# Adapted to recent XCanvas API changes, streamlined and factored out common code with directxcanvas 2004/07/22 20:38:28 thb 1.2.2.5: #110496# Adapted to setData/setPixel API change 2004/07/22 18:40:43 thb 1.2.2.4: #110496# Overhauled sprite redraw algo, to also respect overlapping sprites 2004/07/20 19:23:55 thb 1.2.2.3: #110496# Removed self-references to various interface implementations, along the lines, factored out common base implementation for all c++ canvases 2004/04/12 15:12:25 thb 1.2.2.2: #110496# Adaptions after canvas01 merge 2004/04/05 15:57:57 thb 1.2.2.1: Resync with canvas01 changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: canvascustomsprite.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 17:11:26 $
 *
 *  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 _VCLCANVAS_CANVASCUSTOMSPRITE_HXX
#define _VCLCANVAS_CANVASCUSTOMSPRITE_HXX

#ifndef _CPPUHELPER_COMPBASE3_HXX_
#include <cppuhelper/compbase3.hxx>
#endif

#ifndef _COMPHELPER_UNO3_HXX
#include <comphelper/uno3.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XCUSTOMSPRITE_HPP_
#include <drafts/com/sun/star/rendering/XCustomSprite.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XPOLYPOLYGON2D_HPP_
#include <drafts/com/sun/star/rendering/XPolyPolygon2D.hpp>
#endif

#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif

#ifndef _SV_VIRDEV_HXX
#include <vcl/virdev.hxx>
#endif

#include <canvas/vclwrapper.hxx>
#include <canvas/bitmapcanvasbase.hxx>

#include "canvashelper.hxx"
#include "backbuffer.hxx"
#include "impltools.hxx"
#include "spritecanvas.hxx"
#include "sprite.hxx"

#define CANVASCUSTOMSPRITE_IMPLEMENTATION_NAME "VCLCanvas::CanvasCustomSprite"

namespace vclcanvas
{
    typedef ::cppu::WeakComponentImplHelper3< ::drafts::com::sun::star::rendering::XCustomSprite,
                                               ::drafts::com::sun::star::rendering::XBitmapCanvas,
                                                ::com::sun::star::lang::XServiceInfo >                                  CanvasCustomSpriteBase_Base;
    typedef ::canvas::internal::BitmapCanvasBase< CanvasCustomSpriteBase_Base, CanvasHelper, tools::LocalGuard >    CanvasCustomSprite_Base;

    /* Definition of CanvasCustomSprite class */

    class CanvasCustomSprite : public Sprite,
                               public CanvasCustomSprite_Base
    {
    public:
        CanvasCustomSprite( const ::drafts::com::sun::star::geometry::RealSize2D&   rSpriteSize,
                            const WindowGraphicDevice::ImplRef&                     rDevice,
                            const SpriteCanvas::ImplRef&                            rSpriteCanvas );

        // XInterface

        // Need to employ this macro, because Sprite comes with an
        // unimplemented version of XInterface.

        // Forwarding the XInterface implementation to the
        // cppu::ImplHelper templated base, which does the refcounting and
        // queryInterface for us:  Classname     Base doing refcount and handling queryInterface
        //                             |                 |
        //                             V                 V
        DECLARE_UNO3_AGG_DEFAULTS( CanvasCustomSprite, CanvasCustomSpriteBase_Base );

        virtual void SAL_CALL disposing();

        // XSprite
        virtual void SAL_CALL setAlpha( double alpha ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL move( const ::drafts::com::sun::star::geometry::RealPoint2D& aNewPos, const ::drafts::com::sun::star::rendering::ViewState& viewState, const ::drafts::com::sun::star::rendering::RenderState& renderState ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL transform( const ::drafts::com::sun::star::geometry::AffineMatrix2D& aTransformation ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL clip( const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XPolyPolygon2D >& aClip ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setPriority( double nPriority ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL show(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL hide(  ) throw (::com::sun::star::uno::RuntimeException);

        // XCustomSprite
        virtual ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XCanvas > SAL_CALL
            getContentCanvas(  ) throw (::com::sun::star::uno::RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
        virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()  throw( ::com::sun::star::uno::RuntimeException );

        // Sprite
        virtual void redraw( OutputDevice& rTargetSurface ) const;
        virtual void redraw( OutputDevice& rTargetSurface, const Point& rOutputPosition ) const;
        virtual ::basegfx::B2DPoint getPos() const;
        virtual ::basegfx::B2DSize  getSize() const;

    protected:
        ~CanvasCustomSprite(); // we're a ref-counted UNO class. _We_ destroy ourselves.

    private:
        // default: disabled copy/assignment
        CanvasCustomSprite(const CanvasCustomSprite&);
        CanvasCustomSprite& operator=( const CanvasCustomSprite& );

        // for the integrated bitmap canvas implementation
        BackBufferSharedPtr     mpBackBuffer;
        BackBufferSharedPtr     mpBackBufferMask;

        SpriteCanvas::ImplRef   mpSpriteCanvas;

        mutable ::canvas::vcltools::VCLObject<BitmapEx>             maContent;

        // sprite state
        ::basegfx::B2DPoint                                         maPosition;
        Size                                                        maSize;
        ::com::sun::star::uno::Reference<
              ::drafts::com::sun::star::rendering::XPolyPolygon2D > mxClipPoly;
        double                                                      mfAlpha;
        bool                                                        mbActive;
    };
}

#endif /* _VCLCANVAS_CANVASCUSTOMSPRITE_HXX */
<|endoftext|>


<commit_before><commit_msg>Added some missing #includes in "assert.hpp".<commit_after><|endoftext|>


<commit_before>#include "Memory.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>

#include <libdevcore/Common.h>

#include "Type.h"
#include "Runtime.h"
#include "GasMeter.h"

namespace evmcc
{

Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter):
	m_builder(_builder)
{
	auto i64Ty = m_builder.getInt64Ty();
	llvm::Type* argTypes[] = {i64Ty, i64Ty};
	auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
 	m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
		"evmccrt_memory_dump", _module);

	m_data = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data");
	m_data->setUnnamedAddr(true); // Address is not important

	m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size");
	m_size->setUnnamedAddr(true); // Address is not important

	m_returnDataOffset = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset");
	m_returnDataOffset->setUnnamedAddr(true); // Address is not important

	m_returnDataSize = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize");
	m_returnDataSize->setUnnamedAddr(true); // Address is not important

	m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module);
	m_require = createRequireFunc(_module, _gasMeter);
	m_loadWord = createFunc(false, Type::i256, _module, _gasMeter);
	m_storeWord = createFunc(true, Type::i256, _module, _gasMeter);
	m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter);
}

llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter)
{
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", _module);

	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func);
	auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func);
	auto returnBB = llvm::BasicBlock::Create(func->getContext(), "return", func);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	// BB "check"
	m_builder.SetInsertPoint(checkBB);
	llvm::Value* sizeRequired = func->arg_begin();
	sizeRequired->setName("sizeRequired");
	auto size = m_builder.CreateLoad(m_size, "size");
	auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded");
	m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

	// BB "resize"
	m_builder.SetInsertPoint(resizeBB);
	// Check gas first
	auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired");
	auto words = m_builder.CreateUDiv(m_builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words");
	auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
	_gasMeter.checkMemory(newWords, m_builder);
	// Resize
	m_builder.CreateStore(sizeRequired, m_size);
	auto newData = m_builder.CreateCall(m_resize, m_size, "newData");
	m_builder.CreateStore(newData, m_data);
	m_builder.CreateBr(returnBB);

	// BB "return"
	m_builder.SetInsertPoint(returnBB);
	m_builder.CreateRetVoid();
	return func;
}

llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module, GasMeter& _gasMeter)
{
	auto isWord = _valueType == Type::i256;

	llvm::Type* storeArgs[] = {Type::i256, _valueType};
	auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
	auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false);
	auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, _module);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
	llvm::Value* index = func->arg_begin();
	index->setName("index");

	auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
	this->require(index, Constant::get(valueSize));
	auto data = m_builder.CreateLoad(m_data, "data");
	auto ptr = m_builder.CreateGEP(data, index, "ptr");
	if (isWord)
		ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
	if (_isStore)
	{
		llvm::Value* value = ++func->arg_begin();
		value->setName("value");
		m_builder.CreateStore(value, ptr);
		m_builder.CreateRetVoid();
	}
	else
	{
		auto ret = m_builder.CreateLoad(ptr);
		m_builder.CreateRet(ret);
	}

	return func;
}

llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
	auto value = m_builder.CreateCall(m_loadWord, _addr);

	dump(0);
	return value;
}

void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
	m_builder.CreateCall2(m_storeWord, _addr, _word);

	dump(0);
}

void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
	auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
	m_builder.CreateCall2(m_storeByte, _addr, byte);

	dump(0);
}

llvm::Value* Memory::getData()
{
	return m_builder.CreateLoad(m_data);
}

llvm::Value* Memory::getSize()
{
	return m_builder.CreateLoad(m_size);
}

void Memory::require(llvm::Value* _size)
{
	m_builder.CreateCall(m_require, _size);
}

void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
	auto sizeRequired = m_builder.CreateAdd(_offset, _size, "sizeRequired");
	require(sizeRequired);
}

void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size)
{
	require(_index, _size); // Make sure that memory is allocated and count gas

	m_builder.CreateStore(_index, m_returnDataOffset);
	m_builder.CreateStore(_size, m_returnDataSize);
}

void Memory::dump(uint64_t _begin, uint64_t _end)
{
	if (getenv("EVMCC_DEBUG_MEMORY") == nullptr)
		return;

	auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin);
	auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end);

	std::vector<llvm::Value*> args = {beginVal, endVal};
	m_builder.CreateCall(m_memDump, llvm::ArrayRef<llvm::Value*>(args));
}

} // namespace evmcc

extern "C"
{
	using namespace evmcc;

EXPORT i256 mem_returnDataOffset;
EXPORT i256 mem_returnDataSize;

EXPORT uint8_t* mem_resize(i256* _size)
{
	auto size = _size->a; // Trunc to 64-bit
	auto& memory = Runtime::getMemory();
	memory.resize(size);
	return memory.data();
}

EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
{
	if (_end == 0)
		_end = Runtime::getMemory().size();

	std::cerr << "MEMORY: active size: " << std::dec
			  << Runtime::getMemory().size() / 32 << " words\n";
	std::cerr << "MEMORY: dump from " << std::dec
			  << _begin << " to " << _end << ":";
	if (_end <= _begin)
		return;

	_begin = _begin / 16 * 16;
	for (size_t i = _begin; i < _end; i++)
	{
		if ((i - _begin) % 16 == 0)
			std::cerr << '\n' << std::dec << i << ":  ";

		auto b = Runtime::getMemory()[i];
		std::cerr << std::hex << std::setw(2) << static_cast<int>(b) << ' ';
	}
	std::cerr << std::endl;
}

}	// extern "C"

dev::bytesConstRef evmcc::Memory::getReturnData()
{
	// TODO: Handle large indexes
	auto offset = static_cast<size_t>(llvm2eth(mem_returnDataOffset));
	auto size = static_cast<size_t>(llvm2eth(mem_returnDataSize));
	auto& memory = Runtime::getMemory();
	return {memory.data() + offset, size};
}
<commit_msg>Some LLVM function attribute fun<commit_after>#include "Memory.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>

#include <libdevcore/Common.h>

#include "Type.h"
#include "Runtime.h"
#include "GasMeter.h"

namespace evmcc
{

Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter):
	m_builder(_builder)
{
	auto i64Ty = m_builder.getInt64Ty();
	llvm::Type* argTypes[] = {i64Ty, i64Ty};
	auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
 	m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
		"evmccrt_memory_dump", _module);

	m_data = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data");
	m_data->setUnnamedAddr(true); // Address is not important

	m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size");
	m_size->setUnnamedAddr(true); // Address is not important

	m_returnDataOffset = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset");
	m_returnDataOffset->setUnnamedAddr(true); // Address is not important

	m_returnDataSize = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize");
	m_returnDataSize->setUnnamedAddr(true); // Address is not important

	m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module);
	llvm::AttrBuilder attrBuilder;
	attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
	m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));

	m_require = createRequireFunc(_module, _gasMeter);
	m_loadWord = createFunc(false, Type::i256, _module, _gasMeter);
	m_storeWord = createFunc(true, Type::i256, _module, _gasMeter);
	m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter);
}

llvm::Function* Memory::createRequireFunc(llvm::Module* _module, GasMeter& _gasMeter)
{
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", _module);

	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func);
	auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func);
	auto returnBB = llvm::BasicBlock::Create(func->getContext(), "return", func);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	// BB "check"
	m_builder.SetInsertPoint(checkBB);
	llvm::Value* sizeRequired = func->arg_begin();
	sizeRequired->setName("sizeRequired");
	auto size = m_builder.CreateLoad(m_size, "size");
	auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded");
	m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

	// BB "resize"
	m_builder.SetInsertPoint(resizeBB);
	// Check gas first
	auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired");
	auto words = m_builder.CreateUDiv(m_builder.CreateAdd(size, Constant::get(31)), Constant::get(32), "words");
	auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
	_gasMeter.checkMemory(newWords, m_builder);
	// Resize
	m_builder.CreateStore(sizeRequired, m_size);
	auto newData = m_builder.CreateCall(m_resize, m_size, "newData");
	m_builder.CreateStore(newData, m_data);
	m_builder.CreateBr(returnBB);

	// BB "return"
	m_builder.SetInsertPoint(returnBB);
	m_builder.CreateRetVoid();
	return func;
}

llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module, GasMeter& _gasMeter)
{
	auto isWord = _valueType == Type::i256;

	llvm::Type* storeArgs[] = {Type::i256, _valueType};
	auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
	auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false);
	auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, _module);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
	llvm::Value* index = func->arg_begin();
	index->setName("index");

	auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
	this->require(index, Constant::get(valueSize));
	auto data = m_builder.CreateLoad(m_data, "data");
	auto ptr = m_builder.CreateGEP(data, index, "ptr");
	if (isWord)
		ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
	if (_isStore)
	{
		llvm::Value* value = ++func->arg_begin();
		value->setName("value");
		m_builder.CreateStore(value, ptr);
		m_builder.CreateRetVoid();
	}
	else
	{
		auto ret = m_builder.CreateLoad(ptr);
		m_builder.CreateRet(ret);
	}

	return func;
}

llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
	auto value = m_builder.CreateCall(m_loadWord, _addr);

	dump(0);
	return value;
}

void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
	m_builder.CreateCall2(m_storeWord, _addr, _word);

	dump(0);
}

void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
	auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
	m_builder.CreateCall2(m_storeByte, _addr, byte);

	dump(0);
}

llvm::Value* Memory::getData()
{
	return m_builder.CreateLoad(m_data);
}

llvm::Value* Memory::getSize()
{
	return m_builder.CreateLoad(m_size);
}

void Memory::require(llvm::Value* _size)
{
	m_builder.CreateCall(m_require, _size);
}

void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
	auto sizeRequired = m_builder.CreateAdd(_offset, _size, "sizeRequired");
	require(sizeRequired);
}

void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size)
{
	require(_index, _size); // Make sure that memory is allocated and count gas

	m_builder.CreateStore(_index, m_returnDataOffset);
	m_builder.CreateStore(_size, m_returnDataSize);
}

void Memory::dump(uint64_t _begin, uint64_t _end)
{
	if (getenv("EVMCC_DEBUG_MEMORY") == nullptr)
		return;

	auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin);
	auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end);

	std::vector<llvm::Value*> args = {beginVal, endVal};
	m_builder.CreateCall(m_memDump, llvm::ArrayRef<llvm::Value*>(args));
}

} // namespace evmcc

extern "C"
{
	using namespace evmcc;

EXPORT i256 mem_returnDataOffset;
EXPORT i256 mem_returnDataSize;

EXPORT uint8_t* mem_resize(i256* _size)
{
	auto size = _size->a; // Trunc to 64-bit
	auto& memory = Runtime::getMemory();
	memory.resize(size);
	return memory.data();
}

EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
{
	if (_end == 0)
		_end = Runtime::getMemory().size();

	std::cerr << "MEMORY: active size: " << std::dec
			  << Runtime::getMemory().size() / 32 << " words\n";
	std::cerr << "MEMORY: dump from " << std::dec
			  << _begin << " to " << _end << ":";
	if (_end <= _begin)
		return;

	_begin = _begin / 16 * 16;
	for (size_t i = _begin; i < _end; i++)
	{
		if ((i - _begin) % 16 == 0)
			std::cerr << '\n' << std::dec << i << ":  ";

		auto b = Runtime::getMemory()[i];
		std::cerr << std::hex << std::setw(2) << static_cast<int>(b) << ' ';
	}
	std::cerr << std::endl;
}

}	// extern "C"

dev::bytesConstRef evmcc::Memory::getReturnData()
{
	// TODO: Handle large indexes
	auto offset = static_cast<size_t>(llvm2eth(mem_returnDataOffset));
	auto size = static_cast<size_t>(llvm2eth(mem_returnDataSize));
	auto& memory = Runtime::getMemory();
	return {memory.data() + offset, size};
}
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    timehelper.cxx
// Created: 4/2003
// Author:  Tad E. Smith
//
//
// Copyright 2003-2013 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/internal/internal.h>

#include <algorithm>
#include <vector>
#include <iomanip>
#include <cassert>
#include <cerrno>
#if defined (UNICODE)
#include <cwchar>
#endif

#if defined (LOG4CPLUS_HAVE_SYS_TYPES_H)
#include <sys/types.h>
#endif

#if defined(LOG4CPLUS_HAVE_SYS_TIME_H)
#include <sys/time.h>
#endif

#if defined (LOG4CPLUS_HAVE_SYS_TIMEB_H)
#include <sys/timeb.h>
#endif

#if defined(LOG4CPLUS_HAVE_GMTIME_R) && !defined(LOG4CPLUS_SINGLE_THREADED)
#define LOG4CPLUS_NEED_GMTIME_R
#endif

#if defined(LOG4CPLUS_HAVE_LOCALTIME_R) && !defined(LOG4CPLUS_SINGLE_THREADED)
#define LOG4CPLUS_NEED_LOCALTIME_R
#endif

namespace log4cplus { namespace helpers {

const int ONE_SEC_IN_USEC = 1000000;

using std::mktime;
using std::gmtime;
using std::localtime;
#if defined (UNICODE)
using std::wcsftime;
#else
using std::strftime;
#endif

//////////////////////////////////////////////////////////////////////////////
// Time ctors
//////////////////////////////////////////////////////////////////////////////

Time::Time()
    : tv_sec(0)
    , tv_usec(0)
{
}

Time::Time(time_t tv_sec_, long tv_usec_)
    : tv_sec(tv_sec_)
    , tv_usec(tv_usec_)
{
    assert (tv_usec < ONE_SEC_IN_USEC);
}

Time::Time(time_t time)
    : tv_sec(time)
    , tv_usec(0)
{
}

Time
Time::gettimeofday()
{
#if defined (LOG4CPLUS_HAVE_CLOCK_GETTIME)
    struct timespec ts;
    int res = clock_gettime (CLOCK_REALTIME, &ts);
    assert (res == 0);
    if (res != 0)
        LogLog::getLogLog ()->error (
            LOG4CPLUS_TEXT("clock_gettime() has failed"), true);

    return Time (ts.tv_sec, ts.tv_nsec / 1000);

#elif defined(LOG4CPLUS_HAVE_GETTIMEOFDAY)
    struct timeval tp;
    ::gettimeofday(&tp, 0);

    return Time(tp.tv_sec, tp.tv_usec);

#elif defined (_WIN32)
    FILETIME ft;
    GetSystemTimeAsFileTime (&ft);

    typedef unsigned __int64 uint64_type;
    uint64_type st100ns
        = uint64_type (ft.dwHighDateTime) << 32
        | ft.dwLowDateTime;

    // Number of 100-ns intervals between UNIX epoch and Windows system time
    // is 116444736000000000.
    uint64_type const offset = uint64_type (116444736) * 1000 * 1000 * 1000;
    uint64_type fixed_time = st100ns - offset;

    return Time (fixed_time / (10 * 1000 * 1000),
        fixed_time % (10 * 1000 * 1000) / 10);

#elif defined(LOG4CPLUS_HAVE_FTIME)
    struct timeb tp;
    ftime(&tp);

    return Time(tp.time, tp.millitm * 1000);

#else
#warning "Time::gettimeofday()- low resolution timer: gettimeofday and ftime unavailable"
    return Time(::time(0), 0);
#endif
}

//////////////////////////////////////////////////////////////////////////////
// Time methods
//////////////////////////////////////////////////////////////////////////////

time_t
Time::setTime(tm* t)
{
    time_t time = helpers::mktime(t);
    if (time != -1)
        tv_sec = time;

    return time;
}

time_t
Time::getTime() const
{
    return tv_sec;
}

void
Time::gmtime(tm* t) const
{
    time_t clock = tv_sec;
#if defined (LOG4CPLUS_HAVE_GMTIME_S) && defined (_MSC_VER)
    gmtime_s (t, &clock);
#elif defined (LOG4CPLUS_HAVE_GMTIME_S) && defined (__BORLANDC__)
    gmtime_s (&clock, t);
#elif defined (LOG4CPLUS_NEED_GMTIME_R)
    gmtime_r (&clock, t);
#else
    tm* tmp = helpers::gmtime(&clock);
    *t = *tmp;
#endif
}

void
Time::localtime(tm* t) const
{
    time_t clock = tv_sec;
#ifdef LOG4CPLUS_NEED_LOCALTIME_R
    ::localtime_r(&clock, t);
#else
    tm* tmp = helpers::localtime(&clock);
    *t = *tmp;
#endif
}

namespace
{

static log4cplus::tstring const padding_zeros[4] =
{
    log4cplus::tstring (LOG4CPLUS_TEXT("000")),
    log4cplus::tstring (LOG4CPLUS_TEXT("00")),
    log4cplus::tstring (LOG4CPLUS_TEXT("0")),
    log4cplus::tstring (LOG4CPLUS_TEXT(""))
};

static log4cplus::tstring const uc_q_padding_zeros[4] =
{
    log4cplus::tstring (LOG4CPLUS_TEXT(".000")),
    log4cplus::tstring (LOG4CPLUS_TEXT(".00")),
    log4cplus::tstring (LOG4CPLUS_TEXT(".0")),
    log4cplus::tstring (LOG4CPLUS_TEXT("."))
};

static
void
build_q_value (log4cplus::tstring & q_str, long tv_usec)
{
    convertIntegerToString(q_str, tv_usec / 1000);
    std::size_t const len = q_str.length();
    if (len <= 2)
        q_str.insert (0, padding_zeros[q_str.length()]);
}

static
void
build_uc_q_value (log4cplus::tstring & uc_q_str, long tv_usec,
    log4cplus::tstring & tmp)
{
    build_q_value (uc_q_str, tv_usec);

    convertIntegerToString(tmp, tv_usec % 1000);
    std::size_t const usecs_len = tmp.length();
    tmp.insert (0, usecs_len <= 3
        ? uc_q_padding_zeros[usecs_len] : uc_q_padding_zeros[3]);
    uc_q_str.append (tmp);
}

} // namespace

log4cplus::tstring
Time::getFormattedTime(const log4cplus::tstring& fmt_orig, bool use_gmtime) const
{
    if (fmt_orig.empty () || fmt_orig[0] == 0)
        return log4cplus::tstring ();

    tm time;

    if (use_gmtime)
        gmtime(&time);
    else
        localtime(&time);

    enum State
    {
        TEXT,
        PERCENT_SIGN
    };

    internal::gft_scratch_pad & gft_sp = internal::get_gft_scratch_pad ();
    gft_sp.reset ();

    gft_sp.fmt.assign (fmt_orig);
    std::size_t const fmt_orig_size = gft_sp.fmt.size ();
    gft_sp.ret.reserve (fmt_orig_size + fmt_orig_size / 3);
    State state = TEXT;

    // Walk the format string and process all occurences of %q, %Q and %s.

    for (log4cplus::tstring::const_iterator fmt_it = gft_sp.fmt.begin ();
         fmt_it != gft_sp.fmt.end (); ++fmt_it)
    {
        switch (state)
        {
        case TEXT:
        {
            if (*fmt_it == LOG4CPLUS_TEXT ('%'))
                state = PERCENT_SIGN;
            else
                gft_sp.ret.push_back (*fmt_it);
        }
        break;

        case PERCENT_SIGN:
        {
            switch (*fmt_it)
            {
            case LOG4CPLUS_TEXT ('q'):
            {
                if (! gft_sp.q_str_valid)
                {
                    build_q_value (gft_sp.q_str, tv_usec);
                    gft_sp.q_str_valid = true;
                }
                gft_sp.ret.append (gft_sp.q_str);
                state = TEXT;
            }
            break;

            case LOG4CPLUS_TEXT ('Q'):
            {
                if (! gft_sp.uc_q_str_valid)
                {
                    build_uc_q_value (gft_sp.uc_q_str, tv_usec, gft_sp.tmp);
                    gft_sp.uc_q_str_valid = true;
                }
                gft_sp.ret.append (gft_sp.uc_q_str);
                state = TEXT;
            }
            break;

            // Windows do not support %s format specifier
            // (seconds since epoch).
            case LOG4CPLUS_TEXT ('s'):
            {
                if (! gft_sp.s_str_valid)
                {
                    convertIntegerToString (gft_sp.s_str, tv_sec);
                    gft_sp.s_str_valid = true;
                }
                gft_sp.ret.append (gft_sp.s_str);
                state = TEXT;
            }
            break;

            default:
            {
                gft_sp.ret.push_back (LOG4CPLUS_TEXT ('%'));
                gft_sp.ret.push_back (*fmt_it);
                state = TEXT;
            }
            }
        }
        break;
        }
    }

    // Finally call strftime/wcsftime to format the rest of the string.

    gft_sp.ret.swap (gft_sp.fmt);
    std::size_t buffer_size = gft_sp.fmt.size () + 1;
    std::size_t len;

    // Limit how far can the buffer grow. This is necessary so that we
    // catch bad format string. Some implementations of strftime() signal
    // both too small buffer and invalid format string by returning 0
    // without changing errno.
    std::size_t const buffer_size_max
        = (std::max) (static_cast<std::size_t>(1024), buffer_size * 16);

    do
    {
        gft_sp.buffer.resize (buffer_size);
        errno = 0;
#ifdef UNICODE
        len = helpers::wcsftime(&gft_sp.buffer[0], buffer_size,
            gft_sp.fmt.c_str(), &time);
#else
        len = helpers::strftime(&gft_sp.buffer[0], buffer_size,
            gft_sp.fmt.c_str(), &time);
#endif
        if (len == 0)
        {
            int const eno = errno;
            buffer_size *= 2;
            if (buffer_size > buffer_size_max)
            {
                LogLog::getLogLog ()->error (
                    LOG4CPLUS_TEXT("Error in strftime(): ")
                    + convertIntegerToString (eno), true);
            }
        }
    }
    while (len == 0);

    return tstring (gft_sp.buffer.begin (), gft_sp.buffer.begin () + len);
}

Time&
Time::operator+=(const Time& rhs)
{
    tv_sec += rhs.tv_sec;
    tv_usec += rhs.tv_usec;

    if(tv_usec > ONE_SEC_IN_USEC) {
        ++tv_sec;
        tv_usec -= ONE_SEC_IN_USEC;
    }

    return *this;
}

Time&
Time::operator-=(const Time& rhs)
{
    tv_sec -= rhs.tv_sec;
    tv_usec -= rhs.tv_usec;

    if(tv_usec < 0) {
        --tv_sec;
        tv_usec += ONE_SEC_IN_USEC;
    }

    return *this;
}

Time&
Time::operator/=(long rhs)
{
    long rem_secs = static_cast<long>(tv_sec % rhs);
    tv_sec /= rhs;

    tv_usec /= rhs;
    tv_usec += static_cast<long>((rem_secs * ONE_SEC_IN_USEC) / rhs);

    return *this;
}

Time&
Time::operator*=(long rhs)
{
    long new_usec = tv_usec * rhs;
    long overflow_sec = new_usec / ONE_SEC_IN_USEC;
    tv_usec = new_usec % ONE_SEC_IN_USEC;

    tv_sec *= rhs;
    tv_sec += overflow_sec;

    return *this;
}

//////////////////////////////////////////////////////////////////////////////
// Time globals
//////////////////////////////////////////////////////////////////////////////

const Time
operator+(const Time& lhs, const Time& rhs)
{
    return Time(lhs) += rhs;
}

const Time
operator-(const Time& lhs, const Time& rhs)
{
    return Time(lhs) -= rhs;
}

const Time
operator/(const Time& lhs, long rhs)
{
    return Time(lhs) /= rhs;
}

const Time
operator*(const Time& lhs, long rhs)
{
    return Time(lhs) *= rhs;
}

bool
operator<(const Time& lhs, const Time& rhs)
{
    return (   (lhs.sec() < rhs.sec())
            || (   (lhs.sec() == rhs.sec())
                && (lhs.usec() < rhs.usec())) );
}

bool
operator<=(const Time& lhs, const Time& rhs)
{
    return ((lhs < rhs) || (lhs == rhs));
}

bool
operator>(const Time& lhs, const Time& rhs)
{
    return (   (lhs.sec() > rhs.sec())
            || (   (lhs.sec() == rhs.sec())
                && (lhs.usec() > rhs.usec())) );
}

bool
operator>=(const Time& lhs, const Time& rhs)
{
    return ((lhs > rhs) || (lhs == rhs));
}

bool
operator==(const Time& lhs, const Time& rhs)
{
    return (   lhs.sec() == rhs.sec()
            && lhs.usec() == rhs.usec());
}

bool
operator!=(const Time& lhs, const Time& rhs)
{
    return !(lhs == rhs);
}

} } // namespace log4cplus { namespace helpers {
<commit_msg>timehelper.cxx: Use GetSystemTimePreciseAsFileTime() when _WIN32_WINNT >= 0x602.<commit_after>// Module:  Log4CPLUS
// File:    timehelper.cxx
// Created: 4/2003
// Author:  Tad E. Smith
//
//
// Copyright 2003-2013 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/internal/internal.h>

#include <algorithm>
#include <vector>
#include <iomanip>
#include <cassert>
#include <cerrno>
#if defined (UNICODE)
#include <cwchar>
#endif

#if defined (LOG4CPLUS_HAVE_SYS_TYPES_H)
#include <sys/types.h>
#endif

#if defined(LOG4CPLUS_HAVE_SYS_TIME_H)
#include <sys/time.h>
#endif

#if defined (LOG4CPLUS_HAVE_SYS_TIMEB_H)
#include <sys/timeb.h>
#endif

#if defined(LOG4CPLUS_HAVE_GMTIME_R) && !defined(LOG4CPLUS_SINGLE_THREADED)
#define LOG4CPLUS_NEED_GMTIME_R
#endif

#if defined(LOG4CPLUS_HAVE_LOCALTIME_R) && !defined(LOG4CPLUS_SINGLE_THREADED)
#define LOG4CPLUS_NEED_LOCALTIME_R
#endif

namespace log4cplus { namespace helpers {

const int ONE_SEC_IN_USEC = 1000000;

using std::mktime;
using std::gmtime;
using std::localtime;
#if defined (UNICODE)
using std::wcsftime;
#else
using std::strftime;
#endif

//////////////////////////////////////////////////////////////////////////////
// Time ctors
//////////////////////////////////////////////////////////////////////////////

Time::Time()
    : tv_sec(0)
    , tv_usec(0)
{
}

Time::Time(time_t tv_sec_, long tv_usec_)
    : tv_sec(tv_sec_)
    , tv_usec(tv_usec_)
{
    assert (tv_usec < ONE_SEC_IN_USEC);
}

Time::Time(time_t time)
    : tv_sec(time)
    , tv_usec(0)
{
}

Time
Time::gettimeofday()
{
#if defined (LOG4CPLUS_HAVE_CLOCK_GETTIME)
    struct timespec ts;
    int res = clock_gettime (CLOCK_REALTIME, &ts);
    assert (res == 0);
    if (res != 0)
        LogLog::getLogLog ()->error (
            LOG4CPLUS_TEXT("clock_gettime() has failed"), true);

    return Time (ts.tv_sec, ts.tv_nsec / 1000);

#elif defined(LOG4CPLUS_HAVE_GETTIMEOFDAY)
    struct timeval tp;
    ::gettimeofday(&tp, 0);

    return Time(tp.tv_sec, tp.tv_usec);

#elif defined (_WIN32)
    FILETIME ft;
#if _WIN32_WINNT >= 0x602
    GetSystemTimePreciseAsFileTime (&ft);
#else
    GetSystemTimeAsFileTime (&ft);
#endif

    typedef unsigned __int64 uint64_type;
    uint64_type st100ns
        = uint64_type (ft.dwHighDateTime) << 32
        | ft.dwLowDateTime;

    // Number of 100-ns intervals between UNIX epoch and Windows system time
    // is 116444736000000000.
    uint64_type const offset = uint64_type (116444736) * 1000 * 1000 * 1000;
    uint64_type fixed_time = st100ns - offset;

    return Time (fixed_time / (10 * 1000 * 1000),
        fixed_time % (10 * 1000 * 1000) / 10);

#elif defined(LOG4CPLUS_HAVE_FTIME)
    struct timeb tp;
    ftime(&tp);

    return Time(tp.time, tp.millitm * 1000);

#else
#warning "Time::gettimeofday()- low resolution timer: gettimeofday and ftime unavailable"
    return Time(::time(0), 0);
#endif
}

//////////////////////////////////////////////////////////////////////////////
// Time methods
//////////////////////////////////////////////////////////////////////////////

time_t
Time::setTime(tm* t)
{
    time_t time = helpers::mktime(t);
    if (time != -1)
        tv_sec = time;

    return time;
}

time_t
Time::getTime() const
{
    return tv_sec;
}

void
Time::gmtime(tm* t) const
{
    time_t clock = tv_sec;
#if defined (LOG4CPLUS_HAVE_GMTIME_S) && defined (_MSC_VER)
    gmtime_s (t, &clock);
#elif defined (LOG4CPLUS_HAVE_GMTIME_S) && defined (__BORLANDC__)
    gmtime_s (&clock, t);
#elif defined (LOG4CPLUS_NEED_GMTIME_R)
    gmtime_r (&clock, t);
#else
    tm* tmp = helpers::gmtime(&clock);
    *t = *tmp;
#endif
}

void
Time::localtime(tm* t) const
{
    time_t clock = tv_sec;
#ifdef LOG4CPLUS_NEED_LOCALTIME_R
    ::localtime_r(&clock, t);
#else
    tm* tmp = helpers::localtime(&clock);
    *t = *tmp;
#endif
}

namespace
{

static log4cplus::tstring const padding_zeros[4] =
{
    log4cplus::tstring (LOG4CPLUS_TEXT("000")),
    log4cplus::tstring (LOG4CPLUS_TEXT("00")),
    log4cplus::tstring (LOG4CPLUS_TEXT("0")),
    log4cplus::tstring (LOG4CPLUS_TEXT(""))
};

static log4cplus::tstring const uc_q_padding_zeros[4] =
{
    log4cplus::tstring (LOG4CPLUS_TEXT(".000")),
    log4cplus::tstring (LOG4CPLUS_TEXT(".00")),
    log4cplus::tstring (LOG4CPLUS_TEXT(".0")),
    log4cplus::tstring (LOG4CPLUS_TEXT("."))
};

static
void
build_q_value (log4cplus::tstring & q_str, long tv_usec)
{
    convertIntegerToString(q_str, tv_usec / 1000);
    std::size_t const len = q_str.length();
    if (len <= 2)
        q_str.insert (0, padding_zeros[q_str.length()]);
}

static
void
build_uc_q_value (log4cplus::tstring & uc_q_str, long tv_usec,
    log4cplus::tstring & tmp)
{
    build_q_value (uc_q_str, tv_usec);

    convertIntegerToString(tmp, tv_usec % 1000);
    std::size_t const usecs_len = tmp.length();
    tmp.insert (0, usecs_len <= 3
        ? uc_q_padding_zeros[usecs_len] : uc_q_padding_zeros[3]);
    uc_q_str.append (tmp);
}

} // namespace

log4cplus::tstring
Time::getFormattedTime(const log4cplus::tstring& fmt_orig, bool use_gmtime) const
{
    if (fmt_orig.empty () || fmt_orig[0] == 0)
        return log4cplus::tstring ();

    tm time;

    if (use_gmtime)
        gmtime(&time);
    else
        localtime(&time);

    enum State
    {
        TEXT,
        PERCENT_SIGN
    };

    internal::gft_scratch_pad & gft_sp = internal::get_gft_scratch_pad ();
    gft_sp.reset ();

    gft_sp.fmt.assign (fmt_orig);
    std::size_t const fmt_orig_size = gft_sp.fmt.size ();
    gft_sp.ret.reserve (fmt_orig_size + fmt_orig_size / 3);
    State state = TEXT;

    // Walk the format string and process all occurences of %q, %Q and %s.

    for (log4cplus::tstring::const_iterator fmt_it = gft_sp.fmt.begin ();
         fmt_it != gft_sp.fmt.end (); ++fmt_it)
    {
        switch (state)
        {
        case TEXT:
        {
            if (*fmt_it == LOG4CPLUS_TEXT ('%'))
                state = PERCENT_SIGN;
            else
                gft_sp.ret.push_back (*fmt_it);
        }
        break;

        case PERCENT_SIGN:
        {
            switch (*fmt_it)
            {
            case LOG4CPLUS_TEXT ('q'):
            {
                if (! gft_sp.q_str_valid)
                {
                    build_q_value (gft_sp.q_str, tv_usec);
                    gft_sp.q_str_valid = true;
                }
                gft_sp.ret.append (gft_sp.q_str);
                state = TEXT;
            }
            break;

            case LOG4CPLUS_TEXT ('Q'):
            {
                if (! gft_sp.uc_q_str_valid)
                {
                    build_uc_q_value (gft_sp.uc_q_str, tv_usec, gft_sp.tmp);
                    gft_sp.uc_q_str_valid = true;
                }
                gft_sp.ret.append (gft_sp.uc_q_str);
                state = TEXT;
            }
            break;

            // Windows do not support %s format specifier
            // (seconds since epoch).
            case LOG4CPLUS_TEXT ('s'):
            {
                if (! gft_sp.s_str_valid)
                {
                    convertIntegerToString (gft_sp.s_str, tv_sec);
                    gft_sp.s_str_valid = true;
                }
                gft_sp.ret.append (gft_sp.s_str);
                state = TEXT;
            }
            break;

            default:
            {
                gft_sp.ret.push_back (LOG4CPLUS_TEXT ('%'));
                gft_sp.ret.push_back (*fmt_it);
                state = TEXT;
            }
            }
        }
        break;
        }
    }

    // Finally call strftime/wcsftime to format the rest of the string.

    gft_sp.ret.swap (gft_sp.fmt);
    std::size_t buffer_size = gft_sp.fmt.size () + 1;
    std::size_t len;

    // Limit how far can the buffer grow. This is necessary so that we
    // catch bad format string. Some implementations of strftime() signal
    // both too small buffer and invalid format string by returning 0
    // without changing errno.
    std::size_t const buffer_size_max
        = (std::max) (static_cast<std::size_t>(1024), buffer_size * 16);

    do
    {
        gft_sp.buffer.resize (buffer_size);
        errno = 0;
#ifdef UNICODE
        len = helpers::wcsftime(&gft_sp.buffer[0], buffer_size,
            gft_sp.fmt.c_str(), &time);
#else
        len = helpers::strftime(&gft_sp.buffer[0], buffer_size,
            gft_sp.fmt.c_str(), &time);
#endif
        if (len == 0)
        {
            int const eno = errno;
            buffer_size *= 2;
            if (buffer_size > buffer_size_max)
            {
                LogLog::getLogLog ()->error (
                    LOG4CPLUS_TEXT("Error in strftime(): ")
                    + convertIntegerToString (eno), true);
            }
        }
    }
    while (len == 0);

    return tstring (gft_sp.buffer.begin (), gft_sp.buffer.begin () + len);
}

Time&
Time::operator+=(const Time& rhs)
{
    tv_sec += rhs.tv_sec;
    tv_usec += rhs.tv_usec;

    if(tv_usec > ONE_SEC_IN_USEC) {
        ++tv_sec;
        tv_usec -= ONE_SEC_IN_USEC;
    }

    return *this;
}

Time&
Time::operator-=(const Time& rhs)
{
    tv_sec -= rhs.tv_sec;
    tv_usec -= rhs.tv_usec;

    if(tv_usec < 0) {
        --tv_sec;
        tv_usec += ONE_SEC_IN_USEC;
    }

    return *this;
}

Time&
Time::operator/=(long rhs)
{
    long rem_secs = static_cast<long>(tv_sec % rhs);
    tv_sec /= rhs;

    tv_usec /= rhs;
    tv_usec += static_cast<long>((rem_secs * ONE_SEC_IN_USEC) / rhs);

    return *this;
}

Time&
Time::operator*=(long rhs)
{
    long new_usec = tv_usec * rhs;
    long overflow_sec = new_usec / ONE_SEC_IN_USEC;
    tv_usec = new_usec % ONE_SEC_IN_USEC;

    tv_sec *= rhs;
    tv_sec += overflow_sec;

    return *this;
}

//////////////////////////////////////////////////////////////////////////////
// Time globals
//////////////////////////////////////////////////////////////////////////////

const Time
operator+(const Time& lhs, const Time& rhs)
{
    return Time(lhs) += rhs;
}

const Time
operator-(const Time& lhs, const Time& rhs)
{
    return Time(lhs) -= rhs;
}

const Time
operator/(const Time& lhs, long rhs)
{
    return Time(lhs) /= rhs;
}

const Time
operator*(const Time& lhs, long rhs)
{
    return Time(lhs) *= rhs;
}

bool
operator<(const Time& lhs, const Time& rhs)
{
    return (   (lhs.sec() < rhs.sec())
            || (   (lhs.sec() == rhs.sec())
                && (lhs.usec() < rhs.usec())) );
}

bool
operator<=(const Time& lhs, const Time& rhs)
{
    return ((lhs < rhs) || (lhs == rhs));
}

bool
operator>(const Time& lhs, const Time& rhs)
{
    return (   (lhs.sec() > rhs.sec())
            || (   (lhs.sec() == rhs.sec())
                && (lhs.usec() > rhs.usec())) );
}

bool
operator>=(const Time& lhs, const Time& rhs)
{
    return ((lhs > rhs) || (lhs == rhs));
}

bool
operator==(const Time& lhs, const Time& rhs)
{
    return (   lhs.sec() == rhs.sec()
            && lhs.usec() == rhs.usec());
}

bool
operator!=(const Time& lhs, const Time& rhs)
{
    return !(lhs == rhs);
}

} } // namespace log4cplus { namespace helpers {
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIMinibidiVisualMapping.cpp
    created:    Wed Aug 5 2009
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "CEGUIConfig.h"

#ifdef CEGUI_USE_MINIBIDI

#include "CEGUIMinibidiVisualMapping.h"
#include "CEGUILogger.h"

// include minibidi code directly
#include "minibidi.cpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
BidiCharType MinibidiVisualMapping::getBidiCharType(const utf32 char_to_check) const
{
    switch (getType(char_to_check))
    {
    case R:
        return BCT_RIGHT_TO_LEFT;
        break;

    case L:
        return BCT_LEFT_TO_RIGHT;
        break;

    default:
        return BCT_NEUTRAL;
        break;
    }
}

//----------------------------------------------------------------------------//
bool MinibidiVisualMapping::reorderFromLogicalToVisual(const String& logical,
                                                       String& visual,
                                                       StrIndexList& l2v,
                                                       StrIndexList& v2l) const
{
    visual = logical;

    if (logical.length() <= 1)
        return true;

    l2v.resize(logical.length());
    v2l.resize(logical.length());

    const int res = doBidi(visual.ptr(), static_cast<int>(logical.length()),
                           true, false,
                           &v2l[0], &l2v[0]);

    // success?
    if (res)
        return true;

    // log failure and continue anyway :-p
    Logger::getSingleton().logEvent(
        "MinibidiVisualMapping::reorderFromLogicalToVisual: doBidi call failed "
        "on logical string: " + logical, Errors);

    return false;
}

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

} // End of  CEGUI namespace section

#endif // CEGUI_USE_MINIBIDI
<commit_msg>FIX: Do not log non-errors as errors when using minibidi.  See: http://www.cegui.org.uk/phpBB2/viewtopic.php?f=10&t=4356<commit_after>/***********************************************************************
    filename:   CEGUIMinibidiVisualMapping.cpp
    created:    Wed Aug 5 2009
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

#include "CEGUIConfig.h"

#ifdef CEGUI_USE_MINIBIDI

#include "CEGUIMinibidiVisualMapping.h"
#include "CEGUILogger.h"

// include minibidi code directly
#include "minibidi.cpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
BidiCharType MinibidiVisualMapping::getBidiCharType(const utf32 char_to_check) const
{
    switch (getType(char_to_check))
    {
    case R:
        return BCT_RIGHT_TO_LEFT;
        break;

    case L:
        return BCT_LEFT_TO_RIGHT;
        break;

    default:
        return BCT_NEUTRAL;
        break;
    }
}

//----------------------------------------------------------------------------//
bool MinibidiVisualMapping::reorderFromLogicalToVisual(const String& logical,
                                                       String& visual,
                                                       StrIndexList& l2v,
                                                       StrIndexList& v2l) const
{
    visual = logical;

    if (logical.length() <= 1)
        return true;

    l2v.resize(logical.length());
    v2l.resize(logical.length());

    doBidi(visual.ptr(), static_cast<int>(logical.length()),
           true, false,
           &v2l[0], &l2v[0]);

    return true;
}

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

} // End of  CEGUI namespace section

#endif // CEGUI_USE_MINIBIDI
<|endoftext|>


<commit_before>/** @file main.cpp
 *  @brief
 *
 *  @author Viacheslav Kroilov (metopa) <slavakroilov@gmail.com>
 */

#include "MurmurHash2.h"

int main() {
	MurmurHash2(nullptr, 0, 0);
	return 0;
}
<commit_msg>example initial commit<commit_after>/** @file main.cpp
 *  @brief
 *
 *  @author Viacheslav Kroilov (metopa) <slavakroilov@gmail.com>
 */

#include <iostream>
#include "murmurhash2functor.h"

int main() {
	mmh2::MurmurHash2<int> h;
	std::cout << h(700) << std::endl;
	return 0;
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QDir>
#include <QDebug>
#include <QMutexLocker>
#include <QCoreApplication>

#include "taslogger.h"
#include "tascoreutils.h"

#ifdef Q_OS_SYMBIAN
const char* const C_LOG_PATH = "c:\\logs\\testability\\";
const char* const E_LOG_PATH = "e:\\logs\\testability\\";
#else
const char* const LOG_PATH = "/logs/testability/";
#endif
const int LOG_SIZE = 100000;

void debugOutput(QtMsgType type, const char *msg)
{
    QString message(msg);
    if (message.length() <= 0)
      return;
    switch (type)
        {
        case QtDebugMsg:
            TasLogger::logger()->debug(message);
            break;
        case QtWarningMsg:
            TasLogger::logger()->warning(message);
            break;
        case QtCriticalMsg:
            TasLogger::logger()->error(message);
            break;
        case QtFatalMsg:
            TasLogger::logger()->fatal(message);
            break;
        }
}

TasLogger* TasLogger::mInstance = 0;

TasLogger::TasLogger()
{
    mLogSize = LOG_SIZE;
    mEnabled = false;
    mUseQDebug = false;
    mCurrentLevel = INFO;
    mLogFileName = TasCoreUtils::getApplicationName()+".log";
#ifdef Q_OS_SYMBIAN
    if(QDir(E_LOG_PATH).exists()){
        mLogPath = E_LOG_PATH;
    }
    else{
        mLogPath = C_LOG_PATH;
    }
#else
    mLogPath = LOG_PATH;
#endif
    mOut = 0;
    mEventLogger = new EventLogger();
    mLastLogRollCheck = QTime::currentTime();
}

/*!
  Configures the logger based on the command data.
  Logger will not check the sanity of the settings.
 */
void TasLogger::configureLogger(TasCommand& command)
{
    disableLogger();

    if(command.parameter(CLEAR_LOG) == "true"){
        clearLogFile();
    }

    if(command.parameter(LOG_LEVEL) == "FATAL"){
        setLevel(FATAL);
    }
    else if(command.parameter(LOG_LEVEL) == "ERROR"){
        setLevel(ERROR);
    }
    else if(command.parameter(LOG_LEVEL) == "INFO"){
        setLevel(INFO);
    }
    else if(command.parameter(LOG_LEVEL) == "WARNING"){
        setLevel(WARNING);
    }
    else if(command.parameter(LOG_LEVEL) == "DEBUG"){
        setLevel(DEBUG);
    }

    if(command.parameter(LOG_TO_QDEBUG) == "true"){
        mUseQDebug = true;
    }
    else if(command.parameter(LOG_TO_QDEBUG) == "false"){
        mUseQDebug = false;
    }

    if(!command.parameter(LOG_FOLDER).isEmpty()){
        mLogPath = command.parameter(LOG_FOLDER);
        QDir().mkpath(mLogPath);
    }

//     if(!command.parameter(LOG_FILE).isEmpty()){
//         mLogFileName = command.parameter(LOG_FILE);
//     }

    if(command.parameter(LOG_QDEBUG) == "true"){
        setOutputter(true);
    }
    else if(command.parameter(LOG_QDEBUG) == "false"){
        setOutputter(false);
    }

    if(!command.parameter(LOG_FILE_SIZE).isEmpty()){
        mLogSize = command.parameter(LOG_FILE_SIZE).toInt();
    }

    //by default logger is enabled always
    if(command.parameter(LOG_ENABLE) != "false" && !mUseQDebug){
        enableLogger();
    }
}

void TasLogger::configureEventLogger(TasCommand& command)
{
    if(command.parameter(LOG_EVENTS) == "true"){
        QStringList events;
        if(!command.text().isEmpty()){
            events = command.text().split(",");
        }
        logEvents(events);
    }
    else if(command.parameter(LOG_EVENTS) == "false"){
        stopEventLogging();
    }
}

void TasLogger::setLogSize(int size)
{
    mLogSize = size;
}

TasLogger::~TasLogger()
{
    disableLogger();
    delete mEventLogger;
}

void TasLogger::enableLogger()
{
	QMutexLocker locker(&mMutex);
    mLastLogRollCheck.restart();
    if(!mEnabled && QDir(mLogPath).exists()){
        QString fileName = mLogPath+mLogFileName;
        mOut = new QFile(fileName);
        if(mOut->exists(fileName) && mOut->size() > mLogSize){
            QString storageName = mLogPath + "old_" + mLogFileName;
            QFile::remove(storageName);
            QFile::rename(fileName, storageName);
            mOut->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
        }
        else{
            mOut->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
        }
        mEnabled = true;
    }
}

/*!
  Disables the logger.
 */
void TasLogger::disableLogger()
{
	QMutexLocker locker(&mMutex);
    mEnabled = false;
    if(mOut){
        mOut->close();
        delete mOut;
        mOut = 0;
    }
}

void TasLogger::clearLogFile()
{
    if(mOut){
        mOut->remove();
        mOut->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
    }
    else{
        QFile::remove(mLogPath+mLogFileName);
    }
}

/*!
  Returns the only instance of the logger.
 */
TasLogger* TasLogger::logger()
{
    if(!mInstance){
        mInstance = new TasLogger();
    }
    return mInstance;
}

void TasLogger::removeLogger()
{
    if(mInstance){
        delete mInstance;
        mInstance = 0;
    }

}

void TasLogger::debug(const QString message)
{
    writeLogLine(DEBUG, message);
}

void TasLogger::info(const QString message)
{
    writeLogLine(INFO, message);
}

void TasLogger::error(const QString message)
{
    writeLogLine(ERROR, message);
}

void TasLogger::warning(const QString message)
{
    writeLogLine(WARNING, message);
}

void TasLogger::fatal(const QString message)
{
    writeLogLine(FATAL, message);
}

void TasLogger::setLevel(const LogType& level)
{
    mCurrentLevel = level;

}

/*!
  Set the file and path to where to write the logs. The path needs to exists
  and is not created by the logger. logPath will default to /logs/testability
  if not set. Will also enable the logger.
 */
void TasLogger::setLogFile(const QString logFileName)
{
    mLogFileName = logFileName;
    disableLogger();
    enableLogger();
}

void TasLogger::setLogDir(const QString logPath)
{
    mLogPath = logPath;
    disableLogger();
    enableLogger();
}

void TasLogger::writeLogLine(LogType type, const QString& message)
{
    if(mEnabled && type <= mCurrentLevel){

        if(message.contains("QMetaProperty::read")) return;

        if(!mUseQDebug){
            //check is rolling needed. Done hourly
            if(mLastLogRollCheck.elapsed() > 600000){
                disableLogger();
                enableLogger();
            }
        }
        QString line;
        QTextStream out(&line);

        out << "<";
        out << QTime::currentTime().toString("hh:mm:ss.zzz").toAscii();
        out << ">";
        switch (type) {
        case FATAL:
            out << "FATAL: ";
            break;
        case ERROR:
            out << "ERROR: ";
            break;
        case INFO:
            out << "INFO: ";
            break;
        case WARNING:
            out << "WARNING: ";
            break;
        case DEBUG:
            out << "DEBUG: ";
            break;
        }
        out << message;
        outPut(line);
    }
}

void TasLogger::outPut(const QString& line)
{
    if(mUseQDebug){
        qDebug() << line;
    }
    else{
        QMutexLocker locker(&mMutex);
        mOut->write(line.toAscii());
        mOut->write("\n");
        mOut->flush();
    }
}

/*!
  Directs all output from this logger to qDebug if true.
 */
void TasLogger::useQDebug(bool use)
{
    mUseQDebug = use;
    if(mUseQDebug){
        //disable release the log file if there is one
        disableLogger();
        //enable to allow logging (uses qdebug for output)
        mEnabled = true;
    }
    else{
        enableLogger();
    }
}

/*!
  Set to intercept qDebug messages
 */
void TasLogger::setOutputter(bool intercept)
{
    if(intercept){
        qInstallMsgHandler(debugOutput);
    }
    else{
        qInstallMsgHandler(0);
    }
}

void TasLogger::logEvents(QStringList filters)
{
    if(QCoreApplication::instance()){
        debug("TasLogger::logEvents " + filters.join(","));
        mEventLogger->setFilterStrings(filters);
        QCoreApplication::instance()->installEventFilter(mEventLogger);
    }
    else{
        debug("TasLogger::logEvents Cannot set event logging, no qApp!");
    }
}

void TasLogger::stopEventLogging()
{
    if(QCoreApplication::instance()){
        QCoreApplication::instance()->removeEventFilter(mEventLogger);
        mEventLogger->setFilterStrings(QStringList());
    }
}

bool EventLogger::eventFilter(QObject *target, QEvent *event)
{
    QString eventType = TasCoreUtils::eventType(event);
    if(logEvent(eventType)){
        QString objectName = target->objectName();
        QString className  = target->metaObject()->className();
        QString line = "Event type: ";

        QTextStream(&line) <<  TasCoreUtils::eventType(event) << " target class: " << target->metaObject()->className() << " target id: " << TasCoreUtils::objectId(target);

        TasLogger::logger()->debug(line);
    }
    return false;
}

void EventLogger::setFilterStrings(QStringList filterStrings)
{
    mFilterStrings = filterStrings;
}

bool EventLogger::logEvent(QString eventType)
{
    if(mFilterStrings.size() == 0){
        return true;
    }
    for (int i = 0; i < mFilterStrings.size(); ++i){
        if(eventType.contains(mFilterStrings.at(i))){
            return true;
        }
    }
    return false;
}
<commit_msg>Modified to support disabling and modifying<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QDir>
#include <QDebug>
#include <QMutexLocker>
#include <QCoreApplication>

#include "taslogger.h"
#include "tascoreutils.h"

#ifdef Q_OS_SYMBIAN
const char* const C_LOG_PATH = "c:\\logs\\testability\\";
const char* const E_LOG_PATH = "e:\\logs\\testability\\";
#else
const char* const LOG_PATH = "/logs/testability/";
#endif
const int LOG_SIZE = 100000;

void debugOutput(QtMsgType type, const char *msg)
{
    QString message(msg);
    if (message.length() <= 0)
      return;
    switch (type)
        {
        case QtDebugMsg:
            TasLogger::logger()->debug(message);
            break;
        case QtWarningMsg:
            TasLogger::logger()->warning(message);
            break;
        case QtCriticalMsg:
            TasLogger::logger()->error(message);
            break;
        case QtFatalMsg:
            TasLogger::logger()->fatal(message);
            break;
        }
}

TasLogger* TasLogger::mInstance = 0;

TasLogger::TasLogger()
{
    mLogSize = LOG_SIZE;
    mEnabled = false;
    mUseQDebug = false;
    mCurrentLevel = INFO;
    mLogFileName = TasCoreUtils::getApplicationName()+".log";
#ifdef Q_OS_SYMBIAN
    if(QDir(E_LOG_PATH).exists()){
        mLogPath = E_LOG_PATH;
    }
    else{
        mLogPath = C_LOG_PATH;
    }
#else
    mLogPath = LOG_PATH;
#endif
    mOut = 0;
    mEventLogger = new EventLogger();
    mLastLogRollCheck = QTime::currentTime();
}

/*!
  Configures the logger based on the command data.
  Logger will not check the sanity of the settings.
 */
void TasLogger::configureLogger(TasCommand& command)
{
    bool wasLogging = mEnabled;
    debug(command.parameter(CLEAR_LOG));
    if(mEnabled) disableLogger();

    if(command.parameter(CLEAR_LOG) == "true"){
        clearLogFile();
    }

    if(command.parameter(LOG_LEVEL) == "FATAL"){
        setLevel(FATAL);
    }
    else if(command.parameter(LOG_LEVEL) == "ERROR"){
        setLevel(ERROR);
    }
    else if(command.parameter(LOG_LEVEL) == "INFO"){
        setLevel(INFO);
    }
    else if(command.parameter(LOG_LEVEL) == "WARNING"){
        setLevel(WARNING);
    }
    else if(command.parameter(LOG_LEVEL) == "DEBUG"){
        setLevel(DEBUG);
    }

    if(command.parameter(LOG_TO_QDEBUG) == "true"){
        mUseQDebug = true;
    }
    else if(command.parameter(LOG_TO_QDEBUG) == "false"){
        mUseQDebug = false;
    }

    if(!command.parameter(LOG_FOLDER).isEmpty()){
        mLogPath = command.parameter(LOG_FOLDER);
        QDir().mkpath(mLogPath);
    }

//     if(!command.parameter(LOG_FILE).isEmpty()){
//         mLogFileName = command.parameter(LOG_FILE);
//     }

    if(command.parameter(LOG_QDEBUG) == "true"){
        setOutputter(true);
    }
    else if(command.parameter(LOG_QDEBUG) == "false"){
        setOutputter(false);
    }

    if(!command.parameter(LOG_FILE_SIZE).isEmpty()){
        mLogSize = command.parameter(LOG_FILE_SIZE).toInt();
    }

    //enable the logger unless instructed not to or if it was not on to begin with
    if( ( (wasLogging && command.parameter(LOG_ENABLE) != "false") || command.parameter(LOG_ENABLE) == "true") && !mUseQDebug){
        enableLogger();
        debug("TasLogger::configureLogger configuration done and logging enabled.");
    }
}

void TasLogger::configureEventLogger(TasCommand& command)
{
    if(command.parameter(LOG_EVENTS) == "true"){
        QStringList events;
        if(!command.text().isEmpty()){
            events = command.text().split(",");
        }
        logEvents(events);
    }
    else if(command.parameter(LOG_EVENTS) == "false"){
        stopEventLogging();
    }
}

void TasLogger::setLogSize(int size)
{
    mLogSize = size;
}

TasLogger::~TasLogger()
{
    disableLogger();
    delete mEventLogger;
}

void TasLogger::enableLogger()
{
	QMutexLocker locker(&mMutex);
    mLastLogRollCheck.restart();
    if(!mEnabled && QDir(mLogPath).exists()){
        QString fileName = mLogPath+"/"+mLogFileName;
        mOut = new QFile(fileName);
        if(mOut->exists(fileName) && mOut->size() > mLogSize){
            QString storageName = mLogPath + "old_" + mLogFileName;
            QFile::remove(storageName);
            QFile::rename(fileName, storageName);
            mOut->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
        }
        else{
            mOut->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
        }
        mEnabled = true;
    }
}

/*!
  Disables the logger.
 */
void TasLogger::disableLogger()
{
	QMutexLocker locker(&mMutex);
    mEnabled = false;
    if(mOut){
        mOut->close();
        delete mOut;
        mOut = 0;
    }
}

void TasLogger::clearLogFile()
{
    if(mOut){
        mOut->remove();
        mOut->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
    }
    else{
        QString fileName = mLogPath+"/"+mLogFileName;
        QFile::remove(fileName);
    }
}

/*!
  Returns the only instance of the logger.
 */
TasLogger* TasLogger::logger()
{
    if(!mInstance){
        mInstance = new TasLogger();
    }
    return mInstance;
}

void TasLogger::removeLogger()
{
    if(mInstance){
        delete mInstance;
        mInstance = 0;
    }

}

void TasLogger::debug(const QString message)
{
    writeLogLine(DEBUG, message);
}

void TasLogger::info(const QString message)
{
    writeLogLine(INFO, message);
}

void TasLogger::error(const QString message)
{
    writeLogLine(ERROR, message);
}

void TasLogger::warning(const QString message)
{
    writeLogLine(WARNING, message);
}

void TasLogger::fatal(const QString message)
{
    writeLogLine(FATAL, message);
}

void TasLogger::setLevel(const LogType& level)
{
    mCurrentLevel = level;

}

/*!
  Set the file and path to where to write the logs. The path needs to exists
  and is not created by the logger. logPath will default to /logs/testability
  if not set. Will also enable the logger.
 */
void TasLogger::setLogFile(const QString logFileName)
{
    mLogFileName = logFileName;
    disableLogger();
    enableLogger();
}

void TasLogger::setLogDir(const QString logPath)
{
    mLogPath = logPath;
    disableLogger();
    enableLogger();
}

void TasLogger::writeLogLine(LogType type, const QString& message)
{
    if(mEnabled && type <= mCurrentLevel){

        if(message.contains("QMetaProperty::read")) return;

        if(!mUseQDebug){
            //check is rolling needed. Done hourly
            if(mLastLogRollCheck.elapsed() > 600000){
                disableLogger();
                enableLogger();
            }
        }
        QString line;
        QTextStream out(&line);

        out << "<";
        out << QTime::currentTime().toString("hh:mm:ss.zzz").toAscii();
        out << ">";
        switch (type) {
        case FATAL:
            out << "FATAL: ";
            break;
        case ERROR:
            out << "ERROR: ";
            break;
        case INFO:
            out << "INFO: ";
            break;
        case WARNING:
            out << "WARNING: ";
            break;
        case DEBUG:
            out << "DEBUG: ";
            break;
        }
        out << message;
        outPut(line);
    }
}

void TasLogger::outPut(const QString& line)
{
    if(mUseQDebug){
        qDebug() << line;
    }
    else{
        QMutexLocker locker(&mMutex);
        mOut->write(line.toAscii());
        mOut->write("\n");
        mOut->flush();
    }
}

/*!
  Directs all output from this logger to qDebug if true.
 */
void TasLogger::useQDebug(bool use)
{
    mUseQDebug = use;
    if(mUseQDebug){
        //disable release the log file if there is one
        disableLogger();
        //enable to allow logging (uses qdebug for output)
        mEnabled = true;
    }
    else{
        enableLogger();
    }
}

/*!
  Set to intercept qDebug messages
 */
void TasLogger::setOutputter(bool intercept)
{
    if(intercept){
        qInstallMsgHandler(debugOutput);
    }
    else{
        qInstallMsgHandler(0);
    }
}

void TasLogger::logEvents(QStringList filters)
{
    if(QCoreApplication::instance()){
        debug("TasLogger::logEvents " + filters.join(","));
        mEventLogger->setFilterStrings(filters);
        QCoreApplication::instance()->installEventFilter(mEventLogger);
    }
    else{
        debug("TasLogger::logEvents Cannot set event logging, no qApp!");
    }
}

void TasLogger::stopEventLogging()
{
    if(QCoreApplication::instance()){
        QCoreApplication::instance()->removeEventFilter(mEventLogger);
        mEventLogger->setFilterStrings(QStringList());
    }
}

bool EventLogger::eventFilter(QObject *target, QEvent *event)
{
    QString eventType = TasCoreUtils::eventType(event);
    if(logEvent(eventType)){
        QString objectName = target->objectName();
        QString className  = target->metaObject()->className();
        QString line = "Event type: ";

        QTextStream(&line) <<  TasCoreUtils::eventType(event) << " target class: " << target->metaObject()->className() << " target id: " << TasCoreUtils::objectId(target);

        TasLogger::logger()->debug(line);
    }
    return false;
}

void EventLogger::setFilterStrings(QStringList filterStrings)
{
    mFilterStrings = filterStrings;
}

bool EventLogger::logEvent(QString eventType)
{
    if(mFilterStrings.size() == 0){
        return true;
    }
    for (int i = 0; i < mFilterStrings.size(); ++i){
        if(eventType.contains(mFilterStrings.at(i))){
            return true;
        }
    }
    return false;
}
<|endoftext|>