<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <com/sun/star/ucb/Command.hpp>
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#include <com/sun/star/i18n/XExtendedTransliteration.hpp>
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/script/XInvocation.hpp>

#include <l10ntools/HelpSearch.hxx>

#ifndef INCLUDED_STL_ALGORITHM
#include <algorithm>
#define INCLUDED_STL_ALGORITHM
#endif
#ifndef INCLUDED_STL_SET
#include <set>
#define INCLUDED_STL_SET
#endif

#include <qe/Query.hxx>
#include <qe/DocGenerator.hxx>
#include "resultsetforquery.hxx"
#include "databases.hxx"

using namespace std;
using namespace chelp;
using namespace xmlsearch::excep;
using namespace xmlsearch::qe;
using namespace com::sun::star;
using namespace com::sun::star::ucb;
using namespace com::sun::star::i18n;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;

struct HitItem
{
    rtl::OUString   m_aURL;
    float           m_fScore;

    HitItem( void ) {}
    HitItem( const rtl::OUString& aURL, float fScore )
        : m_aURL( aURL )
        , m_fScore( fScore )
    {}
    bool operator < ( const HitItem& rHitItem ) const
    {
        return rHitItem.m_fScore < m_fScore;
    }
};

ResultSetForQuery::ResultSetForQuery( const uno::Reference< lang::XMultiServiceFactory >&  xMSF,
                                      const uno::Reference< XContentProvider >&  xProvider,
                                      sal_Int32 nOpenMode,
                                      const uno::Sequence< beans::Property >& seq,
                                      const uno::Sequence< NumberedSortingInfo >& seqSort,
                                      URLParameter& aURLParameter,
                                      Databases* pDatabases )
    : ResultSetBase( xMSF,xProvider,nOpenMode,seq,seqSort ),
      m_pDatabases( pDatabases ),
      m_aURLParameter( aURLParameter )
{
    fprintf(stderr, "ResultSetForQuery::ResultSetForQuery\n");

    Reference< XTransliteration > xTrans(
        xMSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.Transliteration" )) ),
        UNO_QUERY );
    Locale aLocale( aURLParameter.get_language(),
                    rtl::OUString(),
                    rtl::OUString() );
    if(xTrans.is())
        xTrans->loadModule(TransliterationModules_UPPERCASE_LOWERCASE,
                           aLocale );

    // EDIT FROM HERE

    vector< vector< rtl::OUString > > queryList;
    {
        sal_Int32 idx;
        rtl::OUString query = m_aURLParameter.get_query();
        while( !query.isEmpty() )
        {
            idx = query.indexOf( sal_Unicode( ' ' ) );
            if( idx == -1 )
                idx = query.getLength();

            vector< rtl::OUString > currentQuery;
            rtl::OUString tmp(query.copy( 0,idx ));
            rtl:: OUString toliterate = tmp;
            if(xTrans.is()) {
                Sequence<sal_Int32> aSeq;
                toliterate = xTrans->transliterate(
                    tmp,0,tmp.getLength(),aSeq);
            }

            currentQuery.push_back( toliterate );
            queryList.push_back( currentQuery );

            int nCpy = 1 + idx;
            if( nCpy >= query.getLength() )
                query = rtl::OUString();
            else
                query = query.copy( 1 + idx );
        }
    }

    vector< rtl::OUString > aCompleteResultVector;
    rtl::OUString scope = m_aURLParameter.get_scope();
    bool bCaptionsOnly = ( scope.compareToAscii( "Heading" ) == 0 );
    sal_Int32 hitCount = m_aURLParameter.get_hitCount();

    IndexFolderIterator aIndexFolderIt( *pDatabases, m_aURLParameter.get_module(), m_aURLParameter.get_language() );
    rtl::OUString idxDir;
    bool bExtension = false;
    int iDir = 0;
    vector< vector<HitItem>* > aIndexFolderResultVectorVector;

    bool bTemporary;
    while( !(idxDir = aIndexFolderIt.nextIndexFolder( bExtension, bTemporary )).isEmpty() )
    {
        vector<HitItem> aIndexFolderResultVector;

        try
        {
            vector< vector<HitItem>* > aQueryListResultVectorVector;
            set< rtl::OUString > aSet,aCurrent,aResultSet;

            int nQueryListSize = queryList.size();
            if( nQueryListSize > 1 )
                hitCount = 2000;

            for( int i = 0; i < nQueryListSize; ++i )
            {
                vector<HitItem>* pQueryResultVector;
                if( nQueryListSize > 1 )
                {
                    pQueryResultVector = new vector<HitItem>();
                    aQueryListResultVectorVector.push_back( pQueryResultVector );
                }
                else
                {
                    pQueryResultVector = &aIndexFolderResultVector;
                }
                pQueryResultVector->reserve( hitCount );

// INVOCATION HERE
                rtl::OUString aLang = m_aURLParameter.get_language();
                rtl::OUString aSystemPath;
                osl::FileBase::getSystemPathFromFileURL( idxDir, aSystemPath );
                const std::vector< rtl::OUString >& aListItem = queryList[i];
                ::rtl::OUString aNewQueryStr = aListItem[0];

                vector<float> aScoreVector;
                vector<rtl::OUString> aPathVector;

                HelpSearch searcher(aLang, aSystemPath);
                searcher.query(aNewQueryStr, bCaptionsOnly, aPathVector, aScoreVector);

                if( nQueryListSize > 1 )
                    aSet.clear();

                for (unsigned j = 0; j < aPathVector.size(); ++i) {
                    pQueryResultVector->push_back(HitItem(aPathVector[j], aScoreVector[j]));
                    if (nQueryListSize > 1)
                        aSet.insert(aPathVector[j]);
                }
// INVOCATION END
                // intersect
                if( nQueryListSize > 1 )
                {
                    if( i == 0 )
                    {
                        aResultSet = aSet;
                    }
                    else
                    {
                        aCurrent = aResultSet;
                        aResultSet.clear();
                        set_intersection( aSet.begin(),aSet.end(),
                                          aCurrent.begin(),aCurrent.end(),
                                          inserter(aResultSet,aResultSet.begin()));
                    }
                }
            }

            // Combine results in aIndexFolderResultVector
            if( nQueryListSize > 1 )
            {
                for( int n = 0 ; n < nQueryListSize ; ++n )
                {
                    vector<HitItem>* pQueryResultVector = aQueryListResultVectorVector[n];
                    vector<HitItem>& rQueryResultVector = *pQueryResultVector;

                    int nItemCount = rQueryResultVector.size();
                    for( int i = 0 ; i < nItemCount ; ++i )
                    {
                        const HitItem& rItem = rQueryResultVector[ i ];
                        set< rtl::OUString >::iterator it;
                        if( (it = aResultSet.find( rItem.m_aURL )) != aResultSet.end() )
                        {
                            HitItem aItemCopy( rItem );
                            aItemCopy.m_fScore /= nQueryListSize;   // To get average score
                            if( n == 0 )
                            {
                                // Use first pass to create entry
                                aIndexFolderResultVector.push_back( aItemCopy );
                            }
                            else
                            {
                                // Find entry in vector
                                int nCount = aIndexFolderResultVector.size();
                                for( int j = 0 ; j < nCount ; ++j )
                                {
                                    HitItem& rFindItem = aIndexFolderResultVector[ j ];
                                    if( rFindItem.m_aURL.equals( aItemCopy.m_aURL ) )
                                    {
                                        rFindItem.m_fScore += aItemCopy.m_fScore;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    delete pQueryResultVector;
                }

                sort( aIndexFolderResultVector.begin(), aIndexFolderResultVector.end() );
            }

            vector<HitItem>* pIndexFolderHitItemVector = new vector<HitItem>( aIndexFolderResultVector );
            aIndexFolderResultVectorVector.push_back( pIndexFolderHitItemVector );
            aIndexFolderResultVector.clear();
        }
        catch( const Exception& )
        {
        }

        ++iDir;

        if( bTemporary )
            aIndexFolderIt.deleteTempIndexFolder( idxDir );

    }   // Iterator

    int nVectorCount = aIndexFolderResultVectorVector.size();
    vector<HitItem>::size_type* pCurrentVectorIndex = new vector<HitItem>::size_type[nVectorCount];
    for( int j = 0 ; j < nVectorCount ; ++j )
        pCurrentVectorIndex[j] = 0;

    sal_Int32 nTotalHitCount = m_aURLParameter.get_hitCount();
    sal_Int32 nHitCount = 0;
    while( nHitCount < nTotalHitCount )
    {
        int iVectorWithBestScore = -1;
        float fBestScore = 0.0;
        for( int k = 0 ; k < nVectorCount ; ++k )
        {
            vector<HitItem>& rIndexFolderVector = *aIndexFolderResultVectorVector[k];
            if( pCurrentVectorIndex[k] < rIndexFolderVector.size() )
            {
                const HitItem& rItem = rIndexFolderVector[ pCurrentVectorIndex[k] ];

                if( fBestScore < rItem.m_fScore )
                {
                    fBestScore = rItem.m_fScore;
                    iVectorWithBestScore = k;
                }
            }
        }

        if( iVectorWithBestScore == -1 )    // No item left at all
            break;

        vector<HitItem>& rIndexFolderVector = *aIndexFolderResultVectorVector[iVectorWithBestScore];
        const HitItem& rItem = rIndexFolderVector[ pCurrentVectorIndex[iVectorWithBestScore] ];

        pCurrentVectorIndex[iVectorWithBestScore]++;

        aCompleteResultVector.push_back( rItem.m_aURL );
        ++nHitCount;
    }

    delete[] pCurrentVectorIndex;
    for( int n = 0 ; n < nVectorCount ; ++n )
    {
        vector<HitItem>* pIndexFolderVector = aIndexFolderResultVectorVector[n];
        delete pIndexFolderVector;
    }

    sal_Int32 replIdx = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "#HLP#" )).getLength();
    rtl::OUString replWith = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.help://" ));

    int nResultCount = aCompleteResultVector.size();
    for( int r = 0 ; r < nResultCount ; ++r )
    {
        rtl::OUString aURL = aCompleteResultVector[r];
        rtl::OUString aResultStr = replWith + aURL.copy(replIdx);
          m_aPath.push_back( aResultStr );
    }

    m_aItems.resize( m_aPath.size() );
    m_aIdents.resize( m_aPath.size() );

    Command aCommand;
    aCommand.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ));
    aCommand.Argument <<= m_sProperty;

    for( m_nRow = 0; sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aPath.size(); ++m_nRow )
    {
        m_aPath[m_nRow] =
            m_aPath[m_nRow]                                          +
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "?Language=" ))           +
            m_aURLParameter.get_language()                           +
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "&System=" ))             +
            m_aURLParameter.get_system();

        uno::Reference< XContent > content = queryContent();
        if( content.is() )
        {
            uno::Reference< XCommandProcessor > cmd( content,uno::UNO_QUERY );
            cmd->execute( aCommand,0,uno::Reference< XCommandEnvironment >( 0 ) ) >>= m_aItems[m_nRow]; //TODO: check return value of operator >>=
        }
    }
    m_nRow = 0xffffffff;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Bugfix resultsetforquery<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <com/sun/star/ucb/Command.hpp>
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#include <com/sun/star/i18n/XExtendedTransliteration.hpp>
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/script/XInvocation.hpp>

#include <l10ntools/HelpSearch.hxx>

#ifndef INCLUDED_STL_ALGORITHM
#include <algorithm>
#define INCLUDED_STL_ALGORITHM
#endif
#ifndef INCLUDED_STL_SET
#include <set>
#define INCLUDED_STL_SET
#endif

#include <qe/Query.hxx>
#include <qe/DocGenerator.hxx>
#include "resultsetforquery.hxx"
#include "databases.hxx"

using namespace std;
using namespace chelp;
using namespace xmlsearch::excep;
using namespace xmlsearch::qe;
using namespace com::sun::star;
using namespace com::sun::star::ucb;
using namespace com::sun::star::i18n;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;

struct HitItem
{
    rtl::OUString   m_aURL;
    float           m_fScore;

    HitItem( void ) {}
    HitItem( const rtl::OUString& aURL, float fScore )
        : m_aURL( aURL )
        , m_fScore( fScore )
    {}
    bool operator < ( const HitItem& rHitItem ) const
    {
        return rHitItem.m_fScore < m_fScore;
    }
};

ResultSetForQuery::ResultSetForQuery( const uno::Reference< lang::XMultiServiceFactory >&  xMSF,
                                      const uno::Reference< XContentProvider >&  xProvider,
                                      sal_Int32 nOpenMode,
                                      const uno::Sequence< beans::Property >& seq,
                                      const uno::Sequence< NumberedSortingInfo >& seqSort,
                                      URLParameter& aURLParameter,
                                      Databases* pDatabases )
    : ResultSetBase( xMSF,xProvider,nOpenMode,seq,seqSort ),
      m_pDatabases( pDatabases ),
      m_aURLParameter( aURLParameter )
{
    fprintf(stderr, "ResultSetForQuery::ResultSetForQuery\n");

    Reference< XTransliteration > xTrans(
        xMSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.Transliteration" )) ),
        UNO_QUERY );
    Locale aLocale( aURLParameter.get_language(),
                    rtl::OUString(),
                    rtl::OUString() );
    if(xTrans.is())
        xTrans->loadModule(TransliterationModules_UPPERCASE_LOWERCASE,
                           aLocale );

    vector< vector< rtl::OUString > > queryList;
    {
        sal_Int32 idx;
        rtl::OUString query = m_aURLParameter.get_query();
        while( !query.isEmpty() )
        {
            idx = query.indexOf( sal_Unicode( ' ' ) );
            if( idx == -1 )
                idx = query.getLength();

            vector< rtl::OUString > currentQuery;
            rtl::OUString tmp(query.copy( 0,idx ));
            rtl:: OUString toliterate = tmp;
            if(xTrans.is()) {
                Sequence<sal_Int32> aSeq;
                toliterate = xTrans->transliterate(
                    tmp,0,tmp.getLength(),aSeq);
            }

            currentQuery.push_back( toliterate );
            queryList.push_back( currentQuery );

            int nCpy = 1 + idx;
            if( nCpy >= query.getLength() )
                query = rtl::OUString();
            else
                query = query.copy( 1 + idx );
        }
    }

    vector< rtl::OUString > aCompleteResultVector;
    rtl::OUString scope = m_aURLParameter.get_scope();
    bool bCaptionsOnly = ( scope.compareToAscii( "Heading" ) == 0 );
    sal_Int32 hitCount = m_aURLParameter.get_hitCount();

    IndexFolderIterator aIndexFolderIt( *pDatabases, m_aURLParameter.get_module(), m_aURLParameter.get_language() );
    rtl::OUString idxDir;
    bool bExtension = false;
    int iDir = 0;
    vector< vector<HitItem>* > aIndexFolderResultVectorVector;

    bool bTemporary;
    while( !(idxDir = aIndexFolderIt.nextIndexFolder( bExtension, bTemporary )).isEmpty() )
    {
        vector<HitItem> aIndexFolderResultVector;

        try
        {
            vector< vector<HitItem>* > aQueryListResultVectorVector;
            set< rtl::OUString > aSet,aCurrent,aResultSet;

            int nQueryListSize = queryList.size();
            if( nQueryListSize > 1 )
                hitCount = 2000;

            for( int i = 0; i < nQueryListSize; ++i )
            {
                vector<HitItem>* pQueryResultVector;
                if( nQueryListSize > 1 )
                {
                    pQueryResultVector = new vector<HitItem>();
                    aQueryListResultVectorVector.push_back( pQueryResultVector );
                }
                else
                {
                    pQueryResultVector = &aIndexFolderResultVector;
                }
                pQueryResultVector->reserve( hitCount );

                // START Invoke CLucene HelpSearch
                rtl::OUString aLang = m_aURLParameter.get_language();
                rtl::OUString aSystemPath;
                osl::FileBase::getSystemPathFromFileURL( idxDir, aSystemPath );
                const std::vector< rtl::OUString >& aListItem = queryList[i];
                ::rtl::OUString aNewQueryStr = aListItem[0];

                vector<float> aScoreVector;
                vector<rtl::OUString> aPathVector;

                HelpSearch searcher(aLang, aSystemPath);
                searcher.query(aNewQueryStr, bCaptionsOnly, aPathVector, aScoreVector);

                if( nQueryListSize > 1 )
                    aSet.clear();

                for (unsigned j = 0; j < aPathVector.size(); ++j) {
                    pQueryResultVector->push_back(HitItem(aPathVector[j], aScoreVector[j]));
                    if (nQueryListSize > 1)
                        aSet.insert(aPathVector[j]);
                }
                // END Invoke CLucene HelpSearch

                // intersect
                if( nQueryListSize > 1 )
                {
                    if( i == 0 )
                    {
                        aResultSet = aSet;
                    }
                    else
                    {
                        aCurrent = aResultSet;
                        aResultSet.clear();
                        set_intersection( aSet.begin(),aSet.end(),
                                          aCurrent.begin(),aCurrent.end(),
                                          inserter(aResultSet,aResultSet.begin()));
                    }
                }
            }

            // Combine results in aIndexFolderResultVector
            if( nQueryListSize > 1 )
            {
                for( int n = 0 ; n < nQueryListSize ; ++n )
                {
                    vector<HitItem>* pQueryResultVector = aQueryListResultVectorVector[n];
                    vector<HitItem>& rQueryResultVector = *pQueryResultVector;

                    int nItemCount = rQueryResultVector.size();
                    for( int i = 0 ; i < nItemCount ; ++i )
                    {
                        const HitItem& rItem = rQueryResultVector[ i ];
                        set< rtl::OUString >::iterator it;
                        if( (it = aResultSet.find( rItem.m_aURL )) != aResultSet.end() )
                        {
                            HitItem aItemCopy( rItem );
                            aItemCopy.m_fScore /= nQueryListSize;   // To get average score
                            if( n == 0 )
                            {
                                // Use first pass to create entry
                                aIndexFolderResultVector.push_back( aItemCopy );
                            }
                            else
                            {
                                // Find entry in vector
                                int nCount = aIndexFolderResultVector.size();
                                for( int j = 0 ; j < nCount ; ++j )
                                {
                                    HitItem& rFindItem = aIndexFolderResultVector[ j ];
                                    if( rFindItem.m_aURL.equals( aItemCopy.m_aURL ) )
                                    {
                                        rFindItem.m_fScore += aItemCopy.m_fScore;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    delete pQueryResultVector;
                }

                sort( aIndexFolderResultVector.begin(), aIndexFolderResultVector.end() );
            }

            vector<HitItem>* pIndexFolderHitItemVector = new vector<HitItem>( aIndexFolderResultVector );
            aIndexFolderResultVectorVector.push_back( pIndexFolderHitItemVector );
            aIndexFolderResultVector.clear();
        }
        catch( const Exception& )
        {
        }

        ++iDir;

        if( bTemporary )
            aIndexFolderIt.deleteTempIndexFolder( idxDir );

    }   // Iterator

    int nVectorCount = aIndexFolderResultVectorVector.size();
    vector<HitItem>::size_type* pCurrentVectorIndex = new vector<HitItem>::size_type[nVectorCount];
    for( int j = 0 ; j < nVectorCount ; ++j )
        pCurrentVectorIndex[j] = 0;

    sal_Int32 nTotalHitCount = m_aURLParameter.get_hitCount();
    sal_Int32 nHitCount = 0;
    while( nHitCount < nTotalHitCount )
    {
        int iVectorWithBestScore = -1;
        float fBestScore = 0.0;
        for( int k = 0 ; k < nVectorCount ; ++k )
        {
            vector<HitItem>& rIndexFolderVector = *aIndexFolderResultVectorVector[k];
            if( pCurrentVectorIndex[k] < rIndexFolderVector.size() )
            {
                const HitItem& rItem = rIndexFolderVector[ pCurrentVectorIndex[k] ];

                if( fBestScore < rItem.m_fScore )
                {
                    fBestScore = rItem.m_fScore;
                    iVectorWithBestScore = k;
                }
            }
        }

        if( iVectorWithBestScore == -1 )    // No item left at all
            break;

        vector<HitItem>& rIndexFolderVector = *aIndexFolderResultVectorVector[iVectorWithBestScore];
        const HitItem& rItem = rIndexFolderVector[ pCurrentVectorIndex[iVectorWithBestScore] ];

        pCurrentVectorIndex[iVectorWithBestScore]++;

        aCompleteResultVector.push_back( rItem.m_aURL );
        ++nHitCount;
    }

    delete[] pCurrentVectorIndex;
    for( int n = 0 ; n < nVectorCount ; ++n )
    {
        vector<HitItem>* pIndexFolderVector = aIndexFolderResultVectorVector[n];
        delete pIndexFolderVector;
    }

    sal_Int32 replIdx = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "#HLP#" )).getLength();
    rtl::OUString replWith = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.help://" ));

    int nResultCount = aCompleteResultVector.size();
    for( int r = 0 ; r < nResultCount ; ++r )
    {
        rtl::OUString aURL = aCompleteResultVector[r];
        rtl::OUString aResultStr = replWith + aURL.copy(replIdx);
          m_aPath.push_back( aResultStr );
    }

    m_aItems.resize( m_aPath.size() );
    m_aIdents.resize( m_aPath.size() );

    Command aCommand;
    aCommand.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ));
    aCommand.Argument <<= m_sProperty;

    for( m_nRow = 0; sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aPath.size(); ++m_nRow )
    {
        m_aPath[m_nRow] =
            m_aPath[m_nRow]                                          +
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "?Language=" ))           +
            m_aURLParameter.get_language()                           +
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "&System=" ))             +
            m_aURLParameter.get_system();

        uno::Reference< XContent > content = queryContent();
        if( content.is() )
        {
            uno::Reference< XCommandProcessor > cmd( content,uno::UNO_QUERY );
            cmd->execute( aCommand,0,uno::Reference< XCommandEnvironment >( 0 ) ) >>= m_aItems[m_nRow]; //TODO: check return value of operator >>=
        }
    }
    m_nRow = 0xffffffff;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p10/procedures/hwp/memory/lib/plug_rules/exp_spd_keys_supported_map.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2020                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef _EXP_SPD_KEYS_SUPPORTED_MAP_H_
#define _EXP_SPD_KEYS_SUPPORTED_MAP_H_

#include <lib/plug_rules/p10_plug_rules.H>

namespace mss
{
namespace plug_rule
{
/// @note These are the latest and minimum allowed DDIMM SPD combined revisions
///       combined revision is the SPD revision and the SPD content revision
///       any DIMMs with older SPD will generate an error
///       The first byte is the major revision
///               any updates to this are usually new bytes and will require code updates
///       The second byte is the content revision
///               updates to this byte are most likely values and it's less likely that code will need to be updated
///       The vectors go from a lookup key to a combined revisions
///       The first vector is the minimum allowed combined revision
///       The second vector is the latest version of the combined revision
/// @note When adding new vendors/heights/sizes, THIS NEEDS TO BE IN SORTED ORDER BY VENDOR ID ENCODING
static const std::vector<std::pair<spd_lookup_key, uint16_t>> MINIMUM_SPD_KEY_COMBINED_REV =
{
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_128GB}, 0x0309},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
};

static const std::vector<std::pair<spd_lookup_key, uint16_t>> LATEST_SPD_KEY_COMBINED_REV =
{
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_128GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
};

} // ns plug_rules
} // ns mss
#endif
<commit_msg>Micron 32G 4U 0_4_0<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p10/procedures/hwp/memory/lib/plug_rules/exp_spd_keys_supported_map.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2020                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef _EXP_SPD_KEYS_SUPPORTED_MAP_H_
#define _EXP_SPD_KEYS_SUPPORTED_MAP_H_

#include <lib/plug_rules/p10_plug_rules.H>

namespace mss
{
namespace plug_rule
{
/// @note These are the latest and minimum allowed DDIMM SPD combined revisions
///       combined revision is the SPD revision and the SPD content revision
///       any DIMMs with older SPD will generate an error
///       The first byte is the major revision
///               any updates to this are usually new bytes and will require code updates
///       The second byte is the content revision
///               updates to this byte are most likely values and it's less likely that code will need to be updated
///       The vectors go from a lookup key to a combined revisions
///       The first vector is the minimum allowed combined revision
///       The second vector is the latest version of the combined revision
/// @note When adding new vendors/heights/sizes, THIS NEEDS TO BE IN SORTED ORDER BY VENDOR ID ENCODING
static const std::vector<std::pair<spd_lookup_key, uint16_t>> MINIMUM_SPD_KEY_COMBINED_REV =
{
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_128GB}, 0x0309},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
};

static const std::vector<std::pair<spd_lookup_key, uint16_t>> LATEST_SPD_KEY_COMBINED_REV =
{
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SMART, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_MICRON, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_16GB}, 0x0308},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_128GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_32GB}, 0x0400},
    {{fapi2::ENUM_ATTR_MEM_EFF_MODULE_MFG_ID_SAMSUNG, fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, fapi2::ENUM_ATTR_MEM_EFF_DIMM_SIZE_64GB}, 0x0400},
};

} // ns plug_rules
} // ns mss
#endif
<|endoftext|>


<commit_before>/*********************************************************************************
 * Copyright (c) 2015, Peter Andreas Entschev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of fft_benchmark nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/

#include "common.hpp"

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <clFFT.h>

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#define CLFFT_CHECK(err) {                  \
    if (err != CLFFT_SUCCESS) {             \
        printf("Error %d in %s:%d.\n",      \
               err, __FILE__, __LINE__);    \
        return -1;                          \
    }                                       \
}

static const int NSamplesMin = 128;
static const int NSamplesMax = 4096;
static const int Batches = 10;
static const int Rank = 2;
static const int Iterations = 10;

int main(int argc, char* argv[])
{
#if __cplusplus > 199711L
    std::chrono::high_resolution_clock::time_point tStart, tEnd;
#else
    std::clock_t tStart, tEnd;
#endif

    // Query platforms and devices
    cl_platform_id platform;
    cl_device_id device;
    cl_uint num_devices, num_platforms;
    cl_int err;
    CLFFT_CHECK(clGetPlatformIDs(1, &platform, &num_platforms));
    CLFFT_CHECK(clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1,
                         &device, &num_devices));

    // Create OpenCL context
    cl_context context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
    CLFFT_CHECK(err);

    // Create OpenCL command queue
    cl_command_queue queue = clCreateCommandQueue(context, device, 0, &err);
    CLFFT_CHECK(err);

    for (int n = NSamplesMin; n <= NSamplesMax; n <<= 1) {
        clfftPlanHandle inPlan, outPlan;
        clfftDim rank = (clfftDim)Rank;
        size_t fft_strides[3], fft_dims[3];
        for (int i = 0; i < Rank; i++) {
            fft_dims[i] = n;
            fft_strides[i] = (i == 0) ? 1 : fft_strides[i-1] * fft_dims[i];
        }

        // Setup clFFT
        clfftSetupData fftSetup;
        err = clfftInitSetupData(&fftSetup);
        err = clfftSetup(&fftSetup);

        // Create a complex clFFT plan
        err = clfftCreateDefaultPlan(&inPlan, context, rank, fft_dims);

        // Configure clFFT inPlan
        CLFFT_CHECK(clfftSetLayout(inPlan, CLFFT_COMPLEX_INTERLEAVED, CLFFT_COMPLEX_INTERLEAVED));
        CLFFT_CHECK(clfftSetPlanBatchSize(inPlan, Batches));
        CLFFT_CHECK(clfftSetPlanDistance(inPlan, fft_strides[Rank], fft_strides[Rank]));
        CLFFT_CHECK(clfftSetPlanInStride(inPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanOutStride(inPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanPrecision(inPlan, CLFFT_SINGLE));
        CLFFT_CHECK(clfftSetResultLocation(inPlan, CLFFT_INPLACE));

        // Bake inPlan
        CLFFT_CHECK(clfftBakePlan(inPlan, 1, &queue, NULL, NULL));

        cl_mem complexIn = 0, complexOut = 0;
        size_t bufferSize = sizeof(float) * 2 * Batches;
        for (int i = 0; i < Rank; i++)
            bufferSize *= n;

        // No data is copied to buffers as FFT performance is not data
        // dependent, but only size dependent
		complexIn  = clCreateBuffer(context, CL_MEM_READ_WRITE, bufferSize, 0, &err);
		complexOut = clCreateBuffer(context, CL_MEM_READ_WRITE, bufferSize, 0, &err);

        std::cout << "Number of dimensions: " << Rank << std::endl;
        std::cout << "Matrix dimensions: " << n << "x" << n << std::endl;
        std::cout << "Batch size: " << Batches << std::endl;

        tStart = getTime();
        for (int i = 0; i < Iterations; i++) {
            // Compute forward FFT
            CLFFT_CHECK(clfftEnqueueTransform(inPlan, CLFFT_FORWARD, 1, &queue,
                                              0, NULL, NULL,
                                              &complexOut, &complexOut, NULL));
        }
        clFinish(queue);
        tEnd = getTime();
        std::cout << "In-place C2C FFT time for " << Iterations << " runs: " << getTimeCount(tEnd, tStart) << " ms" << std::endl;

        // Destroy in-place FFT plan
        clfftDestroyPlan(&inPlan);

        // Create a complex clFFT plan
        err = clfftCreateDefaultPlan(&outPlan, context, rank, fft_dims);

        // Configure clFFT outPlan
        CLFFT_CHECK(clfftSetLayout(outPlan, CLFFT_COMPLEX_INTERLEAVED, CLFFT_COMPLEX_INTERLEAVED));
        CLFFT_CHECK(clfftSetPlanBatchSize(outPlan, Batches));
        CLFFT_CHECK(clfftSetPlanDistance(outPlan, fft_strides[Rank], fft_strides[Rank]));
        CLFFT_CHECK(clfftSetPlanInStride(outPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanOutStride(outPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanPrecision(outPlan, CLFFT_SINGLE));
        CLFFT_CHECK(clfftSetResultLocation(outPlan, CLFFT_INPLACE));

        // Bake outPlan
        CLFFT_CHECK(clfftBakePlan(outPlan, 1, &queue, NULL, NULL));

        tStart = getTime();
        for (int i = 0; i < Iterations; i++) {
            // Compute forward FFT
            CLFFT_CHECK(clfftEnqueueTransform(outPlan, CLFFT_FORWARD, 1, &queue,
                                              0, NULL, NULL,
                                              &complexIn, &complexOut, NULL));
        }
        clFinish(queue);
        tEnd = getTime();
        std::cout << "Out-of-place C2C FFT time for " << Iterations << " runs: " << getTimeCount(tEnd, tStart) << " ms" << std::endl;

        tStart = getTime();
        for (int i = 0; i < Iterations; i++) {
            CLFFT_CHECK(clEnqueueCopyBuffer(queue, complexOut, complexIn, 0, 0, bufferSize, 0, NULL, NULL));
            // Compute forward FFT
            CLFFT_CHECK(clfftEnqueueTransform(outPlan, CLFFT_FORWARD, 1, &queue,
                                              0, NULL, NULL,
                                              &complexIn, &complexOut, NULL));
        }
        clFinish(queue);
        tEnd = getTime();
        std::cout << "Buffer Copy + Out-of-place C2C FFT time for " << Iterations << " runs: " << getTimeCount(tEnd, tStart) << " ms" << std::endl << std::endl;

	    clReleaseMemObject(complexIn);
	    clReleaseMemObject(complexOut);

        // Destroy out-of-place FFT plan
        clfftDestroyPlan(&outPlan);

        // Force release of clFFT temporary buffers
        clfftTeardown();
    }

    // Flush/Release OpenCL resources
    clFlush(queue);
    clFinish(queue);
    clReleaseCommandQueue(queue);
    clReleaseContext(context);

    return 0;
}
<commit_msg>Added missing checks to OpenCL/clFFT calls<commit_after>/*********************************************************************************
 * Copyright (c) 2015, Peter Andreas Entschev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of fft_benchmark nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/

#include "common.hpp"

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <clFFT.h>

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

#define CLFFT_CHECK(err) {                  \
    if (err != CLFFT_SUCCESS) {             \
        printf("Error %d in %s:%d.\n",      \
               err, __FILE__, __LINE__);    \
        return -1;                          \
    }                                       \
}

static const int NSamplesMin = 128;
static const int NSamplesMax = 4096;
static const int Batches = 10;
static const int Rank = 2;
static const int Iterations = 10;

int main(int argc, char* argv[])
{
#if __cplusplus > 199711L
    std::chrono::high_resolution_clock::time_point tStart, tEnd;
#else
    std::clock_t tStart, tEnd;
#endif

    // Query platforms and devices
    cl_platform_id platform;
    cl_device_id device;
    cl_uint num_devices, num_platforms;
    cl_int err;
    CLFFT_CHECK(clGetPlatformIDs(1, &platform, &num_platforms));
    CLFFT_CHECK(clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1,
                         &device, &num_devices));

    // Create OpenCL context
    cl_context context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
    CLFFT_CHECK(err);

    // Create OpenCL command queue
    cl_command_queue queue = clCreateCommandQueue(context, device, 0, &err);
    CLFFT_CHECK(err);

    for (int n = NSamplesMin; n <= NSamplesMax; n <<= 1) {
        clfftPlanHandle inPlan, outPlan;
        clfftDim rank = (clfftDim)Rank;
        size_t fft_strides[3], fft_dims[3];
        for (int i = 0; i < Rank; i++) {
            fft_dims[i] = n;
            fft_strides[i] = (i == 0) ? 1 : fft_strides[i-1] * fft_dims[i];
        }

        // Setup clFFT
        clfftSetupData fftSetup;
        CLFFT_CHECK(clfftInitSetupData(&fftSetup));
        CLFFT_CHECK(clfftSetup(&fftSetup));

        // Create a complex clFFT plan
        CLFFT_CHECK(clfftCreateDefaultPlan(&inPlan, context, rank, fft_dims));

        // Configure clFFT inPlan
        CLFFT_CHECK(clfftSetLayout(inPlan, CLFFT_COMPLEX_INTERLEAVED, CLFFT_COMPLEX_INTERLEAVED));
        CLFFT_CHECK(clfftSetPlanBatchSize(inPlan, Batches));
        CLFFT_CHECK(clfftSetPlanDistance(inPlan, fft_strides[Rank], fft_strides[Rank]));
        CLFFT_CHECK(clfftSetPlanInStride(inPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanOutStride(inPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanPrecision(inPlan, CLFFT_SINGLE));
        CLFFT_CHECK(clfftSetResultLocation(inPlan, CLFFT_INPLACE));

        // Bake inPlan
        CLFFT_CHECK(clfftBakePlan(inPlan, 1, &queue, NULL, NULL));

        cl_mem complexIn = 0, complexOut = 0;
        size_t bufferSize = sizeof(float) * 2 * Batches;
        for (int i = 0; i < Rank; i++)
            bufferSize *= n;

        // No data is copied to buffers as FFT performance is not data
        // dependent, but only size dependent
        complexIn  = clCreateBuffer(context, CL_MEM_READ_WRITE, bufferSize, 0, &err);
        CLFFT_CHECK(err);
        complexOut = clCreateBuffer(context, CL_MEM_READ_WRITE, bufferSize, 0, &err);
        CLFFT_CHECK(err);

        std::cout << "Matrix dimensions: " << n << "x" << n << std::endl;
        std::cout << "Batch size: " << Batches << std::endl;

        tStart = getTime();
        for (int i = 0; i < Iterations; i++) {
            // Compute forward FFT
            CLFFT_CHECK(clfftEnqueueTransform(inPlan, CLFFT_FORWARD, 1, &queue,
                                              0, NULL, NULL,
                                              &complexOut, &complexOut, NULL));
        }
        CLFFT_CHECK(clFinish(queue));
        tEnd = getTime();
        std::cout << "In-place C2C FFT time for " << Iterations << " runs: " << getTimeCount(tEnd, tStart) << " ms" << std::endl;

        // Destroy in-place FFT plan
        CLFFT_CHECK(clfftDestroyPlan(&inPlan));

        // Create a complex clFFT plan
        CLFFT_CHECK(clfftCreateDefaultPlan(&outPlan, context, rank, fft_dims));

        // Configure clFFT outPlan
        CLFFT_CHECK(clfftSetLayout(outPlan, CLFFT_COMPLEX_INTERLEAVED, CLFFT_COMPLEX_INTERLEAVED));
        CLFFT_CHECK(clfftSetPlanBatchSize(outPlan, Batches));
        CLFFT_CHECK(clfftSetPlanDistance(outPlan, fft_strides[Rank], fft_strides[Rank]));
        CLFFT_CHECK(clfftSetPlanInStride(outPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanOutStride(outPlan, rank, fft_strides));
        CLFFT_CHECK(clfftSetPlanPrecision(outPlan, CLFFT_SINGLE));
        CLFFT_CHECK(clfftSetResultLocation(outPlan, CLFFT_INPLACE));

        // Bake outPlan
        CLFFT_CHECK(clfftBakePlan(outPlan, 1, &queue, NULL, NULL));

        tStart = getTime();
        for (int i = 0; i < Iterations; i++) {
            // Compute forward FFT
            CLFFT_CHECK(clfftEnqueueTransform(outPlan, CLFFT_FORWARD, 1, &queue,
                                              0, NULL, NULL,
                                              &complexIn, &complexOut, NULL));
        }
        CLFFT_CHECK(clFinish(queue));
        tEnd = getTime();
        std::cout << "Out-of-place C2C FFT time for " << Iterations << " runs: " << getTimeCount(tEnd, tStart) << " ms" << std::endl;

        tStart = getTime();
        for (int i = 0; i < Iterations; i++) {
            CLFFT_CHECK(clEnqueueCopyBuffer(queue, complexOut, complexIn, 0, 0, bufferSize, 0, NULL, NULL));
            // Compute forward FFT
            CLFFT_CHECK(clfftEnqueueTransform(outPlan, CLFFT_FORWARD, 1, &queue,
                                              0, NULL, NULL,
                                              &complexIn, &complexOut, NULL));
        }
        CLFFT_CHECK(clFinish(queue));
        tEnd = getTime();
        std::cout << "Buffer Copy + Out-of-place C2C FFT time for " << Iterations << " runs: " << getTimeCount(tEnd, tStart) << " ms" << std::endl << std::endl;

        CLFFT_CHECK(clReleaseMemObject(complexIn));
        CLFFT_CHECK(clReleaseMemObject(complexOut));

        // Destroy out-of-place FFT plan
        CLFFT_CHECK(clfftDestroyPlan(&outPlan));

        // Force release of clFFT temporary buffers
        CLFFT_CHECK(clfftTeardown());
    }

    // Flush/Release OpenCL resources
    CLFFT_CHECK(clFlush(queue));
    CLFFT_CHECK(clFinish(queue));
    CLFFT_CHECK(clReleaseCommandQueue(queue));
    CLFFT_CHECK(clReleaseContext(context));

    return 0;
}
<|endoftext|>


<commit_before>/** \file   RegexMatcher.cc
 *  \brief  Implementation of the RegexMatcher class.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015,2017,2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "RegexMatcher.h"
#include "Compiler.h"
#include "util.h"

bool RegexMatcher::utf8_configured_;

bool CompileRegex(const std::string &pattern, const unsigned options, ::pcre **pcre_arg,
                  ::pcre_extra **pcre_extra_arg, std::string * const err_msg)
{
    if (err_msg != nullptr)
        err_msg->clear();

    const char *errptr;
    int erroffset;

    int pcre_options(0);
    if (options & RegexMatcher::ENABLE_UTF8)
        pcre_options |= PCRE_UTF8;
    if (options & RegexMatcher::CASE_INSENSITIVE)
        pcre_options |= PCRE_CASELESS;
    if (options & RegexMatcher::MULTILINE)
        pcre_options |= PCRE_MULTILINE;

    *pcre_arg = ::pcre_compile(pattern.c_str(), pcre_options, &errptr, &erroffset, nullptr);
    if (*pcre_arg == nullptr) {
        *pcre_extra_arg = nullptr;
        if (err_msg != nullptr)
            *err_msg = "failed to compile invalid regular expression: \"" + pattern + "\"! ("
                + std::string(errptr) + ")";
        return false;
    }

    // Can't use PCRE_STUDY_JIT_COMPILE because it's not thread safe.
    *pcre_extra_arg = ::pcre_study(*pcre_arg, 0, &errptr);
    if (*pcre_extra_arg == nullptr and errptr != nullptr) {
        ::pcre_free(*pcre_arg);
        *pcre_arg = nullptr;
        if (err_msg != nullptr)
            *err_msg = "failed to \"study\" the compiled pattern \"" + pattern + "\"! (" + std::string(errptr) + ")";
        return false;
    }

    return true;
}

RegexMatcher *RegexMatcher::RegexMatcherFactory(const std::string &pattern, std::string * const err_msg,
                                                const unsigned options)
{
    // Make sure the PCRE library supports UTF8:
    if ((options & RegexMatcher::ENABLE_UTF8) and not RegexMatcher::utf8_configured_) {
        int utf8_available;
        if (::pcre_config(PCRE_CONFIG_UTF8, reinterpret_cast<void *>(&utf8_available)) == PCRE_ERROR_BADOPTION) {
            if (err_msg != nullptr)
                *err_msg = "PCRE library does not know PCRE_CONFIG_UTF8!";
            return nullptr;
        }

        if (utf8_available != 1) {
            if (err_msg != nullptr)
                *err_msg = "This version of the PCRE library does not support UTF8!";
            return nullptr;
        }

        RegexMatcher::utf8_configured_ = true;
    }

    ::pcre *pcre_ptr;
    ::pcre_extra *pcre_extra_ptr;
    if (not CompileRegex(pattern, options, &pcre_ptr, &pcre_extra_ptr, err_msg))
        return nullptr;

    return new RegexMatcher(pattern, options, pcre_ptr, pcre_extra_ptr);
}

RegexMatcher *RegexMatcher::RegexMatcherFactoryOrDie(const std::string &regex, const unsigned options) {
    std::string error_message;
    RegexMatcher *regex_matcher(RegexMatcher::RegexMatcherFactory(regex, &error_message, options));
    if (not error_message.empty())
        LOG_ERROR("failed to compile regex \"" + regex + "\": " + error_message);

    return regex_matcher;
}

RegexMatcher::RegexMatcher(const RegexMatcher &that): pattern_(that.pattern_) {
    if (this == &that)
        return;

    if (that.pcre_ == nullptr) {
        pcre_ = nullptr;
        pcre_extra_ = nullptr;
    } else {
        std::string err_msg;
        if (not CompileRegex(pattern_, that.options_, &pcre_, &pcre_extra_, &err_msg))
            logger->error("In RegexMatcher copy constructor: unexpected error: " + err_msg);
        substr_vector_    = that.substr_vector_;
        last_match_count_ = that.last_match_count_;
    }
}

RegexMatcher::RegexMatcher(RegexMatcher &&that)
    : pattern_(std::move(that.pattern_)), options_(that.options_), pcre_(that.pcre_),
      pcre_extra_(that.pcre_extra_), last_subject_(std::move(that.last_subject_)),
      substr_vector_(std::move(that.substr_vector_)), last_match_count_(that.last_match_count_)
{
    that.pcre_       = nullptr;
    that.pcre_extra_ = nullptr;
}

bool RegexMatcher::matched(const std::string &subject, std::string * const err_msg,
                           size_t * const start_pos, size_t * const end_pos)
{
    if (err_msg != nullptr)
        err_msg->clear();

    const int retcode = ::pcre_exec(pcre_, pcre_extra_, subject.data(), subject.length(), 0, 0,
                                    &substr_vector_[0], substr_vector_.size());

    if (retcode == 0) {
        if (err_msg != nullptr)
            *err_msg = "Too many captured substrings! (We only support "
                       + std::to_string(substr_vector_.size() / 3 - 1) + " substrings.)";
        return false;
    }

    if (retcode > 0) {
        last_match_count_ = retcode;
        last_subject_     = subject;
        if (start_pos != nullptr)
            *start_pos = substr_vector_[0];
        if (end_pos != nullptr)
            *end_pos = substr_vector_[1];
        return true;
    }

    if (retcode != PCRE_ERROR_NOMATCH) {
        if (retcode == PCRE_ERROR_BADUTF8) {
            if (err_msg != nullptr)
                *err_msg = "A \"subject\" with invalid UTF-8 was passed into RegexMatcher::matched()!";
        } else if (err_msg != nullptr)
            *err_msg = "Unknown error!";
    }

    return false;
}

bool RegexMatcher::Matched(const std::string &regex, const std::string &subject, const unsigned options,
                           std::string * const err_msg, size_t * const start_pos, size_t * const end_pos)
{
    RegexMatcher * const matcher(RegexMatcher::RegexMatcherFactory(regex, err_msg, options));
    if (matcher == nullptr)
        LOG_ERROR("Failed to compile pattern \"" + regex + "\": " + *err_msg);

    return matcher->matched(subject, err_msg, start_pos, end_pos);
}

std::string RegexMatcher::operator[](const unsigned group) const {
    if (unlikely(group >= last_match_count_))
        throw std::out_of_range("in RegexMatcher::operator[]: group(" + std::to_string(group) + ") >= "
                                + std::to_string(last_match_count_) + "!");

    const unsigned first_index(group * 2);
    const unsigned substring_length(substr_vector_[first_index + 1] - substr_vector_[first_index]);
    return (substring_length == 0) ? "" : last_subject_.substr(substr_vector_[first_index], substring_length);
}
<commit_msg>cache for RegexMatcher factory (especially for better performance of RegexMatcher::Match)<commit_after>/** \file   RegexMatcher.cc
 *  \brief  Implementation of the RegexMatcher class.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015,2017,2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "RegexMatcher.h"
#include <unordered_map>
#include "Compiler.h"
#include "StringUtil.h"
#include "util.h"

bool RegexMatcher::utf8_configured_;

bool CompileRegex(const std::string &pattern, const unsigned options, ::pcre **pcre_arg,
                  ::pcre_extra **pcre_extra_arg, std::string * const err_msg)
{
    if (err_msg != nullptr)
        err_msg->clear();

    const char *errptr;
    int erroffset;

    int pcre_options(0);
    if (options & RegexMatcher::ENABLE_UTF8)
        pcre_options |= PCRE_UTF8;
    if (options & RegexMatcher::CASE_INSENSITIVE)
        pcre_options |= PCRE_CASELESS;
    if (options & RegexMatcher::MULTILINE)
        pcre_options |= PCRE_MULTILINE;

    *pcre_arg = ::pcre_compile(pattern.c_str(), pcre_options, &errptr, &erroffset, nullptr);
    if (*pcre_arg == nullptr) {
        *pcre_extra_arg = nullptr;
        if (err_msg != nullptr)
            *err_msg = "failed to compile invalid regular expression: \"" + pattern + "\"! ("
                + std::string(errptr) + ")";
        return false;
    }

    // Can't use PCRE_STUDY_JIT_COMPILE because it's not thread safe.
    *pcre_extra_arg = ::pcre_study(*pcre_arg, 0, &errptr);
    if (*pcre_extra_arg == nullptr and errptr != nullptr) {
        ::pcre_free(*pcre_arg);
        *pcre_arg = nullptr;
        if (err_msg != nullptr)
            *err_msg = "failed to \"study\" the compiled pattern \"" + pattern + "\"! (" + std::string(errptr) + ")";
        return false;
    }

    return true;
}

std::unordered_map<std::string, RegexMatcher*> matcher_cache;

RegexMatcher *RegexMatcher::RegexMatcherFactory(const std::string &pattern, std::string * const err_msg,
                                                const unsigned options)
{
    const std::string cache_key(pattern + "###" + StringUtil::ToString(options));
    auto cache_iter(matcher_cache.find(cache_key));
    if (cache_iter != matcher_cache.end())
        return cache_iter->second;

    // Make sure the PCRE library supports UTF8:
    if ((options & RegexMatcher::ENABLE_UTF8) and not RegexMatcher::utf8_configured_) {
        int utf8_available;
        if (::pcre_config(PCRE_CONFIG_UTF8, reinterpret_cast<void *>(&utf8_available)) == PCRE_ERROR_BADOPTION) {
            if (err_msg != nullptr)
                *err_msg = "PCRE library does not know PCRE_CONFIG_UTF8!";
            return nullptr;
        }

        if (utf8_available != 1) {
            if (err_msg != nullptr)
                *err_msg = "This version of the PCRE library does not support UTF8!";
            return nullptr;
        }

        RegexMatcher::utf8_configured_ = true;
    }

    ::pcre *pcre_ptr;
    ::pcre_extra *pcre_extra_ptr;
    if (not CompileRegex(pattern, options, &pcre_ptr, &pcre_extra_ptr, err_msg))
        return nullptr;

    RegexMatcher * const matcher = new RegexMatcher(pattern, options, pcre_ptr, pcre_extra_ptr);
    matcher_cache.emplace(cache_key, matcher);
    return matcher;
}

RegexMatcher *RegexMatcher::RegexMatcherFactoryOrDie(const std::string &regex, const unsigned options) {
    std::string error_message;
    RegexMatcher *regex_matcher(RegexMatcher::RegexMatcherFactory(regex, &error_message, options));
    if (not error_message.empty())
        LOG_ERROR("failed to compile regex \"" + regex + "\": " + error_message);

    return regex_matcher;
}

RegexMatcher::RegexMatcher(const RegexMatcher &that): pattern_(that.pattern_) {
    if (this == &that)
        return;

    if (that.pcre_ == nullptr) {
        pcre_ = nullptr;
        pcre_extra_ = nullptr;
    } else {
        std::string err_msg;
        if (not CompileRegex(pattern_, that.options_, &pcre_, &pcre_extra_, &err_msg))
            logger->error("In RegexMatcher copy constructor: unexpected error: " + err_msg);
        substr_vector_    = that.substr_vector_;
        last_match_count_ = that.last_match_count_;
    }
}

RegexMatcher::RegexMatcher(RegexMatcher &&that)
    : pattern_(std::move(that.pattern_)), options_(that.options_), pcre_(that.pcre_),
      pcre_extra_(that.pcre_extra_), last_subject_(std::move(that.last_subject_)),
      substr_vector_(std::move(that.substr_vector_)), last_match_count_(that.last_match_count_)
{
    that.pcre_       = nullptr;
    that.pcre_extra_ = nullptr;
}

bool RegexMatcher::matched(const std::string &subject, std::string * const err_msg,
                           size_t * const start_pos, size_t * const end_pos)
{
    if (err_msg != nullptr)
        err_msg->clear();

    const int retcode = ::pcre_exec(pcre_, pcre_extra_, subject.data(), subject.length(), 0, 0,
                                    &substr_vector_[0], substr_vector_.size());

    if (retcode == 0) {
        if (err_msg != nullptr)
            *err_msg = "Too many captured substrings! (We only support "
                       + std::to_string(substr_vector_.size() / 3 - 1) + " substrings.)";
        return false;
    }

    if (retcode > 0) {
        last_match_count_ = retcode;
        last_subject_     = subject;
        if (start_pos != nullptr)
            *start_pos = substr_vector_[0];
        if (end_pos != nullptr)
            *end_pos = substr_vector_[1];
        return true;
    }

    if (retcode != PCRE_ERROR_NOMATCH) {
        if (retcode == PCRE_ERROR_BADUTF8) {
            if (err_msg != nullptr)
                *err_msg = "A \"subject\" with invalid UTF-8 was passed into RegexMatcher::matched()!";
        } else if (err_msg != nullptr)
            *err_msg = "Unknown error!";
    }

    return false;
}

bool RegexMatcher::Matched(const std::string &regex, const std::string &subject, const unsigned options,
                           std::string * const err_msg, size_t * const start_pos, size_t * const end_pos)
{
    RegexMatcher * const matcher(RegexMatcher::RegexMatcherFactory(regex, err_msg, options));
    if (matcher == nullptr)
        LOG_ERROR("Failed to compile pattern \"" + regex + "\": " + *err_msg);

    return matcher->matched(subject, err_msg, start_pos, end_pos);
}

std::string RegexMatcher::operator[](const unsigned group) const {
    if (unlikely(group >= last_match_count_))
        throw std::out_of_range("in RegexMatcher::operator[]: group(" + std::to_string(group) + ") >= "
                                + std::to_string(last_match_count_) + "!");

    const unsigned first_index(group * 2);
    const unsigned substring_length(substr_vector_[first_index + 1] - substr_vector_[first_index]);
    return (substring_length == 0) ? "" : last_subject_.substr(substr_vector_[first_index], substring_length);
}
<|endoftext|>


<commit_before>/*************************************************************************************************//**
		* File: stack.cpp
		* Description: includes realized primitives from stack.h
*****************************************************************************************************/
#include "stack.h"
#include <sys/mman.h>
#include <assert.h>

//StackMap * StackMap::getInstance() {
//	static thread_local StackMap instance;
//	return &instance;
//}

constexpr int PAGE_SIZE = 4096;
constexpr int ELEM_PER_PAGE = PAGE_SIZE / sizeof(StackElement);

void StackMap::register_stack_root(void * newAddr) {
//    precisegc::details::lock_guard<mutex_type> lock(m_mutex);
	if (free_list == nullptr) {
		StackElement * data = (StackElement *) mmap(nullptr, PAGE_SIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
		assert(data != MAP_FAILED);
		for (int i = 0; i < ELEM_PER_PAGE; ++i) {
			data->next = free_list;
			free_list = data;
			data++;
		}
	}
	StackElement *result = free_list;
	free_list = free_list->next;
	result->next = top;
	result->addr = newAddr;
	top = result;
}

void StackMap::delete_stack_root(void * address) {
//    precisegc::details::lock_guard<mutex_type> lock(m_mutex);
	if (top->addr != address) {
		// if it is so, then automatic objects dectructs
		// not in the reverse order with their constructors
		// so we need to find and replace object that might be deleted
		// by object that is on the top
		StackElement *temp = top;
		while (temp != nullptr) {
			if (temp->addr == address) {
				temp->addr = top->addr;
				goto end_a;
			}
			temp = temp->next;
		}
		assert(false);
	}
	end_a:
	StackElement *deleted = top;
	top = top->next;
	deleted->next = free_list;
	free_list = deleted;
}

StackElement* StackMap::begin() {
	return top;
}

StackMap::lock_type StackMap::lock()
{
    return lock_type(m_mutex);
}

StackMap::StackMap()
	: free_list(nullptr)
	, top(nullptr)
{}
<commit_msg>unsafe scope in stack root<commit_after>/*************************************************************************************************//**
		* File: stack.cpp
		* Description: includes realized primitives from stack.h
*****************************************************************************************************/
#include "stack.h"
#include <sys/mman.h>
#include <assert.h>

#include "details/gc_unsafe_scope.h"

//StackMap * StackMap::getInstance() {
//	static thread_local StackMap instance;
//	return &instance;
//}

constexpr int PAGE_SIZE = 4096;
constexpr int ELEM_PER_PAGE = PAGE_SIZE / sizeof(StackElement);

void StackMap::register_stack_root(void * newAddr) {
	precisegc::details::gc_unsafe_scope unsafe_scope;
	if (free_list == nullptr) {
		StackElement * data = (StackElement *) mmap(nullptr, PAGE_SIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
		assert(data != MAP_FAILED);
		for (int i = 0; i < ELEM_PER_PAGE; ++i) {
			data->next = free_list;
			free_list = data;
			data++;
		}
	}
	StackElement *result = free_list;
	free_list = free_list->next;
	result->next = top;
	result->addr = newAddr;
	top = result;
}

void StackMap::delete_stack_root(void * address) {
    precisegc::details::gc_unsafe_scope unsafe_scope;
	if (top->addr != address) {
		// if it is so, then automatic objects dectructs
		// not in the reverse order with their constructors
		// so we need to find and replace object that might be deleted
		// by object that is on the top
		StackElement *temp = top;
		while (temp != nullptr) {
			if (temp->addr == address) {
				temp->addr = top->addr;
				goto end_a;
			}
			temp = temp->next;
		}
		assert(false);
	}
	end_a:
	StackElement *deleted = top;
	top = top->next;
	deleted->next = free_list;
	free_list = deleted;
}

StackElement* StackMap::begin() {
	return top;
}

StackMap::lock_type StackMap::lock()
{
    return lock_type(m_mutex);
}

StackMap::StackMap()
	: free_list(nullptr)
	, top(nullptr)
{}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013 Rajendra Kumar Uppal

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 <iostream>
#include "MailMessage.h"

using std::cout;
using std::cin;
using std::endl;

#define print(s) cout<<endl<<(s)<<endl;

void send(const MailMessage& msg)
{
    /// Just a skeleton.
    /// Assuming that there is a third party send
    /// API which is responsible for sending email.
    print( "Sender: " + msg.getSender() );

    print("Recipients:");
    MailMessage::Recipients recipients = msg.getRecipients();
    for ( auto start = recipients.begin(); start != recipients.end(); ++start )
        print( (*start).getAddress() );

    print("Subject: " + msg.getSubject() );
    print("Content: " + msg.getContent() );
}

void Test_MailMessage()
{
    std::string sender("rajen.iitd@gmail.com");
    std::string recipient("uppal@adobe.com");
    std::string subject("Generated email");
    std::string content = "Hi ";
    content += recipient;
    content += ",\n\n";
    content += "Have a good day!\n\n";
    content += "Regards,\n";
    content += "A-Team";
    std::string attachment("C:\\DSC.jpg");

    MailMessage message;
    message.setSender( sender );
    message.addRecipient( MailRecipient(MailRecipient::PRIMARY_RECIPIENT, recipient) );
    message.setSubject( subject );
    message.setContent( content );
    message.addAttachment( attachment );

    send(message);
}

int main(int argc, char ** argv)
{
    Test_MailMessage();

    print("Press any key to continue...");
    cin.get();
    return 0;
}

// ~EOF
<commit_msg>Update Client.cpp<commit_after>
#include <iostream>
#include "MailMessage.h"

using std::cout;
using std::cin;
using std::endl;

#define print(s) cout<<endl<<(s)<<endl;

void send(const MailMessage& msg)
{
    /// Just a skeleton.
    /// Assuming that there is a third party send
    /// API which is responsible for sending email.
    print( "Sender: " + msg.getSender() );

    print("Recipients:");
    MailMessage::Recipients recipients = msg.getRecipients();
    for ( auto start = recipients.begin(); start != recipients.end(); ++start )
        print( (*start).getAddress() );

    print("Subject: " + msg.getSubject() );
    print("Content: " + msg.getContent() );
}

void Test_MailMessage()
{
    std::string sender("rajen.iitd@gmail.com");
    std::string recipient("uppal@adobe.com");
    std::string subject("Generated email");
    std::string content = "Hi ";
    content += recipient;
    content += ",\n\n";
    content += "Have a good day!\n\n";
    content += "Regards,\n";
    content += "A-Team";
    std::string attachment("C:\\DSC.jpg");

    MailMessage message;
    message.setSender( sender );
    message.addRecipient( MailRecipient(MailRecipient::PRIMARY_RECIPIENT, recipient) );
    message.setSubject( subject );
    message.setContent( content );
    message.addAttachment( attachment );

    send(message);
}

int main(int argc, char ** argv)
{
    Test_MailMessage();

    print("Press any key to continue...");
    cin.get();
    return 0;
}

// ~EOF
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2019 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 "otbOGRExtendedFilenameToOptions.h"
#include <algorithm>
#include <iostream>
#include <fstream>

using namespace otb;

typedef OGRExtendedFilenameToOptions FilenameHelperType;

int otbOGRExtendedFileName(int , char* argv[])
{
  // Verify the number of parameters in the command line
  const char * inputExtendedFilename  = argv[1];
  const char * outputFilename = argv[2];

  std::cout<< argv[1] <<"  "<<argv[2]<<std::endl;
  FilenameHelperType::Pointer helper = FilenameHelperType::New();

  helper->SetExtendedFileName(inputExtendedFilename);

  std::ofstream file;
  file.open(outputFilename);

  file << helper->SimpleFileNameIsSet() << std::endl;
  file << helper->GetSimpleFileName() << std::endl;

  file << "Open option :"<<std::endl;
  FilenameHelperType::GDALOptionType open = helper->GetGDALOpenOptions();
  for ( auto option : open )
    {
    file<< option << std::endl;
    }

  file << "Create option :"<<std::endl;
  FilenameHelperType::GDALOptionType create = helper->GetGDALOptions("creation");
  for ( auto option : create )
    {
    file<< option << std::endl;
    }

  file << "Layer option :"<<std::endl;
  FilenameHelperType::GDALOptionType layer = helper->GetGDALOptions("layer");
  for ( auto option : layer )
    {
    file<< option << std::endl;
    }

  file<< "End of classic helper."<<std::endl;

  layer.push_back("TOTO=first");
  FilenameHelperType::Pointer layerHelper =
    FilenameHelperType::GetGDALLayerOptionsHelper ( layer );
  std::cout<< layerHelper->GetGDALLayerOptions()[0] <<std::endl;
  FilenameHelperType::GDALOptionType newOptions;
    // std::vector< std::string> newOptions;
  newOptions.push_back("TOTO=second");
  newOptions.push_back("TiTi=option");
  layerHelper->AddGDALLayerOptions( newOptions );

  file << layerHelper->SimpleFileNameIsSet() << std::endl;
  file << layerHelper->HasGDALLayerOption() << std::endl;
  file << "Layer option from layer helper:"<<std::endl;
  FilenameHelperType::GDALOptionType latestOptions = layerHelper->GetGDALOptions("layer");
  // need to sort for dummy windows
  std::sort( latestOptions.begin() , latestOptions.end() );
  for ( auto option : latestOptions )
    {
    file<< option << std::endl;
    }

  file.close();
  return EXIT_SUCCESS;
}

<commit_msg>TEST: fix TvOGRExtendedFilename<commit_after>/*
 * Copyright (C) 2005-2019 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 "otbOGRExtendedFilenameToOptions.h"
#include "itksys/SystemTools.hxx"
#include <algorithm>
#include <iostream>
#include <fstream>

using namespace otb;

typedef OGRExtendedFilenameToOptions FilenameHelperType;

int otbOGRExtendedFileName(int , char* argv[])
{
  // Verify the number of parameters in the command line
  const char * inputExtendedFilename  = argv[1];
  const char * outputFilename = argv[2];

  std::cout<< argv[1] <<"  "<<argv[2]<<std::endl;
  FilenameHelperType::Pointer helper = FilenameHelperType::New();

  helper->SetExtendedFileName(inputExtendedFilename);

  std::ofstream file;
  file.open(outputFilename);

  file << helper->SimpleFileNameIsSet() << std::endl;
  file << itksys::SystemTools::GetFilenameName(helper->GetSimpleFileName()) << std::endl;

  file << "Open option :"<<std::endl;
  FilenameHelperType::GDALOptionType open = helper->GetGDALOpenOptions();
  for ( auto option : open )
    {
    file<< option << std::endl;
    }

  file << "Create option :"<<std::endl;
  FilenameHelperType::GDALOptionType create = helper->GetGDALOptions("creation");
  for ( auto option : create )
    {
    file<< option << std::endl;
    }

  file << "Layer option :"<<std::endl;
  FilenameHelperType::GDALOptionType layer = helper->GetGDALOptions("layer");
  for ( auto option : layer )
    {
    file<< option << std::endl;
    }

  file<< "End of classic helper."<<std::endl;

  layer.push_back("TOTO=first");
  FilenameHelperType::Pointer layerHelper =
    FilenameHelperType::GetGDALLayerOptionsHelper ( layer );
  std::cout<< layerHelper->GetGDALLayerOptions()[0] <<std::endl;
  FilenameHelperType::GDALOptionType newOptions;
    // std::vector< std::string> newOptions;
  newOptions.push_back("TOTO=second");
  newOptions.push_back("TiTi=option");
  layerHelper->AddGDALLayerOptions( newOptions );

  file << layerHelper->SimpleFileNameIsSet() << std::endl;
  file << layerHelper->HasGDALLayerOption() << std::endl;
  file << "Layer option from layer helper:"<<std::endl;
  FilenameHelperType::GDALOptionType latestOptions = layerHelper->GetGDALOptions("layer");
  // need to sort for dummy windows
  std::sort( latestOptions.begin() , latestOptions.end() );
  for ( auto option : latestOptions )
    {
    file<< option << std::endl;
    }

  file.close();
  return EXIT_SUCCESS;
}

<|endoftext|>