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

#ifndef OOX_XLS_WORKBOOKHELPER_HXX
#define OOX_XLS_WORKBOOKHELPER_HXX

#include <boost/shared_ptr.hpp>
#include <rtl/ref.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include "oox/xls/biffhelper.hxx"

namespace com { namespace sun { namespace star {
    namespace container { class XNameAccess; }
    namespace container { class XNameContainer; }
    namespace awt { class XDevice; }
    namespace sheet { class XSpreadsheetDocument; }
    namespace sheet { class XSpreadsheet; }
    namespace sheet { class XNamedRanges; }
    namespace sheet { class XDatabaseRanges; }
    namespace style { class XStyle; }
} } }

namespace oox {
    class AttributeList;
    class SegmentProgressBar;
    class RecordInputStream;
}

namespace oox { namespace core {
    class BinaryFilterBase;
    class FilterBase;
    class FragmentHandler;
    class XmlFilterBase;
} }

namespace oox {
namespace xls {

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

/** An enumeration for all supported spreadsheet filter types. */
enum FilterType
{
    FILTER_OOX,         /// MS Excel OOXML (Office Open XML) or OOBIN.
    FILTER_BIFF,        /// MS Excel BIFF (Binary Interchange File Format).
    FILTER_UNKNOWN      /// Unknown filter type.
};

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

#if OSL_DEBUG_LEVEL > 0

class WorkbookHelperDebug
{
public:
    inline explicit     WorkbookHelperDebug( sal_Int32& rnCount ) : mrnCount( rnCount ) { ++mrnCount; }
    inline explicit     WorkbookHelperDebug( const WorkbookHelperDebug& rCopy ) : mrnCount( rCopy.mrnCount ) { ++mrnCount; }
    virtual             ~WorkbookHelperDebug() { --mrnCount; }
private:
    sal_Int32&          mrnCount;
};

#endif

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

class WorkbookData;
class WorkbookSettings;
class ViewSettings;
class WorksheetBuffer;
class ThemeBuffer;
class StylesBuffer;
class SharedStringsBuffer;
class ExternalLinkBuffer;
class DefinedNamesBuffer;
class TableBuffer;
class WebQueryBuffer;
class PivotTableBuffer;
class FormulaParser;
class UnitConverter;
class AddressConverter;
class StylesPropertyHelper;
class PageSettingsPropertyHelper;
class ValidationPropertyHelper;

/** Helper class to provice access to global workbook data.

    All classes derived from this helper class will have access to a singleton
    object of type WorkbookData containing global workbook settings, buffers,
    converters, etc. Nearly all classes in this filter implementation are
    derived directly or indirectly from this class.
 */
class WorkbookHelper
#if OSL_DEBUG_LEVEL > 0
    : private WorkbookHelperDebug
#endif
{
public:
    explicit            WorkbookHelper( WorkbookData& rBookData );
    virtual             ~WorkbookHelper();

    // filter -----------------------------------------------------------------

    /** Returns the base filter object (base class of all filters). */
    ::oox::core::FilterBase& getBaseFilter() const;
    /** Returns the file type of the current filter. */
    FilterType          getFilterType() const;
    /** Returns the filter progress bar. */
    SegmentProgressBar& getProgressBar() const;
    /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */
    bool                isWorkbookFile() const;

    /** Final conversion after importing the workbook. */
    void                finalizeWorkbookImport();

    // document model ---------------------------------------------------------

    /** Returns a reference to the source/target spreadsheet document model. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument >
                        getDocument() const;
    /** Returns a reference to the specified spreadsheet in the document model. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >
                        getSheet( sal_Int32 nSheet ) const;
    /** Returns the reference device of the document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice >
                        getReferenceDevice() const;
    /** Returns the container for defined names from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XNamedRanges >
                        getNamedRanges() const;
    /** Returns the container for database ranges from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDatabaseRanges >
                        getDatabaseRanges() const;
    /** Returns the container for DDE links from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >
                        getDdeLinks() const;

    /** Returns the cell or page styles container from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >
                        getStyleFamily( bool bPageStyles ) const;
    /** Returns the specified cell or page style from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle >
                        getStyleObject( const ::rtl::OUString& rStyleName, bool bPageStyle ) const;

    /** Creates a com.sun.star.style.Style object and returns its final name. */
    ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle >
                        createStyleObject(
                            ::rtl::OUString& orStyleName,
                            bool bPageStyle,
                            bool bRenameOldExisting = false );

    // buffers ----------------------------------------------------------------

    /** Returns the global workbook settings object. */
    WorkbookSettings&   getWorkbookSettings() const;
    /** Returns the workbook and sheet view settings object. */
    ViewSettings&       getViewSettings() const;
    /** Returns the worksheet buffer containing sheet names and properties. */
    WorksheetBuffer&    getWorksheets() const;
    /** Returns the office theme object read from the theme substorage. */
    ThemeBuffer&        getTheme() const;
    /** Returns all cell formatting objects read from the styles substream. */
    StylesBuffer&       getStyles() const;
    /** Returns the shared strings read from the shared strings substream. */
    SharedStringsBuffer& getSharedStrings() const;
    /** Returns the external links read from the external links substream. */
    ExternalLinkBuffer& getExternalLinks() const;
    /** Returns the defined names read from the workbook globals. */
    DefinedNamesBuffer& getDefinedNames() const;
    /** Returns the tables collection (equivalent to Calc's database ranges). */
    TableBuffer&        getTables() const;
    /** Returns the web queries. */
    WebQueryBuffer&     getWebQueries() const;
    /** Returns the pivot tables. */
    PivotTableBuffer&   getPivotTables() const;

    // converters -------------------------------------------------------------

    /** Returns the import formula parser. */
    FormulaParser&      getFormulaParser() const;
    /** Returns the measurement unit converter. */
    UnitConverter&      getUnitConverter() const;
    /** Returns the converter for string to cell address/range conversion. */
    AddressConverter&   getAddressConverter() const;
    /** Returns the converter for properties related to cell styles. */
    StylesPropertyHelper& getStylesPropertyHelper() const;
    /** Returns the converter for properties related to page and print settings. */
    PageSettingsPropertyHelper& getPageSettingsPropertyHelper() const;
    /** Returns the converter for properties related to data validation. */
    ValidationPropertyHelper& getValidationPropertyHelper() const;

    // OOX specific -----------------------------------------------------------

    /** Returns the base OOX filter object.
        Must not be called, if current filter is not the OOX filter. */
    ::oox::core::XmlFilterBase& getOoxFilter() const;

    /** Imports a fragment using the passed fragment handler, which contains
        the full path to the fragment stream. */
    bool                importOoxFragment( const ::rtl::Reference< ::oox::core::FragmentHandler >& rxHandler );

    // BIFF specific ----------------------------------------------------------

    /** Returns the base BIFF filter object. */
    ::oox::core::BinaryFilterBase& getBiffFilter() const;
    /** Returns the BIFF type in binary filter. */
    BiffType            getBiff() const;

    /** Returns the text encoding used to import/export byte strings. */
    rtl_TextEncoding    getTextEncoding() const;
    /** Sets the text encoding to import/export byte strings. */
    void                setTextEncoding( rtl_TextEncoding eTextEnc );
    /** Sets code page read from a CODEPAGE record for byte string import. */
    void                setCodePage( sal_uInt16 nCodePage );
    /** Sets text encoding from the default application font, if CODEPAGE record is missing. */
    void                setAppFontEncoding( rtl_TextEncoding eAppFontEnc );

    /** Enables workbook file mode, used for BIFF4 workspace files. */
    void                setIsWorkbookFile();
    /** Recreates global buffers that are used per sheet in specific BIFF versions. */
    void                createBuffersPerSheet();

    /** Looks for a password provided via API, or queries it via GUI. */
    ::rtl::OUString     queryPassword() const;

private:
    WorkbookData&       mrBookData;
};

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

namespace prv {

typedef ::boost::shared_ptr< WorkbookData > WorkbookDataRef;

struct WorkbookDataOwner
{
    explicit            WorkbookDataOwner( WorkbookDataRef xBookData );
    virtual             ~WorkbookDataOwner();
    WorkbookDataRef     mxBookData;
};

} // namespace prv

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

class WorkbookHelperRoot : private prv::WorkbookDataOwner, public WorkbookHelper
{
public:
    explicit            WorkbookHelperRoot( ::oox::core::XmlFilterBase& rFilter );
    explicit            WorkbookHelperRoot( ::oox::core::BinaryFilterBase& rFilter, BiffType eBiff );

    /** Returns true, if this helper refers to a valid document. */
    bool                isValid() const;

private:
                        WorkbookHelperRoot( const WorkbookHelperRoot& );
    WorkbookHelperRoot& operator=( const WorkbookHelperRoot& );
};

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

} // namespace xls
} // namespace oox

#endif

<commit_msg>INTEGRATION: CWS xmlfilter03_DEV300 (1.2.4); FILE MERGED 2008/02/12 11:33:09 dr 1.2.4.1: handle drawing fragment in WorksheetHelper<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: workbookhelper.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-05 18:10:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef OOX_XLS_WORKBOOKHELPER_HXX
#define OOX_XLS_WORKBOOKHELPER_HXX

#include <boost/shared_ptr.hpp>
#include <rtl/ref.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include "oox/xls/biffhelper.hxx"

namespace com { namespace sun { namespace star {
    namespace container { class XNameAccess; }
    namespace container { class XNameContainer; }
    namespace awt { class XDevice; }
    namespace sheet { class XSpreadsheetDocument; }
    namespace sheet { class XSpreadsheet; }
    namespace sheet { class XNamedRanges; }
    namespace sheet { class XDatabaseRanges; }
    namespace style { class XStyle; }
} } }

namespace oox {
    class AttributeList;
    class SegmentProgressBar;
    class RecordInputStream;
}

namespace oox { namespace core {
    class BinaryFilterBase;
    class FilterBase;
    class FragmentHandler;
    class XmlFilterBase;
} }

namespace oox {
namespace xls {

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

/** An enumeration for all supported spreadsheet filter types. */
enum FilterType
{
    FILTER_OOX,         /// MS Excel OOXML (Office Open XML) or OOBIN.
    FILTER_BIFF,        /// MS Excel BIFF (Binary Interchange File Format).
    FILTER_UNKNOWN      /// Unknown filter type.
};

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

#if OSL_DEBUG_LEVEL > 0

class WorkbookHelperDebug
{
public:
    inline explicit     WorkbookHelperDebug( sal_Int32& rnCount ) : mrnCount( rnCount ) { ++mrnCount; }
    inline explicit     WorkbookHelperDebug( const WorkbookHelperDebug& rCopy ) : mrnCount( rCopy.mrnCount ) { ++mrnCount; }
    virtual             ~WorkbookHelperDebug() { --mrnCount; }
private:
    sal_Int32&          mrnCount;
};

#endif

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

class WorkbookData;
class WorkbookSettings;
class ViewSettings;
class WorksheetBuffer;
class ThemeBuffer;
class StylesBuffer;
class SharedStringsBuffer;
class ExternalLinkBuffer;
class DefinedNamesBuffer;
class TableBuffer;
class WebQueryBuffer;
class PivotTableBuffer;
class FormulaParser;
class UnitConverter;
class AddressConverter;
class StylesPropertyHelper;
class PageSettingsPropertyHelper;
class ValidationPropertyHelper;

/** Helper class to provice access to global workbook data.

    All classes derived from this helper class will have access to a singleton
    object of type WorkbookData containing global workbook settings, buffers,
    converters, etc. Nearly all classes in this filter implementation are
    derived directly or indirectly from this class.
 */
class WorkbookHelper
#if OSL_DEBUG_LEVEL > 0
    : private WorkbookHelperDebug
#endif
{
public:
    /*implicit*/        WorkbookHelper( WorkbookData& rBookData );
    virtual             ~WorkbookHelper();

    // filter -----------------------------------------------------------------

    /** Returns the base filter object (base class of all filters). */
    ::oox::core::FilterBase& getBaseFilter() const;
    /** Returns the file type of the current filter. */
    FilterType          getFilterType() const;
    /** Returns the filter progress bar. */
    SegmentProgressBar& getProgressBar() const;
    /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */
    bool                isWorkbookFile() const;

    /** Final conversion after importing the workbook. */
    void                finalizeWorkbookImport();

    // document model ---------------------------------------------------------

    /** Returns a reference to the source/target spreadsheet document model. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument >
                        getDocument() const;
    /** Returns a reference to the specified spreadsheet in the document model. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >
                        getSheet( sal_Int32 nSheet ) const;
    /** Returns the reference device of the document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDevice >
                        getReferenceDevice() const;
    /** Returns the container for defined names from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XNamedRanges >
                        getNamedRanges() const;
    /** Returns the container for database ranges from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDatabaseRanges >
                        getDatabaseRanges() const;
    /** Returns the container for DDE links from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >
                        getDdeLinks() const;

    /** Returns the cell or page styles container from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >
                        getStyleFamily( bool bPageStyles ) const;
    /** Returns the specified cell or page style from the Calc document. */
    ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle >
                        getStyleObject( const ::rtl::OUString& rStyleName, bool bPageStyle ) const;

    /** Creates a com.sun.star.style.Style object and returns its final name. */
    ::com::sun::star::uno::Reference< ::com::sun::star::style::XStyle >
                        createStyleObject(
                            ::rtl::OUString& orStyleName,
                            bool bPageStyle,
                            bool bRenameOldExisting = false );

    // buffers ----------------------------------------------------------------

    /** Returns the global workbook settings object. */
    WorkbookSettings&   getWorkbookSettings() const;
    /** Returns the workbook and sheet view settings object. */
    ViewSettings&       getViewSettings() const;
    /** Returns the worksheet buffer containing sheet names and properties. */
    WorksheetBuffer&    getWorksheets() const;
    /** Returns the office theme object read from the theme substorage. */
    ThemeBuffer&        getTheme() const;
    /** Returns all cell formatting objects read from the styles substream. */
    StylesBuffer&       getStyles() const;
    /** Returns the shared strings read from the shared strings substream. */
    SharedStringsBuffer& getSharedStrings() const;
    /** Returns the external links read from the external links substream. */
    ExternalLinkBuffer& getExternalLinks() const;
    /** Returns the defined names read from the workbook globals. */
    DefinedNamesBuffer& getDefinedNames() const;
    /** Returns the tables collection (equivalent to Calc's database ranges). */
    TableBuffer&        getTables() const;
    /** Returns the web queries. */
    WebQueryBuffer&     getWebQueries() const;
    /** Returns the pivot tables. */
    PivotTableBuffer&   getPivotTables() const;

    // converters -------------------------------------------------------------

    /** Returns the import formula parser. */
    FormulaParser&      getFormulaParser() const;
    /** Returns the measurement unit converter. */
    UnitConverter&      getUnitConverter() const;
    /** Returns the converter for string to cell address/range conversion. */
    AddressConverter&   getAddressConverter() const;
    /** Returns the converter for properties related to cell styles. */
    StylesPropertyHelper& getStylesPropertyHelper() const;
    /** Returns the converter for properties related to page and print settings. */
    PageSettingsPropertyHelper& getPageSettingsPropertyHelper() const;
    /** Returns the converter for properties related to data validation. */
    ValidationPropertyHelper& getValidationPropertyHelper() const;

    // OOX specific -----------------------------------------------------------

    /** Returns the base OOX filter object.
        Must not be called, if current filter is not the OOX filter. */
    ::oox::core::XmlFilterBase& getOoxFilter() const;

    /** Imports a fragment using the passed fragment handler, which contains
        the full path to the fragment stream. */
    bool                importOoxFragment( const ::rtl::Reference< ::oox::core::FragmentHandler >& rxHandler );

    // BIFF specific ----------------------------------------------------------

    /** Returns the base BIFF filter object. */
    ::oox::core::BinaryFilterBase& getBiffFilter() const;
    /** Returns the BIFF type in binary filter. */
    BiffType            getBiff() const;

    /** Returns the text encoding used to import/export byte strings. */
    rtl_TextEncoding    getTextEncoding() const;
    /** Sets the text encoding to import/export byte strings. */
    void                setTextEncoding( rtl_TextEncoding eTextEnc );
    /** Sets code page read from a CODEPAGE record for byte string import. */
    void                setCodePage( sal_uInt16 nCodePage );
    /** Sets text encoding from the default application font, if CODEPAGE record is missing. */
    void                setAppFontEncoding( rtl_TextEncoding eAppFontEnc );

    /** Enables workbook file mode, used for BIFF4 workspace files. */
    void                setIsWorkbookFile();
    /** Recreates global buffers that are used per sheet in specific BIFF versions. */
    void                createBuffersPerSheet();

    /** Looks for a password provided via API, or queries it via GUI. */
    ::rtl::OUString     queryPassword() const;

private:
    WorkbookData&       mrBookData;
};

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

namespace prv {

typedef ::boost::shared_ptr< WorkbookData > WorkbookDataRef;

struct WorkbookDataOwner
{
    explicit            WorkbookDataOwner( WorkbookDataRef xBookData );
    virtual             ~WorkbookDataOwner();
    WorkbookDataRef     mxBookData;
};

} // namespace prv

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

class WorkbookHelperRoot : private prv::WorkbookDataOwner, public WorkbookHelper
{
public:
    explicit            WorkbookHelperRoot( ::oox::core::XmlFilterBase& rFilter );
    explicit            WorkbookHelperRoot( ::oox::core::BinaryFilterBase& rFilter, BiffType eBiff );

    /** Returns true, if this helper refers to a valid document. */
    bool                isValid() const;

private:
                        WorkbookHelperRoot( const WorkbookHelperRoot& );
    WorkbookHelperRoot& operator=( const WorkbookHelperRoot& );
};

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

} // namespace xls
} // namespace oox

#endif

<|endoftext|>


<commit_before>/***********************************************************************
    created:    Tue Feb 17 2009
    author:     Henri I Hyyryläinen (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 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.
 ***************************************************************************/
#include "CEGUI/RendererModules/Ogre/GeometryBuffer.h"
#include "CEGUI/RendererModules/Ogre/Texture.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RenderEffect.h"

#include <OgreRenderSystem.h>
#include <OgreQuaternion.h>
#include <OgreHardwareBufferManager.h>
#include "CEGUI/Exceptions.h"
#include "CEGUI/ShaderParameterBindings.h"

#include "OgreManualObject.h"
#include "OgreRenderOperation.h"
#include "OgreSceneManager.h"

#define INITIAL_BUFFER_SIZE     64

#define FLOATS_PER_TEXTURED     9
#define FLOATS_PER_COLOURED     7

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
static const Ogre::LayerBlendModeEx S_colourBlendMode =
{
    Ogre::LBT_COLOUR,
    Ogre::LBX_MODULATE,
    Ogre::LBS_TEXTURE,
    Ogre::LBS_DIFFUSE,
    Ogre::ColourValue(0, 0, 0, 0),
    Ogre::ColourValue(0, 0, 0, 0),
    0, 0, 0
};

//----------------------------------------------------------------------------//
static const Ogre::LayerBlendModeEx S_alphaBlendMode =
{
    Ogre::LBT_ALPHA,
    Ogre::LBX_MODULATE,
    Ogre::LBS_TEXTURE,
    Ogre::LBS_DIFFUSE,
    Ogre::ColourValue(0, 0, 0, 0),
    Ogre::ColourValue(0, 0, 0, 0),
    0, 0, 0
};

//----------------------------------------------------------------------------//
static const Ogre::TextureUnitState::UVWAddressingMode S_textureAddressMode =
{
    Ogre::TextureUnitState::TAM_CLAMP,
    Ogre::TextureUnitState::TAM_CLAMP,
    Ogre::TextureUnitState::TAM_CLAMP
};

//----------------------------------------------------------------------------//
OgreGeometryBuffer::OgreGeometryBuffer(OgreRenderer& owner,
    Ogre::RenderSystem& rs, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    GeometryBuffer(renderMaterial),
    d_owner(owner),
    d_renderSystem(rs),
    d_clipRect(0, 0, 0, 0),
    d_matrixValid(false),
    d_vertexHolder(0),
    d_expectedData(MANUALOBJECT_TYPE_INVALID),
    d_renderOp(0),
    d_dataAppended(false)
{

}

//----------------------------------------------------------------------------//
OgreGeometryBuffer::~OgreGeometryBuffer()
{
    cleanUpVertexAttributes();
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::draw() const
{
    if (d_vertexData.empty() || !d_renderOp)
        return;

    if (d_dataAppended)
        syncManualObject();

    // setup clip region
    if (d_clippingActive)
        setScissorRects();

    // Update the model matrix if necessary
    if (!d_matrixValid)
        updateMatrix();

    CEGUI::ShaderParameterBindings* shaderParameterBindings =
        (*d_renderMaterial).getShaderParamBindings();

    // Set the ModelViewProjection matrix in the bindings
    Ogre::Matrix4 omat = d_owner.getWorldViewProjMatrix()*d_matrix;

    glm::mat4 glmmat;

    OgreRenderer::convertOgreMatrixToGLMMatrix(omat, glmmat);

    shaderParameterBindings->setParameter("modelViewPerspMatrix", glmmat);

    d_owner.bindBlendMode(d_blendMode);

    bool found_texture = false;

    // Not sure if this is needed here
    const ShaderParameterBindings::ShaderParameterBindingsMap&
        shader_parameter_bindings = shaderParameterBindings->
        getShaderParameterBindings();

    ShaderParameterBindings::ShaderParameterBindingsMap::const_iterator iter =
        shader_parameter_bindings.begin();
    ShaderParameterBindings::ShaderParameterBindingsMap::const_iterator end =
        shader_parameter_bindings.end();

    while(iter != end)
    {
        const CEGUI::ShaderParameter* parameter = iter->second;
        const ShaderParamType parameterType = parameter->getType();

        if (iter->first == "texture0")
        {

            const CEGUI::ShaderParameterTexture* parameterTexture =
                static_cast<const CEGUI::ShaderParameterTexture*>(parameter);

            const CEGUI::OgreTexture* texture = static_cast<const
                CEGUI::OgreTexture*>(parameterTexture->d_parameterValue);

            d_vertexHolder->setMaterialName(0,
                texture->getOgreTexture()->getName());

            found_texture = true;
            break;
        }
    }

    if (!found_texture)
    {
        // Reset the material
        d_vertexHolder->setMaterialName(0, "BaseWhiteNoLighting");
    }

    const int pass_count = d_effect ? d_effect->getPassCount() : 1;
    for (int pass = 0; pass < pass_count; ++pass)
    {
        // set up RenderEffect
        if (d_effect)
            d_effect->performPreRenderFunctions(pass);

        initialiseTextureStates();

        //Prepare for the rendering process according to the used render material
        d_renderMaterial->prepareForRendering();

        // draw the geometry
        d_renderSystem._render(*d_renderOp);
    }

    // clean up RenderEffect
    if (d_effect)
        d_effect->performPostRenderFunctions();
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::setClippingRegion(const Rectf& region)
{
    d_clipRect.top(ceguimax(0.0f, region.top()));
    d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
    d_clipRect.left(ceguimax(0.0f, region.left()));
    d_clipRect.right(ceguimax(0.0f, region.right()));
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::appendGeometry(const std::vector<float>& vertex_data)
{
    d_vertexData.insert(d_vertexData.end(), vertex_data.begin(),
        vertex_data.end());

    d_dataAppended = true;

    size_t float_per_element;

    switch(d_expectedData){
    case MANUALOBJECT_TYPE_COLOURED: float_per_element = FLOATS_PER_COLOURED; break;
    case MANUALOBJECT_TYPE_TEXTURED: float_per_element = FLOATS_PER_TEXTURED; break;
    }

    d_vertexCount = d_vertexData.size()/float_per_element;
}

void OgreGeometryBuffer::syncManualObject() const
{
    if (!d_dataAppended)
        return;

    // All the data is in the vector so it's safe to clear
    d_vertexHolder->clear();

    // Blank material initially
    d_vertexHolder->begin("BaseWhiteNoLighting",
        Ogre::RenderOperation::OT_TRIANGLE_LIST);

    // Append the data to the manual object
    if (d_expectedData == MANUALOBJECT_TYPE_TEXTURED)
    {
        for (size_t i = 0; i < d_vertexData.size(); i += FLOATS_PER_TEXTURED)
        {
            assert(i+FLOATS_PER_TEXTURED < d_vertexData.size() &&
                "invalid vertex data passed to OgreGeometryBuffer");

            // First the position
            d_vertexHolder->position(d_vertexData[i], d_vertexData[i+1],
                d_vertexData[i+2]);

            // And then the colour
            d_vertexHolder->colour(d_vertexData[i+3], d_vertexData[i+4],
                d_vertexData[i+5], d_vertexData[i+6]);

            // And finally texture coordinate
            d_vertexHolder->textureCoord(d_vertexData[i+7], d_vertexData[i+8]);
        }
    }
    else if (d_expectedData == MANUALOBJECT_TYPE_COLOURED)
    {

        for (size_t i = 0; i < d_vertexData.size(); i += FLOATS_PER_COLOURED)
        {
            assert(i+FLOATS_PER_COLOURED < d_vertexData.size() &&
                "invalid vertex data passed to OgreGeometryBuffer");

            // First the position
            d_vertexHolder->position(d_vertexData[i], d_vertexData[i+1],
                d_vertexData[i+2]);

            // And then the colour
            d_vertexHolder->colour(d_vertexData[i+3], d_vertexData[i+4],
                d_vertexData[i+5], d_vertexData[i+6]);
        }
    }

    auto section = d_vertexHolder->end();

    d_renderOp = section->getRenderOperation();

    d_dataAppended = false;
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::updateMatrix() const
{
    // translation to position geometry and offset to pivot point
    Ogre::Matrix4 trans;

    trans.makeTrans(d_translation.d_x + d_pivot.d_x,
        d_translation.d_y + d_pivot.d_y,
        d_translation.d_z + d_pivot.d_z);

    // rotation
    Ogre::Matrix4 rot(Ogre::Quaternion(
        d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z));

    // translation to remove rotation pivot offset
    Ogre::Matrix4 inv_pivot_trans;
    inv_pivot_trans.makeTrans(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);

    // calculate final matrix
    d_matrix = trans * rot * inv_pivot_trans;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
const Ogre::Matrix4& OgreGeometryBuffer::getMatrix() const{
    if (!d_matrixValid)
        updateMatrix();

    return d_matrix;
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::initialiseTextureStates() const
{
    using namespace Ogre;
    d_renderSystem._setTextureCoordCalculation(0, TEXCALC_NONE);
    d_renderSystem._setTextureCoordSet(0, 0);
    d_renderSystem._setTextureUnitFiltering(0, FO_LINEAR, FO_LINEAR, FO_POINT);
    d_renderSystem._setTextureAddressingMode(0, S_textureAddressMode);
    d_renderSystem._setTextureMatrix(0, Matrix4::IDENTITY);
    d_renderSystem._setAlphaRejectSettings(CMPF_ALWAYS_PASS, 0, false);
    d_renderSystem._setTextureBlendMode(0, S_colourBlendMode);
    d_renderSystem._setTextureBlendMode(0, S_alphaBlendMode);
    d_renderSystem._disableTextureUnitsFrom(1);
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::finaliseVertexAttributes(MANUALOBJECT_TYPE type)
{
    d_expectedData = type;

    if (d_expectedData >= MANUALOBJECT_TYPE_INVALID)
    {
        CEGUI_THROW(RendererException(
            "Unknown d_expectedData type."));
    }

    setVertexBuffer(INITIAL_BUFFER_SIZE);
}

void OgreGeometryBuffer::setVertexBuffer(size_t size)
{
    // create the vertex container
    d_vertexHolder = d_owner.getDummyScene().createManualObject(
        Ogre::SCENE_STATIC);

    if (!d_vertexHolder)
    {
        CEGUI_THROW(RendererException("Failed to create Ogre vertex buffer, "
            "probably because the vertex layout is invalid."));
    }

    d_vertexHolder->setDynamic(false);
    d_vertexHolder->estimateVertexCount(size);
}

void OgreGeometryBuffer::cleanUpVertexAttributes()
{
    d_renderOp = 0;

    d_owner.getDummyScene().destroyManualObject(d_vertexHolder);
    d_vertexHolder = 0;
}

void OgreGeometryBuffer::setScissorRects() const
{
    d_renderSystem.setScissorTest(true, d_clipRect.left(),
        d_clipRect.top(), d_clipRect.right(), d_clipRect.bottom());
}

} // End of  CEGUI namespace section
<commit_msg>IT WORKS! at least the loading screen displays<commit_after>/***********************************************************************
    created:    Tue Feb 17 2009
    author:     Henri I Hyyryläinen (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 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.
 ***************************************************************************/
#include "CEGUI/RendererModules/Ogre/GeometryBuffer.h"
#include "CEGUI/RendererModules/Ogre/Texture.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RenderEffect.h"

#include <OgreRenderSystem.h>
#include <OgreQuaternion.h>
#include <OgreHardwareBufferManager.h>
#include "CEGUI/Exceptions.h"
#include "CEGUI/ShaderParameterBindings.h"

#include "OgreManualObject.h"
#include "OgreRenderOperation.h"
#include "OgreSceneManager.h"

#define INITIAL_BUFFER_SIZE     64

#define FLOATS_PER_TEXTURED     9
#define FLOATS_PER_COLOURED     7

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
static const Ogre::LayerBlendModeEx S_colourBlendMode =
{
    Ogre::LBT_COLOUR,
    Ogre::LBX_MODULATE,
    Ogre::LBS_TEXTURE,
    Ogre::LBS_DIFFUSE,
    Ogre::ColourValue(0, 0, 0, 0),
    Ogre::ColourValue(0, 0, 0, 0),
    0, 0, 0
};

//----------------------------------------------------------------------------//
static const Ogre::LayerBlendModeEx S_alphaBlendMode =
{
    Ogre::LBT_ALPHA,
    Ogre::LBX_MODULATE,
    Ogre::LBS_TEXTURE,
    Ogre::LBS_DIFFUSE,
    Ogre::ColourValue(0, 0, 0, 0),
    Ogre::ColourValue(0, 0, 0, 0),
    0, 0, 0
};

//----------------------------------------------------------------------------//
static const Ogre::TextureUnitState::UVWAddressingMode S_textureAddressMode =
{
    Ogre::TextureUnitState::TAM_CLAMP,
    Ogre::TextureUnitState::TAM_CLAMP,
    Ogre::TextureUnitState::TAM_CLAMP
};

//----------------------------------------------------------------------------//
OgreGeometryBuffer::OgreGeometryBuffer(OgreRenderer& owner,
    Ogre::RenderSystem& rs, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    GeometryBuffer(renderMaterial),
    d_owner(owner),
    d_renderSystem(rs),
    d_clipRect(0, 0, 0, 0),
    d_matrixValid(false),
    d_vertexHolder(0),
    d_expectedData(MANUALOBJECT_TYPE_INVALID),
    d_renderOp(0),
    d_dataAppended(false)
{

}

//----------------------------------------------------------------------------//
OgreGeometryBuffer::~OgreGeometryBuffer()
{
    cleanUpVertexAttributes();
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::draw() const
{
    if (d_vertexData.empty())
        return;

    if (d_dataAppended)
        syncManualObject();

    if (!d_renderOp)
        return;

    // setup clip region
    if (d_clippingActive)
        setScissorRects();

    // Update the model matrix if necessary
    if (!d_matrixValid)
        updateMatrix();

    CEGUI::ShaderParameterBindings* shaderParameterBindings =
        (*d_renderMaterial).getShaderParamBindings();

    // Set the ModelViewProjection matrix in the bindings
    Ogre::Matrix4 omat = d_owner.getWorldViewProjMatrix()*d_matrix;

    glm::mat4 glmmat;

    OgreRenderer::convertOgreMatrixToGLMMatrix(omat, glmmat);

    shaderParameterBindings->setParameter("modelViewPerspMatrix", glmmat);

    d_owner.bindBlendMode(d_blendMode);

    bool found_texture = false;

    // Not sure if this is needed here
    const ShaderParameterBindings::ShaderParameterBindingsMap&
        shader_parameter_bindings = shaderParameterBindings->
        getShaderParameterBindings();

    auto end = shader_parameter_bindings.end();

    for (auto iter = shader_parameter_bindings.begin(); iter != end; ++iter)
    {
        const CEGUI::ShaderParameter* parameter = iter->second;
        const ShaderParamType parameterType = parameter->getType();

        if (iter->first == "texture0")
        {

            const CEGUI::ShaderParameterTexture* parameterTexture =
                static_cast<const CEGUI::ShaderParameterTexture*>(parameter);

            const CEGUI::OgreTexture* texture = static_cast<const
                CEGUI::OgreTexture*>(parameterTexture->d_parameterValue);

            d_vertexHolder->setMaterialName(0,
                texture->getOgreTexture()->getName());

            found_texture = true;
            break;
        }
    }

    if (!found_texture)
    {
        // Reset the material
        d_vertexHolder->setMaterialName(0, "BaseWhiteNoLighting");
    }

    const int pass_count = d_effect ? d_effect->getPassCount() : 1;
    for (int pass = 0; pass < pass_count; ++pass)
    {
        // set up RenderEffect
        if (d_effect)
            d_effect->performPreRenderFunctions(pass);

        initialiseTextureStates();

        //Prepare for the rendering process according to the used render material
        d_renderMaterial->prepareForRendering();

        // draw the geometry
        d_renderSystem._render(*d_renderOp);
    }

    // clean up RenderEffect
    if (d_effect)
        d_effect->performPostRenderFunctions();
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::setClippingRegion(const Rectf& region)
{
    d_clipRect.top(ceguimax(0.0f, region.top()));
    d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
    d_clipRect.left(ceguimax(0.0f, region.left()));
    d_clipRect.right(ceguimax(0.0f, region.right()));
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::appendGeometry(const std::vector<float>& vertex_data)
{
    d_vertexData.insert(d_vertexData.end(), vertex_data.begin(),
        vertex_data.end());

    d_dataAppended = true;

    size_t float_per_element;

    switch(d_expectedData){
    case MANUALOBJECT_TYPE_COLOURED: float_per_element = FLOATS_PER_COLOURED; break;
    case MANUALOBJECT_TYPE_TEXTURED: float_per_element = FLOATS_PER_TEXTURED; break;
    }

    d_vertexCount = d_vertexData.size()/float_per_element;
}

void OgreGeometryBuffer::syncManualObject() const
{
    if (!d_dataAppended)
        return;

    // All the data is in the vector so it's safe to clear
    d_vertexHolder->clear();

    // Blank material initially
    d_vertexHolder->begin("BaseWhiteNoLighting",
        Ogre::RenderOperation::OT_TRIANGLE_LIST);

    // Append the data to the manual object
    if (d_expectedData == MANUALOBJECT_TYPE_TEXTURED)
    {
        for (size_t i = 0; i < d_vertexData.size(); i += FLOATS_PER_TEXTURED)
        {
            assert(i+FLOATS_PER_TEXTURED <= d_vertexData.size() &&
                "invalid vertex data passed to OgreGeometryBuffer");

            // First the position
            d_vertexHolder->position(d_vertexData[i], d_vertexData[i+1],
                d_vertexData[i+2]);

            // And then the colour
            d_vertexHolder->colour(d_vertexData[i+3], d_vertexData[i+4],
                d_vertexData[i+5], d_vertexData[i+6]);

            // And finally texture coordinate
            d_vertexHolder->textureCoord(d_vertexData[i+7], d_vertexData[i+8]);
        }
    }
    else if (d_expectedData == MANUALOBJECT_TYPE_COLOURED)
    {

        for (size_t i = 0; i < d_vertexData.size(); i += FLOATS_PER_COLOURED)
        {
            assert(i+FLOATS_PER_COLOURED <= d_vertexData.size() &&
                "invalid vertex data passed to OgreGeometryBuffer");

            // First the position
            d_vertexHolder->position(d_vertexData[i], d_vertexData[i+1],
                d_vertexData[i+2]);

            // And then the colour
            d_vertexHolder->colour(d_vertexData[i+3], d_vertexData[i+4],
                d_vertexData[i+5], d_vertexData[i+6]);
        }
    }

    auto section = d_vertexHolder->end();

    d_renderOp = section->getRenderOperation();

    d_dataAppended = false;
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::updateMatrix() const
{
    // translation to position geometry and offset to pivot point
    Ogre::Matrix4 trans;

    trans.makeTrans(d_translation.d_x + d_pivot.d_x,
        d_translation.d_y + d_pivot.d_y,
        d_translation.d_z + d_pivot.d_z);

    // rotation
    Ogre::Matrix4 rot(Ogre::Quaternion(
        d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z));

    // translation to remove rotation pivot offset
    Ogre::Matrix4 inv_pivot_trans;
    inv_pivot_trans.makeTrans(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);

    // calculate final matrix
    d_matrix = trans * rot * inv_pivot_trans;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
const Ogre::Matrix4& OgreGeometryBuffer::getMatrix() const{
    if (!d_matrixValid)
        updateMatrix();

    return d_matrix;
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::initialiseTextureStates() const
{
    using namespace Ogre;
    d_renderSystem._setTextureCoordCalculation(0, TEXCALC_NONE);
    d_renderSystem._setTextureCoordSet(0, 0);
    d_renderSystem._setTextureUnitFiltering(0, FO_LINEAR, FO_LINEAR, FO_POINT);
    d_renderSystem._setTextureAddressingMode(0, S_textureAddressMode);
    d_renderSystem._setTextureMatrix(0, Matrix4::IDENTITY);
    d_renderSystem._setAlphaRejectSettings(CMPF_ALWAYS_PASS, 0, false);
    d_renderSystem._setTextureBlendMode(0, S_colourBlendMode);
    d_renderSystem._setTextureBlendMode(0, S_alphaBlendMode);
    d_renderSystem._disableTextureUnitsFrom(1);
}

//----------------------------------------------------------------------------//
void OgreGeometryBuffer::finaliseVertexAttributes(MANUALOBJECT_TYPE type)
{
    d_expectedData = type;

    if (d_expectedData >= MANUALOBJECT_TYPE_INVALID)
    {
        CEGUI_THROW(RendererException(
            "Unknown d_expectedData type."));
    }

    setVertexBuffer(INITIAL_BUFFER_SIZE);
}

void OgreGeometryBuffer::setVertexBuffer(size_t size)
{
    // create the vertex container
    d_vertexHolder = d_owner.getDummyScene().createManualObject(
        Ogre::SCENE_STATIC);

    if (!d_vertexHolder)
    {
        CEGUI_THROW(RendererException("Failed to create Ogre vertex buffer, "
            "probably because the vertex layout is invalid."));
    }

    d_vertexHolder->setDynamic(false);
    d_vertexHolder->estimateVertexCount(size);
}

void OgreGeometryBuffer::cleanUpVertexAttributes()
{
    d_renderOp = 0;

    d_owner.getDummyScene().destroyManualObject(d_vertexHolder);
    d_vertexHolder = 0;
}

void OgreGeometryBuffer::setScissorRects() const
{
    d_renderSystem.setScissorTest(true, d_clipRect.left(),
        d_clipRect.top(), d_clipRect.right(), d_clipRect.bottom());
}

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>/*
 * This file is part of the CitizenFX project - http://citizen.re/
 *
 * See LICENSE and MENTIONS in the root of the source tree for information
 * regarding licensing.
 */

#include "Hooking.Patterns.h"

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <algorithm>

#if PATTERNS_USE_HINTS
#include <map>
#endif

#if PATTERNS_USE_HINTS

// from boost someplace
template <std::uint64_t FnvPrime, std::uint64_t OffsetBasis>
struct basic_fnv_1
{
    std::uint64_t operator()(const char *text) const
    {
        std::uint64_t hash = OffsetBasis;

        while (*text != 0)
        {
            hash *= FnvPrime;
            hash ^= *(uint8_t *)text;

            ++text;
        }

        return hash;
    }
};

const std::uint64_t fnv_prime = 1099511628211u;
const std::uint64_t fnv_offset_basis = 14695981039346656037u;

typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;

#endif

namespace hook
{
    ptrdiff_t baseAddressDifference;

    // sets the base to the process main base
    void set_base()
    {
        set_base((uintptr_t)GetModuleHandle(nullptr));
    }

#if PATTERNS_USE_HINTS
static std::multimap<uint64_t, uintptr_t> g_hints;
#endif

static void TransformPattern(const char *pattern, std::vector<uint8_t>& data, std::vector<uint8_t>& mask)
{
    auto tol = [](char ch) -> uint8_t
    {
        if (ch >= 'A' && ch <= 'F') return uint8_t(ch - 'A' + 10);
        if (ch >= 'a' && ch <= 'f') return uint8_t(ch - 'a' + 10);
        return uint8_t(ch - '0');
    };

    auto is_digit = [](char ch) -> bool
    {
        return (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || (ch >= '0' && ch <= '9');
    };

    char temp_string[2]{ 0, 0 };

    data.clear();
    mask.clear();

    if (!pattern)
    {
        return;
    }

    const char *patit = pattern;
    const char *patend = (pattern + strlen(pattern) + 1);

    while (patit != patend)
    {
        char ch = *patit;

        if (ch == ' ' || ch == 0)
        {
            if (!temp_string[0] && !temp_string[1])
            {
                continue;
            }
            else if (temp_string[0] == '?' && (temp_string[1] == '?' || temp_string[1] == 0))
            {
                data.push_back(0);
                mask.push_back(0u);
            }
            else if (temp_string[0] == '?' && is_digit(temp_string[1]))
            {
                data.push_back(tol(temp_string[1]));
                mask.push_back(0x0Fu);
            }
            else if (temp_string[1] == '?' && is_digit(temp_string[0]))
            {
                data.push_back(tol(temp_string[0]) << 4);
                mask.push_back(0xF0u);
            }
            else if (is_digit(temp_string[0]) && is_digit(temp_string[1]))
            {
                data.push_back((tol(temp_string[0]) << 4) | tol(temp_string[1]));
                mask.push_back(0xFFu);
            }
            else
            {
                data.clear();
                mask.clear();
                return;
            }

            temp_string[0] = 0;
            temp_string[1] = 0;
        }
        else
        {
            if (temp_string[0] == 0)
            {
                temp_string[0] = ch;
            }
            else if (temp_string[1] == 0)
            {
                temp_string[1] = ch;
            }
            else
            {
                data.clear();
                mask.clear();
                return;
            }
        }

        ++patit;
    }
}

class executable_meta
{
private:
    uintptr_t m_begin;
    uintptr_t m_end;

public:
    template<typename TReturn, typename TOffset>
    TReturn* getRVA(TOffset rva)
    {
        return (TReturn*)(m_begin + rva);
    }

    explicit executable_meta(void* module)
        : m_begin((uintptr_t)module), m_end(0)
    {
        static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER
        {
            return reinterpret_cast<PIMAGE_SECTION_HEADER>(
                (UCHAR*)nt_headers->OptionalHeader.DataDirectory +
                nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) +
                section * sizeof(IMAGE_SECTION_HEADER));
        };

        PIMAGE_DOS_HEADER dosHeader = getRVA<IMAGE_DOS_HEADER>(0);
        PIMAGE_NT_HEADERS ntHeader = getRVA<IMAGE_NT_HEADERS>(dosHeader->e_lfanew);

        for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++)
        {
            auto sec = getSection(ntHeader, i);
            auto secSize = sec->SizeOfRawData != 0 ? sec->SizeOfRawData : sec->Misc.VirtualSize;
            if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE)
                m_end = m_begin + sec->VirtualAddress + secSize;

            if ((i == ntHeader->FileHeader.NumberOfSections - 1) && m_end == 0)
                m_end = m_begin + sec->PointerToRawData + secSize;
        }
    }

    executable_meta(uintptr_t begin, uintptr_t end)
        : m_begin(begin), m_end(end)
    {
    }

    inline uintptr_t begin() const { return m_begin; }
    inline uintptr_t end() const   { return m_end; }
};

void pattern::Initialize(const char* pattern)
{
    // get the hash for the base pattern
#if PATTERNS_USE_HINTS
    m_hash = fnv_1()(pattern);
#endif

    // transform the base pattern from IDA format to canonical format
    TransformPattern(pattern, m_bytes, m_mask);

    m_size = m_mask.size();

#if PATTERNS_USE_HINTS
    // if there's hints, try those first
    if (m_module == GetModuleHandle(nullptr))
    {
        auto range = g_hints.equal_range(m_hash);

        if (range.first != range.second)
        {
            std::for_each(range.first, range.second, [&] (const std::pair<uint64_t, uintptr_t>& hint)
            {
                ConsiderMatch(hint.second);
            });

            // if the hints succeeded, we don't need to do anything more
            if (!m_matches.empty())
            {
                m_matched = true;
                return;
            }
        }
    }
#endif
}

void pattern::EnsureMatches(uint32_t maxCount)
{
    if (m_matched)
        return;

    if (!m_rangeStart && !m_rangeEnd && !m_module)
        return;

    // scan the executable for code
    executable_meta executable = m_rangeStart != 0 && m_rangeEnd != 0 ? executable_meta(m_rangeStart, m_rangeEnd) : executable_meta(m_module);

    auto matchSuccess = [&] (uintptr_t address)
    {
#if PATTERNS_USE_HINTS
        g_hints.emplace(m_hash, address);
#else
        (void)address;
#endif

        return (m_matches.size() == maxCount);
    };

    ptrdiff_t BadCharacter[256];

    std::ptrdiff_t index;

    const std::uint8_t *pbytes = m_bytes.data();
    const std::uint8_t *pmask = m_mask.data();

    for (std::uint32_t bc = 0; bc < 256; ++bc)
    {
        for (index = m_size - 1; index >= 0; --index)
        {
            if ((pbytes[index] & pmask[index]) == (bc & pmask[index]))
            {
                break;
            }
        }

        BadCharacter[bc] = index;
    }

    __try
    {
        for (uintptr_t i = executable.begin(), end = executable.end() - m_size; i <= end;)
        {
            uint8_t* ptr = reinterpret_cast<uint8_t*>(i);

            for (index = m_size - 1; index >= 0; --index)
            {
                if ((pbytes[index] & pmask[index]) != (ptr[index] & pmask[index]))
                {
                    break;
                }
            }

            if (index == -1)
            {
                m_matches.emplace_back(ptr);

                if (matchSuccess(i))
                {
                    break;
                }

                i += m_size;
            }
            else
            {
                i += max(index - BadCharacter[ptr[index]], 1);
            }
        }
    }
    __except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    { }
    m_matched = true;
}

bool pattern::ConsiderMatch(uintptr_t offset)
{
    const uint8_t* pattern = m_bytes.data();
    const uint8_t* mask = m_mask.data();

    char* ptr = reinterpret_cast<char*>(offset);

    for (size_t i = 0; i < m_size; i++)
    {
        if ((pattern[i] & mask[i]) != (ptr[i] & mask[i]))
        {
            return false;
        }
    }

    m_matches.emplace_back(ptr);

    return true;
}

#if PATTERNS_USE_HINTS
void pattern::hint(uint64_t hash, uintptr_t address)
{
    auto range = g_hints.equal_range(hash);

    for (auto it = range.first; it != range.second; it++)
    {
        if (it->second == address)
        {
            return;
        }
    }

    g_hints.emplace(hash, address);
}
#endif
}<commit_msg>Fix deadloop at processing continous delimiter.<commit_after>/*
 * This file is part of the CitizenFX project - http://citizen.re/
 *
 * See LICENSE and MENTIONS in the root of the source tree for information
 * regarding licensing.
 */

#include "Hooking.Patterns.h"

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <algorithm>

#if PATTERNS_USE_HINTS
#include <map>
#endif

#if PATTERNS_USE_HINTS

// from boost someplace
template <std::uint64_t FnvPrime, std::uint64_t OffsetBasis>
struct basic_fnv_1
{
    std::uint64_t operator()(const char *text) const
    {
        std::uint64_t hash = OffsetBasis;

        while (*text != 0)
        {
            hash *= FnvPrime;
            hash ^= *(uint8_t *)text;

            ++text;
        }

        return hash;
    }
};

const std::uint64_t fnv_prime = 1099511628211u;
const std::uint64_t fnv_offset_basis = 14695981039346656037u;

typedef basic_fnv_1<fnv_prime, fnv_offset_basis> fnv_1;

#endif

namespace hook
{
    ptrdiff_t baseAddressDifference;

    // sets the base to the process main base
    void set_base()
    {
        set_base((uintptr_t)GetModuleHandle(nullptr));
    }

#if PATTERNS_USE_HINTS
static std::multimap<uint64_t, uintptr_t> g_hints;
#endif

static void TransformPattern(const char *pattern, std::vector<uint8_t>& data, std::vector<uint8_t>& mask)
{
    auto tol = [](char ch) -> uint8_t
    {
        if (ch >= 'A' && ch <= 'F') return uint8_t(ch - 'A' + 10);
        if (ch >= 'a' && ch <= 'f') return uint8_t(ch - 'a' + 10);
        return uint8_t(ch - '0');
    };

    auto is_digit = [](char ch) -> bool
    {
        return (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f') || (ch >= '0' && ch <= '9');
    };

    char temp_string[2]{ 0, 0 };

    data.clear();
    mask.clear();

    if (!pattern)
    {
        return;
    }

    const char *patit = pattern;
    const char *patend = (pattern + strlen(pattern) + 1);

    while (patit != patend)
    {
        char ch = *patit;

        if (ch == ' ' || ch == 0)
        {
            if (!temp_string[0] && !temp_string[1]) //Continous delimiter
            {

            }
            else if (temp_string[0] == '?' && (temp_string[1] == '?' || temp_string[1] == 0)) //??
            {
                data.push_back(0);
                mask.push_back(0u);
            }
            else if (temp_string[0] == '?' && is_digit(temp_string[1])) //?x
            {
                data.push_back(tol(temp_string[1]));
                mask.push_back(0x0Fu);
            }
            else if (temp_string[1] == '?' && is_digit(temp_string[0])) //x?
            {
                data.push_back(tol(temp_string[0]) << 4);
                mask.push_back(0xF0u);
            }
            else if (is_digit(temp_string[0]) && is_digit(temp_string[1])) //xx
            {
                data.push_back((tol(temp_string[0]) << 4) | tol(temp_string[1]));
                mask.push_back(0xFFu);
            }
            else
            {
                data.clear();
                mask.clear();
                return;
            }

            temp_string[0] = 0;
            temp_string[1] = 0;
        }
        else
        {
            if (temp_string[0] == 0)
            {
                temp_string[0] = ch;
            }
            else if (temp_string[1] == 0)
            {
                temp_string[1] = ch;
            }
            else
            {
                data.clear();
                mask.clear();
                return;
            }
        }

        ++patit;
    }
}

class executable_meta
{
private:
    uintptr_t m_begin;
    uintptr_t m_end;

public:
    template<typename TReturn, typename TOffset>
    TReturn* getRVA(TOffset rva)
    {
        return (TReturn*)(m_begin + rva);
    }

    explicit executable_meta(void* module)
        : m_begin((uintptr_t)module), m_end(0)
    {
        static auto getSection = [](const PIMAGE_NT_HEADERS nt_headers, unsigned section) -> PIMAGE_SECTION_HEADER
        {
            return reinterpret_cast<PIMAGE_SECTION_HEADER>(
                (UCHAR*)nt_headers->OptionalHeader.DataDirectory +
                nt_headers->OptionalHeader.NumberOfRvaAndSizes * sizeof(IMAGE_DATA_DIRECTORY) +
                section * sizeof(IMAGE_SECTION_HEADER));
        };

        PIMAGE_DOS_HEADER dosHeader = getRVA<IMAGE_DOS_HEADER>(0);
        PIMAGE_NT_HEADERS ntHeader = getRVA<IMAGE_NT_HEADERS>(dosHeader->e_lfanew);

        for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++)
        {
            auto sec = getSection(ntHeader, i);
            auto secSize = sec->SizeOfRawData != 0 ? sec->SizeOfRawData : sec->Misc.VirtualSize;
            if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE)
                m_end = m_begin + sec->VirtualAddress + secSize;

            if ((i == ntHeader->FileHeader.NumberOfSections - 1) && m_end == 0)
                m_end = m_begin + sec->PointerToRawData + secSize;
        }
    }

    executable_meta(uintptr_t begin, uintptr_t end)
        : m_begin(begin), m_end(end)
    {
    }

    inline uintptr_t begin() const { return m_begin; }
    inline uintptr_t end() const   { return m_end; }
};

void pattern::Initialize(const char* pattern)
{
    // get the hash for the base pattern
#if PATTERNS_USE_HINTS
    m_hash = fnv_1()(pattern);
#endif

    // transform the base pattern from IDA format to canonical format
    TransformPattern(pattern, m_bytes, m_mask);

    m_size = m_mask.size();

#if PATTERNS_USE_HINTS
    // if there's hints, try those first
    if (m_module == GetModuleHandle(nullptr))
    {
        auto range = g_hints.equal_range(m_hash);

        if (range.first != range.second)
        {
            std::for_each(range.first, range.second, [&] (const std::pair<uint64_t, uintptr_t>& hint)
            {
                ConsiderMatch(hint.second);
            });

            // if the hints succeeded, we don't need to do anything more
            if (!m_matches.empty())
            {
                m_matched = true;
                return;
            }
        }
    }
#endif
}

void pattern::EnsureMatches(uint32_t maxCount)
{
    if (m_matched)
        return;

    if (!m_rangeStart && !m_rangeEnd && !m_module)
        return;

    // scan the executable for code
    executable_meta executable = m_rangeStart != 0 && m_rangeEnd != 0 ? executable_meta(m_rangeStart, m_rangeEnd) : executable_meta(m_module);

    auto matchSuccess = [&] (uintptr_t address)
    {
#if PATTERNS_USE_HINTS
        g_hints.emplace(m_hash, address);
#else
        (void)address;
#endif

        return (m_matches.size() == maxCount);
    };

    ptrdiff_t BadCharacter[256];

    std::ptrdiff_t index;

    const std::uint8_t *pbytes = m_bytes.data();
    const std::uint8_t *pmask = m_mask.data();

    for (std::uint32_t bc = 0; bc < 256; ++bc)
    {
        for (index = m_size - 1; index >= 0; --index)
        {
            if ((pbytes[index] & pmask[index]) == (bc & pmask[index]))
            {
                break;
            }
        }

        BadCharacter[bc] = index;
    }

    __try
    {
        for (uintptr_t i = executable.begin(), end = executable.end() - m_size; i <= end;)
        {
            uint8_t* ptr = reinterpret_cast<uint8_t*>(i);

            for (index = m_size - 1; index >= 0; --index)
            {
                if ((pbytes[index] & pmask[index]) != (ptr[index] & pmask[index]))
                {
                    break;
                }
            }

            if (index == -1)
            {
                m_matches.emplace_back(ptr);

                if (matchSuccess(i))
                {
                    break;
                }

                i += m_size;
            }
            else
            {
                i += max(index - BadCharacter[ptr[index]], 1);
            }
        }
    }
    __except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    { }
    m_matched = true;
}

bool pattern::ConsiderMatch(uintptr_t offset)
{
    const uint8_t* pattern = m_bytes.data();
    const uint8_t* mask = m_mask.data();

    char* ptr = reinterpret_cast<char*>(offset);

    for (size_t i = 0; i < m_size; i++)
    {
        if ((pattern[i] & mask[i]) != (ptr[i] & mask[i]))
        {
            return false;
        }
    }

    m_matches.emplace_back(ptr);

    return true;
}

#if PATTERNS_USE_HINTS
void pattern::hint(uint64_t hash, uintptr_t address)
{
    auto range = g_hints.equal_range(hash);

    for (auto it = range.first; it != range.second; it++)
    {
        if (it->second == address)
        {
            return;
        }
    }

    g_hints.emplace(hash, address);
}
#endif
}
<|endoftext|>


<commit_before>#include "s3key_writer.h"

void S3KeyWriter::open(const S3Params& params) {
    this->params = params;

    S3_CHECK_OR_DIE_MSG(this->s3interface != NULL, S3RuntimeError, "s3interface must not be NULL");
    S3_CHECK_OR_DIE_MSG(this->params.getChunkSize() > 0, S3RuntimeError,
                        "chunkSize must not be zero");

    buffer.reserve(this->params.getChunkSize());

    this->uploadId =
        this->s3interface->getUploadId(this->params.getKeyUrl(), this->params.getRegion());
    S3_CHECK_OR_DIE_MSG(!this->uploadId.empty(), S3RuntimeError, "Failed to get upload id");

    S3DEBUG("key: %s, upload id: %s", this->params.getKeyUrl().c_str(), this->uploadId.c_str());
}

// write() first fills up the data buffer before flush it out
uint64_t S3KeyWriter::write(const char* buf, uint64_t count) {
    // Defensive code
    S3_CHECK_OR_DIE_MSG(buf != NULL, S3RuntimeError, "Buffer is NULL");
    this->checkQueryCancelSignal();

    uint64_t offset = 0;
    while (offset < count) {
        if (sharedError) {
            std::rethrow_exception(sharedException);
        }

        uint64_t bufferRemaining = this->params.getChunkSize() - this->buffer.size();
        uint64_t dataRemaining = count - offset;
        uint64_t dataToBuffer = bufferRemaining < dataRemaining ? bufferRemaining : dataRemaining;

        this->buffer.insert(this->buffer.end(), buf + offset, buf + offset + dataToBuffer);

        if (this->buffer.size() == this->params.getChunkSize()) {
            this->flushBuffer();
        }

        offset += dataToBuffer;
    }

    return count;
}

// This should be reentrant, has no side effects when called multiple times.
void S3KeyWriter::close() {
    if (!this->uploadId.empty()) {
        this->completeKeyWriting();
    }
}

void S3KeyWriter::checkQueryCancelSignal() {
    if (S3QueryIsAbortInProgress() && !this->uploadId.empty()) {
        // to avoid dead-lock when other upload threads hold the lock
        pthread_mutex_unlock(&this->mutex);

        // wait for all threads to complete
        for (size_t i = 0; i < threadList.size(); i++) {
            pthread_join(threadList[i], NULL);
        }
        this->threadList.clear();

        // to avoid double unlock as other parts may lock it
        pthread_mutex_lock(&this->mutex);

        S3DEBUG("Start aborting multipart uploading (uploadID: %s, %lu parts uploaded)",
                this->uploadId.c_str(), this->etagList.size());
        this->s3interface->abortUpload(this->params.getKeyUrl(), this->params.getRegion(),
                                       this->uploadId);
        S3DEBUG("Finished aborting multipart uploading (uploadID: %s)", this->uploadId.c_str());

        this->etagList.clear();
        this->uploadId.clear();

        S3_DIE_MSG(S3QueryAbort, "Uploading is interrupted by user");
    }
}

struct ThreadParams {
    S3KeyWriter* keyWriter;
    WriterBuffer data;
    uint64_t currentNumber;
};

void* S3KeyWriter::UploadThreadFunc(void* data) {
    ThreadParams* params = (ThreadParams*)data;
    S3KeyWriter* writer = params->keyWriter;

    try {
        S3DEBUG("Upload thread start: %p, part number: %" PRIu64 ", data size: %" PRIu64,
                pthread_self(), params->currentNumber, params->data.size());
        string etag = writer->s3interface->uploadPartOfData(
            params->data, writer->params.getKeyUrl(), writer->params.getRegion(),
            params->currentNumber, writer->uploadId);

        // when unique_lock destructs it will automatically unlock the mutex.
        UniqueLock threadLock(&writer->mutex);

        // etag is empty if the query is cancelled by user.
        if (!etag.empty()) {
            writer->etagList[params->currentNumber] = etag;
        }
        writer->activeThreads--;
        pthread_cond_broadcast(&writer->cv);
        S3DEBUG("Upload part finish: %p, eTag: %s, part number: %" PRIu64, pthread_self(),
                etag.c_str(), params->currentNumber);
    } catch (S3Exception& e) {
        S3ERROR("Upload thread error: %s", e.getMessage().c_str());
        UniqueLock exceptLock(&writer->exceptionMutex);
        writer->sharedError = true;
        writer->sharedException = std::current_exception();
    }

    delete params;
    return NULL;
}

void S3KeyWriter::flushBuffer() {
    if (!this->buffer.empty()) {
        UniqueLock queueLock(&this->mutex);
        while (this->activeThreads >= this->params.getNumOfChunks()) {
            pthread_cond_wait(&this->cv, &this->mutex);
        }

        // Most time query is canceled during uploadPartOfData(). This is the first chance to cancel
        // and clean up upload.
        this->checkQueryCancelSignal();

        this->activeThreads++;

        pthread_t writerThread;
        ThreadParams* params = new ThreadParams();
        params->keyWriter = this;
        params->data.swap(this->buffer);
        params->currentNumber = ++this->partNumber;
        pthread_create(&writerThread, NULL, UploadThreadFunc, params);
        threadList.emplace_back(writerThread);

        this->buffer.clear();
    }
}

void S3KeyWriter::completeKeyWriting() {
    // make sure the buffer is clear
    this->flushBuffer();

    // wait for all threads to complete
    for (size_t i = 0; i < threadList.size(); i++) {
        pthread_join(threadList[i], NULL);
    }
    this->threadList.clear();

    this->checkQueryCancelSignal();

    vector<string> etags;
    // it is equivalent to foreach(e in etagList) push_back(e.second);
    // transform(etagList.begin(), etagList.end(), etags.begin(),
    //          [](std::pair<const uint64_t, string>& p) { return p.second; });
    etags.reserve(etagList.size());

    for (map<uint64_t, string>::iterator i = etagList.begin(); i != etagList.end(); i++) {
        etags.push_back(i->second);
    }

    if (!this->etagList.empty() && !this->uploadId.empty()) {
        this->s3interface->completeMultiPart(this->params.getKeyUrl(), this->params.getRegion(),
                                             this->uploadId, etags);
    }

    S3DEBUG("Segment %d has finished uploading \"%s\"", s3ext_segid,
            this->params.getKeyUrl().c_str());

    this->buffer.clear();
    this->etagList.clear();
    this->uploadId.clear();
}
<commit_msg>s3ext: fix the hang issue when user interrupts uploading<commit_after>#include "s3key_writer.h"

void S3KeyWriter::open(const S3Params& params) {
    this->params = params;

    S3_CHECK_OR_DIE_MSG(this->s3interface != NULL, S3RuntimeError, "s3interface must not be NULL");
    S3_CHECK_OR_DIE_MSG(this->params.getChunkSize() > 0, S3RuntimeError,
                        "chunkSize must not be zero");

    buffer.reserve(this->params.getChunkSize());

    this->uploadId =
        this->s3interface->getUploadId(this->params.getKeyUrl(), this->params.getRegion());
    S3_CHECK_OR_DIE_MSG(!this->uploadId.empty(), S3RuntimeError, "Failed to get upload id");

    S3DEBUG("key: %s, upload id: %s", this->params.getKeyUrl().c_str(), this->uploadId.c_str());
}

// write() first fills up the data buffer before flush it out
uint64_t S3KeyWriter::write(const char* buf, uint64_t count) {
    // Defensive code
    S3_CHECK_OR_DIE_MSG(buf != NULL, S3RuntimeError, "Buffer is NULL");
    this->checkQueryCancelSignal();

    uint64_t offset = 0;
    while (offset < count) {
        if (sharedError) {
            std::rethrow_exception(sharedException);
        }

        uint64_t bufferRemaining = this->params.getChunkSize() - this->buffer.size();
        uint64_t dataRemaining = count - offset;
        uint64_t dataToBuffer = bufferRemaining < dataRemaining ? bufferRemaining : dataRemaining;

        this->buffer.insert(this->buffer.end(), buf + offset, buf + offset + dataToBuffer);

        if (this->buffer.size() == this->params.getChunkSize()) {
            this->flushBuffer();
        }

        offset += dataToBuffer;
    }

    return count;
}

// This should be reentrant, has no side effects when called multiple times.
void S3KeyWriter::close() {
    if (!this->uploadId.empty()) {
        this->completeKeyWriting();
    }
}

void S3KeyWriter::checkQueryCancelSignal() {
    if (S3QueryIsAbortInProgress() && !this->uploadId.empty()) {
        // to avoid dead-lock when other upload threads hold the lock
        pthread_mutex_unlock(&this->mutex);

        // wait for all threads to complete
        for (size_t i = 0; i < threadList.size(); i++) {
            pthread_join(threadList[i], NULL);
        }
        this->threadList.clear();

        // to avoid double unlock as other parts may lock it
        pthread_mutex_lock(&this->mutex);

        S3DEBUG("Start aborting multipart uploading (uploadID: %s, %lu parts uploaded)",
                this->uploadId.c_str(), this->etagList.size());
        this->s3interface->abortUpload(this->params.getKeyUrl(), this->params.getRegion(),
                                       this->uploadId);
        S3DEBUG("Finished aborting multipart uploading (uploadID: %s)", this->uploadId.c_str());

        this->etagList.clear();
        this->uploadId.clear();

        S3_DIE_MSG(S3QueryAbort, "Uploading is interrupted by user");
    }
}

struct ThreadParams {
    S3KeyWriter* keyWriter;
    WriterBuffer data;
    uint64_t currentNumber;
};

void* S3KeyWriter::UploadThreadFunc(void* data) {
    ThreadParams* params = (ThreadParams*)data;
    S3KeyWriter* writer = params->keyWriter;

    try {
        S3DEBUG("Upload thread start: %p, part number: %" PRIu64 ", data size: %" PRIu64,
                pthread_self(), params->currentNumber, params->data.size());
        string etag = writer->s3interface->uploadPartOfData(
            params->data, writer->params.getKeyUrl(), writer->params.getRegion(),
            params->currentNumber, writer->uploadId);

        // when unique_lock destructs it will automatically unlock the mutex.
        UniqueLock threadLock(&writer->mutex);

        // etag is empty if the query is cancelled by user.
        if (!etag.empty()) {
            writer->etagList[params->currentNumber] = etag;
        }
        writer->activeThreads--;
        pthread_cond_broadcast(&writer->cv);
        S3DEBUG("Upload part finish: %p, eTag: %s, part number: %" PRIu64, pthread_self(),
                etag.c_str(), params->currentNumber);
    } catch (S3Exception& e) {
        S3ERROR("Upload thread error: %s", e.getMessage().c_str());
        UniqueLock exceptLock(&writer->exceptionMutex);
        writer->sharedError = true;
        writer->sharedException = std::current_exception();

        // notify the flushBuffer, otherwise it will be locked when trying to create a new thread.
        writer->activeThreads--;
        pthread_cond_broadcast(&writer->cv);
    }

    delete params;
    return NULL;
}

void S3KeyWriter::flushBuffer() {
    if (!this->buffer.empty()) {
        UniqueLock queueLock(&this->mutex);
        while (this->activeThreads >= this->params.getNumOfChunks()) {
            pthread_cond_wait(&this->cv, &this->mutex);
        }

        // Most time query is canceled during uploadPartOfData(). This is the first chance to cancel
        // and clean up upload.
        this->checkQueryCancelSignal();

        this->activeThreads++;

        pthread_t writerThread;
        ThreadParams* params = new ThreadParams();
        params->keyWriter = this;
        params->data.swap(this->buffer);
        params->currentNumber = ++this->partNumber;
        pthread_create(&writerThread, NULL, UploadThreadFunc, params);
        threadList.emplace_back(writerThread);

        this->buffer.clear();
    }
}

void S3KeyWriter::completeKeyWriting() {
    // make sure the buffer is clear
    this->flushBuffer();

    // wait for all threads to complete
    for (size_t i = 0; i < threadList.size(); i++) {
        pthread_join(threadList[i], NULL);
    }
    this->threadList.clear();

    this->checkQueryCancelSignal();

    vector<string> etags;
    // it is equivalent to foreach(e in etagList) push_back(e.second);
    // transform(etagList.begin(), etagList.end(), etags.begin(),
    //          [](std::pair<const uint64_t, string>& p) { return p.second; });
    etags.reserve(etagList.size());

    for (map<uint64_t, string>::iterator i = etagList.begin(); i != etagList.end(); i++) {
        etags.push_back(i->second);
    }

    if (!this->etagList.empty() && !this->uploadId.empty()) {
        this->s3interface->completeMultiPart(this->params.getKeyUrl(), this->params.getRegion(),
                                             this->uploadId, etags);
    }

    S3DEBUG("Segment %d has finished uploading \"%s\"", s3ext_segid,
            this->params.getKeyUrl().c_str());

    this->buffer.clear();
    this->etagList.clear();
    this->uploadId.clear();
}
<|endoftext|>


<commit_before><commit_msg>fix possible vulnerability<commit_after><|endoftext|>


<commit_before><commit_msg>Bugfix: `"%ld"` is the correct `snprintf` format for `INT32_T`.<commit_after><|endoftext|>


<commit_before>#ifndef SDL_KEYBOARD_HH
#define SDL_KEYBOARD_HH

#include "SDLConfig.hh"

namespace RAGE
{
    namespace SDL
    {

        class EventManager;

        ///This class is not suitable for Full Text Input. Use TextInput instead.
        ///However this class is well adapted to key press / release detection, for gaming purpose...
        class Keyboard
        {

            //State of the Keyboard, updated only on demand by getKeyState
            std::vector<bool> _state;

            friend class EventManager;
        protected:
            bool _quitRequested;

        public:

            typedef enum
            {
                None=KMOD_NONE,
                LShift=KMOD_LSHIFT, RShift=KMOD_RSHIFT,
                LCtrl = KMOD_LCTRL, RCtrl = KMOD_RCTRL,
                LAlt = KMOD_LALT, RAlt = KMOD_RALT,
                LMeta =KMOD_LMETA, RMeta = KMOD_RMETA,
                Num = KMOD_NUM,
                Caps = KMOD_CAPS,
                Mode = KMOD_MODE,
                Ctrl = KMOD_CTRL,
                Shift = KMOD_SHIFT,
                Alt = KMOD_ALT,
                Meta = KMOD_META
            }
            Modifier;

            //TO BE CONTINUED
            typedef enum
            {
                KBackspace = SDLK_BACKSPACE,
                KTab = SDLK_TAB,
                KClear = SDLK_CLEAR,
                KReturn = SDLK_RETURN,
                KPause = SDLK_PAUSE,
                KEscape = SDLK_ESCAPE,
                KSpace = SDLK_SPACE,
                KExclaim = SDLK_EXCLAIM,
                KQuotedbl = SDLK_QUOTEDBL,
                KHash = SDLK_HASH,
                KDollar = SDLK_DOLLAR,
                KAmpersand = SDLK_AMPERSAND,
                KQuote = SDLK_QUOTE,
                KLeftparen = SDLK_LEFTPAREN,
                KRightparen = SDLK_RIGHTPAREN,
                KAsterisk = SDLK_ASTERISK,
                KPlus = SDLK_PLUS,
                KComma = SDLK_COMMA,
                KMinus = SDLK_MINUS,
                KPeriod = SDLK_PERIOD,
                KSlash = SDLK_SLASH,
                K0 = SDLK_0,
                K1 = SDLK_1,
                K2 = SDLK_2,
                K3 = SDLK_3,
                K4 = SDLK_4,
                K5 = SDLK_5,
                K6 = SDLK_6,
                K7 = SDLK_7,
                K8 = SDLK_8,
                K9 = SDLK_9,
                KColon, KSemicolon, KLess, KEquals, KGreater, KQuestion, KAt, KLeftbracket, KBackslash, KRightbracket, KCaret, KUnderscore, KBackquote, KA, KB, KC, KD, KE, KF, KG, KH, KI, KJ, KK, KL, KM, KN, KO, KP , KQ, KR, KS, KT, KU, KV, KW, KX, KY, KZ, KDelete,
                KWorld0,KWorld1,KWorld2,KWorld3, KWorld4, KWorld5, KWorld6, KWorld7, KWorld8, KWorld9,
                KWorld10,KWorld11,KWorld12,KWorld13, KWorld14, KWorld15, KWorld16, KWorld17, KWorld18, KWorld19,
                KWorld20,KWorld21,KWorld22,KWorld23, KWorld24, KWorld25, KWorld26, KWorld27, KWorld28, KWorld29,
                KWorld30,KWorld31,KWorld32,KWorld33, KWorld34, KWorld35, KWorld36, KWorld37, KWorld38, KWorld39,
                KWorld40,KWorld41,KWorld42,KWorld43, KWorld44, KWorld45, KWorld46, KWorld47, KWorld48, KWorld49,
                KWorld50,KWorld51,KWorld52,KWorld53, KWorld54, KWorld55, KWorld56, KWorld57, KWorld58, KWorld59,
                KWorld60,KWorld61,KWorld62,KWorld63, KWorld64, KWorld65, KWorld66, KWorld67, KWorld68, KWorld69,
                KWorld70,KWorld71,KWorld72,KWorld73, KWorld74, KWorld75, KWorld76, KWorld77, KWorld78, KWorld79,
                KWorld80,KWorld81,KWorld82,KWorld83, KWorld84, KWorld85, KWorld86, KWorld87, KWorld88, KWorld89,
                KWorld90,KWorld91,KWorld92,KWorld93, KWorld94, KWorld95,
                KKp0 = SDLK_KP0,
				KKp1 = SDLK_KP1,
				KKp2 = SDLK_KP2,
				KKp3 = SDLK_KP3,
				KKp4 = SDLK_KP4,
				KKp5 = SDLK_KP5,
				KKp6 = SDLK_KP6,
				KKp7 = SDLK_KP7,
				KKp8 = SDLK_KP8,
				KKp9 = SDLK_KP9,
                KKDivide = SDLK_KP_DIVIDE,
				KKMultiply = SDLK_KP_MULTIPLY,
				KKEnter = SDLK_KP_ENTER,
                KUp = SDLK_UP,
                KDown = SDLK_DOWN,
                KRight = SDLK_RIGHT,
                KLeft = SDLK_LEFT,
                KInsert, KHome, KEnd, KPageup, KPagedown, KF1, KF2, KF3, KF4, KF5, KF6, KF7, KF8, KF9, KF10, KF11, KF12, KF13, KF14, KF15,
                KNumlock, KCapslock, KScrollock,
				KRShift = SDLK_RSHIFT,
				KLshift = SDLK_LSHIFT,
				KLctrl = SDLK_LCTRL,
				KRctrl = SDLK_RCTRL,
				KRalt = SDLK_RALT,
				KLalt = SDLK_LALT,
				KRmeta, KLmeta, KRsuper, KLsuper, KMode, KCompose, KHelp, KPrintscreen, KSysreq, KBreak, KMenu, KPower, KEuro, KUndo
            }
            Key;

            class  Sym
            {
                Key _key;
                Modifier _mod;
                long unsigned int _unicode;

                //the only class allowed to create Sym object from SDL_keysym
                friend class CriticalEvent;
                friend class Event;

                Sym(const SDL_keysym & ksym) : _key(static_cast<Key>(ksym.sym)), _mod(static_cast<Modifier>(ksym.mod)), _unicode(ksym.unicode)
                {}

            public :

                inline Key getKey() const
                {
                    return _key;
                }
                inline Modifier getMod() const
                {
                    return _mod;
                }
				//WARNING Will return 0 if unicode not enabled
                inline long unsigned int getUnicode() const
                {
                    return _unicode;
                }
				//just to convert the unicode value
				inline char getChar() const
				{
					return(static_cast<char>(_unicode & 0x7F));
				}

                inline bool isUnicode() const
                {
                    return (_unicode & 0xff80) == 0 ;
                }
            };

            //initialises state at size 255 because of the ASCII table size.
            Keyboard() : _state(255,false), _quitRequested(false)
            {}
            virtual ~Keyboard()
            {}

            //Get a snapshot of the current keyboard state
            ///return a vector indexed by Key
            const std::vector<bool> & updateKeyState (void);
            //return true if key down.
            bool getKeyState(Key k )
            {
                updateKeyState();
                return _state[k];
            }

            //get the name of an SDL virtual key symbol
            std::string getKeyName(Key k);

            //get the current key modifier state
            bool isModDown (Modifier m = None);
            //set the current key modifier state
            void setModDown(Modifier m = None);

            // Unicode keyboard translation
            bool enableUNICODE(void);
            bool disableUNICODE(void);
            bool isUNICODEEnabled(void);

            //Params Key repeat
            bool enableKeyRepeat (int delay = SDL_DEFAULT_REPEAT_DELAY,
                                  int interval = SDL_DEFAULT_REPEAT_INTERVAL);

            //Callbacks on SDL_KEYUP or SDL_KEYDOWN
            virtual bool handleKeyEvent (const Sym &s, bool pressed) = 0;
            inline bool handleKeyPressEvent (const Sym &s)
            {
                return handleKeyEvent (s, true);
            }
            inline bool handleKeyReleaseEvent (const Sym &s)
            {
                return handleKeyEvent (s, false);
            }

        };

        ///This class is not suitable for Gaming Input (doesnt detect key releases). Use Keyboard instead.
        ///However this class is well adapted for accurate text typing, with unicode enabled.
        class TextInput : public Keyboard
        {
        public:
            TextInput();
            virtual ~TextInput();

            static char Unicode2Char (long unsigned int unicode)
            {
                return char(unicode & 0x7F);
            }

            //Callbacks on SDL_KEYUP or SDL_KEYDOWN
            virtual bool handleKeyEvent (const Sym &s, bool pressed);

        };
    }
}

#endif
<commit_msg>Add new keyboard definition<commit_after>#ifndef SDL_KEYBOARD_HH
#define SDL_KEYBOARD_HH

#include "SDLConfig.hh"

namespace RAGE
{
    namespace SDL
    {

        class EventManager;

        ///This class is not suitable for Full Text Input. Use TextInput instead.
        ///However this class is well adapted to key press / release detection, for gaming purpose...
        class Keyboard
        {

            //State of the Keyboard, updated only on demand by getKeyState
            std::vector<bool> _state;

            friend class EventManager;
        protected:
            bool _quitRequested;

        public:

            typedef enum
            {
                None=KMOD_NONE,
                LShift=KMOD_LSHIFT, RShift=KMOD_RSHIFT,
                LCtrl = KMOD_LCTRL, RCtrl = KMOD_RCTRL,
                LAlt = KMOD_LALT, RAlt = KMOD_RALT,
                LMeta =KMOD_LMETA, RMeta = KMOD_RMETA,
                Num = KMOD_NUM,
                Caps = KMOD_CAPS,
                Mode = KMOD_MODE,
                Ctrl = KMOD_CTRL,
                Shift = KMOD_SHIFT,
                Alt = KMOD_ALT,
                Meta = KMOD_META
            }
            Modifier;

            //TO BE CONTINUED
            typedef enum
            {
                KBackspace = SDLK_BACKSPACE,
                KTab = SDLK_TAB,
                KClear = SDLK_CLEAR,
                KReturn = SDLK_RETURN,
                KPause = SDLK_PAUSE,
                KEscape = SDLK_ESCAPE,
                KSpace = SDLK_SPACE,
                KExclaim = SDLK_EXCLAIM,
                KQuotedbl = SDLK_QUOTEDBL,
                KHash = SDLK_HASH,
                KDollar = SDLK_DOLLAR,
                KAmpersand = SDLK_AMPERSAND,
                KQuote = SDLK_QUOTE,
                KLeftparen = SDLK_LEFTPAREN,
                KRightparen = SDLK_RIGHTPAREN,
                KAsterisk = SDLK_ASTERISK,
                KPlus = SDLK_PLUS,
                KComma = SDLK_COMMA,
                KMinus = SDLK_MINUS,
                KPeriod = SDLK_PERIOD,
                KSlash = SDLK_SLASH,
                K0 = SDLK_0,
                K1 = SDLK_1,
                K2 = SDLK_2,
                K3 = SDLK_3,
                K4 = SDLK_4,
                K5 = SDLK_5,
                K6 = SDLK_6,
                K7 = SDLK_7,
                K8 = SDLK_8,
                K9 = SDLK_9,
                KColon, KSemicolon, KLess, KEquals, KGreater, KQuestion, KAt, KLeftbracket, KBackslash, KRightbracket, KCaret, KUnderscore, KBackquote, KA, KB, KC, KD, KE, KF, KG, KH, KI, KJ, KK, KL, KM, KN, KO, KP , KQ, KR, KS, KT, KU, KV, KW, KX, KY, KZ, KDelete,
                KWorld0,KWorld1,KWorld2,KWorld3, KWorld4, KWorld5, KWorld6, KWorld7, KWorld8, KWorld9,
                KWorld10,KWorld11,KWorld12,KWorld13, KWorld14, KWorld15, KWorld16, KWorld17, KWorld18, KWorld19,
                KWorld20,KWorld21,KWorld22,KWorld23, KWorld24, KWorld25, KWorld26, KWorld27, KWorld28, KWorld29,
                KWorld30,KWorld31,KWorld32,KWorld33, KWorld34, KWorld35, KWorld36, KWorld37, KWorld38, KWorld39,
                KWorld40,KWorld41,KWorld42,KWorld43, KWorld44, KWorld45, KWorld46, KWorld47, KWorld48, KWorld49,
                KWorld50,KWorld51,KWorld52,KWorld53, KWorld54, KWorld55, KWorld56, KWorld57, KWorld58, KWorld59,
                KWorld60,KWorld61,KWorld62,KWorld63, KWorld64, KWorld65, KWorld66, KWorld67, KWorld68, KWorld69,
                KWorld70,KWorld71,KWorld72,KWorld73, KWorld74, KWorld75, KWorld76, KWorld77, KWorld78, KWorld79,
                KWorld80,KWorld81,KWorld82,KWorld83, KWorld84, KWorld85, KWorld86, KWorld87, KWorld88, KWorld89,
                KWorld90,KWorld91,KWorld92,KWorld93, KWorld94, KWorld95,
                KKp0 = SDLK_KP0,
				KKp1 = SDLK_KP1,
				KKp2 = SDLK_KP2,
				KKp3 = SDLK_KP3,
				KKp4 = SDLK_KP4,
				KKp5 = SDLK_KP5,
				KKp6 = SDLK_KP6,
				KKp7 = SDLK_KP7,
				KKp8 = SDLK_KP8,
				KKp9 = SDLK_KP9,
                KKDivide = SDLK_KP_DIVIDE,
				KKMultiply = SDLK_KP_MULTIPLY,
				KKEnter = SDLK_KP_ENTER,
                KUp = SDLK_UP,
                KDown = SDLK_DOWN,
                KRight = SDLK_RIGHT,
                KLeft = SDLK_LEFT,
                KInsert, KHome, KEnd, KPageup, KPagedown,
				KF1 = SDLK_F1,
				KF2 = SDLK_F2,
				KF3 = SDLK_F3,
				KF4 = SDLK_F4,
				KF5 = SDLK_F5,
				KF6 = SDLK_F6,
				KF7 = SDLK_F7,
				KF8 = SDLK_F8,
				KF9 = SDLK_F9,
				KF10 = SDLK_F10,
				KF11 = SDLK_F11,
				KF12 = SDLK_F12,
				KF13 = SDLK_F13,
				KF14 = SDLK_F14,
				KF15 = SDLK_F15,
                KNumlock, KCapslock, KScrollock,
				KRShift = SDLK_RSHIFT,
				KLshift = SDLK_LSHIFT,
				KLctrl = SDLK_LCTRL,
				KRctrl = SDLK_RCTRL,
				KRalt = SDLK_RALT,
				KLalt = SDLK_LALT,
				KRmeta, KLmeta, KRsuper, KLsuper, KMode, KCompose, KHelp, KPrintscreen, KSysreq, KBreak, KMenu, KPower, KEuro, KUndo
            }
            Key;

            class  Sym
            {
                Key _key;
                Modifier _mod;
                long unsigned int _unicode;

                //the only class allowed to create Sym object from SDL_keysym
                friend class CriticalEvent;
                friend class Event;

                Sym(const SDL_keysym & ksym) : _key(static_cast<Key>(ksym.sym)), _mod(static_cast<Modifier>(ksym.mod)), _unicode(ksym.unicode)
                {}

            public :

                inline Key getKey() const
                {
                    return _key;
                }
                inline Modifier getMod() const
                {
                    return _mod;
                }
				//WARNING Will return 0 if unicode not enabled
                inline long unsigned int getUnicode() const
                {
                    return _unicode;
                }
				//just to convert the unicode value
				inline char getChar() const
				{
					return(static_cast<char>(_unicode & 0x7F));
				}

                inline bool isUnicode() const
                {
                    return (_unicode & 0xff80) == 0 ;
                }
            };

            //initialises state at size 255 because of the ASCII table size.
            Keyboard() : _state(255,false), _quitRequested(false)
            {}
            virtual ~Keyboard()
            {}

            //Get a snapshot of the current keyboard state
            ///return a vector indexed by Key
            const std::vector<bool> & updateKeyState (void);
            //return true if key down.
            bool getKeyState(Key k )
            {
                updateKeyState();
                return _state[k];
            }

            //get the name of an SDL virtual key symbol
            std::string getKeyName(Key k);

            //get the current key modifier state
            bool isModDown (Modifier m = None);
            //set the current key modifier state
            void setModDown(Modifier m = None);

            // Unicode keyboard translation
            bool enableUNICODE(void);
            bool disableUNICODE(void);
            bool isUNICODEEnabled(void);

            //Params Key repeat
            bool enableKeyRepeat (int delay = SDL_DEFAULT_REPEAT_DELAY,
                                  int interval = SDL_DEFAULT_REPEAT_INTERVAL);

            //Callbacks on SDL_KEYUP or SDL_KEYDOWN
            virtual bool handleKeyEvent (const Sym &s, bool pressed) = 0;
            inline bool handleKeyPressEvent (const Sym &s)
            {
                return handleKeyEvent (s, true);
            }
            inline bool handleKeyReleaseEvent (const Sym &s)
            {
                return handleKeyEvent (s, false);
            }

        };

        ///This class is not suitable for Gaming Input (doesnt detect key releases). Use Keyboard instead.
        ///However this class is well adapted for accurate text typing, with unicode enabled.
        class TextInput : public Keyboard
        {
        public:
            TextInput();
            virtual ~TextInput();

            static char Unicode2Char (long unsigned int unicode)
            {
                return char(unicode & 0x7F);
            }

            //Callbacks on SDL_KEYUP or SDL_KEYDOWN
            virtual bool handleKeyEvent (const Sym &s, bool pressed);

        };
    }
}

#endif
<|endoftext|>


<commit_before><commit_msg>Revert "Remove redundant include bringing an rtti module."<commit_after><|endoftext|>