<commit_before>/*************************************************************************
 *
 *  $RCSfile: xmliteme.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-27 15:42:25 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

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

#pragma hdrstop

#include <hintids.hxx>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _SHL_HXX //autogen wg. SHL_WRITER
#include <tools/shl.hxx>
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif
#ifndef _XMLITMPR_HXX
#include "xmlexpit.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLTABE_HXX
#include <xmloff/xmltabe.hxx>
#endif
#ifndef _XMLBRSHE_HXX
#include "xmlbrshe.hxx"
#endif

#ifndef _SVX_TSPTITEM_HXX
#include <svx/tstpitem.hxx>
#endif
#ifndef _SVX_BRSHITEM_HXX
#include <svx/brshitem.hxx>
#endif
#ifndef _SVX_UNOMID_HXX
#include <svx/unomid.hxx>
#endif

#ifndef _VCL_FLDUNIT_HXX
#include <vcl/fldunit.hxx>
#endif

#ifndef _SWMODULE_HXX //autogen wg. SW_MOD
#include <swmodule.hxx>
#endif
#ifndef _DOC_HXX //autogen wg. SwDoc
#include <doc.hxx>
#endif
#ifndef _FMTORNT_HXX
#include "fmtornt.hxx"
#endif
#ifndef _UNOMID_H
#include <unomid.h>
#endif
#ifndef _FRMFMT_HXX
#include "frmfmt.hxx"
#endif
#ifndef _FMTFSIZE_HXX
#include "fmtfsize.hxx"
#endif
#ifndef _SWRECT_HXX
#include "swrect.hxx"
#endif

#ifndef _XMLEXP_HXX
#include "xmlexp.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

extern SvXMLItemMapEntry aXMLTableItemMap[];
extern SvXMLItemMapEntry aXMLTableRowItemMap[];
extern SvXMLItemMapEntry aXMLTableCellItemMap[];

class SwXMLTableItemMapper_Impl: public SvXMLExportItemMapper
{
    SwXMLBrushItemExport aBrushItemExport;

protected:

    sal_uInt32 nAbsWidth;

    void AddAttribute( sal_uInt16 nPrefix, enum XMLTokenEnum eLName,
                       const OUString& rValue,
                       const SvXMLNamespaceMap& rNamespaceMap,
                       SvXMLAttributeList& rAttrList ) const;

public:

    SwXMLTableItemMapper_Impl(
            SvXMLItemMapEntriesRef rMapEntries,
            SwXMLExport& rExp );

    virtual ~SwXMLTableItemMapper_Impl();

    virtual void handleSpecialItem( SvXMLAttributeList& rAttrList,
                                    const SvXMLItemMapEntry& rEntry,
                                    const SfxPoolItem& rItem,
                                    const SvXMLUnitConverter& rUnitConverter,
                                    const SvXMLNamespaceMap& rNamespaceMap,
                                    const SfxItemSet *pSet = NULL ) const;

    virtual void handleElementItem(
            SvXMLExport& rExport,
            const SvXMLItemMapEntry& rEntry,
            const SfxPoolItem& rItem,
            const SvXMLUnitConverter& rUnitConverter,
            const SfxItemSet& rSet,
            sal_uInt16 nFlags ) const;

    inline void SetAbsWidth( sal_uInt32 nAbs );
};

SwXMLTableItemMapper_Impl::SwXMLTableItemMapper_Impl(
        SvXMLItemMapEntriesRef rMapEntries,
        SwXMLExport& rExp ) :
    SvXMLExportItemMapper( rMapEntries ),
    aBrushItemExport( rExp ),
    nAbsWidth( USHRT_MAX )
{
}

SwXMLTableItemMapper_Impl::~SwXMLTableItemMapper_Impl()
{
}

void SwXMLTableItemMapper_Impl::AddAttribute( sal_uInt16 nPrefix,
        enum XMLTokenEnum eLName,
        const OUString& rValue,
        const SvXMLNamespaceMap& rNamespaceMap,
        SvXMLAttributeList& rAttrList ) const
{
    OUString sName( rNamespaceMap.GetQNameByKey( nPrefix,
                                                 GetXMLToken(eLName) ) );
    rAttrList.AddAttribute( sName, rValue );
}

void SwXMLTableItemMapper_Impl::handleSpecialItem(
        SvXMLAttributeList& rAttrList,
        const SvXMLItemMapEntry& rEntry,
        const SfxPoolItem& rItem,
        const SvXMLUnitConverter& rUnitConverter,
        const SvXMLNamespaceMap& rNamespaceMap,
        const SfxItemSet *pSet ) const
{
    switch( rEntry.nWhichId )
    {
    case RES_LR_SPACE:
        {
            const SfxPoolItem *pItem;
            if( pSet &&
                SFX_ITEM_SET == pSet->GetItemState( RES_HORI_ORIENT, sal_True,
                                                    &pItem ) )
            {
                SwHoriOrient eHoriOrient =
                    ((const SwFmtHoriOrient *)pItem)->GetHoriOrient();
                sal_Bool bExport = sal_False;
                sal_uInt32 nMemberId = rEntry.nMemberId & MID_FLAG_MASK;
                switch( nMemberId )
                {
                case MID_L_MARGIN:
                    bExport = HORI_NONE == eHoriOrient ||
                              HORI_LEFT_AND_WIDTH == eHoriOrient;
                    break;
                case MID_R_MARGIN:
                    bExport = HORI_NONE == eHoriOrient;
                    break;
                }
                OUString sValue;
                if( bExport && SvXMLExportItemMapper::QueryXMLValue(
                    rItem, sValue, nMemberId, rUnitConverter ) )
                {
                    AddAttribute( rEntry.nNameSpace, rEntry.eLocalName, sValue,
                                  rNamespaceMap, rAttrList );
                }
            }
        }
        break;

    case RES_FRM_SIZE:
        {
            sal_uInt32 nMemberId = rEntry.nMemberId & MID_FLAG_MASK;
            switch( nMemberId )
            {
            case MID_FRMSIZE_WIDTH:
                if( nAbsWidth )
                {
                    OUStringBuffer sBuffer;
                    rUnitConverter.convertMeasure( sBuffer, nAbsWidth );
                    AddAttribute( rEntry.nNameSpace, rEntry.eLocalName,
                                  sBuffer.makeStringAndClear(),
                                  rNamespaceMap, rAttrList );
                }
                break;
            case MID_FRMSIZE_REL_WIDTH:
                {
                    OUString sValue;
                    if( SvXMLExportItemMapper::QueryXMLValue(
                        rItem, sValue, nMemberId, rUnitConverter ) )
                    {
                        AddAttribute( rEntry.nNameSpace, rEntry.eLocalName,
                                      sValue, rNamespaceMap, rAttrList );
                    }
                }
                break;
            }
        }
        break;
    }
}

/** this method is called for every item that has the
    MID_FLAG_ELEMENT_EXPORT flag set */
void SwXMLTableItemMapper_Impl::handleElementItem(
        SvXMLExport& rExport,
        const SvXMLItemMapEntry& rEntry,
        const SfxPoolItem& rItem,
        const SvXMLUnitConverter& rUnitConverter,
        const SfxItemSet&,
        sal_uInt16 ) const
{
    switch( rEntry.nWhichId )
    {
    case RES_BACKGROUND:
        {
            ((SwXMLTableItemMapper_Impl *)this)->aBrushItemExport.exportXML(
                                                (const SvxBrushItem&)rItem );
        }
        break;
    }
}

inline void SwXMLTableItemMapper_Impl::SetAbsWidth( sal_uInt32 nAbs )
{
    nAbsWidth = nAbs;
}

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

void SwXMLExport::_InitItemExport()
{
    pTwipUnitConv = new SvXMLUnitConverter( MAP_TWIP,
                                GetMM100UnitConverter().getXMLMeasureUnit() );

    xTableItemMap = new SvXMLItemMapEntries( aXMLTableItemMap );
    xTableRowItemMap = new SvXMLItemMapEntries( aXMLTableRowItemMap );
    xTableCellItemMap = new SvXMLItemMapEntries( aXMLTableCellItemMap );

    pTableItemMapper = new SwXMLTableItemMapper_Impl( xTableItemMap, *this );
}

void SwXMLExport::_FinitItemExport()
{
    delete pTableItemMapper;
    delete pTwipUnitConv;
}

void SwXMLExport::ExportTableFmt( const SwFrmFmt& rFmt, sal_uInt32 nAbsWidth )
{
    ((SwXMLTableItemMapper_Impl *)pTableItemMapper)
        ->SetAbsWidth( nAbsWidth );
    ExportFmt( rFmt, XML_TABLE );
}
<commit_msg>INTEGRATION: CWS os8 (1.8.22.1.50); FILE MERGED 2003/04/03 07:13:21 os 1.8.22.1.50.1: #108583# precompiled headers removed<commit_after>/*************************************************************************
 *
 *  $RCSfile: xmliteme.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-17 15:07:59 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#include <hintids.hxx>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _SHL_HXX //autogen wg. SHL_WRITER
#include <tools/shl.hxx>
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif
#ifndef _XMLITMPR_HXX
#include "xmlexpit.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLTABE_HXX
#include <xmloff/xmltabe.hxx>
#endif
#ifndef _XMLBRSHE_HXX
#include "xmlbrshe.hxx"
#endif

#ifndef _SVX_TSPTITEM_HXX
#include <svx/tstpitem.hxx>
#endif
#ifndef _SVX_BRSHITEM_HXX
#include <svx/brshitem.hxx>
#endif
#ifndef _SVX_UNOMID_HXX
#include <svx/unomid.hxx>
#endif

#ifndef _VCL_FLDUNIT_HXX
#include <vcl/fldunit.hxx>
#endif

#ifndef _SWMODULE_HXX //autogen wg. SW_MOD
#include <swmodule.hxx>
#endif
#ifndef _DOC_HXX //autogen wg. SwDoc
#include <doc.hxx>
#endif
#ifndef _FMTORNT_HXX
#include "fmtornt.hxx"
#endif
#ifndef _UNOMID_H
#include <unomid.h>
#endif
#ifndef _FRMFMT_HXX
#include "frmfmt.hxx"
#endif
#ifndef _FMTFSIZE_HXX
#include "fmtfsize.hxx"
#endif
#ifndef _SWRECT_HXX
#include "swrect.hxx"
#endif

#ifndef _XMLEXP_HXX
#include "xmlexp.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

extern SvXMLItemMapEntry aXMLTableItemMap[];
extern SvXMLItemMapEntry aXMLTableRowItemMap[];
extern SvXMLItemMapEntry aXMLTableCellItemMap[];

class SwXMLTableItemMapper_Impl: public SvXMLExportItemMapper
{
    SwXMLBrushItemExport aBrushItemExport;

protected:

    sal_uInt32 nAbsWidth;

    void AddAttribute( sal_uInt16 nPrefix, enum XMLTokenEnum eLName,
                       const OUString& rValue,
                       const SvXMLNamespaceMap& rNamespaceMap,
                       SvXMLAttributeList& rAttrList ) const;

public:

    SwXMLTableItemMapper_Impl(
            SvXMLItemMapEntriesRef rMapEntries,
            SwXMLExport& rExp );

    virtual ~SwXMLTableItemMapper_Impl();

    virtual void handleSpecialItem( SvXMLAttributeList& rAttrList,
                                    const SvXMLItemMapEntry& rEntry,
                                    const SfxPoolItem& rItem,
                                    const SvXMLUnitConverter& rUnitConverter,
                                    const SvXMLNamespaceMap& rNamespaceMap,
                                    const SfxItemSet *pSet = NULL ) const;

    virtual void handleElementItem(
            SvXMLExport& rExport,
            const SvXMLItemMapEntry& rEntry,
            const SfxPoolItem& rItem,
            const SvXMLUnitConverter& rUnitConverter,
            const SfxItemSet& rSet,
            sal_uInt16 nFlags ) const;

    inline void SetAbsWidth( sal_uInt32 nAbs );
};

SwXMLTableItemMapper_Impl::SwXMLTableItemMapper_Impl(
        SvXMLItemMapEntriesRef rMapEntries,
        SwXMLExport& rExp ) :
    SvXMLExportItemMapper( rMapEntries ),
    aBrushItemExport( rExp ),
    nAbsWidth( USHRT_MAX )
{
}

SwXMLTableItemMapper_Impl::~SwXMLTableItemMapper_Impl()
{
}

void SwXMLTableItemMapper_Impl::AddAttribute( sal_uInt16 nPrefix,
        enum XMLTokenEnum eLName,
        const OUString& rValue,
        const SvXMLNamespaceMap& rNamespaceMap,
        SvXMLAttributeList& rAttrList ) const
{
    OUString sName( rNamespaceMap.GetQNameByKey( nPrefix,
                                                 GetXMLToken(eLName) ) );
    rAttrList.AddAttribute( sName, rValue );
}

void SwXMLTableItemMapper_Impl::handleSpecialItem(
        SvXMLAttributeList& rAttrList,
        const SvXMLItemMapEntry& rEntry,
        const SfxPoolItem& rItem,
        const SvXMLUnitConverter& rUnitConverter,
        const SvXMLNamespaceMap& rNamespaceMap,
        const SfxItemSet *pSet ) const
{
    switch( rEntry.nWhichId )
    {
    case RES_LR_SPACE:
        {
            const SfxPoolItem *pItem;
            if( pSet &&
                SFX_ITEM_SET == pSet->GetItemState( RES_HORI_ORIENT, sal_True,
                                                    &pItem ) )
            {
                SwHoriOrient eHoriOrient =
                    ((const SwFmtHoriOrient *)pItem)->GetHoriOrient();
                sal_Bool bExport = sal_False;
                sal_uInt32 nMemberId = rEntry.nMemberId & MID_FLAG_MASK;
                switch( nMemberId )
                {
                case MID_L_MARGIN:
                    bExport = HORI_NONE == eHoriOrient ||
                              HORI_LEFT_AND_WIDTH == eHoriOrient;
                    break;
                case MID_R_MARGIN:
                    bExport = HORI_NONE == eHoriOrient;
                    break;
                }
                OUString sValue;
                if( bExport && SvXMLExportItemMapper::QueryXMLValue(
                    rItem, sValue, nMemberId, rUnitConverter ) )
                {
                    AddAttribute( rEntry.nNameSpace, rEntry.eLocalName, sValue,
                                  rNamespaceMap, rAttrList );
                }
            }
        }
        break;

    case RES_FRM_SIZE:
        {
            sal_uInt32 nMemberId = rEntry.nMemberId & MID_FLAG_MASK;
            switch( nMemberId )
            {
            case MID_FRMSIZE_WIDTH:
                if( nAbsWidth )
                {
                    OUStringBuffer sBuffer;
                    rUnitConverter.convertMeasure( sBuffer, nAbsWidth );
                    AddAttribute( rEntry.nNameSpace, rEntry.eLocalName,
                                  sBuffer.makeStringAndClear(),
                                  rNamespaceMap, rAttrList );
                }
                break;
            case MID_FRMSIZE_REL_WIDTH:
                {
                    OUString sValue;
                    if( SvXMLExportItemMapper::QueryXMLValue(
                        rItem, sValue, nMemberId, rUnitConverter ) )
                    {
                        AddAttribute( rEntry.nNameSpace, rEntry.eLocalName,
                                      sValue, rNamespaceMap, rAttrList );
                    }
                }
                break;
            }
        }
        break;
    }
}

/** this method is called for every item that has the
    MID_FLAG_ELEMENT_EXPORT flag set */
void SwXMLTableItemMapper_Impl::handleElementItem(
        SvXMLExport& rExport,
        const SvXMLItemMapEntry& rEntry,
        const SfxPoolItem& rItem,
        const SvXMLUnitConverter& rUnitConverter,
        const SfxItemSet&,
        sal_uInt16 ) const
{
    switch( rEntry.nWhichId )
    {
    case RES_BACKGROUND:
        {
            ((SwXMLTableItemMapper_Impl *)this)->aBrushItemExport.exportXML(
                                                (const SvxBrushItem&)rItem );
        }
        break;
    }
}

inline void SwXMLTableItemMapper_Impl::SetAbsWidth( sal_uInt32 nAbs )
{
    nAbsWidth = nAbs;
}

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

void SwXMLExport::_InitItemExport()
{
    pTwipUnitConv = new SvXMLUnitConverter( MAP_TWIP,
                                GetMM100UnitConverter().getXMLMeasureUnit() );

    xTableItemMap = new SvXMLItemMapEntries( aXMLTableItemMap );
    xTableRowItemMap = new SvXMLItemMapEntries( aXMLTableRowItemMap );
    xTableCellItemMap = new SvXMLItemMapEntries( aXMLTableCellItemMap );

    pTableItemMapper = new SwXMLTableItemMapper_Impl( xTableItemMap, *this );
}

void SwXMLExport::_FinitItemExport()
{
    delete pTableItemMapper;
    delete pTwipUnitConv;
}

void SwXMLExport::ExportTableFmt( const SwFrmFmt& rFmt, sal_uInt32 nAbsWidth )
{
    ((SwXMLTableItemMapper_Impl *)pTableItemMapper)
        ->SetAbsWidth( nAbsWidth );
    ExportFmt( rFmt, XML_TABLE );
}
<|endoftext|>


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

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 **************************************************************************/

#include "DepthComplexity.h"

DC_BEGIN_DREEMCHEST

namespace Scene {

// ** DepthComplexity::DepthComplexity
DepthComplexity::DepthComplexity( RenderingContext& context )
    : RenderSystem( context )
{
    // Create shader
    m_technique = context.createTechnique( "constantColor", "../Source/Dreemchest/Scene/Rendering/Shaders/ConstantColor.shader" );

    // Create render operation emitters
    for( s32 i = 0; i < TotalRenderModes; i++ ) {
        m_emitters[i] = DC_NEW StaticMeshEmitter( context, BIT( i ), 0 );
    }
}

// ** DepthComplexity::emitRenderOperations
void DepthComplexity::emitRenderOperations( const Ecs::Entity& entity, const Camera& camera, const Transform& transform, const RenderDepthComplexity& depthComplexity )
{
    // Get active command buffer
    Commands& commands = m_context.commands();

    // Set additive blend rasterization for all rendering modes
    commands.emitRasterOptions( AllRenderModesBit, RasterizationOptions::additive().overrideZWrite( true ) );

    // Set the default technique
    const Technique& tech = m_technique.readLock();
    commands.emitPushTechnique( m_technique );

    // Emit operations for all rendering mode
    for( s32 i = 0; i < TotalRenderModes; i++ ) {
        // Change the constant color for this mode
        commands.emitConstantColor( depthComplexity.colorForMode( static_cast<RenderingMode>( i ) ) * depthComplexity.intensity() );

        // Emit draw calls
        m_emitters[i]->emit( transform.position() );
    }

    // Pop the default technique
    commands.emitPopTechnique();
}

} // namespace Scene

DC_END_DREEMCHEST<commit_msg>Fixed: comment in DepthComplexity rendering system<commit_after>/**************************************************************************

 The MIT License (MIT)

 Copyright (c) 2015 Dmitry Sovetov

 https://github.com/dmsovetov

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 **************************************************************************/

#include "DepthComplexity.h"

DC_BEGIN_DREEMCHEST

namespace Scene {

// ** DepthComplexity::DepthComplexity
DepthComplexity::DepthComplexity( RenderingContext& context )
    : RenderSystem( context )
{
    // Create the technique
    m_technique = context.createTechnique( "constantColor", "../Source/Dreemchest/Scene/Rendering/Shaders/ConstantColor.shader" );

    // Create render operation emitters
    for( s32 i = 0; i < TotalRenderModes; i++ ) {
        m_emitters[i] = DC_NEW StaticMeshEmitter( context, BIT( i ), 0 );
    }
}

// ** DepthComplexity::emitRenderOperations
void DepthComplexity::emitRenderOperations( const Ecs::Entity& entity, const Camera& camera, const Transform& transform, const RenderDepthComplexity& depthComplexity )
{
    // Get active command buffer
    Commands& commands = m_context.commands();

    // Set additive blend rasterization for all rendering modes
    commands.emitRasterOptions( AllRenderModesBit, RasterizationOptions::additive().overrideZWrite( true ) );

    // Set the default technique
    const Technique& tech = m_technique.readLock();
    commands.emitPushTechnique( m_technique );

    // Emit operations for all rendering mode
    for( s32 i = 0; i < TotalRenderModes; i++ ) {
        // Change the constant color for this mode
        commands.emitConstantColor( depthComplexity.colorForMode( static_cast<RenderingMode>( i ) ) * depthComplexity.intensity() );

        // Emit draw calls
        m_emitters[i]->emit( transform.position() );
    }

    // Pop the default technique
    commands.emitPopTechnique();
}

} // namespace Scene

DC_END_DREEMCHEST<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#include "../../StroikaPreComp.h"

#if qPlatform_Windows
#include <windows.h>
#endif

#if qHasLibrary_ODBC
#include <sql.h>
#include <sqlext.h>
#endif

#include "../../Characters/CString/Utilities.h"
#include "../../Characters/Format.h"

#include "../Exception.h"

#include "ODBC.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Database;
using namespace Stroika::Foundation::Database::SQL::ODBC;
using namespace Debug;

#if qHasLibrary_ODBC

namespace {
    void ThrowIfSQLError_ (SQLRETURN r, const String& message)
    {
        if ((r != SQL_SUCCESS) and (r != SQL_SUCCESS_WITH_INFO)) [[UNLIKELY_ATTR]] {
            Execution::Throw (Exception{message});
        }
    }
}

/*
 ********************************************************************************
 *************************** ODBC::Connection::Rep_ *****************************
 ********************************************************************************
 */
struct Connection::Rep_ final : IRep {
    SQLHDBC fConnectionHandle{nullptr};
    SQLHENV fODBCEnvironmentHandle{nullptr};

    Rep_ (const Options& options)
    {
        TraceContextBumper ctx{"SQLite::Connection::Rep_::Rep_"};
        if (not options.fDSN) {
            Execution::Throw (Exception{L"DSN Required"sv});
        }
        try {
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &fODBCEnvironmentHandle), L"Error AllocHandle"sv);
            ThrowIfSQLError_ (::SQLSetEnvAttr (fODBCEnvironmentHandle, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*> (SQL_OV_ODBC3), 0), L"Error SetEnv"sv);
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_DBC, fODBCEnvironmentHandle, &fConnectionHandle), L"Error AllocHDB"sv);

            ::SQLSetConnectAttr (fConnectionHandle, SQL_LOGIN_TIMEOUT, reinterpret_cast<SQLPOINTER*> (5), 0);
            {
                // See the docs on SQLConnect - the error handling needs to be VASTLY more complex. We need some mechanism to return
                // warnings to the caller (to be ignored or whatever).
                // And ONLY thorw exceptions on ERROR!
                SQLRETURN return_value = ::SQLConnect (
                    fConnectionHandle,
                    reinterpret_cast<SQLTCHAR*> (const_cast<TCHAR*> (options.fDSN->AsSDKString ().c_str ())),
                    SQL_NTS,
                    nullptr, SQL_NTS,
                    nullptr, SQL_NTS);
                if ((return_value != SQL_SUCCESS) && (return_value != SQL_SUCCESS_WITH_INFO)) {
                    // This logic for producing an error message completely sucks and is largely incorrect
                    wstring     errorString = L"Error SQLConnect: ";
                    SQLTCHAR    sqlState[6];
                    SQLINTEGER  errorCode;
                    SQLSMALLINT messageLength;
                    SQLTCHAR    errorMessage[1024];
                    DISABLE_COMPILER_MSC_WARNING_START (4267)
                    long errValue = ::SQLGetDiagRec (
                        SQL_HANDLE_DBC, fConnectionHandle, 1,
                        reinterpret_cast<SQLTCHAR*> (sqlState), &errorCode,
                        reinterpret_cast<SQLTCHAR*> (errorMessage),
                        NEltsOf (errorMessage), &messageLength);
                    DISABLE_COMPILER_MSC_WARNING_END (4267)
                    if (errValue == SQL_SUCCESS) {
                        // TCHAR isn't the same SQLTCHAR for 'ANSI' because for some crazy reason, they
                        // used unsigned char for SQLCHAR!
                        errorString += SDKString2Wide (reinterpret_cast<TCHAR*> (errorMessage));
                    }
                    else if (errValue == SQL_SUCCESS_WITH_INFO) {
                        errorString = L"Error message too long at";
                    }
                    else if (errValue == SQL_ERROR) {
                        errorString += L"RecNumber was negative or 0 or BufferLength was less tha 0";
                    }
                    else if (errValue == SQL_NO_DATA) {
                        errorString += L"SQL no data";
                    }
                    Execution::Throw (Exception{errorString});
                }
            }
        }
        catch (...) {
            if (fConnectionHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
                fConnectionHandle = nullptr;
            }
            if (fODBCEnvironmentHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
                fODBCEnvironmentHandle = nullptr;
            }
        }
    }
    ~Rep_ ()
    {
        if (fConnectionHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
        }
        if (fODBCEnvironmentHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
        }
    }
    virtual shared_ptr<const EngineProperties> GetEngineProperties () const override
    {
        AssertNotImplemented ();
        struct MyEngineProperties_ final : EngineProperties {
            virtual String GetEngineName () const override
            {
                return L"ODBC"sv; // must indirect to connection to get more info (from dns at least? not clear)
            }
            virtual String GetSQL (NonStandardSQL n) const override
            {
                // see https://stackoverflow.com/questions/167576/check-if-table-exists-in-sql-server
                AssertNotImplemented ();
                return L"";
            }
            virtual bool SupportsNestedTransactions () const override
            {
                return false;
            }
        };
        return make_shared<const MyEngineProperties_> (); // dynamic info based on connection/dsn
    }
    virtual SQL::Statement mkStatement (const String& sql) override
    {
        Connection::Ptr conn = Connection::Ptr{dynamic_pointer_cast<Connection::IRep> (shared_from_this ())};
        return ODBC::Statement{conn, sql};
    }
    virtual SQL::Transaction mkTransaction () override
    {
        Connection::Ptr conn = Connection::Ptr{dynamic_pointer_cast<Connection::IRep> (shared_from_this ())};
        return ODBC::Transaction{conn};
    }
    virtual void Exec (const String& /*sql*/) override
    {
        AssertNotImplemented ();
    }
};

/*
 ********************************************************************************
 ************************* SQL::ODBC::Connection::Ptr ***************************
 ********************************************************************************
 */
SQL::ODBC::Connection::Ptr::Ptr (const shared_ptr<IRep>& src)
    : inherited{src}
{
}

/*
 ********************************************************************************
 ************************** SQL::ODBC::Connection *******************************
 ********************************************************************************
 */
auto SQL::ODBC::Connection::New (const Options& options) -> Ptr
{
    auto tmp = make_shared<Rep_> (options);
    Ptr  result{tmp};
    return result;
}

/*
 ********************************************************************************
 ******************************* SQLite::Statement ******************************
 ********************************************************************************
 */
struct Statement::MyRep_ : IRep {
    MyRep_ (const Connection::Ptr& db, const String& query)
        : fConnectionPtr_{db}
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        TraceContextBumper ctx{"SQLite::Statement::MyRep_::CTOR", Stroika_Foundation_Debug_OptionalizeTraceArgs (L "db=%p, query='%s'", db, query.c_str ())};
#endif
        RequireNotNull (db);
#if qDebug
        _fSharedContext = fConnectionPtr_.GetSharedContext ();
#endif
        string                                                    queryUTF8 = query.AsUTF8 ();
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
    }
    ~MyRep_ ()
    {
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
    }
    virtual String GetSQL (WhichSQLFlag whichSQL) const override
    {
        shared_lock<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        return String{};
    }
    virtual Sequence<ColumnDescription> GetColumns () const override
    {
        shared_lock<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        return Sequence<ColumnDescription>{};
    };
    virtual Sequence<ParameterDescription> GetParameters () const override
    {
        shared_lock<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        return fParameters_;
    };
    virtual void Bind (unsigned int parameterIndex, const VariantValue& v) override
    {
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        fParameters_[parameterIndex].fValue = v;
        AssertNotImplemented ();
    }
    virtual void Bind (const String& parameterName, const VariantValue& v) override
    {
        Require (not parameterName.empty ());
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        String pn = parameterName;
        if (pn[0] != ':') {
            pn = L":" + pn;
        }
        for (unsigned int i = 0; i < fParameters_.length (); ++i) {
            if (fParameters_[i].fName == pn) {
                Bind (i, v);
                return;
            }
        }
        DbgTrace (L"Statement::Bind: Parameter '%s' not found in list %s", parameterName.c_str (), Characters::ToString (fParameters_.Select<String> ([] (const auto& i) { return i.fName; })).c_str ());
        RequireNotReached (); // invalid paramter name provided
    }
    virtual void Reset () override
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        TraceContextBumper ctx{"SQLite::Statement::MyRep_::Statement::Reset"};
#endif
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
    }
    virtual optional<Row> GetNextRow () override
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        TraceContextBumper ctx{"SQLite::Statement::MyRep_::Statement::GetNextRow"};
#endif
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        return nullopt;
    }

    Connection::Ptr                fConnectionPtr_;
    vector<ColumnDescription>      fColumns_;
    Sequence<ParameterDescription> fParameters_;
};

Statement::Statement (const Connection::Ptr& db, const String& query)
    : inherited{make_unique<MyRep_> (db, query)}
{
}

/*
 ********************************************************************************
 ******************************* SQLite::Transaction ****************************
 ********************************************************************************
 */
struct Transaction::MyRep_ : public SQL::Transaction::IRep {
    MyRep_ (const Connection::Ptr& db)
        : fConnectionPtr_{db}
    {
        AssertNotImplemented ();
    }
    virtual void Commit () override
    {
        Require (not fCompleted_);
        fCompleted_ = true;
        fConnectionPtr_->Exec (L"COMMIT;"sv);
    }
    virtual void Rollback () override
    {
        Require (not fCompleted_);
        fCompleted_ = true;
        fConnectionPtr_->Exec (L"ROLLBACK;"sv);
    }
    virtual Disposition GetDisposition () const override
    {
        // @todo record more info so we can report finer grained status ; try/catch in rollback/commit and dbgtraces
        return fCompleted_ ? Disposition::eCompleted : Disposition::eNone;
    }
    Connection::Ptr fConnectionPtr_;
    bool            fCompleted_{false};
};
Transaction::Transaction (const Connection::Ptr& db)
    : inherited{make_unique<MyRep_> (db)}
{
}

/*
 ********************************************************************************
 ******************************** LEGACY-DEPRECATED *****************************
 ********************************************************************************
 */
class Database::SQL::ODBC::DBConnection::Rep {
public:
    SQLHDBC      fConnectionHandle{nullptr};
    SQLHENV      fODBCEnvironmentHandle{nullptr};
    unsigned int fNestedTransactionCount{0};

public:
    Rep (const wstring& dsn)
    {
        try {
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &fODBCEnvironmentHandle), L"Error AllocHandle"sv);
            ThrowIfSQLError_ (::SQLSetEnvAttr (fODBCEnvironmentHandle, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*> (SQL_OV_ODBC3), 0), L"Error SetEnv"sv);
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_DBC, fODBCEnvironmentHandle, &fConnectionHandle), L"Error AllocHDB"sv);

            ::SQLSetConnectAttr (fConnectionHandle, SQL_LOGIN_TIMEOUT, reinterpret_cast<SQLPOINTER*> (5), 0);
            {
                // See the docs on SQLConnect - the error handling needs to be VASTLY more complex. We need some mechanism to return
                // warnings to the caller (to be ignored or whatever).
                // And ONLY thorw exceptions on ERROR!
                SQLRETURN return_value = ::SQLConnect (
                    fConnectionHandle,
                    reinterpret_cast<SQLTCHAR*> (const_cast<TCHAR*> (ToSDKString (dsn).c_str ())),
                    SQL_NTS,
                    nullptr, SQL_NTS,
                    nullptr, SQL_NTS);
                if ((return_value != SQL_SUCCESS) && (return_value != SQL_SUCCESS_WITH_INFO)) {
                    // This logic for producing an error message completely sucks and is largely incorrect
                    wstring     errorString = L"Error SQLConnect: ";
                    SQLTCHAR    sqlState[6];
                    SQLINTEGER  errorCode;
                    SQLSMALLINT messageLength;
                    SQLTCHAR    errorMessage[1024];
                    DISABLE_COMPILER_MSC_WARNING_START (4267)
                    long errValue = ::SQLGetDiagRec (
                        SQL_HANDLE_DBC, fConnectionHandle, 1,
                        reinterpret_cast<SQLTCHAR*> (sqlState), &errorCode,
                        reinterpret_cast<SQLTCHAR*> (errorMessage),
                        NEltsOf (errorMessage), &messageLength);
                    DISABLE_COMPILER_MSC_WARNING_END (4267)
                    if (errValue == SQL_SUCCESS) {
                        // TCHAR isn't the same SQLTCHAR for 'ANSI' because for some crazy reason, they
                        // used unsigned char for SQLCHAR!
                        errorString += SDKString2Wide (reinterpret_cast<TCHAR*> (errorMessage));
                    }
                    else if (errValue == SQL_SUCCESS_WITH_INFO) {
                        errorString = L"Error message too long at";
                    }
                    else if (errValue == SQL_ERROR) {
                        errorString += L"RecNumber was negative or 0 or BufferLength was less tha 0";
                    }
                    else if (errValue == SQL_NO_DATA) {
                        errorString += L"SQL no data";
                    }
                    Execution::Throw (Exception{errorString});
                }
            }
        }
        catch (...) {
            if (fConnectionHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
                fConnectionHandle = nullptr;
            }
            if (fODBCEnvironmentHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
                fODBCEnvironmentHandle = nullptr;
            }
        }
    }
    virtual ~Rep ()
    {
        if (fConnectionHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
        }
        if (fODBCEnvironmentHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
        }
    }
};
Database::SQL::ODBC::DBConnection::DBConnection (const wstring& dsn)
    : fRep{make_shared<Rep> (dsn)}
{
}

unsigned int Database::SQL::ODBC::DBConnection::GetNestedTransactionCount () const
{
    return fRep->fNestedTransactionCount;
}
#endif
<commit_msg>cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#include "../../StroikaPreComp.h"

#if qPlatform_Windows
#include <windows.h>
#endif

#if qHasLibrary_ODBC
#include <sql.h>
#include <sqlext.h>
#endif

#include "../../Characters/CString/Utilities.h"
#include "../../Characters/Format.h"

#include "../Exception.h"

#include "ODBC.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Database;
using namespace Stroika::Foundation::Database::SQL::ODBC;
using namespace Debug;

#if qHasLibrary_ODBC

namespace {
    void ThrowIfSQLError_ (SQLRETURN r, const String& message)
    {
        if ((r != SQL_SUCCESS) and (r != SQL_SUCCESS_WITH_INFO)) [[UNLIKELY_ATTR]] {
            Execution::Throw (Exception{message});
        }
    }
}

/*
 ********************************************************************************
 *************************** ODBC::Connection::Rep_ *****************************
 ********************************************************************************
 */
struct Connection::Rep_ final : IRep {
    SQLHDBC fConnectionHandle{nullptr};
    SQLHENV fODBCEnvironmentHandle{nullptr};

    Rep_ (const Options& options)
    {
        TraceContextBumper ctx{"SQLite::Connection::Rep_::Rep_"};
        if (not options.fDSN) {
            Execution::Throw (Exception{L"DSN Required"sv});
        }
        try {
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &fODBCEnvironmentHandle), L"Error AllocHandle"sv);
            ThrowIfSQLError_ (::SQLSetEnvAttr (fODBCEnvironmentHandle, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*> (SQL_OV_ODBC3), 0), L"Error SetEnv"sv);
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_DBC, fODBCEnvironmentHandle, &fConnectionHandle), L"Error AllocHDB"sv);

            ::SQLSetConnectAttr (fConnectionHandle, SQL_LOGIN_TIMEOUT, reinterpret_cast<SQLPOINTER*> (5), 0);
            {
                // See the docs on SQLConnect - the error handling needs to be VASTLY more complex. We need some mechanism to return
                // warnings to the caller (to be ignored or whatever).
                // And ONLY thorw exceptions on ERROR!
                SQLRETURN return_value = ::SQLConnect (
                    fConnectionHandle,
                    reinterpret_cast<SQLTCHAR*> (const_cast<TCHAR*> (options.fDSN->AsSDKString ().c_str ())),
                    SQL_NTS,
                    nullptr, SQL_NTS,
                    nullptr, SQL_NTS);
                if ((return_value != SQL_SUCCESS) && (return_value != SQL_SUCCESS_WITH_INFO)) {
                    // This logic for producing an error message completely sucks and is largely incorrect
                    wstring     errorString = L"Error SQLConnect: ";
                    SQLTCHAR    sqlState[6];
                    SQLINTEGER  errorCode;
                    SQLSMALLINT messageLength;
                    SQLTCHAR    errorMessage[1024];
                    DISABLE_COMPILER_MSC_WARNING_START (4267)
                    long errValue = ::SQLGetDiagRec (
                        SQL_HANDLE_DBC, fConnectionHandle, 1,
                        reinterpret_cast<SQLTCHAR*> (sqlState), &errorCode,
                        reinterpret_cast<SQLTCHAR*> (errorMessage),
                        NEltsOf (errorMessage), &messageLength);
                    DISABLE_COMPILER_MSC_WARNING_END (4267)
                    if (errValue == SQL_SUCCESS) {
                        // TCHAR isn't the same SQLTCHAR for 'ANSI' because for some crazy reason, they
                        // used unsigned char for SQLCHAR!
                        errorString += SDKString2Wide (reinterpret_cast<TCHAR*> (errorMessage));
                    }
                    else if (errValue == SQL_SUCCESS_WITH_INFO) {
                        errorString = L"Error message too long at";
                    }
                    else if (errValue == SQL_ERROR) {
                        errorString += L"RecNumber was negative or 0 or BufferLength was less tha 0";
                    }
                    else if (errValue == SQL_NO_DATA) {
                        errorString += L"SQL no data";
                    }
                    Execution::Throw (Exception{errorString});
                }
            }
        }
        catch (...) {
            if (fConnectionHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
                fConnectionHandle = nullptr;
            }
            if (fODBCEnvironmentHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
                fODBCEnvironmentHandle = nullptr;
            }
        }
    }
    ~Rep_ ()
    {
        if (fConnectionHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
        }
        if (fODBCEnvironmentHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
        }
    }
    virtual shared_ptr<const EngineProperties> GetEngineProperties () const override
    {
        AssertNotImplemented ();
        struct MyEngineProperties_ final : EngineProperties {
            virtual String GetEngineName () const override
            {
                return L"ODBC"sv; // must indirect to connection to get more info (from dns at least? not clear)
            }
            virtual String GetSQL ([[maybe_unused]]NonStandardSQL n) const override
            {
                // see https://stackoverflow.com/questions/167576/check-if-table-exists-in-sql-server
                AssertNotImplemented ();
                return String{};
            }
            virtual bool SupportsNestedTransactions () const override
            {
                return false;
            }
        };
        return make_shared<const MyEngineProperties_> (); // dynamic info based on connection/dsn
    }
    virtual SQL::Statement mkStatement (const String& sql) override
    {
        Connection::Ptr conn = Connection::Ptr{dynamic_pointer_cast<Connection::IRep> (shared_from_this ())};
        return ODBC::Statement{conn, sql};
    }
    virtual SQL::Transaction mkTransaction () override
    {
        Connection::Ptr conn = Connection::Ptr{dynamic_pointer_cast<Connection::IRep> (shared_from_this ())};
        return ODBC::Transaction{conn};
    }
    virtual void Exec (const String& /*sql*/) override
    {
        AssertNotImplemented ();
    }
};

/*
 ********************************************************************************
 ************************* SQL::ODBC::Connection::Ptr ***************************
 ********************************************************************************
 */
SQL::ODBC::Connection::Ptr::Ptr (const shared_ptr<IRep>& src)
    : inherited{src}
{
}

/*
 ********************************************************************************
 ************************** SQL::ODBC::Connection *******************************
 ********************************************************************************
 */
auto SQL::ODBC::Connection::New (const Options& options) -> Ptr
{
    auto tmp = make_shared<Rep_> (options);
    Ptr  result{tmp};
    return result;
}

/*
 ********************************************************************************
 ******************************* SQLite::Statement ******************************
 ********************************************************************************
 */
struct Statement::MyRep_ : IRep {
    MyRep_ (const Connection::Ptr& db, const String& query)
        : fConnectionPtr_{db}
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        TraceContextBumper ctx{"SQLite::Statement::MyRep_::CTOR", Stroika_Foundation_Debug_OptionalizeTraceArgs (L "db=%p, query='%s'", db, query.c_str ())};
#endif
        RequireNotNull (db);
#if qDebug
        _fSharedContext = fConnectionPtr_.GetSharedContext ();
#endif
        string                                                    queryUTF8 = query.AsUTF8 ();
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
    }
    ~MyRep_ ()
    {
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
    }
    virtual String GetSQL ([[maybe_unused]]WhichSQLFlag whichSQL) const override
    {
        shared_lock<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        return String{};
    }
    virtual Sequence<ColumnDescription> GetColumns () const override
    {
        shared_lock<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        return Sequence<ColumnDescription>{};
    };
    virtual Sequence<ParameterDescription> GetParameters () const override
    {
        shared_lock<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        return fParameters_;
    };
    virtual void Bind (unsigned int parameterIndex, const VariantValue& v) override
    {
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        fParameters_[parameterIndex].fValue = v;
        AssertNotImplemented ();
    }
    virtual void Bind (const String& parameterName, const VariantValue& v) override
    {
        Require (not parameterName.empty ());
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        String pn = parameterName;
        if (pn[0] != ':') {
            pn = L":" + pn;
        }
        for (unsigned int i = 0; i < fParameters_.length (); ++i) {
            if (fParameters_[i].fName == pn) {
                Bind (i, v);
                return;
            }
        }
        DbgTrace (L"Statement::Bind: Parameter '%s' not found in list %s", parameterName.c_str (), Characters::ToString (fParameters_.Select<String> ([] (const auto& i) { return i.fName; })).c_str ());
        RequireNotReached (); // invalid paramter name provided
    }
    virtual void Reset () override
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        TraceContextBumper ctx{"SQLite::Statement::MyRep_::Statement::Reset"};
#endif
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
    }
    virtual optional<Row> GetNextRow () override
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        TraceContextBumper ctx{"SQLite::Statement::MyRep_::Statement::GetNextRow"};
#endif
        lock_guard<const Debug::AssertExternallySynchronizedLock> critSec{*this};
        AssertNotImplemented ();
        return nullopt;
    }

    Connection::Ptr                fConnectionPtr_;
    vector<ColumnDescription>      fColumns_;
    Sequence<ParameterDescription> fParameters_;
};

Statement::Statement (const Connection::Ptr& db, const String& query)
    : inherited{make_unique<MyRep_> (db, query)}
{
}

/*
 ********************************************************************************
 ******************************* SQLite::Transaction ****************************
 ********************************************************************************
 */
struct Transaction::MyRep_ : public SQL::Transaction::IRep {
    MyRep_ (const Connection::Ptr& db)
        : fConnectionPtr_{db}
    {
        AssertNotImplemented ();
    }
    virtual void Commit () override
    {
        Require (not fCompleted_);
        fCompleted_ = true;
        fConnectionPtr_->Exec (L"COMMIT;"sv);
    }
    virtual void Rollback () override
    {
        Require (not fCompleted_);
        fCompleted_ = true;
        fConnectionPtr_->Exec (L"ROLLBACK;"sv);
    }
    virtual Disposition GetDisposition () const override
    {
        // @todo record more info so we can report finer grained status ; try/catch in rollback/commit and dbgtraces
        return fCompleted_ ? Disposition::eCompleted : Disposition::eNone;
    }
    Connection::Ptr fConnectionPtr_;
    bool            fCompleted_{false};
};
Transaction::Transaction (const Connection::Ptr& db)
    : inherited{make_unique<MyRep_> (db)}
{
}

/*
 ********************************************************************************
 ******************************** LEGACY-DEPRECATED *****************************
 ********************************************************************************
 */
class Database::SQL::ODBC::DBConnection::Rep {
public:
    SQLHDBC      fConnectionHandle{nullptr};
    SQLHENV      fODBCEnvironmentHandle{nullptr};
    unsigned int fNestedTransactionCount{0};

public:
    Rep (const wstring& dsn)
    {
        try {
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &fODBCEnvironmentHandle), L"Error AllocHandle"sv);
            ThrowIfSQLError_ (::SQLSetEnvAttr (fODBCEnvironmentHandle, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*> (SQL_OV_ODBC3), 0), L"Error SetEnv"sv);
            ThrowIfSQLError_ (::SQLAllocHandle (SQL_HANDLE_DBC, fODBCEnvironmentHandle, &fConnectionHandle), L"Error AllocHDB"sv);

            ::SQLSetConnectAttr (fConnectionHandle, SQL_LOGIN_TIMEOUT, reinterpret_cast<SQLPOINTER*> (5), 0);
            {
                // See the docs on SQLConnect - the error handling needs to be VASTLY more complex. We need some mechanism to return
                // warnings to the caller (to be ignored or whatever).
                // And ONLY thorw exceptions on ERROR!
                SQLRETURN return_value = ::SQLConnect (
                    fConnectionHandle,
                    reinterpret_cast<SQLTCHAR*> (const_cast<TCHAR*> (ToSDKString (dsn).c_str ())),
                    SQL_NTS,
                    nullptr, SQL_NTS,
                    nullptr, SQL_NTS);
                if ((return_value != SQL_SUCCESS) && (return_value != SQL_SUCCESS_WITH_INFO)) {
                    // This logic for producing an error message completely sucks and is largely incorrect
                    wstring     errorString = L"Error SQLConnect: ";
                    SQLTCHAR    sqlState[6];
                    SQLINTEGER  errorCode;
                    SQLSMALLINT messageLength;
                    SQLTCHAR    errorMessage[1024];
                    DISABLE_COMPILER_MSC_WARNING_START (4267)
                    long errValue = ::SQLGetDiagRec (
                        SQL_HANDLE_DBC, fConnectionHandle, 1,
                        reinterpret_cast<SQLTCHAR*> (sqlState), &errorCode,
                        reinterpret_cast<SQLTCHAR*> (errorMessage),
                        NEltsOf (errorMessage), &messageLength);
                    DISABLE_COMPILER_MSC_WARNING_END (4267)
                    if (errValue == SQL_SUCCESS) {
                        // TCHAR isn't the same SQLTCHAR for 'ANSI' because for some crazy reason, they
                        // used unsigned char for SQLCHAR!
                        errorString += SDKString2Wide (reinterpret_cast<TCHAR*> (errorMessage));
                    }
                    else if (errValue == SQL_SUCCESS_WITH_INFO) {
                        errorString = L"Error message too long at";
                    }
                    else if (errValue == SQL_ERROR) {
                        errorString += L"RecNumber was negative or 0 or BufferLength was less tha 0";
                    }
                    else if (errValue == SQL_NO_DATA) {
                        errorString += L"SQL no data";
                    }
                    Execution::Throw (Exception{errorString});
                }
            }
        }
        catch (...) {
            if (fConnectionHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
                fConnectionHandle = nullptr;
            }
            if (fODBCEnvironmentHandle != nullptr) {
                ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
                fODBCEnvironmentHandle = nullptr;
            }
        }
    }
    virtual ~Rep ()
    {
        if (fConnectionHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_DBC, fConnectionHandle);
        }
        if (fODBCEnvironmentHandle != nullptr) {
            ::SQLFreeHandle (SQL_HANDLE_ENV, fODBCEnvironmentHandle);
        }
    }
};
Database::SQL::ODBC::DBConnection::DBConnection (const wstring& dsn)
    : fRep{make_shared<Rep> (dsn)}
{
}

unsigned int Database::SQL::ODBC::DBConnection::GetNestedTransactionCount () const
{
    return fRep->fNestedTransactionCount;
}
#endif
<|endoftext|>


<commit_before>
/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#ifndef _Stroika_Foundation_Debug_TimingTrace_inl_
#define _Stroika_Foundation_Debug_TimingTrace_inl_ 1

#include "Trace.h"

namespace Stroika::Foundation::Debug {

    /*
     ********************************************************************************
     ***************************** Debug::TimingTrace *******************************
     ********************************************************************************
     */
    inline TimingTrace::TimingTrace (Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace ("(timeTaken=%f seconds)", timeTaken); }
#else
            nullptr
#endif
    }
    {
    }
    inline TimingTrace::TimingTrace (const char* label, Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [=] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace ("%s (timeTaken=%f seconds)", label, timeTaken); }
#else
            nullptr
#endif
    }
    {
    }
    inline TimingTrace::TimingTrace (const wchar_t* label, Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [=] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace (L"%s (timeTaken=%f seconds)", label, timeTaken); }
#else
            nullptr
#endif
    }
    {
    }
    inline TimingTrace::TimingTrace (const Characters::String& label, Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [=] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace (L"%s (timeTaken=%f seconds)", label.c_str (), timeTaken); }
#else
            nullptr
#endif
    }
    {
    }

}

#endif /*_Stroika_Foundation_Debug_TimingTrace_inl_*/
<commit_msg>silence warning<commit_after>
/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#ifndef _Stroika_Foundation_Debug_TimingTrace_inl_
#define _Stroika_Foundation_Debug_TimingTrace_inl_ 1

#include "Trace.h"

namespace Stroika::Foundation::Debug {

    /*
     ********************************************************************************
     ***************************** Debug::TimingTrace *******************************
     ********************************************************************************
     */
    inline TimingTrace::TimingTrace (Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace ("(timeTaken=%f seconds)", timeTaken); }
#else
            nullptr
#endif
    }
    {
    }
    inline TimingTrace::TimingTrace ([[maybe_unused]]const char* label, Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [=] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace ("%s (timeTaken=%f seconds)", label, timeTaken); }
#else
            nullptr
#endif
    }
    {
    }
    inline TimingTrace::TimingTrace ([[maybe_unused]] const wchar_t* label, Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [=] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace (L"%s (timeTaken=%f seconds)", label, timeTaken); }
#else
            nullptr
#endif
    }
    {
    }
    inline TimingTrace::TimingTrace ([[maybe_unused]] const Characters::String& label, Time::DurationSecondsType warnIfLongerThan)
        : WhenTimeExceeded
    {
        warnIfLongerThan,
#if qDefaultTracingOn
            [=] (Time::DurationSecondsType timeTaken) noexcept { DbgTrace (L"%s (timeTaken=%f seconds)", label.c_str (), timeTaken); }
#else
            nullptr
#endif
    }
    {
    }

}

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


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

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "SaveLoadStateReaction.h"

#include "pqCoreUtilities.h"
#include <vtk_pugixml.h>

#include "ModuleManager.h"
#include "RecentFilesMenu.h"
#include "vtkSMProxyManager.h"

#include <QDir>
#include <QFileDialog>
#include <QtDebug>

namespace tomviz {

SaveLoadStateReaction::SaveLoadStateReaction(QAction* parentObject, bool load)
  : pqReaction(parentObject), m_load(load)
{
}

void SaveLoadStateReaction::onTriggered()
{
  if (m_load) {
    loadState();
  } else {
    saveState();
  }
}

bool SaveLoadStateReaction::saveState()
{
  QFileDialog fileDialog(pqCoreUtilities::mainWidget(), tr("Save State File"),
                         QString(),
                         "tomviz state files (*.tvsm);;All files (*)");
  fileDialog.setObjectName("SaveStateDialog");
  fileDialog.setAcceptMode(QFileDialog::AcceptSave);
  fileDialog.setFileMode(QFileDialog::AnyFile);
  if (fileDialog.exec() == QDialog::Accepted) {
    QString filename = fileDialog.selectedFiles()[0];
    QString format = fileDialog.selectedNameFilter();
    if (!filename.endsWith(".tvsm") &&
        format == "tomviz state files (*.tvsm)") {
      filename = QString("%1%2").arg(filename, ".tvsm");
    }
    return SaveLoadStateReaction::saveState(filename);
  }
  return false;
}

bool SaveLoadStateReaction::loadState()
{
  QFileDialog fileDialog(pqCoreUtilities::mainWidget(), tr("Load State File"),
                         QString(),
                         "tomviz state files (*.tvsm);;All files (*)");
  fileDialog.setObjectName("LoadStateDialog");
  fileDialog.setFileMode(QFileDialog::ExistingFile);
  if (fileDialog.exec() == QDialog::Accepted) {
    return SaveLoadStateReaction::loadState(fileDialog.selectedFiles()[0]);
  }
  return false;
}

bool SaveLoadStateReaction::loadState(const QString& filename)
{
  pugi::xml_document document;
  if (!document.load_file(filename.toLatin1().data())) {
    qCritical() << "Failed to read file (or file not valid xml) :" << filename;
    return false;
  }

  if (ModuleManager::instance().deserialize(document.child("tomvizState"),
                                            QFileInfo(filename).dir())) {
    RecentFilesMenu::pushStateFile(filename);
    return true;
  }
  return false;
}

bool SaveLoadStateReaction::saveState(const QString& filename, bool interactive)
{
  pugi::xml_document document;
  pugi::xml_node root = document.append_child("tomvizState");
  root.append_attribute("version").set_value("0.0a");
  root.append_attribute("paraview_version")
    .set_value(QString("%1.%2.%3")
                 .arg(vtkSMProxyManager::GetVersionMajor())
                 .arg(vtkSMProxyManager::GetVersionMinor())
                 .arg(vtkSMProxyManager::GetVersionPatch())
                 .toLatin1()
                 .data());

  QFileInfo info(filename);

  return (
    ModuleManager::instance().serialize(root, info.dir(), interactive) &&
    document.save_file(/*path*/ filename.toLatin1().data(), /*indent*/ "  "));
}

} // end of namespace
<commit_msg>Minor tweaks<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/
#include "SaveLoadStateReaction.h"

#include "ModuleManager.h"
#include "RecentFilesMenu.h"

#include <pqCoreUtilities.h>
#include <vtkSMProxyManager.h>

#include <vtk_pugixml.h>

#include <QDir>
#include <QFileDialog>
#include <QDebug>

namespace tomviz {

SaveLoadStateReaction::SaveLoadStateReaction(QAction* parentObject, bool load)
  : pqReaction(parentObject), m_load(load)
{
}

void SaveLoadStateReaction::onTriggered()
{
  if (m_load) {
    loadState();
  } else {
    saveState();
  }
}

bool SaveLoadStateReaction::saveState()
{
  QFileDialog fileDialog(pqCoreUtilities::mainWidget(), tr("Save State File"),
                         QString(),
                         "tomviz state files (*.tvsm);;All files (*)");
  fileDialog.setObjectName("SaveStateDialog");
  fileDialog.setAcceptMode(QFileDialog::AcceptSave);
  fileDialog.setFileMode(QFileDialog::AnyFile);
  if (fileDialog.exec() == QDialog::Accepted) {
    QString filename = fileDialog.selectedFiles()[0];
    QString format = fileDialog.selectedNameFilter();
    if (!filename.endsWith(".tvsm") &&
        format == "tomviz state files (*.tvsm)") {
      filename = QString("%1%2").arg(filename, ".tvsm");
    }
    return SaveLoadStateReaction::saveState(filename);
  }
  return false;
}

bool SaveLoadStateReaction::loadState()
{
  QFileDialog fileDialog(pqCoreUtilities::mainWidget(), tr("Load State File"),
                         QString(),
                         "tomviz state files (*.tvsm);;All files (*)");
  fileDialog.setObjectName("LoadStateDialog");
  fileDialog.setFileMode(QFileDialog::ExistingFile);
  if (fileDialog.exec() == QDialog::Accepted) {
    return SaveLoadStateReaction::loadState(fileDialog.selectedFiles()[0]);
  }
  return false;
}

bool SaveLoadStateReaction::loadState(const QString& filename)
{
  pugi::xml_document document;
  if (!document.load_file(filename.toLatin1().data())) {
    qCritical() << "Failed to read file (or file not valid xml) :" << filename;
    return false;
  }

  if (ModuleManager::instance().deserialize(document.child("tomvizState"),
                                            QFileInfo(filename).dir())) {
    RecentFilesMenu::pushStateFile(filename);
    return true;
  }
  return false;
}

bool SaveLoadStateReaction::saveState(const QString& filename, bool interactive)
{
  pugi::xml_document document;
  pugi::xml_node root = document.append_child("tomvizState");
  root.append_attribute("version").set_value("0.0a");
  root.append_attribute("paraview_version")
    .set_value(QString("%1.%2.%3")
                 .arg(vtkSMProxyManager::GetVersionMajor())
                 .arg(vtkSMProxyManager::GetVersionMinor())
                 .arg(vtkSMProxyManager::GetVersionPatch())
                 .toLatin1()
                 .data());

  QFileInfo info(filename);

  return (
    ModuleManager::instance().serialize(root, info.dir(), interactive) &&
    document.save_file(/*path*/ filename.toLatin1().data(), /*indent*/ "  "));
}

} // end of namespace
<|endoftext|>


<commit_before>#include <cstdio>

#include "BitbangSPI_magic.h"
#include "compassTypes.h"

int main(void){
	BitbangSPI spidriver;
	uint_8 data_out[3];
	uint_8 data_in[11];

	data_out[0] = sync_flag;
	data_out[1] = get_mod_info;
	data_out[2] = terminator;

	spidriver.spiSend(data_out, 3);
	spidriver.spiGet(data_in, 11);

	char_u8 tempchr;
	ModInfoResp moduleversion;

		for(int i = 2;i<6;i++) {
			tempchr.u8 = data_in[i];
			moduleversion.module_type[i-2] = tempchr.chr;
		}
		moduleversion.module_type[4] = '\0';//probably usefull

		for(int i = 6;i<10;i++) {
			tempchr.u8 = data_in[i];
			moduleversion.firmware_version[i-6] = tempchr.chr;
		}
		moduleversion.firmware_version[4] = '\0';

	printf("module type:\t%s\n", moduleversion.module_type);
	printf("firmware version:\t%s\n",moduleversion.firmware_version);

}
<commit_msg>simplified testspi.cc<commit_after>#include <cstdio>

#include "BitbangSPI_magic.h"
#include "compassTypes.h"

int main(void){
	BitbangSPI spidriver;
	uint_8 data_out[3];
	uint_8 data_in[11];

	data_out[0] = sync_flag;
	data_out[1] = get_mod_info;
	data_out[2] = terminator;

	spidriver.spiSend(data_out, 3);
	spidriver.spiGet(data_in, 11);

	char_u8 tempchr;
	ModInfoResp moduleversion;

	memcpy(moduleversion.module_type, data_in+2, 4);
	moduleversion.module_type[4] = '\0';
	/*
	for(int i = 2;i<6;i++) {
		tempchr.u8 = data_in[i];
		moduleversion.module_type[i-2] = tempchr.chr;
	}
	moduleversion.module_type[4] = '\0';//probably usefull
	*/

	memcpy(moduleversion.firmware_version, data_in+6, 4);
	moduleversion.firmware_version[4] = '\0';
	/*
	for(int i = 6;i<10;i++) {
		tempchr.u8 = data_in[i];
		moduleversion.firmware_version[i-6] = tempchr.chr;
	}
	moduleversion.firmware_version[4] = '\0';
	*/

	printf("module type:\t%s\n", moduleversion.module_type);
	printf("firmware version:\t%s\n",moduleversion.firmware_version);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "itkMacro.h"
#include "otbImageToImageRCC8Calculator.h"
#include "otbImageList.h"
#include "otbImageFileReader.h"

int otbImageToImageRCC8Calculator(int itkNotUsed(argc), char* argv[])
{
  const unsigned int Dimension = 2;

  int    nbImages  = atoi(argv[1]);
  char * outfile   = argv[2];

  typedef unsigned char                              PixelType;
  typedef otb::Image<PixelType, Dimension>           ImageType;
  typedef otb::ImageFileReader<ImageType>            ReaderType;
  typedef otb::ImageToImageRCC8Calculator<ImageType> CalculatorType;
  typedef otb::ImageList<ImageType>                  ImageListType;
  typedef ImageListType::Iterator                    IteratorType;
  // reference image list
  ImageListType::Pointer images = ImageListType::New();

  // Reading input images
  std::ofstream out;
  out.open(outfile, std::ios::out);
  out << "Test results from otbImageToImageRCC8calculator test." << std::endl;
  for (int k = 1; k <= nbImages; ++k)
    {
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName(argv[2 + k]);
    reader->Update();
    images->PushBack(reader->GetOutput());
    }
  // Declaration
  CalculatorType::Pointer calc, calc1, calc2;
  // Computing relations for each images couple
  int i = 1;
  int j = 1;
  for (IteratorType it1 = images->Begin(); it1 != images->End(); ++it1)
    {
    for (IteratorType it2 = images->Begin(); it2 != images->End(); ++it2)
      {
      std::cout << "Test: computing relation " << i << "," << j << std::endl;
      calc = CalculatorType::New();
      calc->SetInput1(it1.Get());
      calc->SetInput2(it2.Get());
      calc->Update();
      out << calc->GetValue() << "\t";

      if (calc->GetValue() < 3
          || calc->GetValue() == 4
          || calc->GetValue() == 6)
        {
        calc1 = CalculatorType::New();
        calc1->SetInput1(it1.Get());
        calc1->SetInput2(it2.Get());
        calc1->SetLevel1APrioriKnowledge(true);
        calc1->Update();
        if (calc1->GetValue() != calc->GetValue())
          {
          std::cout << "Test failed: Result with level1AprioriKnowledge ";
          std::cout << "different from result without a priori knowledge" << std::endl;
          std::cout << calc->GetValue() << "!=" << calc1->GetValue() << std::endl;
          return EXIT_FAILURE;
          }
        }
      if (calc->GetValue() < 4)
        {
        calc2 = CalculatorType::New();
        calc2->SetInput1(it1.Get());
        calc2->SetInput2(it2.Get());
        calc2->SetLevel3APrioriKnowledge(true);
        calc2->Update();
        if (calc2->GetValue() != calc->GetValue())
          {
          std::cout << "Test failed: Result with level3AprioriKnowledge ";
          std::cout << "different from result without a priori knowledge" << std::endl;
          std::cout << calc->GetValue() << "!=" << calc1->GetValue() << std::endl;
          return EXIT_FAILURE;
          }
        }
      ++j;
      }
    j = 1;
    ++i;
    out << std::endl;
    }
  out.close();

  return EXIT_SUCCESS;
}
<commit_msg>Fix coverity #1266813<commit_after>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "itkMacro.h"
#include "otbImageToImageRCC8Calculator.h"
#include "otbImageList.h"
#include "otbImageFileReader.h"

int otbImageToImageRCC8Calculator(int itkNotUsed(argc), char* argv[])
{
  const unsigned int Dimension = 2;

  int    nbImages  = atoi(argv[1]);
  char * outfile   = argv[2];

  typedef unsigned char                              PixelType;
  typedef otb::Image<PixelType, Dimension>           ImageType;
  typedef otb::ImageFileReader<ImageType>            ReaderType;
  typedef otb::ImageToImageRCC8Calculator<ImageType> CalculatorType;
  typedef otb::ImageList<ImageType>                  ImageListType;
  typedef ImageListType::Iterator                    IteratorType;
  // reference image list
  ImageListType::Pointer images = ImageListType::New();

  // Reading input images
  std::ofstream out;
  out.open(outfile, std::ios::out);
  out << "Test results from otbImageToImageRCC8calculator test." << std::endl;
  for (int k = 1; k <= nbImages; ++k)
    {
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName(argv[2 + k]);
    reader->Update();
    images->PushBack(reader->GetOutput());
    }
  // Declaration
  CalculatorType::Pointer calc, calc1, calc2;
  // Computing relations for each images couple
  int i = 1;
  int j = 1;
  for (IteratorType it1 = images->Begin(); it1 != images->End(); ++it1)
    {
    for (IteratorType it2 = images->Begin(); it2 != images->End(); ++it2)
      {
      std::cout << "Test: computing relation " << i << "," << j << std::endl;
      calc = CalculatorType::New();
      calc->SetInput1(it1.Get());
      calc->SetInput2(it2.Get());
      calc->Update();
      out << calc->GetValue() << "\t";

      if (calc->GetValue() < 3
          || calc->GetValue() == 4
          || calc->GetValue() == 6)
        {
        calc1 = CalculatorType::New();
        calc1->SetInput1(it1.Get());
        calc1->SetInput2(it2.Get());
        calc1->SetLevel1APrioriKnowledge(true);
        calc1->Update();
        if (calc1->GetValue() != calc->GetValue())
          {
          std::cout << "Test failed: Result with level1AprioriKnowledge ";
          std::cout << "different from result without a priori knowledge" << std::endl;
          std::cout << calc->GetValue() << "!=" << calc1->GetValue() << std::endl;
          return EXIT_FAILURE;
          }
        }
      if (calc->GetValue() < 4)
        {
        calc2 = CalculatorType::New();
        calc2->SetInput1(it1.Get());
        calc2->SetInput2(it2.Get());
        calc2->SetLevel3APrioriKnowledge(true);
        calc2->Update();
        if (calc2->GetValue() != calc->GetValue())
          {
          std::cout << "Test failed: Result with level3AprioriKnowledge ";
          std::cout << "different from result without a priori knowledge" << std::endl;
          std::cout << calc->GetValue() << "!=" << calc2->GetValue() << std::endl;
          return EXIT_FAILURE;
          }
        }
      ++j;
      }
    j = 1;
    ++i;
    out << std::endl;
    }
  out.close();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <vector>
#include <algorithm>

#include "NativeCore.hpp"

static DWORD GetRemotePeb(HANDLE process, PPEB* ppeb)
{
	const auto ntdll = GetModuleHandle(TEXT("ntdll"));
	if (!ntdll)
		return ERROR_MOD_NOT_FOUND;

	using tRtlNtStatusToDosError = ULONG (NTAPI *)(
			_In_ NTSTATUS Status
		);
	const auto pRtlNtStatusToDosError = tRtlNtStatusToDosError(GetProcAddress(ntdll, "RtlNtStatusToDosError"));
	if (!pRtlNtStatusToDosError)
		return ERROR_NOT_FOUND;

	using tNtQueryInformationProcess = NTSTATUS (NTAPI *)(
			_In_ HANDLE ProcessHandle,
			_In_ PROCESSINFOCLASS ProcessInformationClass,
			_Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
			_In_ ULONG ProcessInformationLength,
			_Out_opt_ PULONG ReturnLength
		);

	const auto pNtQueryInformationProcess = tNtQueryInformationProcess(GetProcAddress(ntdll, "NtQueryInformationProcess"));
	if (!pNtQueryInformationProcess)
		return ERROR_NOT_FOUND;

	PROCESS_BASIC_INFORMATION pbi;
	const auto status = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), nullptr);
	if (!NT_SUCCESS(status))
		return pRtlNtStatusToDosError(status);

	*ppeb = pbi.PebBaseAddress;

	return ERROR_SUCCESS;
}

template <typename Proc>
static DWORD EnumerateRemoteModulesNative(HANDLE process, Proc proc)
{
	PPEB ppeb;
	const auto error = GetRemotePeb(process, &ppeb);
	if (error != ERROR_SUCCESS)
		return error;

	PPEB_LDR_DATA ldr;
	auto success = ReadRemoteMemory(process, &ppeb->Ldr, &ldr, 0, sizeof(ldr));
	if (!success)
		return ERROR_READ_FAULT; // we seem to swallow the error anyways, might aswell give a distinctive one back

	const auto list_head = &ldr->InMemoryOrderModuleList; // remote address
	PLIST_ENTRY list_current; // remote address
	success = ReadRemoteMemory(process, &list_head->Flink, &list_current, 0, sizeof(list_current));
	if (!success)
		return ERROR_READ_FAULT;

	while (list_current != list_head)
	{
		// TODO: error handling - what do we do if module list changed? We can't un-call the callback

		LDR_DATA_TABLE_ENTRY mod;
		success = ReadRemoteMemory(process, CONTAINING_RECORD(list_current, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks), &mod, 0, sizeof(mod));
		if (!success)
			return ERROR_SUCCESS; // return success here to prevent running the other one

		EnumerateRemoteModuleData data = {};
		data.BaseAddress = mod.DllBase;
		data.Size = *(ULONG*)&mod.Reserved2[1]; // instead of undocced member could read ImageSize from headers
		const auto path_len = std::min(sizeof(RC_UnicodeChar) * (PATH_MAXIMUM_LENGTH - 1), size_t(mod.FullDllName.Length));
		success = ReadRemoteMemory(process, mod.FullDllName.Buffer, data.Path, 0, int(path_len));
		if (!success)
			return ERROR_SUCCESS; // return success here to prevent running the other one

		// UNICODE_STRING is not guaranteed to be null terminated
		data.Path[path_len / 2] = 0;

		proc(&data);

		list_current = mod.InMemoryOrderLinks.Flink;
	}

	return ERROR_SUCCESS;
}

template <typename Proc>
static DWORD EnumerateRemoteModulesWinapi(HANDLE process, Proc proc)
{
	const auto handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetProcessId(process));
	if (handle == INVALID_HANDLE_VALUE)
		return GetLastError();

	MODULEENTRY32W me32 = {};
	me32.dwSize = sizeof(MODULEENTRY32W);
	if (Module32FirstW(handle, &me32))
	{
		do
		{
			EnumerateRemoteModuleData data = {};
			data.BaseAddress = me32.modBaseAddr;
			data.Size = me32.modBaseSize;
			std::memcpy(data.Path, me32.szExePath, std::min(MAX_PATH, PATH_MAXIMUM_LENGTH));

			proc(&data);
		} while (Module32NextW(handle, &me32));
	}

	CloseHandle(handle);

	return ERROR_SUCCESS;
}

void RC_CallConv EnumerateRemoteSectionsAndModules(RC_Pointer process, EnumerateRemoteSectionsCallback callbackSection, EnumerateRemoteModulesCallback callbackModule)
{
	if (callbackSection == nullptr && callbackModule == nullptr)
	{
		return;
	}

	std::vector<EnumerateRemoteSectionData> sections;

	MEMORY_BASIC_INFORMATION memInfo = { };
	memInfo.RegionSize = 0x1000;
	size_t address = 0;
	while (VirtualQueryEx(process, reinterpret_cast<LPCVOID>(address), &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0 && address + memInfo.RegionSize > address)
	{
		if (memInfo.State == MEM_COMMIT)
		{
			EnumerateRemoteSectionData section = {};
			section.BaseAddress = memInfo.BaseAddress;
			section.Size = memInfo.RegionSize;

			section.Protection = SectionProtection::NoAccess;
			if ((memInfo.Protect & PAGE_EXECUTE) == PAGE_EXECUTE) section.Protection |= SectionProtection::Execute;
			if ((memInfo.Protect & PAGE_EXECUTE_READ) == PAGE_EXECUTE_READ) section.Protection |= SectionProtection::Execute | SectionProtection::Read;
			if ((memInfo.Protect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE) section.Protection |= SectionProtection::Execute | SectionProtection::Read | SectionProtection::Write;
			if ((memInfo.Protect & PAGE_EXECUTE_WRITECOPY) == PAGE_EXECUTE_WRITECOPY) section.Protection |= SectionProtection::Execute | SectionProtection::Read | SectionProtection::CopyOnWrite;
			if ((memInfo.Protect & PAGE_READONLY) == PAGE_READONLY) section.Protection |= SectionProtection::Read;
			if ((memInfo.Protect & PAGE_READWRITE) == PAGE_READWRITE) section.Protection |= SectionProtection::Read | SectionProtection::Write;
			if ((memInfo.Protect & PAGE_WRITECOPY) == PAGE_WRITECOPY) section.Protection |= SectionProtection::Read | SectionProtection::CopyOnWrite;
			if ((memInfo.Protect & PAGE_GUARD) == PAGE_GUARD) section.Protection |= SectionProtection::Guard;

			switch (memInfo.Type)
			{
			case MEM_IMAGE:
				section.Type = SectionType::Image;
				break;
			case MEM_MAPPED:
				section.Type = SectionType::Mapped;
				break;
			case MEM_PRIVATE:
				section.Type = SectionType::Private;
				break;
			}

			section.Category = section.Type == SectionType::Private ? SectionCategory::HEAP : SectionCategory::Unknown;

			sections.push_back(section);
		}
		address = reinterpret_cast<size_t>(memInfo.BaseAddress) + memInfo.RegionSize;
	}

	const auto moduleEnumerator = [&](EnumerateRemoteModuleData* data)
	{
		if (callbackModule != nullptr)
		{
			callbackModule(data);
		}

		if (callbackSection != nullptr)
		{
			auto it = std::lower_bound(std::begin(sections), std::end(sections), static_cast<LPVOID>(data->BaseAddress), [&sections](const auto& lhs, const LPVOID& rhs)
			{
				return lhs.BaseAddress < rhs;
			});

			IMAGE_DOS_HEADER imageDosHeader = {};
			IMAGE_NT_HEADERS imageNtHeaders = {};

			if (!ReadRemoteMemory(process, data->BaseAddress, &imageDosHeader, 0, sizeof(IMAGE_DOS_HEADER))
				|| !ReadRemoteMemory(process, PUCHAR(data->BaseAddress) + imageDosHeader.e_lfanew, &imageNtHeaders, 0, sizeof(IMAGE_NT_HEADERS)))
			{
				return;
			}

			std::vector<IMAGE_SECTION_HEADER> sectionHeaders(imageNtHeaders.FileHeader.NumberOfSections);
			ReadRemoteMemory(process, PUCHAR(data->BaseAddress) + imageDosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS), sectionHeaders.data(), 0, imageNtHeaders.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
			for (auto&& sectionHeader : sectionHeaders)
			{
				const auto sectionAddress = reinterpret_cast<size_t>(data->BaseAddress) + sectionHeader.VirtualAddress;

				for (; it != std::end(sections); ++it)
				{
					auto&& section = *it;

					if (sectionAddress >= reinterpret_cast<size_t>(section.BaseAddress)
						&& sectionAddress < reinterpret_cast<size_t>(section.BaseAddress) + static_cast<size_t>(section.Size)
						&& sectionHeader.VirtualAddress + sectionHeader.Misc.VirtualSize <= data->Size)
					{
						if ((sectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) == IMAGE_SCN_CNT_CODE)
						{
							section.Category = SectionCategory::CODE;
						}
						else if (sectionHeader.Characteristics & (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA))
						{
							section.Category = SectionCategory::DATA;
						}

						try
						{
							// Copy the name because it is not null padded.
							char buffer[IMAGE_SIZEOF_SHORT_NAME + 1] = { 0 };
							std::memcpy(buffer, sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME);
							MultiByteToUnicode(buffer, section.Name, IMAGE_SIZEOF_SHORT_NAME);
						}
						catch (std::range_error &)
						{
							std::memset(section.Name, 0, sizeof(section.Name));
						}
						std::memcpy(section.ModulePath, data->Path, std::min(MAX_PATH, PATH_MAXIMUM_LENGTH));

						break;
					}
				}
			}
		}
	};

	if (EnumerateRemoteModulesNative(process, moduleEnumerator) != ERROR_SUCCESS)
	{
		EnumerateRemoteModulesWinapi(process, moduleEnumerator);
	}

	if (callbackSection != nullptr)
	{
		for (auto&& section : sections)
		{
			callbackSection(&section);
		}
	}
}
<commit_msg>Restructured code (2/4)<commit_after>#include <windows.h>
#include <winternl.h>
#include <tlhelp32.h>
#include <vector>
#include <algorithm>
#include <functional>

#include "NativeCore.hpp"

static DWORD GetRemotePeb(HANDLE process, PPEB* ppeb)
{
	const auto ntdll = GetModuleHandle(TEXT("ntdll"));
	if (!ntdll)
		return ERROR_MOD_NOT_FOUND;

	using tRtlNtStatusToDosError = ULONG (NTAPI *)(
			_In_ NTSTATUS Status
		);
	const auto pRtlNtStatusToDosError = tRtlNtStatusToDosError(GetProcAddress(ntdll, "RtlNtStatusToDosError"));
	if (!pRtlNtStatusToDosError)
		return ERROR_NOT_FOUND;

	using tNtQueryInformationProcess = NTSTATUS (NTAPI *)(
			_In_ HANDLE ProcessHandle,
			_In_ PROCESSINFOCLASS ProcessInformationClass,
			_Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
			_In_ ULONG ProcessInformationLength,
			_Out_opt_ PULONG ReturnLength
		);

	const auto pNtQueryInformationProcess = tNtQueryInformationProcess(GetProcAddress(ntdll, "NtQueryInformationProcess"));
	if (!pNtQueryInformationProcess)
		return ERROR_NOT_FOUND;

	PROCESS_BASIC_INFORMATION pbi;
	const auto status = pNtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), nullptr);
	if (!NT_SUCCESS(status))
		return pRtlNtStatusToDosError(status);

	*ppeb = pbi.PebBaseAddress;

	return ERROR_SUCCESS;
}

using InternalEnumerateRemoteModulesCallback = std::function<void(EnumerateRemoteModuleData&)>;

static bool EnumerateRemoteModulesNative(HANDLE process, const InternalEnumerateRemoteModulesCallback& callback)
{
	PPEB ppeb;
	const auto error = GetRemotePeb(process, &ppeb);
	if (error != ERROR_SUCCESS)
		return false;

	PPEB_LDR_DATA ldr;
	auto success = ReadRemoteMemory(process, &ppeb->Ldr, &ldr, 0, sizeof(ldr));
	if (!success)
		return false;

	const auto list_head = &ldr->InMemoryOrderModuleList; // remote address
	PLIST_ENTRY list_current; // remote address
	success = ReadRemoteMemory(process, &list_head->Flink, &list_current, 0, sizeof(list_current));
	if (!success)
		return false;

	while (list_current != list_head)
	{
		// TODO: error handling - what do we do if module list changed? We can't un-call the callback

		LDR_DATA_TABLE_ENTRY mod;
		success = ReadRemoteMemory(process, CONTAINING_RECORD(list_current, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks), &mod, 0, sizeof(mod));
		if (!success)
			break;

		EnumerateRemoteModuleData data = {};
		data.BaseAddress = mod.DllBase;
		data.Size = *(ULONG*)&mod.Reserved2[1]; // instead of undocced member could read ImageSize from headers
		const auto path_len = std::min(sizeof(RC_UnicodeChar) * (PATH_MAXIMUM_LENGTH - 1), size_t(mod.FullDllName.Length));
		success = ReadRemoteMemory(process, mod.FullDllName.Buffer, data.Path, 0, int(path_len));
		if (!success)
			break;

		// UNICODE_STRING is not guaranteed to be null terminated
		data.Path[path_len / 2] = 0;

		callback(data);

		list_current = mod.InMemoryOrderLinks.Flink;
	}

	return true;
}

bool EnumerateRemoteModulesWinapi(HANDLE process, const InternalEnumerateRemoteModulesCallback& callback)
{
	const auto handle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetProcessId(process));
	if (handle == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	MODULEENTRY32W me32 = {};
	me32.dwSize = sizeof(MODULEENTRY32W);
	if (Module32FirstW(handle, &me32))
	{
		do
		{
			EnumerateRemoteModuleData data = {};
			data.BaseAddress = me32.modBaseAddr;
			data.Size = me32.modBaseSize;
			std::memcpy(data.Path, me32.szExePath, std::min(MAX_PATH, PATH_MAXIMUM_LENGTH));

			callback(data);
		} while (Module32NextW(handle, &me32));
	}

	CloseHandle(handle);

	return true;
}

void RC_CallConv EnumerateRemoteSectionsAndModules(RC_Pointer process, EnumerateRemoteSectionsCallback callbackSection, EnumerateRemoteModulesCallback callbackModule)
{
	if (callbackSection == nullptr && callbackModule == nullptr)
	{
		return;
	}

	std::vector<EnumerateRemoteSectionData> sections;

	MEMORY_BASIC_INFORMATION memInfo = { };
	memInfo.RegionSize = 0x1000;
	size_t address = 0;
	while (VirtualQueryEx(process, reinterpret_cast<LPCVOID>(address), &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0 && address + memInfo.RegionSize > address)
	{
		if (memInfo.State == MEM_COMMIT)
		{
			EnumerateRemoteSectionData section = {};
			section.BaseAddress = memInfo.BaseAddress;
			section.Size = memInfo.RegionSize;

			section.Protection = SectionProtection::NoAccess;
			if ((memInfo.Protect & PAGE_EXECUTE) == PAGE_EXECUTE) section.Protection |= SectionProtection::Execute;
			if ((memInfo.Protect & PAGE_EXECUTE_READ) == PAGE_EXECUTE_READ) section.Protection |= SectionProtection::Execute | SectionProtection::Read;
			if ((memInfo.Protect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE) section.Protection |= SectionProtection::Execute | SectionProtection::Read | SectionProtection::Write;
			if ((memInfo.Protect & PAGE_EXECUTE_WRITECOPY) == PAGE_EXECUTE_WRITECOPY) section.Protection |= SectionProtection::Execute | SectionProtection::Read | SectionProtection::CopyOnWrite;
			if ((memInfo.Protect & PAGE_READONLY) == PAGE_READONLY) section.Protection |= SectionProtection::Read;
			if ((memInfo.Protect & PAGE_READWRITE) == PAGE_READWRITE) section.Protection |= SectionProtection::Read | SectionProtection::Write;
			if ((memInfo.Protect & PAGE_WRITECOPY) == PAGE_WRITECOPY) section.Protection |= SectionProtection::Read | SectionProtection::CopyOnWrite;
			if ((memInfo.Protect & PAGE_GUARD) == PAGE_GUARD) section.Protection |= SectionProtection::Guard;

			switch (memInfo.Type)
			{
			case MEM_IMAGE:
				section.Type = SectionType::Image;
				break;
			case MEM_MAPPED:
				section.Type = SectionType::Mapped;
				break;
			case MEM_PRIVATE:
				section.Type = SectionType::Private;
				break;
			}

			section.Category = section.Type == SectionType::Private ? SectionCategory::HEAP : SectionCategory::Unknown;

			sections.push_back(section);
		}
		address = reinterpret_cast<size_t>(memInfo.BaseAddress) + memInfo.RegionSize;
	}

	const auto moduleEnumerator = [&](EnumerateRemoteModuleData& data)
	{
		if (callbackModule != nullptr)
		{
			callbackModule(&data);
		}

		if (callbackSection != nullptr)
		{
			auto it = std::lower_bound(std::begin(sections), std::end(sections), static_cast<LPVOID>(data.BaseAddress), [&sections](const auto& lhs, const LPVOID& rhs)
			{
				return lhs.BaseAddress < rhs;
			});

			IMAGE_DOS_HEADER imageDosHeader = {};
			IMAGE_NT_HEADERS imageNtHeaders = {};

			if (!ReadRemoteMemory(process, data.BaseAddress, &imageDosHeader, 0, sizeof(IMAGE_DOS_HEADER))
				|| !ReadRemoteMemory(process, PUCHAR(data.BaseAddress) + imageDosHeader.e_lfanew, &imageNtHeaders, 0, sizeof(IMAGE_NT_HEADERS)))
			{
				return;
			}

			std::vector<IMAGE_SECTION_HEADER> sectionHeaders(imageNtHeaders.FileHeader.NumberOfSections);
			ReadRemoteMemory(process, PUCHAR(data.BaseAddress) + imageDosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS), sectionHeaders.data(), 0, imageNtHeaders.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
			for (auto&& sectionHeader : sectionHeaders)
			{
				const auto sectionAddress = reinterpret_cast<size_t>(data.BaseAddress) + sectionHeader.VirtualAddress;

				for (; it != std::end(sections); ++it)
				{
					auto&& section = *it;

					if (sectionAddress >= reinterpret_cast<size_t>(section.BaseAddress)
						&& sectionAddress < reinterpret_cast<size_t>(section.BaseAddress) + static_cast<size_t>(section.Size)
						&& sectionHeader.VirtualAddress + sectionHeader.Misc.VirtualSize <= data.Size)
					{
						if ((sectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) == IMAGE_SCN_CNT_CODE)
						{
							section.Category = SectionCategory::CODE;
						}
						else if (sectionHeader.Characteristics & (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA))
						{
							section.Category = SectionCategory::DATA;
						}

						try
						{
							// Copy the name because it is not null padded.
							char buffer[IMAGE_SIZEOF_SHORT_NAME + 1] = { 0 };
							std::memcpy(buffer, sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME);
							MultiByteToUnicode(buffer, section.Name, IMAGE_SIZEOF_SHORT_NAME);
						}
						catch (std::range_error &)
						{
							std::memset(section.Name, 0, sizeof(section.Name));
						}
						std::memcpy(section.ModulePath, data.Path, std::min(MAX_PATH, PATH_MAXIMUM_LENGTH));

						break;
					}
				}
			}
		}
	};

	if (!EnumerateRemoteModulesNative(process, moduleEnumerator))
	{
		EnumerateRemoteModulesWinapi(process, moduleEnumerator);
	}

	if (callbackSection != nullptr)
	{
		for (auto&& section : sections)
		{
			callbackSection(&section);
		}
	}
}
<|endoftext|>