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

#ifndef _CONNECTIVITY_ODBC_ODRIVER_HXX_
#include "odbc/ODriver.hxx"
#endif
#ifndef _CONNECTIVITY_OTOOLS_HXX_
#include "odbc/OTools.hxx"
#endif
#ifndef _CONNECTIVITY_ODBC_OFUNCTIONS_HXX_
#include "odbc/OFunctions.hxx"
#endif
#ifndef CONNECTIVITY_DIAGNOSE_EX_H
#include "diagnose_ex.h"
#endif

namespace connectivity
{
    sal_Bool LoadFunctions(oslModule pODBCso);
    sal_Bool LoadLibrary_ODBC3(::rtl::OUString &_rPath);
    // extern declaration of the function pointer
    extern T3SQLAllocHandle pODBC3SQLAllocHandle;
    extern T3SQLConnect pODBC3SQLConnect;
    extern T3SQLDriverConnect pODBC3SQLDriverConnect;
    extern T3SQLBrowseConnect pODBC3SQLBrowseConnect;
    extern T3SQLDataSources pODBC3SQLDataSources;
    extern T3SQLDrivers pODBC3SQLDrivers;
    extern T3SQLGetInfo pODBC3SQLGetInfo;
    extern T3SQLGetFunctions pODBC3SQLGetFunctions;
    extern T3SQLGetTypeInfo pODBC3SQLGetTypeInfo;
    extern T3SQLSetConnectAttr pODBC3SQLSetConnectAttr;
    extern T3SQLGetConnectAttr pODBC3SQLGetConnectAttr;
    extern T3SQLSetEnvAttr pODBC3SQLSetEnvAttr;
    extern T3SQLGetEnvAttr pODBC3SQLGetEnvAttr;
    extern T3SQLSetStmtAttr pODBC3SQLSetStmtAttr;
    extern T3SQLGetStmtAttr pODBC3SQLGetStmtAttr;
    //extern T3SQLSetDescField pODBC3SQLSetDescField;
    //extern T3SQLGetDescField pODBC3SQLGetDescField;
    //extern T3SQLGetDescRec pODBC3SQLGetDescRec;
    //extern T3SQLSetDescRec pODBC3SQLSetDescRec;
    extern T3SQLPrepare pODBC3SQLPrepare;
    extern T3SQLBindParameter pODBC3SQLBindParameter;
    //extern T3SQLGetCursorName pODBC3SQLGetCursorName;
    extern T3SQLSetCursorName pODBC3SQLSetCursorName;
    extern T3SQLExecute pODBC3SQLExecute;
    extern T3SQLExecDirect pODBC3SQLExecDirect;
    //extern T3SQLNativeSql pODBC3SQLNativeSql;
    extern T3SQLDescribeParam pODBC3SQLDescribeParam;
    extern T3SQLNumParams pODBC3SQLNumParams;
    extern T3SQLParamData pODBC3SQLParamData;
    extern T3SQLPutData pODBC3SQLPutData;
    extern T3SQLRowCount pODBC3SQLRowCount;
    extern T3SQLNumResultCols pODBC3SQLNumResultCols;
    extern T3SQLDescribeCol pODBC3SQLDescribeCol;
    extern T3SQLColAttribute pODBC3SQLColAttribute;
    extern T3SQLBindCol pODBC3SQLBindCol;
    extern T3SQLFetch pODBC3SQLFetch;
    extern T3SQLFetchScroll pODBC3SQLFetchScroll;
    extern T3SQLGetData pODBC3SQLGetData;
    extern T3SQLSetPos pODBC3SQLSetPos;
    extern T3SQLBulkOperations pODBC3SQLBulkOperations;
    extern T3SQLMoreResults pODBC3SQLMoreResults;
    //extern T3SQLGetDiagField pODBC3SQLGetDiagField;
    extern T3SQLGetDiagRec pODBC3SQLGetDiagRec;
    extern T3SQLColumnPrivileges pODBC3SQLColumnPrivileges;
    extern T3SQLColumns pODBC3SQLColumns;
    extern T3SQLForeignKeys pODBC3SQLForeignKeys;
    extern T3SQLPrimaryKeys pODBC3SQLPrimaryKeys;
    extern T3SQLProcedureColumns pODBC3SQLProcedureColumns;
    extern T3SQLProcedures pODBC3SQLProcedures;
    extern T3SQLSpecialColumns pODBC3SQLSpecialColumns;
    extern T3SQLStatistics pODBC3SQLStatistics;
    extern T3SQLTablePrivileges pODBC3SQLTablePrivileges;
    extern T3SQLTables pODBC3SQLTables;
    extern T3SQLFreeStmt pODBC3SQLFreeStmt;
    extern T3SQLCloseCursor pODBC3SQLCloseCursor;
    extern T3SQLCancel pODBC3SQLCancel;
    extern T3SQLEndTran pODBC3SQLEndTran;
    extern T3SQLDisconnect pODBC3SQLDisconnect;
    extern T3SQLFreeHandle pODBC3SQLFreeHandle;
    extern T3SQLGetCursorName pODBC3SQLGetCursorName;
    extern T3SQLNativeSql pODBC3SQLNativeSql;

    namespace odbc
    {
        class ORealObdcDriver : public ODBCDriver
        {
        protected:
            virtual oslGenericFunction  getOdbcFunction(sal_Int32 _nIndex)  const;
            virtual SQLHANDLE   EnvironmentHandle(::rtl::OUString &_rPath);
        public:
            ORealObdcDriver(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) : ODBCDriver(_rxFactory) {}
        };

        //------------------------------------------------------------------
oslGenericFunction ORealObdcDriver::getOdbcFunction(sal_Int32 _nIndex) const
{
    oslGenericFunction pFunction = NULL;
    switch(_nIndex)
    {
        case ODBC3SQLAllocHandle:
            pFunction = (oslGenericFunction)pODBC3SQLAllocHandle;
            break;
        case ODBC3SQLConnect:
            pFunction = (oslGenericFunction)pODBC3SQLConnect;
            break;
        case ODBC3SQLDriverConnect:
            pFunction = (oslGenericFunction)pODBC3SQLDriverConnect;
            break;
        case ODBC3SQLBrowseConnect:
            pFunction = (oslGenericFunction)pODBC3SQLBrowseConnect;
            break;
        case ODBC3SQLDataSources:
            pFunction = (oslGenericFunction)pODBC3SQLDataSources;
            break;
        case ODBC3SQLDrivers:
            pFunction = (oslGenericFunction)pODBC3SQLDrivers;
            break;
        case ODBC3SQLGetInfo:

            pFunction = (oslGenericFunction)pODBC3SQLGetInfo;
            break;
        case ODBC3SQLGetFunctions:

            pFunction = (oslGenericFunction)pODBC3SQLGetFunctions;
            break;
        case ODBC3SQLGetTypeInfo:

            pFunction = (oslGenericFunction)pODBC3SQLGetTypeInfo;
            break;
        case ODBC3SQLSetConnectAttr:

            pFunction = (oslGenericFunction)pODBC3SQLSetConnectAttr;
            break;
        case ODBC3SQLGetConnectAttr:

            pFunction = (oslGenericFunction)pODBC3SQLGetConnectAttr;
            break;
        case ODBC3SQLSetEnvAttr:

            pFunction = (oslGenericFunction)pODBC3SQLSetEnvAttr;
            break;
        case ODBC3SQLGetEnvAttr:

            pFunction = (oslGenericFunction)pODBC3SQLGetEnvAttr;
            break;
        case ODBC3SQLSetStmtAttr:

            pFunction = (oslGenericFunction)pODBC3SQLSetStmtAttr;
            break;
        case ODBC3SQLGetStmtAttr:

            pFunction = (oslGenericFunction)pODBC3SQLGetStmtAttr;
            break;
        case ODBC3SQLPrepare:

            pFunction = (oslGenericFunction)pODBC3SQLPrepare;
            break;
        case ODBC3SQLBindParameter:

            pFunction = (oslGenericFunction)pODBC3SQLBindParameter;
            break;
        case ODBC3SQLSetCursorName:

            pFunction = (oslGenericFunction)pODBC3SQLSetCursorName;
            break;
        case ODBC3SQLExecute:

            pFunction = (oslGenericFunction)pODBC3SQLExecute;
            break;
        case ODBC3SQLExecDirect:

            pFunction = (oslGenericFunction)pODBC3SQLExecDirect;
            break;
        case ODBC3SQLDescribeParam:

            pFunction = (oslGenericFunction)pODBC3SQLDescribeParam;
            break;
        case ODBC3SQLNumParams:

            pFunction = (oslGenericFunction)pODBC3SQLNumParams;
            break;
        case ODBC3SQLParamData:

            pFunction = (oslGenericFunction)pODBC3SQLParamData;
            break;
        case ODBC3SQLPutData:

            pFunction = (oslGenericFunction)pODBC3SQLPutData;
            break;
        case ODBC3SQLRowCount:

            pFunction = (oslGenericFunction)pODBC3SQLRowCount;
            break;
        case ODBC3SQLNumResultCols:

            pFunction = (oslGenericFunction)pODBC3SQLNumResultCols;
            break;
        case ODBC3SQLDescribeCol:

            pFunction = (oslGenericFunction)pODBC3SQLDescribeCol;
            break;
        case ODBC3SQLColAttribute:

            pFunction = (oslGenericFunction)pODBC3SQLColAttribute;
            break;
        case ODBC3SQLBindCol:

            pFunction = (oslGenericFunction)pODBC3SQLBindCol;
            break;
        case ODBC3SQLFetch:

            pFunction = (oslGenericFunction)pODBC3SQLFetch;
            break;
        case ODBC3SQLFetchScroll:

            pFunction = (oslGenericFunction)pODBC3SQLFetchScroll;
            break;
        case ODBC3SQLGetData:

            pFunction = (oslGenericFunction)pODBC3SQLGetData;
            break;
        case ODBC3SQLSetPos:

            pFunction = (oslGenericFunction)pODBC3SQLSetPos;
            break;
        case ODBC3SQLBulkOperations:

            pFunction = (oslGenericFunction)pODBC3SQLBulkOperations;
            break;
        case ODBC3SQLMoreResults:

            pFunction = (oslGenericFunction)pODBC3SQLMoreResults;
            break;
        case ODBC3SQLGetDiagRec:

            pFunction = (oslGenericFunction)pODBC3SQLGetDiagRec;
            break;
        case ODBC3SQLColumnPrivileges:

            pFunction = (oslGenericFunction)pODBC3SQLColumnPrivileges;
            break;
        case ODBC3SQLColumns:

            pFunction = (oslGenericFunction)pODBC3SQLColumns;
            break;
        case ODBC3SQLForeignKeys:

            pFunction = (oslGenericFunction)pODBC3SQLForeignKeys;
            break;
        case ODBC3SQLPrimaryKeys:

            pFunction = (oslGenericFunction)pODBC3SQLPrimaryKeys;
            break;
        case ODBC3SQLProcedureColumns:

            pFunction = (oslGenericFunction)pODBC3SQLProcedureColumns;
            break;
        case ODBC3SQLProcedures:

            pFunction = (oslGenericFunction)pODBC3SQLProcedures;
            break;
        case ODBC3SQLSpecialColumns:

            pFunction = (oslGenericFunction)pODBC3SQLSpecialColumns;
            break;
        case ODBC3SQLStatistics:

            pFunction = (oslGenericFunction)pODBC3SQLStatistics;
            break;
        case ODBC3SQLTablePrivileges:

            pFunction = (oslGenericFunction)pODBC3SQLTablePrivileges;
            break;
        case ODBC3SQLTables:

            pFunction = (oslGenericFunction)pODBC3SQLTables;
            break;
        case ODBC3SQLFreeStmt:

            pFunction = (oslGenericFunction)pODBC3SQLFreeStmt;
            break;
        case ODBC3SQLCloseCursor:

            pFunction = (oslGenericFunction)pODBC3SQLCloseCursor;
            break;
        case ODBC3SQLCancel:

            pFunction = (oslGenericFunction)pODBC3SQLCancel;
            break;
        case ODBC3SQLEndTran:

            pFunction = (oslGenericFunction)pODBC3SQLEndTran;
            break;
        case ODBC3SQLDisconnect:

            pFunction = (oslGenericFunction)pODBC3SQLDisconnect;
            break;
        case ODBC3SQLFreeHandle:

            pFunction = (oslGenericFunction)pODBC3SQLFreeHandle;
            break;
        case ODBC3SQLGetCursorName:

            pFunction = (oslGenericFunction)pODBC3SQLGetCursorName;
            break;
        case ODBC3SQLNativeSql:

            pFunction = (oslGenericFunction)pODBC3SQLNativeSql;
            break;
        default:
            OSL_ENSURE(0,"Function unknown!");
    }
    return pFunction;
}

//------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >  SAL_CALL ODBCDriver_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception )
{
    return *(new ORealObdcDriver(_rxFactory));
}
// -----------------------------------------------------------------------------
// ODBC Environment (gemeinsam fuer alle Connections):
SQLHANDLE ORealObdcDriver::EnvironmentHandle(::rtl::OUString &_rPath)
{
    // Ist (fuer diese Instanz) bereits ein Environment erzeugt worden?
    if (!m_pDriverHandle)
    {
        SQLHANDLE h = SQL_NULL_HANDLE;
        // Environment allozieren

        // ODBC-DLL jetzt laden:
        if (!LoadLibrary_ODBC3(_rPath) || N3SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&h) != SQL_SUCCESS)
            return SQL_NULL_HANDLE;

        // In globaler Struktur merken ...
        m_pDriverHandle = h;
        SQLRETURN nError = N3SQLSetEnvAttr(h, SQL_ATTR_ODBC_VERSION,(SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER);
        OSL_UNUSED( nError );
        //N3SQLSetEnvAttr(h, SQL_ATTR_CONNECTION_POOLING,(SQLPOINTER) SQL_CP_ONE_PER_HENV, SQL_IS_INTEGER);
    }

    return m_pDriverHandle;
}
// -----------------------------------------------------------------------------

    }
}

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

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

#ifndef _CONNECTIVITY_ODBC_ODRIVER_HXX_
#include "odbc/ODriver.hxx"
#endif
#ifndef _CONNECTIVITY_OTOOLS_HXX_
#include "odbc/OTools.hxx"
#endif
#ifndef _CONNECTIVITY_ODBC_OFUNCTIONS_HXX_
#include "odbc/OFunctions.hxx"
#endif
#ifndef CONNECTIVITY_DIAGNOSE_EX_H
#include "diagnose_ex.h"
#endif

namespace connectivity
{
    sal_Bool LoadFunctions(oslModule pODBCso);
    sal_Bool LoadLibrary_ODBC3(::rtl::OUString &_rPath);
    // extern declaration of the function pointer
    extern T3SQLAllocHandle pODBC3SQLAllocHandle;
    extern T3SQLConnect pODBC3SQLConnect;
    extern T3SQLDriverConnect pODBC3SQLDriverConnect;
    extern T3SQLBrowseConnect pODBC3SQLBrowseConnect;
    extern T3SQLDataSources pODBC3SQLDataSources;
    extern T3SQLDrivers pODBC3SQLDrivers;
    extern T3SQLGetInfo pODBC3SQLGetInfo;
    extern T3SQLGetFunctions pODBC3SQLGetFunctions;
    extern T3SQLGetTypeInfo pODBC3SQLGetTypeInfo;
    extern T3SQLSetConnectAttr pODBC3SQLSetConnectAttr;
    extern T3SQLGetConnectAttr pODBC3SQLGetConnectAttr;
    extern T3SQLSetEnvAttr pODBC3SQLSetEnvAttr;
    extern T3SQLGetEnvAttr pODBC3SQLGetEnvAttr;
    extern T3SQLSetStmtAttr pODBC3SQLSetStmtAttr;
    extern T3SQLGetStmtAttr pODBC3SQLGetStmtAttr;
    //extern T3SQLSetDescField pODBC3SQLSetDescField;
    //extern T3SQLGetDescField pODBC3SQLGetDescField;
    //extern T3SQLGetDescRec pODBC3SQLGetDescRec;
    //extern T3SQLSetDescRec pODBC3SQLSetDescRec;
    extern T3SQLPrepare pODBC3SQLPrepare;
    extern T3SQLBindParameter pODBC3SQLBindParameter;
    //extern T3SQLGetCursorName pODBC3SQLGetCursorName;
    extern T3SQLSetCursorName pODBC3SQLSetCursorName;
    extern T3SQLExecute pODBC3SQLExecute;
    extern T3SQLExecDirect pODBC3SQLExecDirect;
    //extern T3SQLNativeSql pODBC3SQLNativeSql;
    extern T3SQLDescribeParam pODBC3SQLDescribeParam;
    extern T3SQLNumParams pODBC3SQLNumParams;
    extern T3SQLParamData pODBC3SQLParamData;
    extern T3SQLPutData pODBC3SQLPutData;
    extern T3SQLRowCount pODBC3SQLRowCount;
    extern T3SQLNumResultCols pODBC3SQLNumResultCols;
    extern T3SQLDescribeCol pODBC3SQLDescribeCol;
    extern T3SQLColAttribute pODBC3SQLColAttribute;
    extern T3SQLBindCol pODBC3SQLBindCol;
    extern T3SQLFetch pODBC3SQLFetch;
    extern T3SQLFetchScroll pODBC3SQLFetchScroll;
    extern T3SQLGetData pODBC3SQLGetData;
    extern T3SQLSetPos pODBC3SQLSetPos;
    extern T3SQLBulkOperations pODBC3SQLBulkOperations;
    extern T3SQLMoreResults pODBC3SQLMoreResults;
    //extern T3SQLGetDiagField pODBC3SQLGetDiagField;
    extern T3SQLGetDiagRec pODBC3SQLGetDiagRec;
    extern T3SQLColumnPrivileges pODBC3SQLColumnPrivileges;
    extern T3SQLColumns pODBC3SQLColumns;
    extern T3SQLForeignKeys pODBC3SQLForeignKeys;
    extern T3SQLPrimaryKeys pODBC3SQLPrimaryKeys;
    extern T3SQLProcedureColumns pODBC3SQLProcedureColumns;
    extern T3SQLProcedures pODBC3SQLProcedures;
    extern T3SQLSpecialColumns pODBC3SQLSpecialColumns;
    extern T3SQLStatistics pODBC3SQLStatistics;
    extern T3SQLTablePrivileges pODBC3SQLTablePrivileges;
    extern T3SQLTables pODBC3SQLTables;
    extern T3SQLFreeStmt pODBC3SQLFreeStmt;
    extern T3SQLCloseCursor pODBC3SQLCloseCursor;
    extern T3SQLCancel pODBC3SQLCancel;
    extern T3SQLEndTran pODBC3SQLEndTran;
    extern T3SQLDisconnect pODBC3SQLDisconnect;
    extern T3SQLFreeHandle pODBC3SQLFreeHandle;
    extern T3SQLGetCursorName pODBC3SQLGetCursorName;
    extern T3SQLNativeSql pODBC3SQLNativeSql;

    namespace odbc
    {
        class ORealObdcDriver : public ODBCDriver
        {
        protected:
            virtual oslGenericFunction  getOdbcFunction(sal_Int32 _nIndex)  const;
            virtual SQLHANDLE   EnvironmentHandle(::rtl::OUString &_rPath);
        public:
            ORealObdcDriver(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) : ODBCDriver(_rxFactory) {}
        };

        //------------------------------------------------------------------
oslGenericFunction ORealObdcDriver::getOdbcFunction(sal_Int32 _nIndex) const
{
    oslGenericFunction pFunction = NULL;
    switch(_nIndex)
    {
        case ODBC3SQLAllocHandle:
            pFunction = (oslGenericFunction)pODBC3SQLAllocHandle;
            break;
        case ODBC3SQLConnect:
            pFunction = (oslGenericFunction)pODBC3SQLConnect;
            break;
        case ODBC3SQLDriverConnect:
            pFunction = (oslGenericFunction)pODBC3SQLDriverConnect;
            break;
        case ODBC3SQLBrowseConnect:
            pFunction = (oslGenericFunction)pODBC3SQLBrowseConnect;
            break;
        case ODBC3SQLDataSources:
            pFunction = (oslGenericFunction)pODBC3SQLDataSources;
            break;
        case ODBC3SQLDrivers:
            pFunction = (oslGenericFunction)pODBC3SQLDrivers;
            break;
        case ODBC3SQLGetInfo:

            pFunction = (oslGenericFunction)pODBC3SQLGetInfo;
            break;
        case ODBC3SQLGetFunctions:

            pFunction = (oslGenericFunction)pODBC3SQLGetFunctions;
            break;
        case ODBC3SQLGetTypeInfo:

            pFunction = (oslGenericFunction)pODBC3SQLGetTypeInfo;
            break;
        case ODBC3SQLSetConnectAttr:

            pFunction = (oslGenericFunction)pODBC3SQLSetConnectAttr;
            break;
        case ODBC3SQLGetConnectAttr:

            pFunction = (oslGenericFunction)pODBC3SQLGetConnectAttr;
            break;
        case ODBC3SQLSetEnvAttr:

            pFunction = (oslGenericFunction)pODBC3SQLSetEnvAttr;
            break;
        case ODBC3SQLGetEnvAttr:

            pFunction = (oslGenericFunction)pODBC3SQLGetEnvAttr;
            break;
        case ODBC3SQLSetStmtAttr:

            pFunction = (oslGenericFunction)pODBC3SQLSetStmtAttr;
            break;
        case ODBC3SQLGetStmtAttr:

            pFunction = (oslGenericFunction)pODBC3SQLGetStmtAttr;
            break;
        case ODBC3SQLPrepare:

            pFunction = (oslGenericFunction)pODBC3SQLPrepare;
            break;
        case ODBC3SQLBindParameter:

            pFunction = (oslGenericFunction)pODBC3SQLBindParameter;
            break;
        case ODBC3SQLSetCursorName:

            pFunction = (oslGenericFunction)pODBC3SQLSetCursorName;
            break;
        case ODBC3SQLExecute:

            pFunction = (oslGenericFunction)pODBC3SQLExecute;
            break;
        case ODBC3SQLExecDirect:

            pFunction = (oslGenericFunction)pODBC3SQLExecDirect;
            break;
        case ODBC3SQLDescribeParam:

            pFunction = (oslGenericFunction)pODBC3SQLDescribeParam;
            break;
        case ODBC3SQLNumParams:

            pFunction = (oslGenericFunction)pODBC3SQLNumParams;
            break;
        case ODBC3SQLParamData:

            pFunction = (oslGenericFunction)pODBC3SQLParamData;
            break;
        case ODBC3SQLPutData:

            pFunction = (oslGenericFunction)pODBC3SQLPutData;
            break;
        case ODBC3SQLRowCount:

            pFunction = (oslGenericFunction)pODBC3SQLRowCount;
            break;
        case ODBC3SQLNumResultCols:

            pFunction = (oslGenericFunction)pODBC3SQLNumResultCols;
            break;
        case ODBC3SQLDescribeCol:

            pFunction = (oslGenericFunction)pODBC3SQLDescribeCol;
            break;
        case ODBC3SQLColAttribute:

            pFunction = (oslGenericFunction)pODBC3SQLColAttribute;
            break;
        case ODBC3SQLBindCol:

            pFunction = (oslGenericFunction)pODBC3SQLBindCol;
            break;
        case ODBC3SQLFetch:

            pFunction = (oslGenericFunction)pODBC3SQLFetch;
            break;
        case ODBC3SQLFetchScroll:

            pFunction = (oslGenericFunction)pODBC3SQLFetchScroll;
            break;
        case ODBC3SQLGetData:

            pFunction = (oslGenericFunction)pODBC3SQLGetData;
            break;
        case ODBC3SQLSetPos:

            pFunction = (oslGenericFunction)pODBC3SQLSetPos;
            break;
        case ODBC3SQLBulkOperations:

            pFunction = (oslGenericFunction)pODBC3SQLBulkOperations;
            break;
        case ODBC3SQLMoreResults:

            pFunction = (oslGenericFunction)pODBC3SQLMoreResults;
            break;
        case ODBC3SQLGetDiagRec:

            pFunction = (oslGenericFunction)pODBC3SQLGetDiagRec;
            break;
        case ODBC3SQLColumnPrivileges:

            pFunction = (oslGenericFunction)pODBC3SQLColumnPrivileges;
            break;
        case ODBC3SQLColumns:

            pFunction = (oslGenericFunction)pODBC3SQLColumns;
            break;
        case ODBC3SQLForeignKeys:

            pFunction = (oslGenericFunction)pODBC3SQLForeignKeys;
            break;
        case ODBC3SQLPrimaryKeys:

            pFunction = (oslGenericFunction)pODBC3SQLPrimaryKeys;
            break;
        case ODBC3SQLProcedureColumns:

            pFunction = (oslGenericFunction)pODBC3SQLProcedureColumns;
            break;
        case ODBC3SQLProcedures:

            pFunction = (oslGenericFunction)pODBC3SQLProcedures;
            break;
        case ODBC3SQLSpecialColumns:

            pFunction = (oslGenericFunction)pODBC3SQLSpecialColumns;
            break;
        case ODBC3SQLStatistics:

            pFunction = (oslGenericFunction)pODBC3SQLStatistics;
            break;
        case ODBC3SQLTablePrivileges:

            pFunction = (oslGenericFunction)pODBC3SQLTablePrivileges;
            break;
        case ODBC3SQLTables:

            pFunction = (oslGenericFunction)pODBC3SQLTables;
            break;
        case ODBC3SQLFreeStmt:

            pFunction = (oslGenericFunction)pODBC3SQLFreeStmt;
            break;
        case ODBC3SQLCloseCursor:

            pFunction = (oslGenericFunction)pODBC3SQLCloseCursor;
            break;
        case ODBC3SQLCancel:

            pFunction = (oslGenericFunction)pODBC3SQLCancel;
            break;
        case ODBC3SQLEndTran:

            pFunction = (oslGenericFunction)pODBC3SQLEndTran;
            break;
        case ODBC3SQLDisconnect:

            pFunction = (oslGenericFunction)pODBC3SQLDisconnect;
            break;
        case ODBC3SQLFreeHandle:

            pFunction = (oslGenericFunction)pODBC3SQLFreeHandle;
            break;
        case ODBC3SQLGetCursorName:

            pFunction = (oslGenericFunction)pODBC3SQLGetCursorName;
            break;
        case ODBC3SQLNativeSql:

            pFunction = (oslGenericFunction)pODBC3SQLNativeSql;
            break;
        default:
            OSL_ENSURE(0,"Function unknown!");
    }
    return pFunction;
}

//------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >  SAL_CALL ODBCDriver_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception )
{
    return *(new ORealObdcDriver(_rxFactory));
}
// -----------------------------------------------------------------------------
// ODBC Environment (gemeinsam fuer alle Connections):
SQLHANDLE ORealObdcDriver::EnvironmentHandle(::rtl::OUString &_rPath)
{
    // Ist (fuer diese Instanz) bereits ein Environment erzeugt worden?
    if (!m_pDriverHandle)
    {
        SQLHANDLE h = SQL_NULL_HANDLE;
        // Environment allozieren

        // ODBC-DLL jetzt laden:
        if (!LoadLibrary_ODBC3(_rPath) || N3SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&h) != SQL_SUCCESS)
            return SQL_NULL_HANDLE;

        // In globaler Struktur merken ...
        m_pDriverHandle = h;
        SQLRETURN nError = N3SQLSetEnvAttr(h, SQL_ATTR_ODBC_VERSION,(SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER);
        OSL_UNUSED( nError );
        //N3SQLSetEnvAttr(h, SQL_ATTR_CONNECTION_POOLING,(SQLPOINTER) SQL_CP_ONE_PER_HENV, SQL_IS_INTEGER);
    }

    return m_pDriverHandle;
}
// -----------------------------------------------------------------------------

    }
}

<|endoftext|>


<commit_before>/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/uint32_t.h>
#include "imgui/imgui.h"

#include <bgfx/embedded_shader.h>

// embedded shaders
#include "vs_drawstress.bin.h"
#include "fs_drawstress.bin.h"

static const bgfx::EmbeddedShader s_embeddedShaders[] =
{
	BGFX_EMBEDDED_SHADER(vs_drawstress),
	BGFX_EMBEDDED_SHADER(fs_drawstress),

	BGFX_EMBEDDED_SHADER_END()
};

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	}

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

#if BX_PLATFORM_EMSCRIPTEN
static const int64_t highwm = 1000000/35;
static const int64_t lowwm  = 1000000/27;
#else
static const int64_t highwm = 1000000/65;
static const int64_t lowwm  = 1000000/57;
#endif // BX_PLATFORM_EMSCRIPTEN

class ExampleDrawStress : public entry::AppI
{
	void init(int _argc, char** _argv) BX_OVERRIDE
	{
		Args args(_argc, _argv);

		m_width  = 1280;
		m_height = 720;
		m_debug  = BGFX_DEBUG_TEXT;
		m_reset  = BGFX_RESET_NONE;

		m_autoAdjust = true;
		m_scrollArea = 0;
		m_dim        = 16;
		m_maxDim     = 40;
		m_transform  = 0;

		m_timeOffset = bx::getHPCounter();

		m_deltaTimeNs    = 0;
		m_deltaTimeAvgNs = 0;
		m_numFrames      = 0;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		const bgfx::Caps* caps = bgfx::getCaps();
		m_maxDim = (int32_t)bx::fpow(float(caps->limits.maxDrawCalls), 1.0f/3.0f);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
				, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
				, 0x303030ff
				, 1.0f
				, 0
				);

		// Create vertex stream declaration.
		PosColorVertex::init();

		bgfx::RendererType::Enum type = bgfx::getRendererType();

		// Create program from shaders.
		m_program = bgfx::createProgram(
				  bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress")
				, bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress")
				, true /* destroy shaders when program is destroyed */
				);

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
					  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
					, PosColorVertex::ms_decl
					);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );

		// Imgui.
		imguiCreate();
	}

	int shutdown() BX_OVERRIDE
	{
		// Cleanup.
		imguiDestroy();
		bgfx::destroyIndexBuffer(m_ibh);
		bgfx::destroyVertexBuffer(m_vbh);
		bgfx::destroyProgram(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() BX_OVERRIDE
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t hpFreq = bx::getHPFrequency();
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(hpFreq);
			const double toMs = 1000.0/freq;

			m_deltaTimeNs += frameTime*1000000/hpFreq;

			if (m_deltaTimeNs > 1000000)
			{
				m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames);

				if (m_autoAdjust)
				{
					if (m_deltaTimeAvgNs < highwm)
					{
						m_dim = bx::uint32_min(m_dim + 2, m_maxDim);
					}
					else if (m_deltaTimeAvgNs > lowwm)
					{
						m_dim = bx::uint32_max(m_dim - 1, 2);
					}
				}

				m_deltaTimeNs = 0;
				m_numFrames   = 0;
			}
			else
			{
				++m_numFrames;
			}

			float time = (float)( (now-m_timeOffset)/freq);

			imguiBeginFrame(m_mouseState.m_mx
					,  m_mouseState.m_my
					, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
					| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
					| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
					,  m_mouseState.m_mz
					, uint16_t(m_width)
					, uint16_t(m_height)
					);

			ImGui::SetNextWindowPos(ImVec2((float)m_width - (float)m_width / 4.0f - 10.0f, 10.0f) );
			ImGui::SetNextWindowSize(ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) );
			ImGui::Begin("Settings"
						 , NULL
						 , ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f)
						 , ImGuiWindowFlags_AlwaysAutoResize
						 );

			ImGui::RadioButton("Rotate",&m_transform,0);
			ImGui::RadioButton("No fragments",&m_transform,1);
			ImGui::Separator();

			ImGui::Checkbox("Auto adjust", &m_autoAdjust);

			ImGui::SliderInt("Dim", &m_dim, 5, m_maxDim);
			ImGui::Text("Draw calls: %d", m_dim*m_dim*m_dim);
			ImGui::Text("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f);

			ImGui::Separator();
			const bgfx::Stats* stats = bgfx::getStats();
			ImGui::Text("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq);
			ImGui::Text("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq);
			ImGui::Text("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs);
			ImGui::Text("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs);

			ImGui::End();

			imguiEndFrame();

			float at[3] = { 0.0f, 0.0f, 0.0f };
			float eye[3] = { 0.0f, 0.0f, -35.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const bgfx::Caps* caps = bgfx::getCaps();
			float proj[16];
			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);

			// Set view and projection matrix for view 0.
			bgfx::setViewTransform(0, view, proj);

			// Set view 0 default viewport.
			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			// Use debug font to print information about this example.
			bgfx::dbgTextClear();
			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/17-drawstress");
			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Draw stress, maximizing number of draw calls.");
			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: %7.3f[ms]", double(frameTime)*toMs);

			float mtxS[16];
			const float scale = 0 == m_transform ? 0.25f : 0.0f;
			bx::mtxScale(mtxS, scale, scale, scale);

			const float step = 0.6f;
			float pos[3];
			pos[0] = -step*m_dim / 2.0f;
			pos[1] = -step*m_dim / 2.0f;
			pos[2] = -15.0;

			for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz)
			{
				for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy)
				{
					for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx)
					{
						float mtxR[16];
						bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f);

						float mtx[16];
						bx::mtxMul(mtx, mtxS, mtxR);

						mtx[12] = pos[0] + float(xx)*step;
						mtx[13] = pos[1] + float(yy)*step;
						mtx[14] = pos[2] + float(zz)*step;

						// Set model matrix for rendering.
						bgfx::setTransform(mtx);

						// Set vertex and index buffer.
						bgfx::setVertexBuffer(0, m_vbh);
						bgfx::setIndexBuffer(m_ibh);

						// Set render states.
						bgfx::setState(BGFX_STATE_DEFAULT);

						// Submit primitive for rendering to view 0.
						bgfx::submit(0, m_program);
					}
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	bool     m_autoAdjust;
	int32_t  m_scrollArea;
	int32_t  m_dim;
	int32_t  m_maxDim;
	int32_t  m_transform;

	int64_t  m_timeOffset;

	int64_t  m_deltaTimeNs;
	int64_t  m_deltaTimeAvgNs;
	int64_t  m_numFrames;

	bgfx::ProgramHandle m_program;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
};

ENTRY_IMPLEMENT_MAIN(ExampleDrawStress);
<commit_msg>Cleanup.<commit_after>/*
 * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
 */

#include "common.h"
#include "bgfx_utils.h"

#include <bx/uint32_t.h>
#include "imgui/imgui.h"

#include <bgfx/embedded_shader.h>

// embedded shaders
#include "vs_drawstress.bin.h"
#include "fs_drawstress.bin.h"

static const bgfx::EmbeddedShader s_embeddedShaders[] =
{
	BGFX_EMBEDDED_SHADER(vs_drawstress),
	BGFX_EMBEDDED_SHADER(fs_drawstress),

	BGFX_EMBEDDED_SHADER_END()
};

struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_decl
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	}

	static bgfx::VertexDecl ms_decl;
};

bgfx::VertexDecl PosColorVertex::ms_decl;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};

#if BX_PLATFORM_EMSCRIPTEN
static const int64_t highwm = 1000000/35;
static const int64_t lowwm  = 1000000/27;
#else
static const int64_t highwm = 1000000/65;
static const int64_t lowwm  = 1000000/57;
#endif // BX_PLATFORM_EMSCRIPTEN

class ExampleDrawStress : public entry::AppI
{
	void init(int _argc, char** _argv) BX_OVERRIDE
	{
		Args args(_argc, _argv);

		m_width  = 1280;
		m_height = 720;
		m_debug  = BGFX_DEBUG_TEXT;
		m_reset  = BGFX_RESET_NONE;

		m_autoAdjust = true;
		m_scrollArea = 0;
		m_dim        = 16;
		m_maxDim     = 40;
		m_transform  = 0;

		m_timeOffset = bx::getHPCounter();

		m_deltaTimeNs    = 0;
		m_deltaTimeAvgNs = 0;
		m_numFrames      = 0;

		bgfx::init(args.m_type, args.m_pciId);
		bgfx::reset(m_width, m_height, m_reset);

		const bgfx::Caps* caps = bgfx::getCaps();
		m_maxDim = (int32_t)bx::fpow(float(caps->limits.maxDrawCalls), 1.0f/3.0f);

		// Enable debug text.
		bgfx::setDebug(m_debug);

		// Set view 0 clear state.
		bgfx::setViewClear(0
			, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
			, 0x303030ff
			, 1.0f
			, 0
			);

		// Create vertex stream declaration.
		PosColorVertex::init();

		bgfx::RendererType::Enum type = bgfx::getRendererType();

		// Create program from shaders.
		m_program = bgfx::createProgram(
			  bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress")
			, bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress")
			, true /* destroy shaders when program is destroyed */
			);

		// Create static vertex buffer.
		m_vbh = bgfx::createVertexBuffer(
			  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
			, PosColorVertex::ms_decl
			);

		// Create static index buffer.
		m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) );

		// Imgui.
		imguiCreate();
	}

	int shutdown() BX_OVERRIDE
	{
		// Cleanup.
		imguiDestroy();
		bgfx::destroyIndexBuffer(m_ibh);
		bgfx::destroyVertexBuffer(m_vbh);
		bgfx::destroyProgram(m_program);

		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}

	bool update() BX_OVERRIDE
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			int64_t now = bx::getHPCounter();
			static int64_t last = now;
			const int64_t hpFreq = bx::getHPFrequency();
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(hpFreq);
			const double toMs = 1000.0/freq;

			m_deltaTimeNs += frameTime*1000000/hpFreq;

			if (m_deltaTimeNs > 1000000)
			{
				m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames);

				if (m_autoAdjust)
				{
					if (m_deltaTimeAvgNs < highwm)
					{
						m_dim = bx::uint32_min(m_dim + 2, m_maxDim);
					}
					else if (m_deltaTimeAvgNs > lowwm)
					{
						m_dim = bx::uint32_max(m_dim - 1, 2);
					}
				}

				m_deltaTimeNs = 0;
				m_numFrames   = 0;
			}
			else
			{
				++m_numFrames;
			}

			float time = (float)( (now-m_timeOffset)/freq);

			imguiBeginFrame(m_mouseState.m_mx
				,  m_mouseState.m_my
				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
				,  m_mouseState.m_mz
				, uint16_t(m_width)
				, uint16_t(m_height)
				);

			ImGui::SetNextWindowPos(ImVec2((float)m_width - (float)m_width / 4.0f - 10.0f, 10.0f) );
			ImGui::SetNextWindowSize(ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) );
			ImGui::Begin("Settings"
				, NULL
				, ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f)
				, ImGuiWindowFlags_AlwaysAutoResize
				);

			ImGui::RadioButton("Rotate",&m_transform,0);
			ImGui::RadioButton("No fragments",&m_transform,1);
			ImGui::Separator();

			ImGui::Checkbox("Auto adjust", &m_autoAdjust);

			ImGui::SliderInt("Dim", &m_dim, 5, m_maxDim);
			ImGui::Text("Draw calls: %d", m_dim*m_dim*m_dim);
			ImGui::Text("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f);

			ImGui::Separator();
			const bgfx::Stats* stats = bgfx::getStats();
			ImGui::Text("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq);
			ImGui::Text("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq);
			ImGui::Text("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs);
			ImGui::Text("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs);

			ImGui::End();

			imguiEndFrame();

			float at[3] = { 0.0f, 0.0f, 0.0f };
			float eye[3] = { 0.0f, 0.0f, -35.0f };

			float view[16];
			bx::mtxLookAt(view, eye, at);

			const bgfx::Caps* caps = bgfx::getCaps();
			float proj[16];
			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);

			// Set view and projection matrix for view 0.
			bgfx::setViewTransform(0, view, proj);

			// Set view 0 default viewport.
			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);

			// Use debug font to print information about this example.
			bgfx::dbgTextClear();
			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/17-drawstress");
			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Draw stress, maximizing number of draw calls.");
			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: %7.3f[ms]", double(frameTime)*toMs);

			float mtxS[16];
			const float scale = 0 == m_transform ? 0.25f : 0.0f;
			bx::mtxScale(mtxS, scale, scale, scale);

			const float step = 0.6f;
			float pos[3];
			pos[0] = -step*m_dim / 2.0f;
			pos[1] = -step*m_dim / 2.0f;
			pos[2] = -15.0;

			for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz)
			{
				for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy)
				{
					for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx)
					{
						float mtxR[16];
						bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f);

						float mtx[16];
						bx::mtxMul(mtx, mtxS, mtxR);

						mtx[12] = pos[0] + float(xx)*step;
						mtx[13] = pos[1] + float(yy)*step;
						mtx[14] = pos[2] + float(zz)*step;

						// Set model matrix for rendering.
						bgfx::setTransform(mtx);

						// Set vertex and index buffer.
						bgfx::setVertexBuffer(0, m_vbh);
						bgfx::setIndexBuffer(m_ibh);

						// Set render states.
						bgfx::setState(BGFX_STATE_DEFAULT);

						// Submit primitive for rendering to view 0.
						bgfx::submit(0, m_program);
					}
				}
			}

			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			bgfx::frame();

			return true;
		}

		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;

	bool     m_autoAdjust;
	int32_t  m_scrollArea;
	int32_t  m_dim;
	int32_t  m_maxDim;
	int32_t  m_transform;

	int64_t  m_timeOffset;

	int64_t  m_deltaTimeNs;
	int64_t  m_deltaTimeAvgNs;
	int64_t  m_numFrames;

	bgfx::ProgramHandle m_program;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
};

ENTRY_IMPLEMENT_MAIN(ExampleDrawStress);
<|endoftext|>


<commit_before>#include "magic.h"

using namespace cv;

Point point1, point2; /* vertical points of the bounding box */
bool drag = false;
bool select_flag = false;
Rect rect; /* bounding box */
Mat img, roiImg; /* roiImg - the part of the image in the bounding box */

void mouseHandler(int event, int x, int y, int flags, void* param){
    if (event == CV_EVENT_LBUTTONDOWN && !drag){
        /* left button clicked. ROI selection begins */
        point1 = Point(x, y);
        drag = true;
    }

    if (event == CV_EVENT_MOUSEMOVE && drag){
        /* mouse dragged. ROI being selected */
        Mat img1 = img.clone();
        point2 = Point(x, y);
        rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
        imshow("image", img1);
    }

    if (event == CV_EVENT_LBUTTONUP && drag){
        point2 = Point(x, y);
        rect = Rect(point1.x,point1.y,x-point1.x,y-point1.y);
        drag = false;
        roiImg = img(rect);
    }

    if (event == CV_EVENT_LBUTTONUP){
       /* ROI selected */
        select_flag = true;
        drag = false;
    }
}

int main(int argc, char* argv[]){
  if(argc < 2){
    printf("usage: Magic <Video_Path> [output_dir] [skip_frames] [background]\n");
  }

  std::string output;
  if(argc >= 3) {
    output = argv[2];
  } else {
    output = ".";
  }

  int skip_frames = 0;
  if(argc >= 4) {
    skip_frames = std::atoi(argv[3]);
  }

  VideoCapture cap(argv[1]); // load the video
  if(!cap.isOpened())  // check if we succeeded
        return -1;

  // Write some info about File
  int frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
  double fps = cap.get(CV_CAP_PROP_FPS);
  printf("Number of Frames: %d\n", frames);
  printf("FPS: %f\n", fps);

  // Contains the working image
  Mat dst, in, temp;

  if(argc >= 5) {
    in = imread(argv[4]);
  } else {
    cap >> in;
  }

  img = in.clone();
  imshow("image", img);
  int k;
  while(1){
    cvSetMouseCallback("image", mouseHandler, NULL);
    if (select_flag){
        imshow("ROI", roiImg);  //show the image bounded by the box
    }
    rectangle(img, rect, CV_RGB(255, 0, 0), 3, 8, 0);
    imshow("image", img);
    k = waitKey(10);
    // if(k != -1) {
    //   printf("Key pressed %d\n", k);
    // }
    if (k == 27){ //ESC
        break;
    }
  }

  waitKey(1);
  destroyAllWindows();
  waitKey(1);

  if(!select_flag){
    rect = Rect(0,0,img.cols, img.rows);
  }

  // Background
  // TODO: support loading from file
  temp = in(rect);
  Mat background;
  cvtColor(temp, background, CV_RGB2GRAY);

  //Set image parameter
  vector<int> imageout_params;
  imwrite(output + "/bg.tiff", background, imageout_params);

  std::vector<Point2i> points;
  Point2f center;
  float radius;

  std::ofstream fs (output + "/positions.csv", std::ofstream::out);
  fs << "Frame,Time,Radius,x,y\n";

  for(int i = 0; i <= frames-1;i++){
    cap >> in;
    if(i > skip_frames) {
    temp = in(rect);
    cvtColor(temp, dst, CV_RGB2GRAY, 0);
    absdiff(dst, background, temp);
    threshold(temp, dst, 30, 255, THRESH_BINARY);

    points.clear();
    findNonZero(dst, points);
    minEnclosingCircle(points, center, radius);

    fs << i <<","<< i/fps <<","<< radius <<","<< center.x <<","<< center.y << "\n";
    std::cout << "\r" << i << "/" << frames;
    // imwrite(output + "/test-"+ std::to_string(i)+".tiff", dst, imageout_params);
    }
  }

  fs << std::endl;
  fs.close();
}<commit_msg>add hough transform on background for petridish detection<commit_after>#include "magic.h"

using namespace cv;

Point point1, point2; /* vertical points of the bounding box */
bool drag = false;
bool select_flag = false;
Rect rect; /* bounding box */
Mat img, roiImg; /* roiImg - the part of the image in the bounding box */

void mouseHandler(int event, int x, int y, int flags, void* param){
    if (event == CV_EVENT_LBUTTONDOWN && !drag){
        /* left button clicked. ROI selection begins */
        point1 = Point(x, y);
        drag = true;
    }

    if (event == CV_EVENT_MOUSEMOVE && drag){
        /* mouse dragged. ROI being selected */
        Mat img1 = img.clone();
        point2 = Point(x, y);
        rectangle(img1, point1, point2, CV_RGB(255, 0, 0), 3, 8, 0);
        imshow("image", img1);
    }

    if (event == CV_EVENT_LBUTTONUP && drag){
        point2 = Point(x, y);
        rect = Rect(point1.x,point1.y,x-point1.x,y-point1.y);
        drag = false;
        roiImg = img(rect);
    }

    if (event == CV_EVENT_LBUTTONUP){
       /* ROI selected */
        select_flag = true;
        drag = false;
    }
}

int main(int argc, char* argv[]){
  if(argc < 2){
    printf("usage: Magic <Video_Path> [output_dir] [skip_frames] [background]\n");
  }

  std::string output;
  if(argc >= 3) {
    output = argv[2];
  } else {
    output = ".";
  }

  int skip_frames = 0;
  if(argc >= 4) {
    skip_frames = std::atoi(argv[3]);
  }

  VideoCapture cap(argv[1]); // load the video
  if(!cap.isOpened())  // check if we succeeded
        return -1;

  // Write some info about File
  int frames = cap.get(CV_CAP_PROP_FRAME_COUNT);
  double fps = cap.get(CV_CAP_PROP_FPS);
  printf("Number of Frames: %d\n", frames);
  printf("FPS: %f\n", fps);

  // Contains the working image
  Mat dst, in, temp;

  if(argc >= 5) {
    in = imread(argv[4]);
  } else {
    cap >> in;
  }

  img = in.clone();
  imshow("image", img);
  int k;
  while(1){
    cvSetMouseCallback("image", mouseHandler, NULL);
    if (select_flag){
        imshow("ROI", roiImg);  //show the image bounded by the box
    }
    rectangle(img, rect, CV_RGB(255, 0, 0), 3, 8, 0);
    imshow("image", img);
    k = waitKey(10);
    // if(k != -1) {
    //   printf("Key pressed %d\n", k);
    // }
    if (k == 27){ //ESC
        destroyAllWindows();
        waitKey(1);
        break;
    }
  }

  if(!select_flag){
    rect = Rect(0,0,img.cols, img.rows);
  }

  // Background
  temp = in(rect);
  Mat background;
  cvtColor(temp, background, CV_RGB2GRAY);

  vector<Vec3f> circles;

  /// Apply the Hough Transform to find the circles
  HoughCircles(background, circles, CV_HOUGH_GRADIENT, 1, 100, 200, 100, 0, 0);

  /// Draw the circles detected
  for( size_t i = 0; i < circles.size(); i++ )
  {
      Point2f center(circles[i][0], circles[i][1]);
      float radius = circles[i][2];
      // circle center
      circle(temp, center, 3, Scalar(0,255,0), -1, 8, 0 );
      // circle outline
      circle(temp, center, radius, Scalar(0,0,255), 3, 8, 0 );
      printf("Circle %d with r=%f at x=%f, y=%f\n", i, radius, center.x, center.y);
   }

  imshow("image", temp);
  waitKey(0);
  destroyWindow("image");
  waitKey(1);

  //Set image parameter
  vector<int> imageout_params;
  imwrite(output + "/bg_circle.tiff", temp, imageout_params);
  imwrite(output + "/bg.tiff", background, imageout_params);

  std::vector<Point2i> points;
  Point2f center;
  float radius;

  std::ofstream fs (output + "/positions.csv", std::ofstream::out);
  fs << "Frame,Time,Radius,x,y\n";

  for(int i = 0; i <= frames-1;i++){
    cap >> in;
    if(i > skip_frames) {
    temp = in(rect);
    cvtColor(temp, dst, CV_RGB2GRAY, 0);
    absdiff(dst, background, temp);
    threshold(temp, dst, 30, 255, THRESH_BINARY);

    points.clear();
    findNonZero(dst, points);
    minEnclosingCircle(points, center, radius);

    fs << i <<","<< i/fps <<","<< radius <<","<< center.x <<","<< center.y << "\n";
    std::cout << "\r" << i << "/" << frames;
    // imwrite(output + "/test-"+ std::to_string(i)+".tiff", dst, imageout_params);
    }
  }

  fs << std::endl;
  fs.close();
}<|endoftext|>


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

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <com/sun/star/i18n/WordType.hpp>
#include <com/sun/star/i18n/BreakType.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/CharType.hpp>
#include <com/sun/star/i18n/XLocaleData.hpp>
#include <cppuhelper/implbase2.hxx> // helper for implementations

#include <vector>

namespace com { namespace sun { namespace star { namespace i18n {

//  ----------------------------------------------------
//  class BreakIterator
//  ----------------------------------------------------
class BreakIteratorImpl : public cppu::WeakImplHelper2
<
    XBreakIterator,
    com::sun::star::lang::XServiceInfo
>
{
public:
    BreakIteratorImpl( const com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory >& rxMSF );
    BreakIteratorImpl();
    ~BreakIteratorImpl();

    virtual sal_Int32 SAL_CALL nextCharacters( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& rLocale, sal_Int16 nCharacterIteratorMode, sal_Int32 nCount,
        sal_Int32& nDone ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL previousCharacters( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 nCharacterIteratorMode, sal_Int32 nCount,
        sal_Int32& nDone ) throw(com::sun::star::uno::RuntimeException);

    virtual Boundary SAL_CALL previousWord( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType) throw(com::sun::star::uno::RuntimeException);
    virtual Boundary SAL_CALL nextWord( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType) throw(com::sun::star::uno::RuntimeException);
    virtual Boundary SAL_CALL getWordBoundary( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType, sal_Bool bDirection )
        throw(com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL isBeginWord( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL isEndWord( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getWordType( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale ) throw(com::sun::star::uno::RuntimeException);

    virtual sal_Int32 SAL_CALL beginOfSentence( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL endOfSentence( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale ) throw(com::sun::star::uno::RuntimeException);

    virtual LineBreakResults SAL_CALL getLineBreak( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int32 nMinBreakPos,
        const LineBreakHyphenationOptions& hOptions, const LineBreakUserOptions& bOptions )
        throw(com::sun::star::uno::RuntimeException);

    virtual sal_Int16 SAL_CALL getScriptType( const rtl::OUString& Text, sal_Int32 nPos )
        throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL beginOfScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL endOfScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL previousScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL nextScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);

    virtual sal_Int32 SAL_CALL beginOfCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL endOfCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL previousCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL nextCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);

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

    static sal_Int16 SAL_CALL getScriptClass(sal_Unicode cChar );
protected:
    Boundary result; // for word break iterator

private :

    struct lookupTableItem {
        lookupTableItem(const com::sun::star::lang::Locale& _aLocale, com::sun::star::uno::Reference < XBreakIterator >& _xBI) : aLocale(_aLocale), xBI(_xBI) {};
        com::sun::star::lang::Locale aLocale;
        com::sun::star::uno::Reference < XBreakIterator > xBI;
    };
    std::vector<lookupTableItem*> lookupTable;
    com::sun::star::lang::Locale aLocale;
    com::sun::star::uno::Reference < XBreakIterator > xBI;

    com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xMSF;
    sal_Bool SAL_CALL createLocaleSpecificBreakIterator( const rtl::OUString& aLocaleName )
        throw( com::sun::star::uno::RuntimeException );
    com::sun::star::uno::Reference < XBreakIterator > SAL_CALL getLocaleSpecificBreakIterator( const com::sun::star::lang::Locale& rLocale )
        throw( com::sun::star::uno::RuntimeException );
    const com::sun::star::lang::Locale& SAL_CALL getLocaleByScriptType(const com::sun::star::lang::Locale& rLocale, const rtl::OUString& Text,
        sal_Int32 nStartPos, sal_Bool forward, sal_Bool skipWhiteSpace)
        throw(com::sun::star::uno::RuntimeException);

};

} // i18n
} // star
} // sun
} // com

#endif // _I18N_BREAKITERATOR_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.54); FILE MERGED 2005/09/05 17:47:21 rt 1.5.54.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: breakiteratorImpl.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 16:46:40 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _I18N_BREAKITERATOR_HXX_
#define _I18N_BREAKITERATOR_HXX_

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <com/sun/star/i18n/WordType.hpp>
#include <com/sun/star/i18n/BreakType.hpp>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/CharType.hpp>
#include <com/sun/star/i18n/XLocaleData.hpp>
#include <cppuhelper/implbase2.hxx> // helper for implementations

#include <vector>

namespace com { namespace sun { namespace star { namespace i18n {

//  ----------------------------------------------------
//  class BreakIterator
//  ----------------------------------------------------
class BreakIteratorImpl : public cppu::WeakImplHelper2
<
    XBreakIterator,
    com::sun::star::lang::XServiceInfo
>
{
public:
    BreakIteratorImpl( const com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory >& rxMSF );
    BreakIteratorImpl();
    ~BreakIteratorImpl();

    virtual sal_Int32 SAL_CALL nextCharacters( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& rLocale, sal_Int16 nCharacterIteratorMode, sal_Int32 nCount,
        sal_Int32& nDone ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL previousCharacters( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 nCharacterIteratorMode, sal_Int32 nCount,
        sal_Int32& nDone ) throw(com::sun::star::uno::RuntimeException);

    virtual Boundary SAL_CALL previousWord( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType) throw(com::sun::star::uno::RuntimeException);
    virtual Boundary SAL_CALL nextWord( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType) throw(com::sun::star::uno::RuntimeException);
    virtual Boundary SAL_CALL getWordBoundary( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType, sal_Bool bDirection )
        throw(com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL isBeginWord( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL isEndWord( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 WordType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int16 SAL_CALL getWordType( const rtl::OUString& Text, sal_Int32 nPos,
        const com::sun::star::lang::Locale& nLocale ) throw(com::sun::star::uno::RuntimeException);

    virtual sal_Int32 SAL_CALL beginOfSentence( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL endOfSentence( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale ) throw(com::sun::star::uno::RuntimeException);

    virtual LineBreakResults SAL_CALL getLineBreak( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int32 nMinBreakPos,
        const LineBreakHyphenationOptions& hOptions, const LineBreakUserOptions& bOptions )
        throw(com::sun::star::uno::RuntimeException);

    virtual sal_Int16 SAL_CALL getScriptType( const rtl::OUString& Text, sal_Int32 nPos )
        throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL beginOfScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL endOfScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL previousScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL nextScript( const rtl::OUString& Text, sal_Int32 nStartPos,
        sal_Int16 ScriptType ) throw(com::sun::star::uno::RuntimeException);

    virtual sal_Int32 SAL_CALL beginOfCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL endOfCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL previousCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL nextCharBlock( const rtl::OUString& Text, sal_Int32 nStartPos,
        const com::sun::star::lang::Locale& nLocale, sal_Int16 CharType ) throw(com::sun::star::uno::RuntimeException);

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

    static sal_Int16 SAL_CALL getScriptClass(sal_Unicode cChar );
protected:
    Boundary result; // for word break iterator

private :

    struct lookupTableItem {
        lookupTableItem(const com::sun::star::lang::Locale& _aLocale, com::sun::star::uno::Reference < XBreakIterator >& _xBI) : aLocale(_aLocale), xBI(_xBI) {};
        com::sun::star::lang::Locale aLocale;
        com::sun::star::uno::Reference < XBreakIterator > xBI;
    };
    std::vector<lookupTableItem*> lookupTable;
    com::sun::star::lang::Locale aLocale;
    com::sun::star::uno::Reference < XBreakIterator > xBI;

    com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xMSF;
    sal_Bool SAL_CALL createLocaleSpecificBreakIterator( const rtl::OUString& aLocaleName )
        throw( com::sun::star::uno::RuntimeException );
    com::sun::star::uno::Reference < XBreakIterator > SAL_CALL getLocaleSpecificBreakIterator( const com::sun::star::lang::Locale& rLocale )
        throw( com::sun::star::uno::RuntimeException );
    const com::sun::star::lang::Locale& SAL_CALL getLocaleByScriptType(const com::sun::star::lang::Locale& rLocale, const rtl::OUString& Text,
        sal_Int32 nStartPos, sal_Bool forward, sal_Bool skipWhiteSpace)
        throw(com::sun::star::uno::RuntimeException);

};

} // i18n
} // star
} // sun
} // com

#endif // _I18N_BREAKITERATOR_HXX_
<|endoftext|>


<commit_before><commit_msg>remove "expire time" check / function<commit_after><|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief Delegate implementation for the `leaf` plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

#include <numeric>

#include <kdbassert.h>
#include <kdbease.h>
#include <kdblogger.h>

#include "leaf_delegate.hpp"

using std::accumulate;
using std::ignore;
using std::make_pair;
using std::pair;
using std::range_error;
using std::string;
using std::tie;

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

namespace elektra
{
using CppKey = kdb::Key;

/**
 * @brief This function splits the given keyset into directory leaves (marked with `DIRECTORY_POSTFIX`) and other keys.
 *
 * @param input The function searches for directory leaves in this key set.
 *
 * @return A pair of key sets, where the first key set contains all directory leaves and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitDirectoryLeavesOther (CppKeySet const & input)
{
	CppKeySet directoryLeaves;
	CppKeySet other;

	for (auto key : input)
	{
		if (key.getBaseName () == DIRECTORY_POSTFIX)
		{
			directoryLeaves.append (key);
		}
		else
		{
			other.append (key);
		}
	}
	return make_pair (directoryLeaves, other);
}

/**
 * @brief This function splits the given keyset into array leaves (first element of an array parent) and other keys.
 *
 * @param input The function searches for array leaves in this key set.
 *
 * @return A pair of key sets, where the first key set contains all array leaves and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitArrayLeavesOther (CppKeySet const & arrayParents, CppKeySet const & keys)
{
	bool isFirstElement = false;
	CppKeySet firstElements;
	CppKeySet others;

	for (auto key : keys)
	{
		(isFirstElement ? firstElements : others).append (key);
		isFirstElement = arrayParents.lookup (key);
	}

	return make_pair (firstElements, others);
}

/**
 * @brief This function removes the basename (last level) from the given keys.
 *
 * @param keys This parameter contains the keys for which this function removes the basename.
 *
 * @return A copy of the input, where the last level of each key was removed
 */
CppKeySet removeBaseName (CppKeySet const & keys)
{
	CppKeySet directories;

	for (auto key : keys)
	{
		CppKey directory = key.dup ();
		keySetBaseName (*directory, 0);
		directories.append (directory);
	}
	return directories;
}

/**
 * @brief This function returns a modified copy of `child`, where child is directly below `parent`.
 *
 * For example, if `child` has the name `user/parent/level1/level2/level3` and parent has the name `user/parent`, then the function will
 * return a key with the name `user/parent/level1`.
 *
 * @pre The key `child` has to be below `parent`.
 *
 * @param parent This parameter specifies a parent key of `child`.
 * @param keys This variable stores a child key of `parent`.
 *
 * @return A copy of `child` that is directly below `parent`
 */
CppKey convertToDirectChild (CppKey const & parent, CppKey const & child)
{
	ELEKTRA_ASSERT (child.isBelow (parent), "The key `child` is not located below `parent`");

	CppKey directChild = child.dup ();
	while (!directChild.isDirectBelow (parent))
	{
		keySetBaseName (*directChild, 0);
	}
	return directChild;
}

/**
 * @brief This function determines if the given key is an array parent.
 *
 * @param parent This parameter specifies a possible array parent.
 * @param keys This variable stores the key set of `parent`.
 *
 * @retval true If `parent` is the parent key of an array
 * @retval false Otherwise
 */
bool isArrayParent (CppKey const & parent, CppKeySet const & keys)
{
	CppKeySet children = accumulate (keys.begin (), keys.end (), CppKeySet{}, [&parent](CppKeySet collected, CppKey key) {
		if (key.isBelow (parent)) collected.append (key);
		return collected;
	});

	for (auto child : children)
	{
		CppKey directChild = convertToDirectChild (parent, child);
		if (elektraArrayValidateName (*directChild) < 0) return false;
	}

	return true;
}

/**
 * @brief Split `keys` into two key sets, one for array parents and one for all other keys.
 *
 * @param keys This parameter contains the key set this function splits.
 *
 * @return A pair of key sets, where the first key set contains all array parents and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitArrayParentsOther (CppKeySet const & keys)
{
	CppKeySet arrayParents;
	CppKeySet others;

	keys.rewind ();
	CppKey previous;
	for (previous = keys.next (); keys.next (); previous = keys.current ())
	{
		bool previousIsArray =
			previous.hasMeta ("array") ||
			(keys.current ().isBelow (previous) && keys.current ().getBaseName ()[0] == '#' && isArrayParent (previous, keys));

		(previousIsArray ? arrayParents : others).append (previous);
	}
	(previous.hasMeta ("array") ? arrayParents : others).append (previous);

	ELEKTRA_ASSERT (arrayParents.size () + others.size () == keys.size (),
			"Number of keys in split key sets: %zu ≠ number in given key set %zu", arrayParents.size () + others.size (),
			keys.size ());

	return make_pair (arrayParents, others);
}

/**
 * @brief This function splits `keys` into two key sets, one for array parents and elements, and the other one for all other keys.
 *
 * @param arrayParents This key set contains a (copy) of all array parents of `keys`.
 * @param keys This parameter contains the key set this function splits.
 *
 * @return A pair of key sets, where the first key set contains all array parents and elements,
 *         and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitArrayOther (CppKeySet const & arrayParents, CppKeySet const & keys)
{
	CppKeySet others = keys.dup ();
	CppKeySet arrays;

	for (auto parent : arrayParents)
	{
		arrays.append (others.cut (parent));
	}

	return make_pair (arrays, others);
}

/**
 * @brief This function changes an array index of the given array element by one.
 *
 * @param parent This key set stores an array parent of `element`. The function will change the index of `element` that is directly below
 *               this key.
 * @param element This parameter stores an array element.
 * @param increment This boolean parameter specifies if the function should increase or decrease the index by one.
 *
 * @return A copy of `element`, where the index below `parent` was increased or decreased by one
 */
CppKey changeArrayIndexByOne (CppKey const & parent, CppKey const & element, bool increment = true)
{
	CppKey elementNewIndex = convertToDirectChild (parent, element);
	string postfix = elektraKeyGetRelativeName (*element, *elementNewIndex);

	if (increment ? elektraArrayIncName (*elementNewIndex) : elektraArrayDecName (*elementNewIndex))
	{
		throw range_error (string ("Unable to ") + (increment ? "increment" : "decrement") + " index of key “" +
				   elementNewIndex.getName () + "”");
	}
	elementNewIndex.addName (postfix);

	ELEKTRA_LOG_DEBUG ("New name of “%s” is “%s”", element.getName ().c_str (), elementNewIndex.getName ().c_str ());

	return elementNewIndex;
}

/**
 * @brief Increase the array index of array elements by one.
 *
 * Since it is also possible that one of the array parents is part of another array, this function also updates the indices of the given
 * array parents.
 *
 * @param parents This parameter contains the array parents for which this function increases the index by one.
 * @param arrays This variable stores the arrays elements this function updates.
 *
 * @return A pair containing a copy of `parents` and `arrays`, where all indices specified by `parents` are increased by one
 */
pair<CppKeySet, CppKeySet> increaseArrayIndices (CppKeySet const & parents, CppKeySet const & arrays)
{
	CppKeySet arraysIncreasedIndex = arrays.dup ();
	CppKeySet arrayParents = parents.dup ();
	CppKeySet updatedParents = parents.dup ();

	while (CppKey parent = arrayParents.pop ())
	{
		ELEKTRA_LOG_DEBUG ("Increase indices for array parent “%s”", parent.getName ().c_str ());

		CppKeySet newArrays;
		for (auto key : arraysIncreasedIndex)
		{
			if (key.isBelow (parent))
			{
				auto updated = changeArrayIndexByOne (parent, key);
				if (updatedParents.lookup (key, KDB_O_POP)) updatedParents.append (updated);
				newArrays.append (updated);
			}
			else
			{
				newArrays.append (key);
			}
		}
		arraysIncreasedIndex = newArrays;
	}

	return make_pair (updatedParents, arraysIncreasedIndex);
}

/**
 * @brief Split `keys` into two key sets, one for directories (keys without children) and one for all other keys.
 *
 * @param keys This parameter contains the key set this function splits.
 *
 * @return A pair of key sets, where the first key set contains all directories and the second key set contains all leaves
 */
pair<CppKeySet, CppKeySet> splitDirectoriesLeaves (CppKeySet const & keys)
{
	CppKeySet leaves;
	CppKeySet directories;

	keys.rewind ();
	CppKey previous;
	for (previous = keys.next (); keys.next (); previous = keys.current ())
	{
		if (keys.current ().isBelow (previous))
		{
			directories.append (previous);
		}
		else
		{
			leaves.append (previous);
		}
	}
	leaves.append (previous);

	return make_pair (directories, leaves);
}

/**
 * @brief Convert all keys in `parents` to an empty array parent and an array element with index `#0` storing the data of the old key.
 *
 * @param parents This parameter contains the set of array parent this function converts.
 *
 * @return A key set containing only empty array parents and corresponding array elements storing the values of the old array parent
 */
CppKeySet convertArrayParentsToLeaves (CppKeySet const & parents)
{
	CppKeySet converted;

	for (auto parent : parents)
	{
		CppKey directory{ parent.getName (), KS_END };
		CppKey leaf = parent.dup ();
		leaf.addBaseName ("#0");
		converted.append (directory);
		converted.append (leaf);
	}

	return converted;
}

/**
 * @brief Convert all keys in `directories` to an empty key and a leaf key containing the data of the old key.
 *
 * @param directories This parameter contains a set of directory keys this function converts.
 *
 * @return A key set containing only empty directory keys and corresponding leaf keys storing the values of the old directory keys
 */
CppKeySet convertDirectoriesToLeaves (CppKeySet const & directories)
{
	CppKeySet directoryLeaves;

	for (auto directory : directories)
	{
		CppKey emptyDirectory{ directory.getName (), KS_END };
		CppKey leaf = directory.dup ();
		leaf.addBaseName (DIRECTORY_POSTFIX);
		directoryLeaves.append (leaf);
		directoryLeaves.append (emptyDirectory);
	}

	return directoryLeaves;
}

// -- Class --------------------------------------------------------------------------------------------------------------------------------

/**
 * @brief This constructor creates a new delegate object used by the `leaf` plugin
 *
 * @param config This key set contains configuration values provided by the `leaf` plugin
 */
LeafDelegate::LeafDelegate (CppKeySet config ELEKTRA_UNUSED)
{
}

/**
 * @brief This method converts all leaf keys in the given key set to directory keys.
 *
 * @param keys This parameter specifies the key set this function converts.
 *
 * @retval ELEKTRA_PLUGIN_STATUS_SUCCESS If the plugin converted any value in the given key set
 * @retval ELEKTRA_PLUGIN_STATUS_NO_UPDATE If the plugin did not update `keys`
 */
int LeafDelegate::convertToDirectories (CppKeySet & keys)
{
	CppKeySet directoryLeaves;
	CppKeySet nonDirectoryLeaves;
	CppKeySet arrayParents;
	CppKeySet notArrayParents;
	CppKeySet arrays;
	CppKeySet arrayLeaves;
	CppKeySet maps;

	/**
	 * - Split array parents
	 * - Split first array child containing directory value prefix, others
	 * - Convert first array child back to array parent
	 * - Decrease index of arrays
	 * - Merge everything back together and convert directories to leaves
	 */

	tie (arrayParents, notArrayParents) = splitArrayParentsOther (keys);
	tie (arrays, maps) = splitArrayOther (arrayParents, keys);
	tie (arrayLeaves, arrays) = splitArrayLeavesOther (arrayParents, arrays);

	arrayParents = removeBaseName (arrayLeaves);

	tie (directoryLeaves, nonDirectoryLeaves) = splitDirectoryLeavesOther (notArrayParents);

	bool status = directoryLeaves.size () > 0 ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_NO_UPDATE;

	auto directories = removeBaseName (directoryLeaves);

	keys.clear ();
	keys.append (nonDirectoryLeaves);
	keys.append (directories);

	return status;
}

/**
 * @brief This method converts all directory keys in the given key set to leaf keys.
 *
 * @param keys This parameter specifies the key set this function converts.
 *
 * @retval ELEKTRA_PLUGIN_STATUS_SUCCESS If the plugin converted any value in the given key set
 * @retval ELEKTRA_PLUGIN_STATUS_NO_UPDATE If the plugin did not update `keys`
 */
int LeafDelegate::convertToLeaves (CppKeySet & keys)
{
	CppKeySet notArrayParents;
	CppKeySet arrayParents;
	CppKeySet arrays;
	CppKeySet nonArrays;
	CppKeySet directories;
	CppKeySet leaves;

	tie (arrayParents, ignore) = splitArrayParentsOther (keys);
	tie (arrays, nonArrays) = splitArrayOther (arrayParents, keys);

	tie (arrayParents, arrays) = increaseArrayIndices (arrayParents, arrays);
	notArrayParents.append (arrays);
	notArrayParents.append (nonArrays);
	notArrayParents = accumulate (notArrayParents.begin (), notArrayParents.end (), CppKeySet{},
				      [&arrayParents](CppKeySet collected, CppKey key) {
					      if (!arrayParents.lookup (key)) collected.append (key);
					      return collected;
				      });
	arrayParents = convertArrayParentsToLeaves (arrayParents);

	tie (directories, leaves) = splitDirectoriesLeaves (notArrayParents);
	bool status = directories.size () > 0 || arrayParents.size () > 0 ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_NO_UPDATE;

	auto directoryLeaves = convertDirectoriesToLeaves (directories);

	keys.clear ();
	keys.append (arrays);
	keys.append (arrayParents);
	keys.append (directoryLeaves);
	keys.append (leaves);

	return status;
}

} // end namespace elektra
<commit_msg>Leaf: Add function to decrease array indices<commit_after>/**
 * @file
 *
 * @brief Delegate implementation for the `leaf` plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

#include <numeric>

#include <kdbassert.h>
#include <kdbease.h>
#include <kdblogger.h>

#include "leaf_delegate.hpp"

using std::accumulate;
using std::ignore;
using std::make_pair;
using std::pair;
using std::range_error;
using std::string;
using std::tie;

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

namespace elektra
{
using CppKey = kdb::Key;

/**
 * @brief This function splits the given keyset into directory leaves (marked with `DIRECTORY_POSTFIX`) and other keys.
 *
 * @param input The function searches for directory leaves in this key set.
 *
 * @return A pair of key sets, where the first key set contains all directory leaves and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitDirectoryLeavesOther (CppKeySet const & input)
{
	CppKeySet directoryLeaves;
	CppKeySet other;

	for (auto key : input)
	{
		if (key.getBaseName () == DIRECTORY_POSTFIX)
		{
			directoryLeaves.append (key);
		}
		else
		{
			other.append (key);
		}
	}
	return make_pair (directoryLeaves, other);
}

/**
 * @brief This function splits the given keyset into array leaves (first element of an array parent) and other keys.
 *
 * @param input The function searches for array leaves in this key set.
 *
 * @return A pair of key sets, where the first key set contains all array leaves and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitArrayLeavesOther (CppKeySet const & arrayParents, CppKeySet const & keys)
{
	bool isFirstElement = false;
	CppKeySet firstElements;
	CppKeySet others;

	for (auto key : keys)
	{
		(isFirstElement ? firstElements : others).append (key);
		isFirstElement = arrayParents.lookup (key);
	}

	return make_pair (firstElements, others);
}

/**
 * @brief This function removes the basename (last level) from the given keys.
 *
 * @param keys This parameter contains the keys for which this function removes the basename.
 *
 * @return A copy of the input, where the last level of each key was removed
 */
CppKeySet removeBaseName (CppKeySet const & keys)
{
	CppKeySet directories;

	for (auto key : keys)
	{
		CppKey directory = key.dup ();
		keySetBaseName (*directory, 0);
		directories.append (directory);
	}
	return directories;
}

/**
 * @brief This function returns a modified copy of `child`, where child is directly below `parent`.
 *
 * For example, if `child` has the name `user/parent/level1/level2/level3` and parent has the name `user/parent`, then the function will
 * return a key with the name `user/parent/level1`.
 *
 * @pre The key `child` has to be below `parent`.
 *
 * @param parent This parameter specifies a parent key of `child`.
 * @param keys This variable stores a child key of `parent`.
 *
 * @return A copy of `child` that is directly below `parent`
 */
CppKey convertToDirectChild (CppKey const & parent, CppKey const & child)
{
	ELEKTRA_ASSERT (child.isBelow (parent), "The key `child` is not located below `parent`");

	CppKey directChild = child.dup ();
	while (!directChild.isDirectBelow (parent))
	{
		keySetBaseName (*directChild, 0);
	}
	return directChild;
}

/**
 * @brief This function determines if the given key is an array parent.
 *
 * @param parent This parameter specifies a possible array parent.
 * @param keys This variable stores the key set of `parent`.
 *
 * @retval true If `parent` is the parent key of an array
 * @retval false Otherwise
 */
bool isArrayParent (CppKey const & parent, CppKeySet const & keys)
{
	CppKeySet children = accumulate (keys.begin (), keys.end (), CppKeySet{}, [&parent](CppKeySet collected, CppKey key) {
		if (key.isBelow (parent)) collected.append (key);
		return collected;
	});

	for (auto child : children)
	{
		CppKey directChild = convertToDirectChild (parent, child);
		if (elektraArrayValidateName (*directChild) < 0) return false;
	}

	return true;
}

/**
 * @brief Split `keys` into two key sets, one for array parents and one for all other keys.
 *
 * @param keys This parameter contains the key set this function splits.
 *
 * @return A pair of key sets, where the first key set contains all array parents and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitArrayParentsOther (CppKeySet const & keys)
{
	CppKeySet arrayParents;
	CppKeySet others;

	keys.rewind ();
	CppKey previous;
	for (previous = keys.next (); keys.next (); previous = keys.current ())
	{
		bool previousIsArray =
			previous.hasMeta ("array") ||
			(keys.current ().isBelow (previous) && keys.current ().getBaseName ()[0] == '#' && isArrayParent (previous, keys));

		(previousIsArray ? arrayParents : others).append (previous);
	}
	(previous.hasMeta ("array") ? arrayParents : others).append (previous);

	ELEKTRA_ASSERT (arrayParents.size () + others.size () == keys.size (),
			"Number of keys in split key sets: %zu ≠ number in given key set %zu", arrayParents.size () + others.size (),
			keys.size ());

	return make_pair (arrayParents, others);
}

/**
 * @brief This function splits `keys` into two key sets, one for array parents and elements, and the other one for all other keys.
 *
 * @param arrayParents This key set contains a (copy) of all array parents of `keys`.
 * @param keys This parameter contains the key set this function splits.
 *
 * @return A pair of key sets, where the first key set contains all array parents and elements,
 *         and the second key set contains all other keys
 */
pair<CppKeySet, CppKeySet> splitArrayOther (CppKeySet const & arrayParents, CppKeySet const & keys)
{
	CppKeySet others = keys.dup ();
	CppKeySet arrays;

	for (auto parent : arrayParents)
	{
		arrays.append (others.cut (parent));
	}

	return make_pair (arrays, others);
}

/**
 * @brief This function changes an array index of the given array element by one.
 *
 * @param parent This key set stores an array parent of `element`. The function will change the index of `element` that is directly below
 *               this key.
 * @param element This parameter stores an array element.
 * @param increment This boolean parameter specifies if the function should increase or decrease the index by one.
 *
 * @return A copy of `element`, where the index below `parent` was increased or decreased by one
 */
CppKey changeArrayIndexByOne (CppKey const & parent, CppKey const & element, bool increment = true)
{
	CppKey elementNewIndex = convertToDirectChild (parent, element);
	string postfix = elektraKeyGetRelativeName (*element, *elementNewIndex);

	if (increment ? elektraArrayIncName (*elementNewIndex) : elektraArrayDecName (*elementNewIndex))
	{
		throw range_error (string ("Unable to ") + (increment ? "increment" : "decrement") + " index of key “" +
				   elementNewIndex.getName () + "”");
	}
	elementNewIndex.addName (postfix);

	ELEKTRA_LOG_DEBUG ("New name of “%s” is “%s”", element.getName ().c_str (), elementNewIndex.getName ().c_str ());

	return elementNewIndex;
}

/**
 * @brief Decrease the array index of array elements by one.
 *
 * @param parents This parameter contains the array parents for which this function decrease the index by one.
 * @param arrays This variable stores the arrays elements (and parents) this function updates.
 *
 * @return A copy of `arrays`, where all indices specified by `parents` are decreased by one
 */
CppKeySet decreaseArrayIndices (CppKeySet const & parents, CppKeySet const & arrays)
{
	CppKeySet arraysIndexDecreased = arrays.dup ();
	CppKeySet arrayParents = parents.dup ();

	while (CppKey parent = arrayParents.pop ())
	{
		arraysIndexDecreased = accumulate (arraysIndexDecreased.begin (), arraysIndexDecreased.end (), CppKeySet{},
						   [&parent](CppKeySet collected, CppKey key) {
							   if (key.isBelow (parent)) changeArrayIndexByOne (parent, key, false);
							   collected.append (key);
							   return collected;
						   });
	}

	return arraysIndexDecreased;
}

/**
 * @brief Increase the array index of array elements by one.
 *
 * Since it is also possible that one of the array parents is part of another array, this function also updates the indices of the given
 * array parents.
 *
 * @param parents This parameter contains the array parents for which this function increases the index by one.
 * @param arrays This variable stores the arrays elements this function updates.
 *
 * @return A pair containing a copy of `parents` and `arrays`, where all indices specified by `parents` are increased by one
 */
pair<CppKeySet, CppKeySet> increaseArrayIndices (CppKeySet const & parents, CppKeySet const & arrays)
{
	CppKeySet arraysIncreasedIndex = arrays.dup ();
	CppKeySet arrayParents = parents.dup ();
	CppKeySet updatedParents = parents.dup ();

	while (CppKey parent = arrayParents.pop ())
	{
		ELEKTRA_LOG_DEBUG ("Increase indices for array parent “%s”", parent.getName ().c_str ());

		CppKeySet newArrays;
		for (auto key : arraysIncreasedIndex)
		{
			if (key.isBelow (parent))
			{
				auto updated = changeArrayIndexByOne (parent, key);
				if (updatedParents.lookup (key, KDB_O_POP)) updatedParents.append (updated);
				newArrays.append (updated);
			}
			else
			{
				newArrays.append (key);
			}
		}
		arraysIncreasedIndex = newArrays;
	}

	return make_pair (updatedParents, arraysIncreasedIndex);
}

/**
 * @brief Split `keys` into two key sets, one for directories (keys without children) and one for all other keys.
 *
 * @param keys This parameter contains the key set this function splits.
 *
 * @return A pair of key sets, where the first key set contains all directories and the second key set contains all leaves
 */
pair<CppKeySet, CppKeySet> splitDirectoriesLeaves (CppKeySet const & keys)
{
	CppKeySet leaves;
	CppKeySet directories;

	keys.rewind ();
	CppKey previous;
	for (previous = keys.next (); keys.next (); previous = keys.current ())
	{
		if (keys.current ().isBelow (previous))
		{
			directories.append (previous);
		}
		else
		{
			leaves.append (previous);
		}
	}
	leaves.append (previous);

	return make_pair (directories, leaves);
}

/**
 * @brief Convert all keys in `parents` to an empty array parent and an array element with index `#0` storing the data of the old key.
 *
 * @param parents This parameter contains the set of array parent this function converts.
 *
 * @return A key set containing only empty array parents and corresponding array elements storing the values of the old array parent
 */
CppKeySet convertArrayParentsToLeaves (CppKeySet const & parents)
{
	CppKeySet converted;

	for (auto parent : parents)
	{
		CppKey directory{ parent.getName (), KS_END };
		CppKey leaf = parent.dup ();
		leaf.addBaseName ("#0");
		converted.append (directory);
		converted.append (leaf);
	}

	return converted;
}

/**
 * @brief Convert all keys in `directories` to an empty key and a leaf key containing the data of the old key.
 *
 * @param directories This parameter contains a set of directory keys this function converts.
 *
 * @return A key set containing only empty directory keys and corresponding leaf keys storing the values of the old directory keys
 */
CppKeySet convertDirectoriesToLeaves (CppKeySet const & directories)
{
	CppKeySet directoryLeaves;

	for (auto directory : directories)
	{
		CppKey emptyDirectory{ directory.getName (), KS_END };
		CppKey leaf = directory.dup ();
		leaf.addBaseName (DIRECTORY_POSTFIX);
		directoryLeaves.append (leaf);
		directoryLeaves.append (emptyDirectory);
	}

	return directoryLeaves;
}

// -- Class --------------------------------------------------------------------------------------------------------------------------------

/**
 * @brief This constructor creates a new delegate object used by the `leaf` plugin
 *
 * @param config This key set contains configuration values provided by the `leaf` plugin
 */
LeafDelegate::LeafDelegate (CppKeySet config ELEKTRA_UNUSED)
{
}

/**
 * @brief This method converts all leaf keys in the given key set to directory keys.
 *
 * @param keys This parameter specifies the key set this function converts.
 *
 * @retval ELEKTRA_PLUGIN_STATUS_SUCCESS If the plugin converted any value in the given key set
 * @retval ELEKTRA_PLUGIN_STATUS_NO_UPDATE If the plugin did not update `keys`
 */
int LeafDelegate::convertToDirectories (CppKeySet & keys)
{
	CppKeySet directoryLeaves;
	CppKeySet nonDirectoryLeaves;
	CppKeySet arrayParents;
	CppKeySet notArrayParents;
	CppKeySet arrays;
	CppKeySet arrayLeaves;
	CppKeySet maps;

	/**
	 * - Split array parents
	 * - Split first array child containing directory value prefix, others
	 * - Convert first array child back to array parent
	 * - Decrease index of arrays
	 * - Merge everything back together and convert directories to leaves
	 */

	tie (arrayParents, notArrayParents) = splitArrayParentsOther (keys);
	tie (arrays, maps) = splitArrayOther (arrayParents, keys);
	tie (arrayLeaves, arrays) = splitArrayLeavesOther (arrayParents, arrays);

	arrayParents = removeBaseName (arrayLeaves);

	tie (directoryLeaves, nonDirectoryLeaves) = splitDirectoryLeavesOther (notArrayParents);

	bool status = directoryLeaves.size () > 0 ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_NO_UPDATE;

	auto directories = removeBaseName (directoryLeaves);

	keys.clear ();
	keys.append (nonDirectoryLeaves);
	keys.append (directories);

	return status;
}

/**
 * @brief This method converts all directory keys in the given key set to leaf keys.
 *
 * @param keys This parameter specifies the key set this function converts.
 *
 * @retval ELEKTRA_PLUGIN_STATUS_SUCCESS If the plugin converted any value in the given key set
 * @retval ELEKTRA_PLUGIN_STATUS_NO_UPDATE If the plugin did not update `keys`
 */
int LeafDelegate::convertToLeaves (CppKeySet & keys)
{
	CppKeySet notArrayParents;
	CppKeySet arrayParents;
	CppKeySet arrays;
	CppKeySet nonArrays;
	CppKeySet directories;
	CppKeySet leaves;

	tie (arrayParents, ignore) = splitArrayParentsOther (keys);
	tie (arrays, nonArrays) = splitArrayOther (arrayParents, keys);

	tie (arrayParents, arrays) = increaseArrayIndices (arrayParents, arrays);
	notArrayParents.append (arrays);
	notArrayParents.append (nonArrays);
	notArrayParents = accumulate (notArrayParents.begin (), notArrayParents.end (), CppKeySet{},
				      [&arrayParents](CppKeySet collected, CppKey key) {
					      if (!arrayParents.lookup (key)) collected.append (key);
					      return collected;
				      });
	arrayParents = convertArrayParentsToLeaves (arrayParents);

	tie (directories, leaves) = splitDirectoriesLeaves (notArrayParents);
	bool status = directories.size () > 0 || arrayParents.size () > 0 ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_NO_UPDATE;

	auto directoryLeaves = convertDirectoriesToLeaves (directories);

	keys.clear ();
	keys.append (arrays);
	keys.append (arrayParents);
	keys.append (directoryLeaves);
	keys.append (leaves);

	return status;
}

} // end namespace elektra
<|endoftext|>