<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: process_impl.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:59:24 $
 *
 *  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
 *
 ************************************************************************/

#include "osl/process.h"

#ifndef INCLUDED_LIMITS_H
#include <limits.h>
#define INCLUDED_LIMITS_H
#endif

#ifndef INCLUDED_PTHREAD_H
#include <pthread.h>
#define INCLUDED_PTHREAD_H
#endif

#ifndef INCLUDED_STDLIB_H
#include <stdlib.h>
#define INCLUDED_STDLIB_H
#endif

#ifndef INCLUDED_STRING_H
#include <string.h>
#define INCLUDED_STRING_H
#endif

#ifndef _OSL_DIAGNOSE_H_
#include "osl/diagnose.h"
#endif

#ifndef _OSL_FILE_H_
#include <osl/file.h>
#endif

#ifndef _OSL_MODULE_H_
#include "osl/module.h"
#endif

#ifndef _OSL_THREAD_H_
#include "osl/thread.h"
#endif

#ifndef _RTL_USTRING_HXX_
#include "rtl/ustring.hxx"
#endif

#ifndef _OSL_FILE_PATH_HELPER_H_
#include "file_path_helper.h"
#endif

#ifndef _OSL_UUNXAPI_H_
#include "uunxapi.h"
#endif

/***************************************
  osl_bootstrap_getExecutableFile_Impl().

  @internal
  @see rtl_bootstrap
  @see #i37371#

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

extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C();

#if defined(MACOSX)
#include <mach-o/dyld.h>

oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C()
{
    oslProcessError result = osl_Process_E_NotFound;

    char   buffer[PATH_MAX];
    size_t buflen = sizeof(buffer);

    if (_NSGetExecutablePath (buffer, &buflen) == 0)
    {
        /* Determine absolute path. */
        char abspath[PATH_MAX];
        if (realpath (buffer, abspath) != 0)
        {
            /* Convert from utf8 to unicode. */
            rtl_uString * pAbsPath = 0;
            rtl_string2UString (
                &(pAbsPath),
                abspath, rtl_str_getLength (abspath),
                RTL_TEXTENCODING_UTF8,
                OSTRING_TO_OUSTRING_CVTFLAGS);

            if (pAbsPath)
            {
                /* Convert from path to url. */
                if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
                {
                    /* Success. */
                    result = osl_Process_E_None;
                }
                rtl_uString_release (pAbsPath);
            }
        }
    }

    return (result);
}

#elif !defined(NO_DL_FUNCTIONS)
#include <dlfcn.h>

oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C()
{
    oslProcessError result = osl_Process_E_NotFound;

    /* Determine address of "main()" function. */
    void * addr = dlsym (RTLD_DEFAULT, "main");
    if (addr != 0)
    {
        /* Determine module URL. */
        if (osl_getModuleURLFromAddress (addr, ppFileURL))
        {
            /* Success. */
            result = osl_Process_E_None;
        }
    }

    return (result);
}

#else  /* NO_DL_FUNCTIONS */

oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C()
{
    /* Fallback to ordinary osl_getExecutableFile(). */
    return osl_getExecutableFile (ppFileURL);
}

#endif /* NO_DL_FUNCTIONS */

/***************************************
 CommandArgs_Impl.
 **************************************/
struct CommandArgs_Impl
{
    pthread_mutex_t m_mutex;
    sal_uInt32      m_nCount;
    rtl_uString **  m_ppArgs;
};

static struct CommandArgs_Impl g_command_args =
{
    PTHREAD_MUTEX_INITIALIZER,
    0,
    0
};

/***************************************
  osl_getExecutableFile().
 **************************************/
oslProcessError SAL_CALL osl_getExecutableFile (rtl_uString ** ppustrFile)
{
    oslProcessError result = osl_Process_E_NotFound;

    pthread_mutex_lock (&(g_command_args.m_mutex));
    if (g_command_args.m_nCount > 0)
    {
        /* CommandArgs set. Obtain argv[0]. */
        rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
        result = osl_Process_E_None;
    }
    pthread_mutex_unlock (&(g_command_args.m_mutex));

    return (result);
}

/***************************************
 osl_getCommandArgCount().
 **************************************/
sal_uInt32 SAL_CALL osl_getCommandArgCount (void)
{
    sal_uInt32 result = 0;

    pthread_mutex_lock (&(g_command_args.m_mutex));
    if (g_command_args.m_nCount > 0)
        result = g_command_args.m_nCount - 1;
    pthread_mutex_unlock (&(g_command_args.m_mutex));

    return (result);
}

/***************************************
 osl_getCommandArg().
 **************************************/
oslProcessError SAL_CALL osl_getCommandArg (sal_uInt32 nArg, rtl_uString ** strCommandArg)
{
    oslProcessError result = osl_Process_E_NotFound;

    pthread_mutex_lock (&(g_command_args.m_mutex));
    if (g_command_args.m_nCount > (nArg + 1))
    {
        rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
        result = osl_Process_E_None;
    }
    pthread_mutex_unlock (&(g_command_args.m_mutex));

    return (result);
}

/***************************************
 osl_setCommandArgs().
 **************************************/
void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
{
    pthread_mutex_lock (&(g_command_args.m_mutex));
    OSL_ENSURE (g_command_args.m_nCount == 0, "osl_setCommandArgs(): CommandArgs already set.");
    if (g_command_args.m_nCount == 0)
    {
        rtl_uString** ppArgs = (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
        if (ppArgs != 0)
        {
            rtl_TextEncoding encoding = osl_getThreadTextEncoding();
            for (int i = 0; i < argc; i++)
            {
                rtl_string2UString (
                    &(ppArgs[i]),
                    argv[i], rtl_str_getLength (argv[i]), encoding,
                    OSTRING_TO_OUSTRING_CVTFLAGS);
            }
            if (ppArgs[0] != 0)
            {
                /* see @ osl_getExecutableFile(). */
                if (rtl_ustr_indexOfChar (rtl_uString_getStr(ppArgs[0]), sal_Unicode('/')) == -1)
                {
                    const rtl::OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));

                    rtl_uString * pSearchPath = 0;
                    osl_getEnvironment (PATH.pData, &pSearchPath);
                    if (pSearchPath)
                    {
                        rtl_uString * pSearchResult = 0;
                        osl_searchPath (ppArgs[0], pSearchPath, &pSearchResult);
                        if (pSearchResult)
                        {
                            rtl_uString_assign (&(ppArgs[0]), pSearchResult);
                            rtl_uString_release (pSearchResult);
                        }
                        rtl_uString_release (pSearchPath);
                    }
                }

                rtl_uString * pArg0 = 0;
                if (realpath_u (ppArgs[0], &pArg0))
                {
                    osl_getFileURLFromSystemPath (pArg0, &(ppArgs[0]));
                    rtl_uString_release (pArg0);
                }
            }
            g_command_args.m_nCount = argc;
            g_command_args.m_ppArgs = ppArgs;
        }
    }
    pthread_mutex_unlock (&(g_command_args.m_mutex));
}

/***************************************
 osl_getEnvironment().
 **************************************/
oslProcessError SAL_CALL osl_getEnvironment(rtl_uString* pustrEnvVar, rtl_uString** ppustrValue)
{
    oslProcessError  result   = osl_Process_E_NotFound;
    rtl_TextEncoding encoding = osl_getThreadTextEncoding();
    rtl_String* pstr_env_var  = 0;

    OSL_PRECOND(pustrEnvVar, "osl_getEnvironment(): Invalid parameter");
    OSL_PRECOND(ppustrValue, "osl_getEnvironment(): Invalid parameter");

    rtl_uString2String(
        &pstr_env_var,
        rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
        OUSTRING_TO_OSTRING_CVTFLAGS);
    if (pstr_env_var != 0)
    {
        const char* p_env_var = getenv (rtl_string_getStr (pstr_env_var));
        if (p_env_var != 0)
        {
            rtl_string2UString(
                ppustrValue,
                p_env_var, strlen(p_env_var), encoding,
                OSTRING_TO_OUSTRING_CVTFLAGS);
            OSL_ASSERT(*ppustrValue != NULL);

            result = osl_Process_E_None;
        }
        rtl_string_release(pstr_env_var);
    }

    return (result);
}

/***************************************
 osl_getProcessWorkingDir().
 **************************************/
oslProcessError SAL_CALL osl_getProcessWorkingDir(rtl_uString **ppustrWorkingDir)
{
    oslProcessError result = osl_Process_E_Unknown;
    char buffer[PATH_MAX];

    OSL_PRECOND(ppustrWorkingDir, "osl_getProcessWorkingDir(): Invalid parameter");

    if (getcwd (buffer, sizeof(buffer)) != 0)
    {
        rtl_uString* ustrTmp = 0;

        rtl_string2UString(
            &ustrTmp,
            buffer, strlen(buffer), osl_getThreadTextEncoding(),
            OSTRING_TO_OUSTRING_CVTFLAGS);
        if (ustrTmp != 0)
        {
            if (osl_getFileURLFromSystemPath (ustrTmp, ppustrWorkingDir) == osl_File_E_None)
                result = osl_Process_E_None;
            rtl_uString_release (ustrTmp);
        }
    }

    return (result);
}

/******************************************************************************
 *
 *              new functions to set/return the current process locale
 *
 *****************************************************************************/

struct ProcessLocale_Impl
{
    pthread_mutex_t m_mutex;
    rtl_Locale *    m_pLocale;
};

static struct ProcessLocale_Impl g_process_locale =
{
    PTHREAD_MUTEX_INITIALIZER,
    0
};

extern "C" void _imp_getProcessLocale( rtl_Locale ** );
extern "C" int  _imp_setProcessLocale( rtl_Locale * );

/**********************************************
 osl_getProcessLocale().
 *********************************************/
oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
{
    OSL_PRECOND(ppLocale, "osl_getProcessLocale(): Invalid parameter.");

    pthread_mutex_lock(&(g_process_locale.m_mutex));

    if (g_process_locale.m_pLocale == 0)
        _imp_getProcessLocale (&(g_process_locale.m_pLocale));
    *ppLocale = g_process_locale.m_pLocale;

    pthread_mutex_unlock (&(g_process_locale.m_mutex));

    return (osl_Process_E_None);
}

/**********************************************
 osl_setProcessLocale().
 *********************************************/
oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
{
    oslProcessError result = osl_Process_E_Unknown;

    OSL_PRECOND(pLocale, "osl_setProcessLocale(): Invalid parameter.");

    pthread_mutex_lock(&(g_process_locale.m_mutex));
    if (_imp_setProcessLocale (pLocale) == 0)
    {
        g_process_locale.m_pLocale = pLocale;
        result = osl_Process_E_None;
    }
    pthread_mutex_unlock (&(g_process_locale.m_mutex));

    return (result);
}
<commit_msg>INTEGRATION: CWS macosxgcc4 (1.8.64); FILE MERGED 2005/09/20 03:34:38 fheckl 1.8.64.2: RESYNC: (1.8-1.9); FILE MERGED 2005/09/19 19:39:21 fheckl 1.8.64.1: Adding some casts necessary for compilation to succeed with gcc4 on MacOSX (i49046)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: process_impl.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-10-17 14:25:34 $
 *
 *  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
 *
 ************************************************************************/

#include "osl/process.h"

#ifndef INCLUDED_LIMITS_H
#include <limits.h>
#define INCLUDED_LIMITS_H
#endif

#ifndef INCLUDED_PTHREAD_H
#include <pthread.h>
#define INCLUDED_PTHREAD_H
#endif

#ifndef INCLUDED_STDLIB_H
#include <stdlib.h>
#define INCLUDED_STDLIB_H
#endif

#ifndef INCLUDED_STRING_H
#include <string.h>
#define INCLUDED_STRING_H
#endif

#ifndef _OSL_DIAGNOSE_H_
#include "osl/diagnose.h"
#endif

#ifndef _OSL_FILE_H_
#include <osl/file.h>
#endif

#ifndef _OSL_MODULE_H_
#include "osl/module.h"
#endif

#ifndef _OSL_THREAD_H_
#include "osl/thread.h"
#endif

#ifndef _RTL_USTRING_HXX_
#include "rtl/ustring.hxx"
#endif

#ifndef _OSL_FILE_PATH_HELPER_H_
#include "file_path_helper.h"
#endif

#ifndef _OSL_UUNXAPI_H_
#include "uunxapi.h"
#endif

/***************************************
  osl_bootstrap_getExecutableFile_Impl().

  @internal
  @see rtl_bootstrap
  @see #i37371#

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

extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C();

#if defined(MACOSX)
#include <mach-o/dyld.h>

oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C()
{
    oslProcessError result = osl_Process_E_NotFound;

    char   buffer[PATH_MAX];
    size_t buflen = sizeof(buffer);

#if __GNUC__ >= 4 && defined(MACOSX)
    if (_NSGetExecutablePath (buffer, (uint32_t*)&buflen) == 0)
#else
    if (_NSGetExecutablePath (buffer, &buflen) == 0)
#endif
    {
        /* Determine absolute path. */
        char abspath[PATH_MAX];
        if (realpath (buffer, abspath) != 0)
        {
            /* Convert from utf8 to unicode. */
            rtl_uString * pAbsPath = 0;
            rtl_string2UString (
                &(pAbsPath),
                abspath, rtl_str_getLength (abspath),
                RTL_TEXTENCODING_UTF8,
                OSTRING_TO_OUSTRING_CVTFLAGS);

            if (pAbsPath)
            {
                /* Convert from path to url. */
                if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
                {
                    /* Success. */
                    result = osl_Process_E_None;
                }
                rtl_uString_release (pAbsPath);
            }
        }
    }

    return (result);
}

#elif !defined(NO_DL_FUNCTIONS)
#include <dlfcn.h>

oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C()
{
    oslProcessError result = osl_Process_E_NotFound;

    /* Determine address of "main()" function. */
    void * addr = dlsym (RTLD_DEFAULT, "main");
    if (addr != 0)
    {
        /* Determine module URL. */
        if (osl_getModuleURLFromAddress (addr, ppFileURL))
        {
            /* Success. */
            result = osl_Process_E_None;
        }
    }

    return (result);
}

#else  /* NO_DL_FUNCTIONS */

oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
    rtl_uString ** ppFileURL
) SAL_THROW_EXTERN_C()
{
    /* Fallback to ordinary osl_getExecutableFile(). */
    return osl_getExecutableFile (ppFileURL);
}

#endif /* NO_DL_FUNCTIONS */

/***************************************
 CommandArgs_Impl.
 **************************************/
struct CommandArgs_Impl
{
    pthread_mutex_t m_mutex;
    sal_uInt32      m_nCount;
    rtl_uString **  m_ppArgs;
};

static struct CommandArgs_Impl g_command_args =
{
    PTHREAD_MUTEX_INITIALIZER,
    0,
    0
};

/***************************************
  osl_getExecutableFile().
 **************************************/
oslProcessError SAL_CALL osl_getExecutableFile (rtl_uString ** ppustrFile)
{
    oslProcessError result = osl_Process_E_NotFound;

    pthread_mutex_lock (&(g_command_args.m_mutex));
    if (g_command_args.m_nCount > 0)
    {
        /* CommandArgs set. Obtain argv[0]. */
        rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
        result = osl_Process_E_None;
    }
    pthread_mutex_unlock (&(g_command_args.m_mutex));

    return (result);
}

/***************************************
 osl_getCommandArgCount().
 **************************************/
sal_uInt32 SAL_CALL osl_getCommandArgCount (void)
{
    sal_uInt32 result = 0;

    pthread_mutex_lock (&(g_command_args.m_mutex));
    if (g_command_args.m_nCount > 0)
        result = g_command_args.m_nCount - 1;
    pthread_mutex_unlock (&(g_command_args.m_mutex));

    return (result);
}

/***************************************
 osl_getCommandArg().
 **************************************/
oslProcessError SAL_CALL osl_getCommandArg (sal_uInt32 nArg, rtl_uString ** strCommandArg)
{
    oslProcessError result = osl_Process_E_NotFound;

    pthread_mutex_lock (&(g_command_args.m_mutex));
    if (g_command_args.m_nCount > (nArg + 1))
    {
        rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
        result = osl_Process_E_None;
    }
    pthread_mutex_unlock (&(g_command_args.m_mutex));

    return (result);
}

/***************************************
 osl_setCommandArgs().
 **************************************/
void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
{
    pthread_mutex_lock (&(g_command_args.m_mutex));
    OSL_ENSURE (g_command_args.m_nCount == 0, "osl_setCommandArgs(): CommandArgs already set.");
    if (g_command_args.m_nCount == 0)
    {
        rtl_uString** ppArgs = (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
        if (ppArgs != 0)
        {
            rtl_TextEncoding encoding = osl_getThreadTextEncoding();
            for (int i = 0; i < argc; i++)
            {
                rtl_string2UString (
                    &(ppArgs[i]),
                    argv[i], rtl_str_getLength (argv[i]), encoding,
                    OSTRING_TO_OUSTRING_CVTFLAGS);
            }
            if (ppArgs[0] != 0)
            {
                /* see @ osl_getExecutableFile(). */
                if (rtl_ustr_indexOfChar (rtl_uString_getStr(ppArgs[0]), sal_Unicode('/')) == -1)
                {
                    const rtl::OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));

                    rtl_uString * pSearchPath = 0;
                    osl_getEnvironment (PATH.pData, &pSearchPath);
                    if (pSearchPath)
                    {
                        rtl_uString * pSearchResult = 0;
                        osl_searchPath (ppArgs[0], pSearchPath, &pSearchResult);
                        if (pSearchResult)
                        {
                            rtl_uString_assign (&(ppArgs[0]), pSearchResult);
                            rtl_uString_release (pSearchResult);
                        }
                        rtl_uString_release (pSearchPath);
                    }
                }

                rtl_uString * pArg0 = 0;
                if (realpath_u (ppArgs[0], &pArg0))
                {
                    osl_getFileURLFromSystemPath (pArg0, &(ppArgs[0]));
                    rtl_uString_release (pArg0);
                }
            }
            g_command_args.m_nCount = argc;
            g_command_args.m_ppArgs = ppArgs;
        }
    }
    pthread_mutex_unlock (&(g_command_args.m_mutex));
}

/***************************************
 osl_getEnvironment().
 **************************************/
oslProcessError SAL_CALL osl_getEnvironment(rtl_uString* pustrEnvVar, rtl_uString** ppustrValue)
{
    oslProcessError  result   = osl_Process_E_NotFound;
    rtl_TextEncoding encoding = osl_getThreadTextEncoding();
    rtl_String* pstr_env_var  = 0;

    OSL_PRECOND(pustrEnvVar, "osl_getEnvironment(): Invalid parameter");
    OSL_PRECOND(ppustrValue, "osl_getEnvironment(): Invalid parameter");

    rtl_uString2String(
        &pstr_env_var,
        rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
        OUSTRING_TO_OSTRING_CVTFLAGS);
    if (pstr_env_var != 0)
    {
        const char* p_env_var = getenv (rtl_string_getStr (pstr_env_var));
        if (p_env_var != 0)
        {
            rtl_string2UString(
                ppustrValue,
                p_env_var, strlen(p_env_var), encoding,
                OSTRING_TO_OUSTRING_CVTFLAGS);
            OSL_ASSERT(*ppustrValue != NULL);

            result = osl_Process_E_None;
        }
        rtl_string_release(pstr_env_var);
    }

    return (result);
}

/***************************************
 osl_getProcessWorkingDir().
 **************************************/
oslProcessError SAL_CALL osl_getProcessWorkingDir(rtl_uString **ppustrWorkingDir)
{
    oslProcessError result = osl_Process_E_Unknown;
    char buffer[PATH_MAX];

    OSL_PRECOND(ppustrWorkingDir, "osl_getProcessWorkingDir(): Invalid parameter");

    if (getcwd (buffer, sizeof(buffer)) != 0)
    {
        rtl_uString* ustrTmp = 0;

        rtl_string2UString(
            &ustrTmp,
            buffer, strlen(buffer), osl_getThreadTextEncoding(),
            OSTRING_TO_OUSTRING_CVTFLAGS);
        if (ustrTmp != 0)
        {
            if (osl_getFileURLFromSystemPath (ustrTmp, ppustrWorkingDir) == osl_File_E_None)
                result = osl_Process_E_None;
            rtl_uString_release (ustrTmp);
        }
    }

    return (result);
}

/******************************************************************************
 *
 *              new functions to set/return the current process locale
 *
 *****************************************************************************/

struct ProcessLocale_Impl
{
    pthread_mutex_t m_mutex;
    rtl_Locale *    m_pLocale;
};

static struct ProcessLocale_Impl g_process_locale =
{
    PTHREAD_MUTEX_INITIALIZER,
    0
};

extern "C" void _imp_getProcessLocale( rtl_Locale ** );
extern "C" int  _imp_setProcessLocale( rtl_Locale * );

/**********************************************
 osl_getProcessLocale().
 *********************************************/
oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
{
    OSL_PRECOND(ppLocale, "osl_getProcessLocale(): Invalid parameter.");

    pthread_mutex_lock(&(g_process_locale.m_mutex));

    if (g_process_locale.m_pLocale == 0)
        _imp_getProcessLocale (&(g_process_locale.m_pLocale));
    *ppLocale = g_process_locale.m_pLocale;

    pthread_mutex_unlock (&(g_process_locale.m_mutex));

    return (osl_Process_E_None);
}

/**********************************************
 osl_setProcessLocale().
 *********************************************/
oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
{
    oslProcessError result = osl_Process_E_Unknown;

    OSL_PRECOND(pLocale, "osl_setProcessLocale(): Invalid parameter.");

    pthread_mutex_lock(&(g_process_locale.m_mutex));
    if (_imp_setProcessLocale (pLocale) == 0)
    {
        g_process_locale.m_pLocale = pLocale;
        result = osl_Process_E_None;
    }
    pthread_mutex_unlock (&(g_process_locale.m_mutex));

    return (result);
}
<|endoftext|>


<commit_before>#include "folder.h"
#include "exception.h"
#include "fileops.h"
#include "types.h"
#include <iterator>

namespace IO {
	bool Folder::Path(const std::string& path) {
		std::lock_guard<std::mutex> l(m_mxCall);

		if (!IO::DoPathExist(path)) {
			return false;
		}
		m_path = path;

		return true;
	}

	std::string Folder::Path() const {
		std::lock_guard<std::mutex> l(m_mxCall);
		return m_path;
	}

	FileList Folder::CurrentContents() const {
		auto iter = CreateIterator();
		FileList files;

		for (auto x = iter; x != boost::filesystem::directory_iterator(); x++) {
			FolderEntry toRet;
			if (boost::filesystem::is_directory(*x)) {
				toRet.Type = TypeFolder;
			}
			if (boost::filesystem::is_regular_file(*x)) {
				toRet.Type = TypeFile;
			}

			toRet.Name = x->path().filename().string();
			files.push_back(toRet);
		}
		return files;
	}

	boost::filesystem::directory_iterator  Folder::CreateIterator() const {
		std::lock_guard<std::mutex> l(m_mxCall);
		return boost::filesystem::directory_iterator(m_path);
	}
}
<commit_msg>Avoid terminating if Pictus fails to iterate all files/subfolders<commit_after>#include "folder.h"
#include "exception.h"
#include "fileops.h"
#include "types.h"
#include <iterator>

namespace IO {
	bool Folder::Path(const std::string& path) {
		std::lock_guard<std::mutex> l(m_mxCall);

		if (!IO::DoPathExist(path)) {
			return false;
		}
		m_path = path;

		return true;
	}

	std::string Folder::Path() const {
		std::lock_guard<std::mutex> l(m_mxCall);
		return m_path;
	}

	FileList Folder::CurrentContents() const {
		auto iter = CreateIterator();
		FileList files;

		for (auto x = iter; x != boost::filesystem::directory_iterator(); x++) {
			try
			{
				FolderEntry toRet;
				if (boost::filesystem::is_directory(*x)) {
					toRet.Type = TypeFolder;
				}
				if (boost::filesystem::is_regular_file(*x)) {
					toRet.Type = TypeFile;
				}

				toRet.Name = x->path().filename().string();
				files.push_back(toRet);
			}
			catch (boost::filesystem::filesystem_error& err)
			{
				// Boost can throw exceptions in is_directory and probably is_regular_file for various reasons that are
				// entirely uninteresting to us. Try to do the best of the situation and ignore files/folders that
				// are causing issues.
			}
		}
		return files;
	}

	boost::filesystem::directory_iterator  Folder::CreateIterator() const {
		std::lock_guard<std::mutex> l(m_mxCall);
		return boost::filesystem::directory_iterator(m_path);
	}
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "results.hpp"

#include <stdexcept>

using namespace realm;

#ifdef __has_cpp_attribute
#define REALM_HAS_CCP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
#else
#define REALM_HAS_CCP_ATTRIBUTE(attr) 0
#endif

#if REALM_HAS_CCP_ATTRIBUTE(clang::fallthrough)
#define REALM_FALLTHROUGH [[clang::fallthrough]]
#else
#define REALM_FALLTHROUGH
#endif

Results::Results(SharedRealm r, Query q, SortOrder s)
: m_realm(std::move(r))
, m_query(std::move(q))
, m_table(m_query.get_table().get())
, m_sort(std::move(s))
, m_mode(Mode::Query)
{
}

Results::Results(SharedRealm r, Table& table)
: m_realm(std::move(r))
, m_table(&table)
, m_mode(Mode::Table)
{
}

void Results::validate_read() const
{
    if (m_realm)
        m_realm->verify_thread();
    if (m_table && !m_table->is_attached())
        throw InvalidatedException();
}

void Results::validate_write() const
{
    validate_read();
    if (!m_realm || !m_realm->is_in_transaction())
        throw InvalidTransactionException("Must be in a write transaction");
}

size_t Results::size()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty: return 0;
        case Mode::Table: return m_table->size();
        case Mode::Query: return m_query.count();
        case Mode::TableView:
            update_tableview();
            return m_table_view.size();
    }
    REALM_UNREACHABLE();
}

RowExpr Results::get(size_t row_ndx)
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty: break;
        case Mode::Table:
            if (row_ndx < m_table->size())
                return m_table->get(row_ndx);
            break;
        case Mode::Query:
        case Mode::TableView:
            update_tableview();
            if (row_ndx < m_table_view.size())
                return m_table_view.get(row_ndx);
            break;
    }

    throw OutOfBoundsIndexException{row_ndx, size()};
}

util::Optional<RowExpr> Results::first()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return none;
        case Mode::Table:
            return m_table->size() == 0 ? util::none : util::make_optional(m_table->front());
        case Mode::Query:
            update_tableview();
            REALM_FALLTHROUGH;
        case Mode::TableView:
            return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front());
    }
    REALM_UNREACHABLE();
}

util::Optional<RowExpr> Results::last()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return none;
        case Mode::Table:
            return m_table->size() == 0 ? util::none : util::make_optional(m_table->back());
        case Mode::Query:
            update_tableview();
            REALM_FALLTHROUGH;
        case Mode::TableView:
            return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back());
    }
    REALM_UNREACHABLE();
}

void Results::update_tableview()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
        case Mode::Table:
            return;
        case Mode::Query:
            m_table_view = m_query.find_all();
            if (m_sort) {
                m_table_view.sort(m_sort.columnIndices, m_sort.ascending);
            }
            m_mode = Mode::TableView;
            break;
        case Mode::TableView:
            m_table_view.sync_if_needed();
            break;
    }
}

size_t Results::index_of(Row const& row)
{
    validate_read();
    if (!row) {
        throw DetatchedAccessorException{};
    }
    if (m_table && row.get_table() != m_table) {
        throw IncorrectTableException{
            ObjectStore::object_type_for_table_name(m_table->get_name()),
            ObjectStore::object_type_for_table_name(row.get_table()->get_name())};
    }
    return index_of(row.get_index());
}

size_t Results::index_of(size_t row_ndx)
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return not_found;
        case Mode::Table:
            return row_ndx;
        case Mode::Query:
            if (!m_sort)
                return m_query.count(row_ndx, row_ndx + 1) ? m_query.count(0, row_ndx) : not_found;
            REALM_FALLTHROUGH;
        case Mode::TableView:
            update_tableview();
            return m_table_view.find_by_source_ndx(row_ndx);
    }
    REALM_UNREACHABLE();
}

template<typename Int, typename Float, typename Double, typename DateTime>
util::Optional<Mixed> Results::aggregate(size_t column, bool return_none_for_empty,
                                         Int agg_int, Float agg_float,
                                         Double agg_double, DateTime agg_datetime)
{
    validate_read();
    if (!m_table)
        return none;
    if (column > m_table->get_column_count())
        throw OutOfBoundsIndexException{column, m_table->get_column_count()};

    auto do_agg = [&](auto const& getter) -> util::Optional<Mixed> {
        switch (m_mode) {
            case Mode::Empty:
                return none;
            case Mode::Table:
                if (return_none_for_empty && m_table->size() == 0)
                    return none;
                return util::Optional<Mixed>(getter(*m_table));
            case Mode::Query:
            case Mode::TableView:
                this->update_tableview();
                if (return_none_for_empty && m_table_view.size() == 0)
                    return none;
                return util::Optional<Mixed>(getter(m_table_view));
        }
        REALM_UNREACHABLE();
    };

    switch (m_table->get_column_type(column))
    {
        case type_DateTime: return do_agg(agg_datetime);
        case type_Double: return do_agg(agg_double);
        case type_Float: return do_agg(agg_float);
        case type_Int: return do_agg(agg_int);
        default:
            throw UnsupportedColumnTypeException{column, m_table};
    }
}

util::Optional<Mixed> Results::max(size_t column)
{
    return aggregate(column, true,
                     [=](auto const& table) { return table.maximum_int(column); },
                     [=](auto const& table) { return table.maximum_float(column); },
                     [=](auto const& table) { return table.maximum_double(column); },
                     [=](auto const& table) { return table.maximum_datetime(column); });
}

util::Optional<Mixed> Results::min(size_t column)
{
    return aggregate(column, true,
                     [=](auto const& table) { return table.minimum_int(column); },
                     [=](auto const& table) { return table.minimum_float(column); },
                     [=](auto const& table) { return table.minimum_double(column); },
                     [=](auto const& table) { return table.minimum_datetime(column); });
}

util::Optional<Mixed> Results::sum(size_t column)
{
    return aggregate(column, false,
                     [=](auto const& table) { return table.sum_int(column); },
                     [=](auto const& table) { return table.sum_float(column); },
                     [=](auto const& table) { return table.sum_double(column); },
                     [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table}; });
}

util::Optional<Mixed> Results::average(size_t column)
{
    return aggregate(column, true,
                     [=](auto const& table) { return table.average_int(column); },
                     [=](auto const& table) { return table.average_float(column); },
                     [=](auto const& table) { return table.average_double(column); },
                     [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table}; });
}

void Results::clear()
{
    switch (m_mode) {
        case Mode::Empty:
            return;
        case Mode::Table:
            validate_write();
            m_table->clear();
            break;
        case Mode::Query:
            // Not using Query:remove() because building the tableview and
            // clearing it is actually significantly faster
        case Mode::TableView:
            validate_write();
            update_tableview();
            m_table_view.clear();
            break;
    }
}

Query Results::get_query() const
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
        case Mode::Query:
        case Mode::TableView:
            return m_query;
        case Mode::Table:
            return m_table->where();
    }
    REALM_UNREACHABLE();
}

TableView Results::get_tableview()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return {};
        case Mode::Query:
        case Mode::TableView:
            update_tableview();
            return m_table_view;
        case Mode::Table:
            return m_table->where().find_all();
    }
    REALM_UNREACHABLE();
}

StringData Results::get_object_type() const noexcept
{
    return ObjectStore::object_type_for_table_name(m_table->get_name());
}

Results Results::sort(realm::SortOrder&& sort) const
{
    return Results(m_realm, get_query(), std::move(sort));
}

Results Results::filter(Query&& q) const
{
    return Results(m_realm, get_query().and_query(std::move(q)), get_sort());
}

Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) {
    column_index = column;
    column_name = table->get_column_name(column);
    column_type = table->get_column_type(column);
}
<commit_msg>Update existing TableViews in first() and last()<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "results.hpp"

#include <stdexcept>

using namespace realm;

#ifdef __has_cpp_attribute
#define REALM_HAS_CCP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
#else
#define REALM_HAS_CCP_ATTRIBUTE(attr) 0
#endif

#if REALM_HAS_CCP_ATTRIBUTE(clang::fallthrough)
#define REALM_FALLTHROUGH [[clang::fallthrough]]
#else
#define REALM_FALLTHROUGH
#endif

Results::Results(SharedRealm r, Query q, SortOrder s)
: m_realm(std::move(r))
, m_query(std::move(q))
, m_table(m_query.get_table().get())
, m_sort(std::move(s))
, m_mode(Mode::Query)
{
}

Results::Results(SharedRealm r, Table& table)
: m_realm(std::move(r))
, m_table(&table)
, m_mode(Mode::Table)
{
}

void Results::validate_read() const
{
    if (m_realm)
        m_realm->verify_thread();
    if (m_table && !m_table->is_attached())
        throw InvalidatedException();
}

void Results::validate_write() const
{
    validate_read();
    if (!m_realm || !m_realm->is_in_transaction())
        throw InvalidTransactionException("Must be in a write transaction");
}

size_t Results::size()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty: return 0;
        case Mode::Table: return m_table->size();
        case Mode::Query: return m_query.count();
        case Mode::TableView:
            update_tableview();
            return m_table_view.size();
    }
    REALM_UNREACHABLE();
}

RowExpr Results::get(size_t row_ndx)
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty: break;
        case Mode::Table:
            if (row_ndx < m_table->size())
                return m_table->get(row_ndx);
            break;
        case Mode::Query:
        case Mode::TableView:
            update_tableview();
            if (row_ndx < m_table_view.size())
                return m_table_view.get(row_ndx);
            break;
    }

    throw OutOfBoundsIndexException{row_ndx, size()};
}

util::Optional<RowExpr> Results::first()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return none;
        case Mode::Table:
            return m_table->size() == 0 ? util::none : util::make_optional(m_table->front());
        case Mode::Query:
        case Mode::TableView:
            update_tableview();
            return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front());
    }
    REALM_UNREACHABLE();
}

util::Optional<RowExpr> Results::last()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return none;
        case Mode::Table:
            return m_table->size() == 0 ? util::none : util::make_optional(m_table->back());
        case Mode::Query:
        case Mode::TableView:
            update_tableview();
            return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back());
    }
    REALM_UNREACHABLE();
}

void Results::update_tableview()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
        case Mode::Table:
            return;
        case Mode::Query:
            m_table_view = m_query.find_all();
            if (m_sort) {
                m_table_view.sort(m_sort.columnIndices, m_sort.ascending);
            }
            m_mode = Mode::TableView;
            break;
        case Mode::TableView:
            m_table_view.sync_if_needed();
            break;
    }
}

size_t Results::index_of(Row const& row)
{
    validate_read();
    if (!row) {
        throw DetatchedAccessorException{};
    }
    if (m_table && row.get_table() != m_table) {
        throw IncorrectTableException{
            ObjectStore::object_type_for_table_name(m_table->get_name()),
            ObjectStore::object_type_for_table_name(row.get_table()->get_name())};
    }
    return index_of(row.get_index());
}

size_t Results::index_of(size_t row_ndx)
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return not_found;
        case Mode::Table:
            return row_ndx;
        case Mode::Query:
            if (!m_sort)
                return m_query.count(row_ndx, row_ndx + 1) ? m_query.count(0, row_ndx) : not_found;
            REALM_FALLTHROUGH;
        case Mode::TableView:
            update_tableview();
            return m_table_view.find_by_source_ndx(row_ndx);
    }
    REALM_UNREACHABLE();
}

template<typename Int, typename Float, typename Double, typename DateTime>
util::Optional<Mixed> Results::aggregate(size_t column, bool return_none_for_empty,
                                         Int agg_int, Float agg_float,
                                         Double agg_double, DateTime agg_datetime)
{
    validate_read();
    if (!m_table)
        return none;
    if (column > m_table->get_column_count())
        throw OutOfBoundsIndexException{column, m_table->get_column_count()};

    auto do_agg = [&](auto const& getter) -> util::Optional<Mixed> {
        switch (m_mode) {
            case Mode::Empty:
                return none;
            case Mode::Table:
                if (return_none_for_empty && m_table->size() == 0)
                    return none;
                return util::Optional<Mixed>(getter(*m_table));
            case Mode::Query:
            case Mode::TableView:
                this->update_tableview();
                if (return_none_for_empty && m_table_view.size() == 0)
                    return none;
                return util::Optional<Mixed>(getter(m_table_view));
        }
        REALM_UNREACHABLE();
    };

    switch (m_table->get_column_type(column))
    {
        case type_DateTime: return do_agg(agg_datetime);
        case type_Double: return do_agg(agg_double);
        case type_Float: return do_agg(agg_float);
        case type_Int: return do_agg(agg_int);
        default:
            throw UnsupportedColumnTypeException{column, m_table};
    }
}

util::Optional<Mixed> Results::max(size_t column)
{
    return aggregate(column, true,
                     [=](auto const& table) { return table.maximum_int(column); },
                     [=](auto const& table) { return table.maximum_float(column); },
                     [=](auto const& table) { return table.maximum_double(column); },
                     [=](auto const& table) { return table.maximum_datetime(column); });
}

util::Optional<Mixed> Results::min(size_t column)
{
    return aggregate(column, true,
                     [=](auto const& table) { return table.minimum_int(column); },
                     [=](auto const& table) { return table.minimum_float(column); },
                     [=](auto const& table) { return table.minimum_double(column); },
                     [=](auto const& table) { return table.minimum_datetime(column); });
}

util::Optional<Mixed> Results::sum(size_t column)
{
    return aggregate(column, false,
                     [=](auto const& table) { return table.sum_int(column); },
                     [=](auto const& table) { return table.sum_float(column); },
                     [=](auto const& table) { return table.sum_double(column); },
                     [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table}; });
}

util::Optional<Mixed> Results::average(size_t column)
{
    return aggregate(column, true,
                     [=](auto const& table) { return table.average_int(column); },
                     [=](auto const& table) { return table.average_float(column); },
                     [=](auto const& table) { return table.average_double(column); },
                     [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table}; });
}

void Results::clear()
{
    switch (m_mode) {
        case Mode::Empty:
            return;
        case Mode::Table:
            validate_write();
            m_table->clear();
            break;
        case Mode::Query:
            // Not using Query:remove() because building the tableview and
            // clearing it is actually significantly faster
        case Mode::TableView:
            validate_write();
            update_tableview();
            m_table_view.clear();
            break;
    }
}

Query Results::get_query() const
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
        case Mode::Query:
        case Mode::TableView:
            return m_query;
        case Mode::Table:
            return m_table->where();
    }
    REALM_UNREACHABLE();
}

TableView Results::get_tableview()
{
    validate_read();
    switch (m_mode) {
        case Mode::Empty:
            return {};
        case Mode::Query:
        case Mode::TableView:
            update_tableview();
            return m_table_view;
        case Mode::Table:
            return m_table->where().find_all();
    }
    REALM_UNREACHABLE();
}

StringData Results::get_object_type() const noexcept
{
    return ObjectStore::object_type_for_table_name(m_table->get_name());
}

Results Results::sort(realm::SortOrder&& sort) const
{
    return Results(m_realm, get_query(), std::move(sort));
}

Results Results::filter(Query&& q) const
{
    return Results(m_realm, get_query().and_query(std::move(q)), get_sort());
}

Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) {
    column_index = column;
    column_name = table->get_column_name(column);
    column_type = table->get_column_type(column);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <string>
#include <vector>

using namespace std;

// void rowSum(int a[][4],int nRow){
// 	for(int i=0;i<nRow;i++){
// 		for(int j=0;j<4;j++){
// 			a[i][0] = a[i][j];
// 		}
// 	}
// }
// void splitFloat(float x,int *intPart, float *fracPart){
// 	*intPart = static_cast<int>(x);
// 	*fracPart = x - *intPart;
// }

// int* search(int* a, int num){
// 	for(int i=0;i<num;i++){
// 		if(a[i] == 0){
// 			return &a[i];
// 		}
// 	}
// }

// int compute(int a, int b,int(*func)(int,int)){
// 	return func(a,b);
// }
// int max(int a, int b){
// 	return((a>b)?a:b);
// }
// int min(int a, int b){
// 	return((a<b)?a:b);
// }
// int sum(int a, int b){
// 	return a+b;
// }
// class Point {
// public:
//   Point(int x = 0, int y = 0) : x(x), y(y) { }
//      int getX() const { return x; }
//      int getY() const { return y; }
// private:
//      int x, y;
// };

// double average(const vector<double> &arr){
// 	double sum = 0;
// 	for(unsigned i=0;i<arr.size();i++){
// 		sum += arr[i];
// 	}
// 	return sum/arr.size();
// }

class Base1{
public:
	void display() const{
		cout<<"Base1::display()"<<endl;
	}
};
class Base2: public Base1{
public:
	void display() const{
		cout<<"Base2::display()"<<endl;
	}
};
class Derived: public Base2{
public:
	void display() const{
		cout<<"Derived::display()"<<endl;
	}
};

void func(Base1 *ptr){
	ptr->display();
}

int main(){
	Base1 base1;
	Base2 base2;
	Derived derived;

	func(&base1);
	func(&base2);
	func(&derived);

	// unsigned n;
	// cout<<"n = ";
	// cin>>n;

	// vector<double> arr(n);
	// cout<<"Please input "<<n<<" real numbers: "<<endl;
	// for(int i=0;i<n;i++)
	// 	cin>>arr[i];
	// cout<<"Average = "<<average(arr)<<endl;

	// int (*fp)[9][8] = new int[7][9][8];
	// for (int i = 0; i < 7; i++)
 //    	for (int j = 0; j < 9; j++)
 //    		for (int k = 0; k < 8; k++)
 //    			*(*(*(fp + i) + j) + k) = (i*100+j*10+k);
 //    for (int i = 0; i < 7; i++) {
 //    	for (int j = 0; j < 9; j++) {
 //    		for (int k = 0; k < 8; k++)
 //    			cout<<fp[i][j][k]<<' ';
 //    			cout<<endl;
 //    		}
 //    		cout<<endl;
 //    	}
 //    	delete[] fp;

	// Point a(4,5);
	// Point *ptr = &a;
	// cout<<ptr->getX()<<endl;
	// cout<<a.getX()<<endl;

	// int a,b,res;
	// cout<<"Please enter a: "; cin>>a;
	// cout<<"Please enter b: "; cin>>b;

	// res = compute(a,b,&max);
	// cout<<"max of a and b is "<<res<<endl;
	// res = compute(a,b,&min);
	// cout<<"min of a and b is "<<res<<endl;
	// res = compute(a,b,&sum);
	// cout<<"sum of a and b is "<<res<<endl;

	// int array[10];
	// int* search(int* a, int num);
	// for(int i=0;i<10;i++){
	// 	cin>>array[i];
	// }
	// int* zeroptr = search(array, 10);

	// cout<<"Enter 3 float point numbers: "<<endl;
	// for(int i=0;i<3;i++){
	// 	float x, f;
	// 	int n;
	// 	cin>>x;
	// 	splitFloat(x, &n, &f);
	// 	cout<<"Integer part: "<<n<<" Fraction part: "<<f<<endl;
	// }

	// int line1[] = {1,2,3};
	// int line2[] = {4,5,6};
	// int line3[] = {7,8,9};
	// int *pline[] = {line1,line2,line3};
	// cout<<"Matrix test: "<<endl;
	// for(int i=0;i<3;i++){
	// 	for(int j=0;j<3;j++){
	// 		cout<<pline[i][j]<<",";
	// 	}
	// 	cout<<endl;
	// }

	// int array[3] = {1,2,3};
	// for(int &e:array){
	// 	e += 2;
	// 	cout<<e<<endl;
	// }

	// int table[3][4] = {{1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6}};
	// for (int i = 0; i < 3; i++)  {
 //         for (int j = 0; j < 4; j++)
 //              cout << table[i][j] << "   ";
 //         cout << endl;
 //     }
 //     rowSum(table, 3);
 //     for(int i=0;i<3;i++){
 //     	cout << "Sum of row " << i << " is " << table[i][0] << endl;
 //     }

	// const char key[] = {'a','c','b','a','d'};
	// const int ques_num = 5;
	// char usr_input;
	// int ques = 0, correct_num = 0;

	// cout<<"Enter the "<<ques_num<<" question tests:"<<endl;
	// while(cin.get(usr_input)){
	// 	if(usr_input != '\n'){
	// 		if(usr_input == key[ques]){
	// 			correct_num++;
	// 			cout<<" ";
	// 		}
	// 		else{
	// 			cout<<"*";
	// 		}
	// 		ques++;
	// 	}
	// 	else{
	// 		cout<<"Score: "<<static_cast<float>(correct_num)/ques_num*100<<"%";
	// 		ques = 0; correct_num = 0;cout<<endl;
	// 	}
	// }

	// int f[20] = {1,1};
	// for (int i=2;i<20;i++){
	// 	f[i] = f[i-1] + f[i-2];
	// }
	// for (int i=0;i<20;i++){
	// 	if(i%4 == 0)cout<<endl;
	// 	cout.width(5);
	// 	cout<<f[i];
	// }
	// cout<<endl;

	// int a[10], b[10];
 //  	for(int i = 0; i < 10; i++) {
	//     a[i] = i * 2 - 1;
	//     b[10 - i - 1] = a[i];
 //  	}
 //  	for(int i = 0; i < 10; i++) {
	//     cout << "a[" << i << "] = " << a[i] << "  ";
	//     cout << "b[" << i << "] = " << b[i] << endl;
 //  	}

  	return 0;
}

<commit_msg>to be added.<commit_after>#include <iostream>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <string>
#include <vector>

using namespace std;

// void rowSum(int a[][4],int nRow){
// 	for(int i=0;i<nRow;i++){
// 		for(int j=0;j<4;j++){
// 			a[i][0] = a[i][j];
// 		}
// 	}
// }
// void splitFloat(float x,int *intPart, float *fracPart){
// 	*intPart = static_cast<int>(x);
// 	*fracPart = x - *intPart;
// }

// int* search(int* a, int num){
// 	for(int i=0;i<num;i++){
// 		if(a[i] == 0){
// 			return &a[i];
// 		}
// 	}
// }

// int compute(int a, int b,int(*func)(int,int)){
// 	return func(a,b);
// }
// int max(int a, int b){
// 	return((a>b)?a:b);
// }
// int min(int a, int b){
// 	return((a<b)?a:b);
// }
// int sum(int a, int b){
// 	return a+b;
// }
// class Point {
// public:
//   Point(int x = 0, int y = 0) : x(x), y(y) { }
//      int getX() const { return x; }
//      int getY() const { return y; }
// private:
//      int x, y;
// };

// double average(const vector<double> &arr){
// 	double sum = 0;
// 	for(unsigned i=0;i<arr.size();i++){
// 		sum += arr[i];
// 	}
// 	return sum/arr.size();
// }

// class Base1{
// public:
// 	void display() const{
// 		cout<<"Base1::display()"<<endl;
// 	}
// };
// class Base2: public Base1{
// public:
// 	void display() const{
// 		cout<<"Base2::display()"<<endl;
// 	}
// };
// class Derived: public Base2{
// public:
// 	void display() const{
// 		cout<<"Derived::display()"<<endl;
// 	}
// };

// void func(Base1 *ptr){
// 	ptr->display();
// }

int main(){
	// Base1 base1;
	// Base2 base2;
	// Derived derived;

	// func(&base1);
	// func(&base2);
	// func(&derived);

	// unsigned n;
	// cout<<"n = ";
	// cin>>n;

	// vector<double> arr(n);
	// cout<<"Please input "<<n<<" real numbers: "<<endl;
	// for(int i=0;i<n;i++)
	// 	cin>>arr[i];
	// cout<<"Average = "<<average(arr)<<endl;

	// int (*fp)[9][8] = new int[7][9][8];
	// for (int i = 0; i < 7; i++)
 //    	for (int j = 0; j < 9; j++)
 //    		for (int k = 0; k < 8; k++)
 //    			*(*(*(fp + i) + j) + k) = (i*100+j*10+k);
 //    for (int i = 0; i < 7; i++) {
 //    	for (int j = 0; j < 9; j++) {
 //    		for (int k = 0; k < 8; k++)
 //    			cout<<fp[i][j][k]<<' ';
 //    			cout<<endl;
 //    		}
 //    		cout<<endl;
 //    	}
 //    	delete[] fp;

	// Point a(4,5);
	// Point *ptr = &a;
	// cout<<ptr->getX()<<endl;
	// cout<<a.getX()<<endl;

	// int a,b,res;
	// cout<<"Please enter a: "; cin>>a;
	// cout<<"Please enter b: "; cin>>b;

	// res = compute(a,b,&max);
	// cout<<"max of a and b is "<<res<<endl;
	// res = compute(a,b,&min);
	// cout<<"min of a and b is "<<res<<endl;
	// res = compute(a,b,&sum);
	// cout<<"sum of a and b is "<<res<<endl;

	// int array[10];
	// int* search(int* a, int num);
	// for(int i=0;i<10;i++){
	// 	cin>>array[i];
	// }
	// int* zeroptr = search(array, 10);

	// cout<<"Enter 3 float point numbers: "<<endl;
	// for(int i=0;i<3;i++){
	// 	float x, f;
	// 	int n;
	// 	cin>>x;
	// 	splitFloat(x, &n, &f);
	// 	cout<<"Integer part: "<<n<<" Fraction part: "<<f<<endl;
	// }

	// int line1[] = {1,2,3};
	// int line2[] = {4,5,6};
	// int line3[] = {7,8,9};
	// int *pline[] = {line1,line2,line3};
	// cout<<"Matrix test: "<<endl;
	// for(int i=0;i<3;i++){
	// 	for(int j=0;j<3;j++){
	// 		cout<<pline[i][j]<<",";
	// 	}
	// 	cout<<endl;
	// }

	// int array[3] = {1,2,3};
	// for(int &e:array){
	// 	e += 2;
	// 	cout<<e<<endl;
	// }

	// int table[3][4] = {{1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6}};
	// for (int i = 0; i < 3; i++)  {
 //         for (int j = 0; j < 4; j++)
 //              cout << table[i][j] << "   ";
 //         cout << endl;
 //     }
 //     rowSum(table, 3);
 //     for(int i=0;i<3;i++){
 //     	cout << "Sum of row " << i << " is " << table[i][0] << endl;
 //     }

	// const char key[] = {'a','c','b','a','d'};
	// const int ques_num = 5;
	// char usr_input;
	// int ques = 0, correct_num = 0;

	// cout<<"Enter the "<<ques_num<<" question tests:"<<endl;
	// while(cin.get(usr_input)){
	// 	if(usr_input != '\n'){
	// 		if(usr_input == key[ques]){
	// 			correct_num++;
	// 			cout<<" ";
	// 		}
	// 		else{
	// 			cout<<"*";
	// 		}
	// 		ques++;
	// 	}
	// 	else{
	// 		cout<<"Score: "<<static_cast<float>(correct_num)/ques_num*100<<"%";
	// 		ques = 0; correct_num = 0;cout<<endl;
	// 	}
	// }

	// int f[20] = {1,1};
	// for (int i=2;i<20;i++){
	// 	f[i] = f[i-1] + f[i-2];
	// }
	// for (int i=0;i<20;i++){
	// 	if(i%4 == 0)cout<<endl;
	// 	cout.width(5);
	// 	cout<<f[i];
	// }
	// cout<<endl;

	// int a[10], b[10];
 //  	for(int i = 0; i < 10; i++) {
	//     a[i] = i * 2 - 1;
	//     b[10 - i - 1] = a[i];
 //  	}
 //  	for(int i = 0; i < 10; i++) {
	//     cout << "a[" << i << "] = " << a[i] << "  ";
	//     cout << "b[" << i << "] = " << b[i] << endl;
 //  	}

  	return 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: docfunc.hxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:21:03 $
 *
 *  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 SC_DOCFUNC_HXX
#define SC_DOCFUNC_HXX

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif

#ifndef SC_POSTIT_HXX
#include "postit.hxx"
#endif

class ScEditEngineDefaulter;
class SfxUndoAction;
class ScAddress;
class ScDocShell;
class ScMarkData;
class ScPatternAttr;
class ScRange;
class ScRangeName;
class ScBaseCell;
struct ScTabOpParam;

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

class ScDocFunc
{
private:
    ScDocShell&     rDocShell;

    BOOL            AdjustRowHeight( const ScRange& rRange, BOOL bPaint = TRUE );
    void            CreateOneName( ScRangeName& rList,
                                    SCCOL nPosX, SCROW nPosY, SCTAB nTab,
                                    SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
                                    BOOL& rCancel, BOOL bApi );
    void            NotifyInputHandler( const ScAddress& rPos );

public:
                    ScDocFunc( ScDocShell& rDocSh ): rDocShell(rDocSh) {}
                    ~ScDocFunc() {}

    DECL_LINK( NotifyDrawUndo, SfxUndoAction* );

    BOOL            DetectiveAddPred(const ScAddress& rPos);
    BOOL            DetectiveDelPred(const ScAddress& rPos);
    BOOL            DetectiveAddSucc(const ScAddress& rPos);
    BOOL            DetectiveDelSucc(const ScAddress& rPos);
    BOOL            DetectiveAddError(const ScAddress& rPos);
    BOOL            DetectiveMarkInvalid(SCTAB nTab);
    BOOL            DetectiveDelAll(SCTAB nTab);
    BOOL            DetectiveRefresh(BOOL bAutomatic = FALSE);

    BOOL            DeleteContents( const ScMarkData& rMark, USHORT nFlags,
                                    BOOL bRecord, BOOL bApi );

    BOOL            TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
                                    BOOL bRecord, BOOL bApi );

    BOOL            SetNormalString( const ScAddress& rPos, const String& rText, BOOL bApi );
    BOOL            PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, BOOL bApi );
    BOOL            PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine,
                                BOOL bInterpret, BOOL bApi );
    BOOL            SetCellText( const ScAddress& rPos, const String& rText,
                                    BOOL bInterpret, BOOL bEnglish, BOOL bApi );

                    // creates a new cell for use with PutCell
    ScBaseCell*     InterpretEnglishString( const ScAddress& rPos, const String& rText );

    BOOL            SetNoteText( const ScAddress& rPos, const String& rText, BOOL bApi );

    BOOL            ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
                                    BOOL bRecord, BOOL bApi );
    BOOL            ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
                                    BOOL bRecord, BOOL bApi );

    BOOL            InsertCells( const ScRange& rRange, InsCellCmd eCmd, BOOL bRecord, BOOL bApi,
                                    BOOL bPartOfPaste = FALSE );
    BOOL            DeleteCells( const ScRange& rRange, DelCellCmd eCmd, BOOL bRecord, BOOL bApi );

    BOOL            MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
                                BOOL bCut, BOOL bRecord, BOOL bPaint, BOOL bApi );

    BOOL            InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi );
    BOOL            RenameTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi );
    BOOL            DeleteTable( SCTAB nTab, BOOL bRecord, BOOL bApi );

    BOOL            SetTableVisible( SCTAB nTab, BOOL bVisible, BOOL bApi );

    BOOL            SetLayoutRTL( SCTAB nTab, BOOL bRTL, BOOL bApi );

    BOOL            SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges,
                                    SCTAB nTab, ScSizeMode eMode, USHORT nSizeTwips,
                                    BOOL bRecord, BOOL bApi );

    BOOL            InsertPageBreak( BOOL bColumn, const ScAddress& rPos,
                                    BOOL bRecord, BOOL bSetModified, BOOL bApi );
    BOOL            RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
                                    BOOL bRecord, BOOL bSetModified, BOOL bApi );

    BOOL            Protect( SCTAB nTab, const String& rPassword, BOOL bApi );
    BOOL            Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi );

    BOOL            ClearItems( const ScMarkData& rMark, const USHORT* pWhich, BOOL bApi );
    BOOL            ChangeIndent( const ScMarkData& rMark, BOOL bIncrement, BOOL bApi );
    BOOL            AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
                                    USHORT nFormatNo, BOOL bRecord, BOOL bApi );

    BOOL            EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
                                    const String& rString, BOOL bApi, BOOL bEnglish );

    BOOL            TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
                            const ScTabOpParam& rParam, BOOL bRecord, BOOL bApi );

    BOOL            FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
                                FillDir eDir, BOOL bRecord, BOOL bApi );
    BOOL            FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
                                FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
                                double fStart, double fStep, double fMax,
                                BOOL bRecord, BOOL bApi );
                    // FillAuto: rRange wird von Source-Range auf Dest-Range angepasst
    BOOL            FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
                                FillDir eDir, ULONG nCount, BOOL bRecord, BOOL bApi );

    BOOL            ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, BOOL bApi );

    BOOL            MergeCells( const ScRange& rRange, BOOL bContents,
                                BOOL bRecord, BOOL bApi );
    BOOL            UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi );

    BOOL            SetNote( const ScAddress& rPos, const ScPostIt& rNote, BOOL bApi );

    BOOL            ModifyRangeNames( const ScRangeName& rNewRanges, BOOL bApi );

    BOOL            CreateNames( const ScRange& rRange, USHORT nFlags, BOOL bApi );
    BOOL            InsertNameList( const ScAddress& rStartPos, BOOL bApi );

    BOOL            InsertAreaLink( const String& rFile, const String& rFilter,
                                    const String& rOptions, const String& rSource,
                                    const ScRange& rDestRange, ULONG nRefresh,
                                    BOOL bFitBlock, BOOL bApi );
};

#endif

<commit_msg>INTEGRATION: CWS calc36 (1.12.156); FILE MERGED 2006/04/06 09:22:03 nn 1.12.156.1: #i63513# new method SetNewRangeNames to avoid extra copy of ScRangeName<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: docfunc.hxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: rt $ $Date: 2006-05-05 09:44: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 SC_DOCFUNC_HXX
#define SC_DOCFUNC_HXX

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif

#ifndef SC_POSTIT_HXX
#include "postit.hxx"
#endif

class ScEditEngineDefaulter;
class SfxUndoAction;
class ScAddress;
class ScDocShell;
class ScMarkData;
class ScPatternAttr;
class ScRange;
class ScRangeName;
class ScBaseCell;
struct ScTabOpParam;

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

class ScDocFunc
{
private:
    ScDocShell&     rDocShell;

    BOOL            AdjustRowHeight( const ScRange& rRange, BOOL bPaint = TRUE );
    void            CreateOneName( ScRangeName& rList,
                                    SCCOL nPosX, SCROW nPosY, SCTAB nTab,
                                    SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
                                    BOOL& rCancel, BOOL bApi );
    void            NotifyInputHandler( const ScAddress& rPos );

public:
                    ScDocFunc( ScDocShell& rDocSh ): rDocShell(rDocSh) {}
                    ~ScDocFunc() {}

    DECL_LINK( NotifyDrawUndo, SfxUndoAction* );

    BOOL            DetectiveAddPred(const ScAddress& rPos);
    BOOL            DetectiveDelPred(const ScAddress& rPos);
    BOOL            DetectiveAddSucc(const ScAddress& rPos);
    BOOL            DetectiveDelSucc(const ScAddress& rPos);
    BOOL            DetectiveAddError(const ScAddress& rPos);
    BOOL            DetectiveMarkInvalid(SCTAB nTab);
    BOOL            DetectiveDelAll(SCTAB nTab);
    BOOL            DetectiveRefresh(BOOL bAutomatic = FALSE);

    BOOL            DeleteContents( const ScMarkData& rMark, USHORT nFlags,
                                    BOOL bRecord, BOOL bApi );

    BOOL            TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
                                    BOOL bRecord, BOOL bApi );

    BOOL            SetNormalString( const ScAddress& rPos, const String& rText, BOOL bApi );
    BOOL            PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, BOOL bApi );
    BOOL            PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine,
                                BOOL bInterpret, BOOL bApi );
    BOOL            SetCellText( const ScAddress& rPos, const String& rText,
                                    BOOL bInterpret, BOOL bEnglish, BOOL bApi );

                    // creates a new cell for use with PutCell
    ScBaseCell*     InterpretEnglishString( const ScAddress& rPos, const String& rText );

    BOOL            SetNoteText( const ScAddress& rPos, const String& rText, BOOL bApi );

    BOOL            ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
                                    BOOL bRecord, BOOL bApi );
    BOOL            ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
                                    BOOL bRecord, BOOL bApi );

    BOOL            InsertCells( const ScRange& rRange, InsCellCmd eCmd, BOOL bRecord, BOOL bApi,
                                    BOOL bPartOfPaste = FALSE );
    BOOL            DeleteCells( const ScRange& rRange, DelCellCmd eCmd, BOOL bRecord, BOOL bApi );

    BOOL            MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
                                BOOL bCut, BOOL bRecord, BOOL bPaint, BOOL bApi );

    BOOL            InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi );
    BOOL            RenameTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi );
    BOOL            DeleteTable( SCTAB nTab, BOOL bRecord, BOOL bApi );

    BOOL            SetTableVisible( SCTAB nTab, BOOL bVisible, BOOL bApi );

    BOOL            SetLayoutRTL( SCTAB nTab, BOOL bRTL, BOOL bApi );

    BOOL            SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges,
                                    SCTAB nTab, ScSizeMode eMode, USHORT nSizeTwips,
                                    BOOL bRecord, BOOL bApi );

    BOOL            InsertPageBreak( BOOL bColumn, const ScAddress& rPos,
                                    BOOL bRecord, BOOL bSetModified, BOOL bApi );
    BOOL            RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
                                    BOOL bRecord, BOOL bSetModified, BOOL bApi );

    BOOL            Protect( SCTAB nTab, const String& rPassword, BOOL bApi );
    BOOL            Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi );

    BOOL            ClearItems( const ScMarkData& rMark, const USHORT* pWhich, BOOL bApi );
    BOOL            ChangeIndent( const ScMarkData& rMark, BOOL bIncrement, BOOL bApi );
    BOOL            AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
                                    USHORT nFormatNo, BOOL bRecord, BOOL bApi );

    BOOL            EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
                                    const String& rString, BOOL bApi, BOOL bEnglish );

    BOOL            TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
                            const ScTabOpParam& rParam, BOOL bRecord, BOOL bApi );

    BOOL            FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
                                FillDir eDir, BOOL bRecord, BOOL bApi );
    BOOL            FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
                                FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
                                double fStart, double fStep, double fMax,
                                BOOL bRecord, BOOL bApi );
                    // FillAuto: rRange wird von Source-Range auf Dest-Range angepasst
    BOOL            FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
                                FillDir eDir, ULONG nCount, BOOL bRecord, BOOL bApi );

    BOOL            ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, BOOL bApi );

    BOOL            MergeCells( const ScRange& rRange, BOOL bContents,
                                BOOL bRecord, BOOL bApi );
    BOOL            UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi );

    BOOL            SetNote( const ScAddress& rPos, const ScPostIt& rNote, BOOL bApi );

    BOOL            SetNewRangeNames( ScRangeName* pNewRanges, BOOL bApi );     // takes ownership of pNewRanges
    BOOL            ModifyRangeNames( const ScRangeName& rNewRanges, BOOL bApi );

    BOOL            CreateNames( const ScRange& rRange, USHORT nFlags, BOOL bApi );
    BOOL            InsertNameList( const ScAddress& rStartPos, BOOL bApi );

    BOOL            InsertAreaLink( const String& rFile, const String& rFilter,
                                    const String& rOptions, const String& rSource,
                                    const ScRange& rDestRange, ULONG nRefresh,
                                    BOOL bFitBlock, BOOL bApi );
};

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pivotsh.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:44:03 $
 *
 *  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 SC_PIVOTSH_HXX
#define SC_PIVOTSH_HXX

#ifndef _SFXMODULE_HXX //autogen
#include <sfx2/module.hxx>
#endif
#ifndef _SFX_SHELL_HXX //autogen
#include <sfx2/shell.hxx>
#endif

#include "shellids.hxx"

class ScTabViewShell;
class ScDPObject;

class ScPivotShell : public SfxShell
{
public:
    TYPEINFO();
    SFX_DECL_INTERFACE(SCID_PIVOT_SHELL);

                    ScPivotShell( ScTabViewShell* pView );
                    ~ScPivotShell();

    void    Execute ( SfxRequest& rReq );
    void    GetState( SfxItemSet& rSet );

private:
    ScTabViewShell* pViewShell;

    ScDPObject*     GetCurrDPObject();
};

#endif

<commit_msg>INTEGRATION: CWS calcwarnings (1.3.322); FILE MERGED 2006/12/14 17:57:13 nn 1.3.322.1: #i69284# warning-free: ui, unxsols4<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pivotsh.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2007-02-27 13:25:18 $
 *
 *  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 SC_PIVOTSH_HXX
#define SC_PIVOTSH_HXX

#ifndef _SFXMODULE_HXX //autogen
#include <sfx2/module.hxx>
#endif
#ifndef _SFX_SHELL_HXX //autogen
#include <sfx2/shell.hxx>
#endif

#include "shellids.hxx"

class ScTabViewShell;
class ScDPObject;

class ScPivotShell : public SfxShell
{
public:
    TYPEINFO();
    SFX_DECL_INTERFACE(SCID_PIVOT_SHELL)

                    ScPivotShell( ScTabViewShell* pView );
                    ~ScPivotShell();

    void    Execute ( SfxRequest& rReq );
    void    GetState( SfxItemSet& rSet );

private:
    ScTabViewShell* pViewShell;

    ScDPObject*     GetCurrDPObject();
};

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: target.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 22:38:07 $
 *
 *  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
 *
 ************************************************************************/

// System - Includes -----------------------------------------------------

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

// INCLUDE ---------------------------------------------------------------

#include "target.hxx"

// STATIC DATA -----------------------------------------------------------

TYPEINIT1(ScTabViewTarget, SfxRepeatTarget);

__EXPORT ScTabViewTarget::~ScTabViewTarget()
{
}
<commit_msg>INTEGRATION: CWS pchfix01 (1.3.214); FILE MERGED 2006/07/12 10:02:52 kaib 1.3.214.1: #i67080# Converted cxx files in sc, added initial project level pch and stripped old PCH definitions.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: target.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2006-07-21 14:25:45 $
 *
 *  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_sc.hxx"

// System - Includes -----------------------------------------------------

// INCLUDE ---------------------------------------------------------------

#include "target.hxx"

// STATIC DATA -----------------------------------------------------------

TYPEINIT1(ScTabViewTarget, SfxRepeatTarget);

__EXPORT ScTabViewTarget::~ScTabViewTarget()
{
}
<|endoftext|>


<commit_before>//
// Aspia Project
// Copyright (C) 2016-2022 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "relay/controller.h"

#include "base/logging.h"
#include "base/task_runner.h"
#include "base/peer/client_authenticator.h"
#include "proto/router_common.pb.h"
#include "relay/settings.h"

namespace relay {

namespace {

const std::chrono::seconds kReconnectTimeout{ 15 };

#if defined(OS_WIN)
const wchar_t kFirewallRuleName[] = L"Aspia Relay Service";
const wchar_t kFirewallRuleDecription[] = L"Allow incoming TCP connections";
#endif // defined(OS_WIN)

class KeyDeleter
{
public:
    KeyDeleter(std::unique_ptr<SharedPool> pool, uint32_t key_id)
        : pool_(std::move(pool)),
          key_id_(key_id)
    {
        DCHECK(pool_);
    }

    ~KeyDeleter() = default;

    void deleteKey()
    {
        pool_->setKeyExpired(key_id_);
    }

private:
    std::unique_ptr<SharedPool> pool_;
    const uint32_t key_id_;

    DISALLOW_COPY_AND_ASSIGN(KeyDeleter);
};

} // namespace

Controller::Controller(std::shared_ptr<base::TaskRunner> task_runner)
    : task_runner_(task_runner),
      reconnect_timer_(base::WaitableTimer::Type::SINGLE_SHOT, task_runner),
      shared_pool_(std::make_unique<SharedPool>(this))
{
    Settings settings;

    // Router settings.
    router_address_ = settings.routerAddress();
    router_port_ = settings.routerPort();
    router_public_key_ = settings.routerPublicKey();

    LOG(LS_INFO) << "Router address: " << router_address_;
    LOG(LS_INFO) << "Router port: " << router_port_;
    LOG(LS_INFO) << "Router public key: " << base::toHex(router_public_key_);

    // Peers settings.
    peer_address_ = settings.peerAddress();
    peer_port_ = settings.peerPort();
    peer_idle_timeout_ = settings.peerIdleTimeout();
    max_peer_count_ = settings.maxPeerCount();

    LOG(LS_INFO) << "Peer address: " << peer_address_;
    LOG(LS_INFO) << "Peer port: " << peer_port_;
    LOG(LS_INFO) << "Peer idle timeout: " << peer_idle_timeout_.count();
    LOG(LS_INFO) << "Max peer count: " << max_peer_count_;
}

Controller::~Controller() = default;

bool Controller::start()
{
    LOG(LS_INFO) << "Starting controller";

    if (router_address_.empty())
    {
        LOG(LS_ERROR) << "Empty router address";
        return false;
    }

    if (router_port_ == 0)
    {
        LOG(LS_ERROR) << "Invalid router port";
        return false;
    }

    if (router_public_key_.empty())
    {
        LOG(LS_ERROR) << "Empty router public key";
        return false;
    }

    if (peer_address_.empty())
    {
        LOG(LS_ERROR) << "Empty peer address";
        return false;
    }

    if (peer_port_ == 0)
    {
        LOG(LS_ERROR) << "Invalid peer port";
        return false;
    }

    if (peer_idle_timeout_ < std::chrono::minutes(1) || peer_idle_timeout_ > std::chrono::minutes(60))
    {
        LOG(LS_WARNING) << "Invalid peer idle specified";
        return false;
    }

    sessions_worker_ = std::make_unique<SessionsWorker>(
        peer_port_, peer_idle_timeout_, shared_pool_->share());
    sessions_worker_->start(task_runner_, this);

    connectToRouter();
    return true;
}

void Controller::onConnected()
{
    LOG(LS_INFO) << "Connection to the router is established";

    channel_->setOwnKeepAlive(true);
    channel_->setNoDelay(true);

    authenticator_ = std::make_unique<base::ClientAuthenticator>(task_runner_);

    authenticator_->setIdentify(proto::IDENTIFY_ANONYMOUS);
    authenticator_->setPeerPublicKey(router_public_key_);
    authenticator_->setSessionType(proto::ROUTER_SESSION_RELAY);

    authenticator_->start(std::move(channel_),
                          [this](base::ClientAuthenticator::ErrorCode error_code)
    {
        if (error_code == base::ClientAuthenticator::ErrorCode::SUCCESS)
        {
            // The authenticator takes the listener on itself, we return the receipt of
            // notifications.
            channel_ = authenticator_->takeChannel();
            channel_->setListener(this);

            LOG(LS_INFO) << "Authentication complete";

            // Now the session will receive incoming messages.
            channel_->resume();

            sendKeyPool(max_peer_count_);
        }
        else
        {
            LOG(LS_WARNING) << "Authentication failed: "
                            << base::ClientAuthenticator::errorToString(error_code);
            delayedConnectToRouter();
        }

        // Authenticator is no longer needed.
        task_runner_->deleteSoon(std::move(authenticator_));
    });
}

void Controller::onDisconnected(base::NetworkChannel::ErrorCode error_code)
{
    LOG(LS_INFO) << "The connection to the router has been lost: "
                 << base::NetworkChannel::errorToString(error_code);

    // Clearing the key pool.
    shared_pool_->clear();

    // Retrying a connection at a time interval.
    delayedConnectToRouter();
}

void Controller::onMessageReceived(const base::ByteArray& buffer)
{
    std::unique_ptr<proto::RouterToRelay> message = std::make_unique<proto::RouterToRelay>();
    if (!base::parse(buffer, message.get()))
    {
        LOG(LS_ERROR) << "Invalid message from router";
        return;
    }

    if (message->has_key_used())
    {
        std::shared_ptr<KeyDeleter> key_deleter =
            std::make_shared<KeyDeleter>(shared_pool_->share(), message->key_used().key_id());

        // The router gave the key to the peers. They are required to use it within 30 seconds.
        // If it is not used during this time, then it will be removed from the pool.
        task_runner_->postDelayedTask(
            std::bind(&KeyDeleter::deleteKey, key_deleter), std::chrono::seconds(30));
    }
    else
    {
        LOG(LS_WARNING) << "Unhandled message from router";
    }
}

void Controller::onMessageWritten(size_t /* pending */)
{
    // Nothing
}

void Controller::onSessionFinished()
{
    // After disconnecting the peer, one key is released.
    // Add a new key to the pool and send it to the router.
    sendKeyPool(1);
}

void Controller::onPoolKeyExpired(uint32_t /* key_id */)
{
    // The key has expired and has been removed from the pool.
    // Add a new key to the pool and send it to the router.
    sendKeyPool(1);
}

void Controller::connectToRouter()
{
    LOG(LS_INFO) << "Connecting to router...";

    // Create channel.
    channel_ = std::make_unique<base::NetworkChannel>();

    // Connect to router.
    channel_->setListener(this);
    channel_->connect(router_address_, router_port_);
}

void Controller::delayedConnectToRouter()
{
    LOG(LS_INFO) << "Reconnect after " << kReconnectTimeout.count() << " seconds";
    reconnect_timer_.start(kReconnectTimeout, std::bind(&Controller::connectToRouter, this));
}

void Controller::sendKeyPool(uint32_t key_count)
{
    std::unique_ptr<proto::RelayToRouter> message = std::make_unique<proto::RelayToRouter>();
    proto::RelayKeyPool* relay_key_pool = message->mutable_key_pool();

    relay_key_pool->set_peer_host(base::utf8FromUtf16(peer_address_));
    relay_key_pool->set_peer_port(peer_port_);

    // Add the requested number of keys to the pool.
    for (uint32_t i = 0; i < key_count; ++i)
    {
        SessionKey session_key = SessionKey::create();
        if (!session_key.isValid())
            return;

        // Add the key to the outgoing message.
        proto::RelayKey* key = relay_key_pool->add_key();

        key->set_type(proto::RelayKey::TYPE_X25519);
        key->set_encryption(proto::RelayKey::ENCRYPTION_CHACHA20_POLY1305);
        key->set_public_key(base::toStdString(session_key.publicKey()));
        key->set_iv(base::toStdString(session_key.iv()));

        // Add the key to the pool.
        key->set_key_id(shared_pool_->addKey(std::move(session_key)));
    }

    // Send a message to the router.
    channel_->send(base::serialize(*message));
}

} // namespace relay
<commit_msg>Cleanup.<commit_after>//
// Aspia Project
// Copyright (C) 2016-2022 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "relay/controller.h"

#include "base/logging.h"
#include "base/task_runner.h"
#include "base/peer/client_authenticator.h"
#include "proto/router_common.pb.h"
#include "relay/settings.h"

namespace relay {

namespace {

const std::chrono::seconds kReconnectTimeout{ 15 };

class KeyDeleter
{
public:
    KeyDeleter(std::unique_ptr<SharedPool> pool, uint32_t key_id)
        : pool_(std::move(pool)),
          key_id_(key_id)
    {
        DCHECK(pool_);
    }

    ~KeyDeleter() = default;

    void deleteKey()
    {
        pool_->setKeyExpired(key_id_);
    }

private:
    std::unique_ptr<SharedPool> pool_;
    const uint32_t key_id_;

    DISALLOW_COPY_AND_ASSIGN(KeyDeleter);
};

} // namespace

Controller::Controller(std::shared_ptr<base::TaskRunner> task_runner)
    : task_runner_(task_runner),
      reconnect_timer_(base::WaitableTimer::Type::SINGLE_SHOT, task_runner),
      shared_pool_(std::make_unique<SharedPool>(this))
{
    Settings settings;

    // Router settings.
    router_address_ = settings.routerAddress();
    router_port_ = settings.routerPort();
    router_public_key_ = settings.routerPublicKey();

    LOG(LS_INFO) << "Router address: " << router_address_;
    LOG(LS_INFO) << "Router port: " << router_port_;
    LOG(LS_INFO) << "Router public key: " << base::toHex(router_public_key_);

    // Peers settings.
    peer_address_ = settings.peerAddress();
    peer_port_ = settings.peerPort();
    peer_idle_timeout_ = settings.peerIdleTimeout();
    max_peer_count_ = settings.maxPeerCount();

    LOG(LS_INFO) << "Peer address: " << peer_address_;
    LOG(LS_INFO) << "Peer port: " << peer_port_;
    LOG(LS_INFO) << "Peer idle timeout: " << peer_idle_timeout_.count();
    LOG(LS_INFO) << "Max peer count: " << max_peer_count_;
}

Controller::~Controller() = default;

bool Controller::start()
{
    LOG(LS_INFO) << "Starting controller";

    if (router_address_.empty())
    {
        LOG(LS_ERROR) << "Empty router address";
        return false;
    }

    if (router_port_ == 0)
    {
        LOG(LS_ERROR) << "Invalid router port";
        return false;
    }

    if (router_public_key_.empty())
    {
        LOG(LS_ERROR) << "Empty router public key";
        return false;
    }

    if (peer_address_.empty())
    {
        LOG(LS_ERROR) << "Empty peer address";
        return false;
    }

    if (peer_port_ == 0)
    {
        LOG(LS_ERROR) << "Invalid peer port";
        return false;
    }

    if (peer_idle_timeout_ < std::chrono::minutes(1) || peer_idle_timeout_ > std::chrono::minutes(60))
    {
        LOG(LS_WARNING) << "Invalid peer idle specified";
        return false;
    }

    sessions_worker_ = std::make_unique<SessionsWorker>(
        peer_port_, peer_idle_timeout_, shared_pool_->share());
    sessions_worker_->start(task_runner_, this);

    connectToRouter();
    return true;
}

void Controller::onConnected()
{
    LOG(LS_INFO) << "Connection to the router is established";

    channel_->setOwnKeepAlive(true);
    channel_->setNoDelay(true);

    authenticator_ = std::make_unique<base::ClientAuthenticator>(task_runner_);

    authenticator_->setIdentify(proto::IDENTIFY_ANONYMOUS);
    authenticator_->setPeerPublicKey(router_public_key_);
    authenticator_->setSessionType(proto::ROUTER_SESSION_RELAY);

    authenticator_->start(std::move(channel_),
                          [this](base::ClientAuthenticator::ErrorCode error_code)
    {
        if (error_code == base::ClientAuthenticator::ErrorCode::SUCCESS)
        {
            // The authenticator takes the listener on itself, we return the receipt of
            // notifications.
            channel_ = authenticator_->takeChannel();
            channel_->setListener(this);

            LOG(LS_INFO) << "Authentication complete";

            // Now the session will receive incoming messages.
            channel_->resume();

            sendKeyPool(max_peer_count_);
        }
        else
        {
            LOG(LS_WARNING) << "Authentication failed: "
                            << base::ClientAuthenticator::errorToString(error_code);
            delayedConnectToRouter();
        }

        // Authenticator is no longer needed.
        task_runner_->deleteSoon(std::move(authenticator_));
    });
}

void Controller::onDisconnected(base::NetworkChannel::ErrorCode error_code)
{
    LOG(LS_INFO) << "The connection to the router has been lost: "
                 << base::NetworkChannel::errorToString(error_code);

    // Clearing the key pool.
    shared_pool_->clear();

    // Retrying a connection at a time interval.
    delayedConnectToRouter();
}

void Controller::onMessageReceived(const base::ByteArray& buffer)
{
    std::unique_ptr<proto::RouterToRelay> message = std::make_unique<proto::RouterToRelay>();
    if (!base::parse(buffer, message.get()))
    {
        LOG(LS_ERROR) << "Invalid message from router";
        return;
    }

    if (message->has_key_used())
    {
        std::shared_ptr<KeyDeleter> key_deleter =
            std::make_shared<KeyDeleter>(shared_pool_->share(), message->key_used().key_id());

        // The router gave the key to the peers. They are required to use it within 30 seconds.
        // If it is not used during this time, then it will be removed from the pool.
        task_runner_->postDelayedTask(
            std::bind(&KeyDeleter::deleteKey, key_deleter), std::chrono::seconds(30));
    }
    else
    {
        LOG(LS_WARNING) << "Unhandled message from router";
    }
}

void Controller::onMessageWritten(size_t /* pending */)
{
    // Nothing
}

void Controller::onSessionFinished()
{
    // After disconnecting the peer, one key is released.
    // Add a new key to the pool and send it to the router.
    sendKeyPool(1);
}

void Controller::onPoolKeyExpired(uint32_t /* key_id */)
{
    // The key has expired and has been removed from the pool.
    // Add a new key to the pool and send it to the router.
    sendKeyPool(1);
}

void Controller::connectToRouter()
{
    LOG(LS_INFO) << "Connecting to router...";

    // Create channel.
    channel_ = std::make_unique<base::NetworkChannel>();

    // Connect to router.
    channel_->setListener(this);
    channel_->connect(router_address_, router_port_);
}

void Controller::delayedConnectToRouter()
{
    LOG(LS_INFO) << "Reconnect after " << kReconnectTimeout.count() << " seconds";
    reconnect_timer_.start(kReconnectTimeout, std::bind(&Controller::connectToRouter, this));
}

void Controller::sendKeyPool(uint32_t key_count)
{
    std::unique_ptr<proto::RelayToRouter> message = std::make_unique<proto::RelayToRouter>();
    proto::RelayKeyPool* relay_key_pool = message->mutable_key_pool();

    relay_key_pool->set_peer_host(base::utf8FromUtf16(peer_address_));
    relay_key_pool->set_peer_port(peer_port_);

    // Add the requested number of keys to the pool.
    for (uint32_t i = 0; i < key_count; ++i)
    {
        SessionKey session_key = SessionKey::create();
        if (!session_key.isValid())
            return;

        // Add the key to the outgoing message.
        proto::RelayKey* key = relay_key_pool->add_key();

        key->set_type(proto::RelayKey::TYPE_X25519);
        key->set_encryption(proto::RelayKey::ENCRYPTION_CHACHA20_POLY1305);
        key->set_public_key(base::toStdString(session_key.publicKey()));
        key->set_iv(base::toStdString(session_key.iv()));

        // Add the key to the pool.
        key->set_key_id(shared_pool_->addKey(std::move(session_key)));
    }

    // Send a message to the router.
    channel_->send(base::serialize(*message));
}

} // namespace relay
<|endoftext|>