<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//*****************************************************************************
// unixinterface.cpp
//
// Implementation for the interface exposed by libcoreclr.so
//

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

#include "stdafx.h"
#include <utilcode.h>
#include <corhost.h>
#include <configuration.h>
#ifdef FEATURE_GDBJIT
#include "../../vm/gdbjithelpers.h"
#endif // FEATURE_GDBJIT

typedef int (STDMETHODCALLTYPE *HostMain)(
    const int argc,
    const wchar_t** argv
    );

#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr))

// Holder for const wide strings
typedef NewArrayHolder<const WCHAR> ConstWStringHolder;

// Holder for array of wide strings
class ConstWStringArrayHolder : public NewArrayHolder<LPCWSTR>
{
    int m_cElements;

public:
    ConstWStringArrayHolder() :
        NewArrayHolder<LPCWSTR>(),
        m_cElements(0)
    {
    }

    void Set(LPCWSTR* value, int cElements)
    {
        NewArrayHolder<LPCWSTR>::operator=(value);
        m_cElements = cElements;
    }

    ~ConstWStringArrayHolder()
    {
        for (int i = 0; i < m_cElements; i++)
        {
            delete [] this->m_value[i];
        }
    }
};

// Convert 8 bit string to unicode
static LPCWSTR StringToUnicode(LPCSTR str)
{
    int length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    ASSERTE_ALL_BUILDS(length != 0);

    LPWSTR result = new (nothrow) WCHAR[length];
    ASSERTE_ALL_BUILDS(result != NULL);

    length = MultiByteToWideChar(CP_UTF8, 0, str, -1, result, length);
    ASSERTE_ALL_BUILDS(length != 0);

    return result;
}

// Convert 8 bit string array to unicode string array
static LPCWSTR* StringArrayToUnicode(int argc, LPCSTR* argv)
{
    LPCWSTR* argvW = nullptr;

    if (argc > 0)
    {
        argvW = new (nothrow) LPCWSTR[argc];
        ASSERTE_ALL_BUILDS(argvW != 0);

        for (int i = 0; i < argc; i++)
        {
            argvW[i] = StringToUnicode(argv[i]);
        }
    }

    return argvW;
}

static void InitializeStartupFlags(STARTUP_FLAGS* startupFlagsRef)
{
    STARTUP_FLAGS startupFlags = static_cast<STARTUP_FLAGS>(
            STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN |
            STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN);

    if (Configuration::GetKnobBooleanValue(W("System.GC.Concurrent"), CLRConfig::UNSUPPORTED_gcConcurrent))
    {
        startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_CONCURRENT_GC);
    }
    if (Configuration::GetKnobBooleanValue(W("System.GC.Server"), CLRConfig::UNSUPPORTED_gcServer))
    {
        startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_SERVER_GC);
    }
    if (Configuration::GetKnobBooleanValue(W("System.GC.RetainVM"), CLRConfig::UNSUPPORTED_GCRetainVM))
    {
        startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_HOARD_GC_VM);
    }

    *startupFlagsRef = startupFlags;
}

static void ConvertConfigPropertiesToUnicode(
    const char** propertyKeys,
    const char** propertyValues,
    int propertyCount,
    LPCWSTR** propertyKeysWRef,
    LPCWSTR** propertyValuesWRef)
{
    LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount];
    ASSERTE_ALL_BUILDS(propertyKeysW != nullptr);

    LPCWSTR* propertyValuesW = new (nothrow) LPCWSTR[propertyCount];
    ASSERTE_ALL_BUILDS(propertyValuesW != nullptr);

    for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
    {
        propertyKeysW[propertyIndex] = StringToUnicode(propertyKeys[propertyIndex]);
        propertyValuesW[propertyIndex] = StringToUnicode(propertyValues[propertyIndex]);
    }

    *propertyKeysWRef = propertyKeysW;
    *propertyValuesWRef = propertyValuesW;
}

#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
// Reference to the global holding the path to the JIT
extern "C" LPCWSTR g_CLRJITPath;
#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)

#ifdef FEATURE_GDBJIT
GetInfoForMethodDelegate getInfoForMethodDelegate = NULL;
extern "C" int coreclr_create_delegate(void*, unsigned int, const char*, const char*, const char*, void**);
#endif //FEATURE_GDBJIT

//
// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
//
// Parameters:
//  exePath                 - Absolute path of the executable that invoked the ExecuteAssembly
//  appDomainFriendlyName   - Friendly name of the app domain that will be created to execute the assembly
//  propertyCount           - Number of properties (elements of the following two arguments)
//  propertyKeys            - Keys of properties of the app domain
//  propertyValues          - Values of properties of the app domain
//  hostHandle              - Output parameter, handle of the created host
//  domainId                - Output parameter, id of the created app domain
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_initialize(
            const char* exePath,
            const char* appDomainFriendlyName,
            int propertyCount,
            const char** propertyKeys,
            const char** propertyValues,
            void** hostHandle,
            unsigned int* domainId)
{
    HRESULT hr;
#ifdef FEATURE_PAL
    DWORD error = PAL_InitializeCoreCLR(exePath);
    hr = HRESULT_FROM_WIN32(error);

    // If PAL initialization failed, then we should return right away and avoid
    // calling any other APIs because they can end up calling into the PAL layer again.
    if (FAILED(hr))
    {
        return hr;
    }
#endif

    ReleaseHolder<ICLRRuntimeHost2> host;

    hr = CorHost2::CreateObject(IID_ICLRRuntimeHost2, (void**)&host);
    IfFailRet(hr);

    ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName);

    LPCWSTR* propertyKeysW;
    LPCWSTR* propertyValuesW;
    ConvertConfigPropertiesToUnicode(
        propertyKeys,
        propertyValues,
        propertyCount,
        &propertyKeysW,
        &propertyValuesW);

    // This will take ownership of propertyKeysWTemp and propertyValuesWTemp
    Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW);

#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
    // Fetch the path to JIT binary, if specified
    g_CLRJITPath = Configuration::GetKnobStringValue(W("JIT_PATH"));
#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)

    STARTUP_FLAGS startupFlags;
    InitializeStartupFlags(&startupFlags);

    hr = host->SetStartupFlags(startupFlags);
    IfFailRet(hr);

    hr = host->Start();
    IfFailRet(hr);

    hr = host->CreateAppDomainWithManager(
        appDomainFriendlyNameW,
        // Flags:
        // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS
        // - By default CoreCLR only allows platform neutral assembly to be run. To allow
        //   assemblies marked as platform specific, include this flag
        //
        // APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP
        // - Allows sandboxed applications to make P/Invoke calls and use COM interop
        //
        // APPDOMAIN_SECURITY_SANDBOXED
        // - Enables sandboxing. If not set, the app is considered full trust
        //
        // APPDOMAIN_IGNORE_UNHANDLED_EXCEPTION
        // - Prevents the application from being torn down if a managed exception is unhandled
        //
        APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS |
        APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP |
        APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT,
        NULL,                    // Name of the assembly that contains the AppDomainManager implementation
        NULL,                    // The AppDomainManager implementation type name
        propertyCount,
        propertyKeysW,
        propertyValuesW,
        (DWORD *)domainId);

    if (SUCCEEDED(hr))
    {
        host.SuppressRelease();
        *hostHandle = host;
#ifdef FEATURE_GDBJIT

        hr = coreclr_create_delegate(*hostHandle,
                                     *domainId,
                                     "SOS.NETCore",
                                     "SOS.SymbolReader",
                                     "GetInfoForMethod",
                                     (void**)&getInfoForMethodDelegate);

        if (!SUCCEEDED(hr))
        {
            fprintf(stderr,
                    "Can't create delegate for 'SOS.SymbolReader.GetInfoForMethod' "
                    "method - status: 0x%08x\n", hr);
        }

        hr = S_OK; // We don't need to fail if we can't create delegate
#endif
    }
    return hr;
}

//
// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
//
// Parameters:
//  hostHandle              - Handle of the host
//  domainId                - Id of the domain
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_shutdown(
            void* hostHandle,
            unsigned int domainId)
{
    ReleaseHolder<ICLRRuntimeHost2> host(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle));

    HRESULT hr = host->UnloadAppDomain(domainId, true); // Wait until done
    IfFailRet(hr);

    hr = host->Stop();

#ifdef FEATURE_PAL
    PAL_Shutdown();
#endif

    return hr;
}

//
// Create a native callable delegate for a managed method.
//
// Parameters:
//  hostHandle              - Handle of the host
//  domainId                - Id of the domain
//  entryPointAssemblyName  - Name of the assembly which holds the custom entry point
//  entryPointTypeName      - Name of the type which holds the custom entry point
//  entryPointMethodName    - Name of the method which is the custom entry point
//  delegate                - Output parameter, the function stores a pointer to the delegate at the specified address
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_create_delegate(
            void* hostHandle,
            unsigned int domainId,
            const char* entryPointAssemblyName,
            const char* entryPointTypeName,
            const char* entryPointMethodName,
            void** delegate)
{
    ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);

    ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName);
    ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName);
    ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName);

    HRESULT hr = host->CreateDelegate(
                            domainId,
                            entryPointAssemblyNameW,
                            entryPointTypeNameW,
                            entryPointMethodNameW,
                            (INT_PTR*)delegate);

    return hr;
}

//
// Execute a managed assembly with given arguments
//
// Parameters:
//  hostHandle              - Handle of the host
//  domainId                - Id of the domain
//  argc                    - Number of arguments passed to the executed assembly
//  argv                    - Array of arguments passed to the executed assembly
//  managedAssemblyPath     - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
//  exitCode                - Exit code returned by the executed assembly
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_execute_assembly(
            void* hostHandle,
            unsigned int domainId,
            int argc,
            const char** argv,
            const char* managedAssemblyPath,
            unsigned int* exitCode)
{
    if (exitCode == NULL)
    {
        return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
    }
    *exitCode = -1;

    ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);

    ConstWStringArrayHolder argvW;
    argvW.Set(StringArrayToUnicode(argc, argv), argc);

    ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath);

    HRESULT hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, (DWORD *)exitCode);
    IfFailRet(hr);

    return hr;
}
<commit_msg>Suppress SOS.NETCore.dll error msg in release mode (#6975)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//*****************************************************************************
// unixinterface.cpp
//
// Implementation for the interface exposed by libcoreclr.so
//

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

#include "stdafx.h"
#include <utilcode.h>
#include <corhost.h>
#include <configuration.h>
#ifdef FEATURE_GDBJIT
#include "../../vm/gdbjithelpers.h"
#endif // FEATURE_GDBJIT

typedef int (STDMETHODCALLTYPE *HostMain)(
    const int argc,
    const wchar_t** argv
    );

#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr))

// Holder for const wide strings
typedef NewArrayHolder<const WCHAR> ConstWStringHolder;

// Holder for array of wide strings
class ConstWStringArrayHolder : public NewArrayHolder<LPCWSTR>
{
    int m_cElements;

public:
    ConstWStringArrayHolder() :
        NewArrayHolder<LPCWSTR>(),
        m_cElements(0)
    {
    }

    void Set(LPCWSTR* value, int cElements)
    {
        NewArrayHolder<LPCWSTR>::operator=(value);
        m_cElements = cElements;
    }

    ~ConstWStringArrayHolder()
    {
        for (int i = 0; i < m_cElements; i++)
        {
            delete [] this->m_value[i];
        }
    }
};

// Convert 8 bit string to unicode
static LPCWSTR StringToUnicode(LPCSTR str)
{
    int length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    ASSERTE_ALL_BUILDS(length != 0);

    LPWSTR result = new (nothrow) WCHAR[length];
    ASSERTE_ALL_BUILDS(result != NULL);

    length = MultiByteToWideChar(CP_UTF8, 0, str, -1, result, length);
    ASSERTE_ALL_BUILDS(length != 0);

    return result;
}

// Convert 8 bit string array to unicode string array
static LPCWSTR* StringArrayToUnicode(int argc, LPCSTR* argv)
{
    LPCWSTR* argvW = nullptr;

    if (argc > 0)
    {
        argvW = new (nothrow) LPCWSTR[argc];
        ASSERTE_ALL_BUILDS(argvW != 0);

        for (int i = 0; i < argc; i++)
        {
            argvW[i] = StringToUnicode(argv[i]);
        }
    }

    return argvW;
}

static void InitializeStartupFlags(STARTUP_FLAGS* startupFlagsRef)
{
    STARTUP_FLAGS startupFlags = static_cast<STARTUP_FLAGS>(
            STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN |
            STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN);

    if (Configuration::GetKnobBooleanValue(W("System.GC.Concurrent"), CLRConfig::UNSUPPORTED_gcConcurrent))
    {
        startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_CONCURRENT_GC);
    }
    if (Configuration::GetKnobBooleanValue(W("System.GC.Server"), CLRConfig::UNSUPPORTED_gcServer))
    {
        startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_SERVER_GC);
    }
    if (Configuration::GetKnobBooleanValue(W("System.GC.RetainVM"), CLRConfig::UNSUPPORTED_GCRetainVM))
    {
        startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_HOARD_GC_VM);
    }

    *startupFlagsRef = startupFlags;
}

static void ConvertConfigPropertiesToUnicode(
    const char** propertyKeys,
    const char** propertyValues,
    int propertyCount,
    LPCWSTR** propertyKeysWRef,
    LPCWSTR** propertyValuesWRef)
{
    LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount];
    ASSERTE_ALL_BUILDS(propertyKeysW != nullptr);

    LPCWSTR* propertyValuesW = new (nothrow) LPCWSTR[propertyCount];
    ASSERTE_ALL_BUILDS(propertyValuesW != nullptr);

    for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
    {
        propertyKeysW[propertyIndex] = StringToUnicode(propertyKeys[propertyIndex]);
        propertyValuesW[propertyIndex] = StringToUnicode(propertyValues[propertyIndex]);
    }

    *propertyKeysWRef = propertyKeysW;
    *propertyValuesWRef = propertyValuesW;
}

#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
// Reference to the global holding the path to the JIT
extern "C" LPCWSTR g_CLRJITPath;
#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)

#ifdef FEATURE_GDBJIT
GetInfoForMethodDelegate getInfoForMethodDelegate = NULL;
extern "C" int coreclr_create_delegate(void*, unsigned int, const char*, const char*, const char*, void**);
#endif //FEATURE_GDBJIT

//
// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
//
// Parameters:
//  exePath                 - Absolute path of the executable that invoked the ExecuteAssembly
//  appDomainFriendlyName   - Friendly name of the app domain that will be created to execute the assembly
//  propertyCount           - Number of properties (elements of the following two arguments)
//  propertyKeys            - Keys of properties of the app domain
//  propertyValues          - Values of properties of the app domain
//  hostHandle              - Output parameter, handle of the created host
//  domainId                - Output parameter, id of the created app domain
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_initialize(
            const char* exePath,
            const char* appDomainFriendlyName,
            int propertyCount,
            const char** propertyKeys,
            const char** propertyValues,
            void** hostHandle,
            unsigned int* domainId)
{
    HRESULT hr;
#ifdef FEATURE_PAL
    DWORD error = PAL_InitializeCoreCLR(exePath);
    hr = HRESULT_FROM_WIN32(error);

    // If PAL initialization failed, then we should return right away and avoid
    // calling any other APIs because they can end up calling into the PAL layer again.
    if (FAILED(hr))
    {
        return hr;
    }
#endif

    ReleaseHolder<ICLRRuntimeHost2> host;

    hr = CorHost2::CreateObject(IID_ICLRRuntimeHost2, (void**)&host);
    IfFailRet(hr);

    ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName);

    LPCWSTR* propertyKeysW;
    LPCWSTR* propertyValuesW;
    ConvertConfigPropertiesToUnicode(
        propertyKeys,
        propertyValues,
        propertyCount,
        &propertyKeysW,
        &propertyValuesW);

    // This will take ownership of propertyKeysWTemp and propertyValuesWTemp
    Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW);

#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
    // Fetch the path to JIT binary, if specified
    g_CLRJITPath = Configuration::GetKnobStringValue(W("JIT_PATH"));
#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)

    STARTUP_FLAGS startupFlags;
    InitializeStartupFlags(&startupFlags);

    hr = host->SetStartupFlags(startupFlags);
    IfFailRet(hr);

    hr = host->Start();
    IfFailRet(hr);

    hr = host->CreateAppDomainWithManager(
        appDomainFriendlyNameW,
        // Flags:
        // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS
        // - By default CoreCLR only allows platform neutral assembly to be run. To allow
        //   assemblies marked as platform specific, include this flag
        //
        // APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP
        // - Allows sandboxed applications to make P/Invoke calls and use COM interop
        //
        // APPDOMAIN_SECURITY_SANDBOXED
        // - Enables sandboxing. If not set, the app is considered full trust
        //
        // APPDOMAIN_IGNORE_UNHANDLED_EXCEPTION
        // - Prevents the application from being torn down if a managed exception is unhandled
        //
        APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS |
        APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP |
        APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT,
        NULL,                    // Name of the assembly that contains the AppDomainManager implementation
        NULL,                    // The AppDomainManager implementation type name
        propertyCount,
        propertyKeysW,
        propertyValuesW,
        (DWORD *)domainId);

    if (SUCCEEDED(hr))
    {
        host.SuppressRelease();
        *hostHandle = host;
#ifdef FEATURE_GDBJIT
        HRESULT createDelegateResult;
        createDelegateResult = coreclr_create_delegate(*hostHandle,
                                                       *domainId,
                                                       "SOS.NETCore",
                                                       "SOS.SymbolReader",
                                                       "GetInfoForMethod",
                                                       (void**)&getInfoForMethodDelegate);

#if defined(_DEBUG)
        if (!SUCCEEDED(createDelegateResult))
        {
            fprintf(stderr,
                    "Can't create delegate for 'SOS.SymbolReader.GetInfoForMethod' "
                    "method - status: 0x%08x\n", createDelegateResult);
        }
#endif // _DEBUG

#endif
    }
    return hr;
}

//
// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
//
// Parameters:
//  hostHandle              - Handle of the host
//  domainId                - Id of the domain
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_shutdown(
            void* hostHandle,
            unsigned int domainId)
{
    ReleaseHolder<ICLRRuntimeHost2> host(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle));

    HRESULT hr = host->UnloadAppDomain(domainId, true); // Wait until done
    IfFailRet(hr);

    hr = host->Stop();

#ifdef FEATURE_PAL
    PAL_Shutdown();
#endif

    return hr;
}

//
// Create a native callable delegate for a managed method.
//
// Parameters:
//  hostHandle              - Handle of the host
//  domainId                - Id of the domain
//  entryPointAssemblyName  - Name of the assembly which holds the custom entry point
//  entryPointTypeName      - Name of the type which holds the custom entry point
//  entryPointMethodName    - Name of the method which is the custom entry point
//  delegate                - Output parameter, the function stores a pointer to the delegate at the specified address
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_create_delegate(
            void* hostHandle,
            unsigned int domainId,
            const char* entryPointAssemblyName,
            const char* entryPointTypeName,
            const char* entryPointMethodName,
            void** delegate)
{
    ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);

    ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName);
    ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName);
    ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName);

    HRESULT hr = host->CreateDelegate(
                            domainId,
                            entryPointAssemblyNameW,
                            entryPointTypeNameW,
                            entryPointMethodNameW,
                            (INT_PTR*)delegate);

    return hr;
}

//
// Execute a managed assembly with given arguments
//
// Parameters:
//  hostHandle              - Handle of the host
//  domainId                - Id of the domain
//  argc                    - Number of arguments passed to the executed assembly
//  argv                    - Array of arguments passed to the executed assembly
//  managedAssemblyPath     - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
//  exitCode                - Exit code returned by the executed assembly
//
// Returns:
//  HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
//
extern "C"
int coreclr_execute_assembly(
            void* hostHandle,
            unsigned int domainId,
            int argc,
            const char** argv,
            const char* managedAssemblyPath,
            unsigned int* exitCode)
{
    if (exitCode == NULL)
    {
        return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
    }
    *exitCode = -1;

    ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);

    ConstWStringArrayHolder argvW;
    argvW.Set(StringArrayToUnicode(argc, argv), argc);

    ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath);

    HRESULT hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, (DWORD *)exitCode);
    IfFailRet(hr);

    return hr;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2021 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "escape/HTML.hxx"
#include "escape/Class.hxx"
#include "escape/Static.hxx"

#include <gtest/gtest.h>

static const char *
html_unescape(const char *p)
{
	return unescape_static(&html_escape_class, p);
}

static size_t
html_unescape_inplace(char *p, size_t length)
{
	return unescape_inplace(&html_escape_class, p, length);
}

TEST(HtmlEscape, Basic)
{
	size_t length;

	ASSERT_STREQ(html_unescape("foo bar"), "foo bar");
	ASSERT_STREQ(html_unescape("foo&bar"), "foo&bar");
	ASSERT_STREQ(html_unescape("<>"), "<>");
	ASSERT_STREQ(html_unescape("""), "\"");
	ASSERT_STREQ(html_unescape("&amp;"), "&");
	ASSERT_STREQ(html_unescape("&&""), "&&\"");
	ASSERT_STREQ(html_unescape("&gt<'"), "&gt<'");

	char a[] = "foo bar";
	length = html_unescape_inplace(a, sizeof(a) - 1);
	ASSERT_EQ(length, 7u);

	char e[] = "foo&bar";
	length = html_unescape_inplace(e, sizeof(e) - 1);
	ASSERT_EQ(length, 7u);
	ASSERT_EQ(memcmp(e, "foo&bar", 7), 0);

	char f[] = "<foo>bar'";
	length = html_unescape_inplace(f, sizeof(f) - 1);
	ASSERT_EQ(length, 9u);
	ASSERT_EQ(memcmp(f, "<foo>bar'", 9), 0);

	char b[] = "<>'";
	length = html_unescape_inplace(b, sizeof(b) - 1);
	ASSERT_EQ(length, 3u);
	ASSERT_EQ(memcmp(b, "<>'", 3), 0);

	char c[] = "&quot";
	length = html_unescape_inplace(c, sizeof(c) - 1);
	ASSERT_EQ(length, 5u);
	ASSERT_EQ(memcmp(c, "&quot", 5), 0);

	char d[] = "&&"";
	length = html_unescape_inplace(d, sizeof(d) - 1);
	ASSERT_EQ(length, 3u);
	ASSERT_EQ(memcmp(d, "&&\"", 3), 0);
}
<commit_msg>test/t_html_escape: simplify using std::string_view<commit_after>/*
 * Copyright 2007-2021 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "escape/HTML.hxx"
#include "escape/Class.hxx"
#include "escape/Static.hxx"

#include <gtest/gtest.h>

#include <string_view>

using std::string_view_literals::operator""sv;

static const char *
html_unescape(const char *p)
{
	return unescape_static(&html_escape_class, p);
}

static std::string_view
html_unescape_inplace(char *p, size_t length)
{
	return {p, unescape_inplace(&html_escape_class, p, length)};
}

TEST(HtmlEscape, Basic)
{
	ASSERT_STREQ(html_unescape("foo bar"), "foo bar");
	ASSERT_STREQ(html_unescape("foo&bar"), "foo&bar");
	ASSERT_STREQ(html_unescape("<>"), "<>");
	ASSERT_STREQ(html_unescape("""), "\"");
	ASSERT_STREQ(html_unescape("&amp;"), "&");
	ASSERT_STREQ(html_unescape("&&""), "&&\"");
	ASSERT_STREQ(html_unescape("&gt<'"), "&gt<'");

	char a[] = "foo bar";
	ASSERT_EQ(html_unescape_inplace(a, sizeof(a) - 1), "foo bar"sv);

	char e[] = "foo&bar";
	ASSERT_EQ(html_unescape_inplace(e, sizeof(e) - 1), "foo&bar"sv);

	char f[] = "<foo>bar'";
	ASSERT_EQ(html_unescape_inplace(f, sizeof(f) - 1), "<foo>bar'"sv);

	char b[] = "<>'";
	ASSERT_EQ(html_unescape_inplace(b, sizeof(b) - 1), "<>'"sv);

	char c[] = "&quot";
	ASSERT_EQ(html_unescape_inplace(c, sizeof(c) - 1), "&quot"sv);

	char d[] = "&&"";
	ASSERT_EQ(html_unescape_inplace(d, sizeof(d) - 1), "&&\""sv);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define HAVE_EXPECT_100
#define HAVE_CHUNKED_REQUEST_BODY
#define ENABLE_CLOSE_IGNORED_REQUEST_BODY
#define ENABLE_HUGE_BODY
#define USE_BUCKETS

#include "t_client.hxx"
#include "http_client.hxx"
#include "http_headers.hxx"
#include "system/SetupProcess.hxx"
#include "io/FileDescriptor.hxx"
#include "net/SocketDescriptor.hxx"
#include "fs/FilteredSocket.hxx"
#include "direct.hxx"
#include "fb_pool.hxx"
#include "istream/UnusedPtr.hxx"

#include <sys/wait.h>

struct Connection {
    EventLoop &event_loop;
    const pid_t pid;
    FilteredSocket socket;

    Connection(EventLoop &_event_loop, pid_t _pid, SocketDescriptor fd)
        :event_loop(_event_loop), pid(_pid), socket(_event_loop) {
        socket.Init(fd, FdType::FD_SOCKET);
    }

    static Connection *New(EventLoop &event_loop,
                           const char *path, const char *mode);

    ~Connection();

    void Request(struct pool *pool,
                 Lease &lease,
                 http_method_t method, const char *uri,
                 StringMap &&headers,
                 UnusedIstreamPtr body,
                 bool expect_100,
                 HttpResponseHandler &handler,
                 CancellablePointer &cancel_ptr) {
        http_client_request(*pool, socket, lease,
                            "localhost",
                            method, uri, HttpHeaders(std::move(headers)),
                            std::move(body), expect_100,
                            handler, cancel_ptr);
    }

    static Connection *NewMirror(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "mirror");
    }

    static Connection *NewNull(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "null");
    }

    static Connection *NewDummy(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "dummy");
    }

    static Connection *NewClose(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "close");
    }

    static Connection *NewFixed(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "fixed");
    }

    static Connection *NewTiny(struct pool &p, EventLoop &event_loop) {
        return NewFixed(p, event_loop);
    }

    static Connection *NewHuge(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "huge");
    }

    static Connection *NewTwice100(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/twice_100.sh", nullptr);
    }

    static Connection *NewClose100(struct pool &, EventLoop &event_loop);

    static Connection *NewHold(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "hold");
    }
};

Connection::~Connection()
{
    assert(pid >= 1);

    socket.Close();
    socket.Destroy();

    int status;
    if (waitpid(pid, &status, 0) < 0) {
        perror("waitpid() failed");
        exit(EXIT_FAILURE);
    }

    assert(!WIFSIGNALED(status));
}

Connection *
Connection::New(EventLoop &event_loop, const char *path, const char *mode)
{
    SocketDescriptor client_socket, server_socket;
    if (!SocketDescriptor::CreateSocketPair(AF_LOCAL, SOCK_STREAM, 0,
                                            client_socket, server_socket)) {
        perror("socketpair() failed");
        exit(EXIT_FAILURE);
    }

    const auto pid = fork();
    if (pid < 0) {
        perror("fork() failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        server_socket.CheckDuplicate(FileDescriptor(STDIN_FILENO));
        server_socket.CheckDuplicate(FileDescriptor(STDOUT_FILENO));

        execl(path, path,
              "0", "0", mode, nullptr);

        const char *srcdir = getenv("srcdir");
        if (srcdir != nullptr) {
            /* support automake out-of-tree build */
            if (chdir(srcdir) == 0)
                execl(path, path,
                      "0", "0", mode, nullptr);
        }

        perror("exec() failed");
        _exit(EXIT_FAILURE);
    }

    server_socket.Close();
    client_socket.SetNonBlocking();
    return new Connection(event_loop, pid, client_socket);
}

Connection *
Connection::NewClose100(struct pool &, EventLoop &event_loop)
{
    SocketDescriptor client_socket, server_socket;
    if (!SocketDescriptor::CreateSocketPair(AF_LOCAL, SOCK_STREAM, 0,
                                            client_socket, server_socket)) {
        perror("socketpair() failed");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();
    if (pid < 0) {
        perror("fork() failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        client_socket.Close();

        static const char response[] = "HTTP/1.1 100 Continue\n\n";
        (void)server_socket.Write(response, sizeof(response) - 1);
        server_socket.ShutdownWrite();

        char buffer[64];
        while (server_socket.Read(buffer, sizeof(buffer)) > 0) {}

        _exit(EXIT_SUCCESS);
    }

    server_socket.Close();
    client_socket.SetNonBlocking();
    return new Connection(event_loop, pid, client_socket);
}

/**
 * Keep-alive disabled, and response body has unknown length, ends
 * when server closes socket.  Check if our HTTP client handles such
 * responses correctly.
 */
template<class Connection>
static void
test_no_keepalive(Context<Connection> &c)
{
    c.connection = Connection::NewClose(*c.pool, c.event_loop);
    c.connection->Request(c.pool, c,
                          HTTP_METHOD_GET, "/foo", StringMap(*c.pool),
                          nullptr,
#ifdef HAVE_EXPECT_100
                          false,
#endif
                          c, c.cancel_ptr);
    pool_unref(c.pool);
    pool_commit();

    c.WaitForResponse();

    assert(c.status == HTTP_STATUS_OK);
    assert(c.request_error == nullptr);

    /* receive the rest of the response body from the buffer */
    c.event_loop.Dispatch();

    assert(c.released);
    assert(c.body_eof);
    assert(c.body_data > 0);
    assert(c.body_error == nullptr);
}

/*
 * main
 *
 */

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

    SetupProcess();

    direct_global_init();
    const ScopeFbPoolInit fb_pool_init;

    run_all_tests<Connection>();
    run_test<Connection>(test_no_keepalive);
}
<commit_msg>test/t_http_client: add missing include<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define HAVE_EXPECT_100
#define HAVE_CHUNKED_REQUEST_BODY
#define ENABLE_CLOSE_IGNORED_REQUEST_BODY
#define ENABLE_HUGE_BODY
#define USE_BUCKETS

#include "t_client.hxx"
#include "http_client.hxx"
#include "http_headers.hxx"
#include "system/SetupProcess.hxx"
#include "io/FileDescriptor.hxx"
#include "net/SocketDescriptor.hxx"
#include "fs/FilteredSocket.hxx"
#include "direct.hxx"
#include "fb_pool.hxx"
#include "istream/UnusedPtr.hxx"

#include <sys/socket.h>
#include <sys/wait.h>

struct Connection {
    EventLoop &event_loop;
    const pid_t pid;
    FilteredSocket socket;

    Connection(EventLoop &_event_loop, pid_t _pid, SocketDescriptor fd)
        :event_loop(_event_loop), pid(_pid), socket(_event_loop) {
        socket.Init(fd, FdType::FD_SOCKET);
    }

    static Connection *New(EventLoop &event_loop,
                           const char *path, const char *mode);

    ~Connection();

    void Request(struct pool *pool,
                 Lease &lease,
                 http_method_t method, const char *uri,
                 StringMap &&headers,
                 UnusedIstreamPtr body,
                 bool expect_100,
                 HttpResponseHandler &handler,
                 CancellablePointer &cancel_ptr) {
        http_client_request(*pool, socket, lease,
                            "localhost",
                            method, uri, HttpHeaders(std::move(headers)),
                            std::move(body), expect_100,
                            handler, cancel_ptr);
    }

    static Connection *NewMirror(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "mirror");
    }

    static Connection *NewNull(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "null");
    }

    static Connection *NewDummy(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "dummy");
    }

    static Connection *NewClose(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "close");
    }

    static Connection *NewFixed(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "fixed");
    }

    static Connection *NewTiny(struct pool &p, EventLoop &event_loop) {
        return NewFixed(p, event_loop);
    }

    static Connection *NewHuge(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "huge");
    }

    static Connection *NewTwice100(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/twice_100.sh", nullptr);
    }

    static Connection *NewClose100(struct pool &, EventLoop &event_loop);

    static Connection *NewHold(struct pool &, EventLoop &event_loop) {
        return New(event_loop, "./test/run_http_server", "hold");
    }
};

Connection::~Connection()
{
    assert(pid >= 1);

    socket.Close();
    socket.Destroy();

    int status;
    if (waitpid(pid, &status, 0) < 0) {
        perror("waitpid() failed");
        exit(EXIT_FAILURE);
    }

    assert(!WIFSIGNALED(status));
}

Connection *
Connection::New(EventLoop &event_loop, const char *path, const char *mode)
{
    SocketDescriptor client_socket, server_socket;
    if (!SocketDescriptor::CreateSocketPair(AF_LOCAL, SOCK_STREAM, 0,
                                            client_socket, server_socket)) {
        perror("socketpair() failed");
        exit(EXIT_FAILURE);
    }

    const auto pid = fork();
    if (pid < 0) {
        perror("fork() failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        server_socket.CheckDuplicate(FileDescriptor(STDIN_FILENO));
        server_socket.CheckDuplicate(FileDescriptor(STDOUT_FILENO));

        execl(path, path,
              "0", "0", mode, nullptr);

        const char *srcdir = getenv("srcdir");
        if (srcdir != nullptr) {
            /* support automake out-of-tree build */
            if (chdir(srcdir) == 0)
                execl(path, path,
                      "0", "0", mode, nullptr);
        }

        perror("exec() failed");
        _exit(EXIT_FAILURE);
    }

    server_socket.Close();
    client_socket.SetNonBlocking();
    return new Connection(event_loop, pid, client_socket);
}

Connection *
Connection::NewClose100(struct pool &, EventLoop &event_loop)
{
    SocketDescriptor client_socket, server_socket;
    if (!SocketDescriptor::CreateSocketPair(AF_LOCAL, SOCK_STREAM, 0,
                                            client_socket, server_socket)) {
        perror("socketpair() failed");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();
    if (pid < 0) {
        perror("fork() failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        client_socket.Close();

        static const char response[] = "HTTP/1.1 100 Continue\n\n";
        (void)server_socket.Write(response, sizeof(response) - 1);
        server_socket.ShutdownWrite();

        char buffer[64];
        while (server_socket.Read(buffer, sizeof(buffer)) > 0) {}

        _exit(EXIT_SUCCESS);
    }

    server_socket.Close();
    client_socket.SetNonBlocking();
    return new Connection(event_loop, pid, client_socket);
}

/**
 * Keep-alive disabled, and response body has unknown length, ends
 * when server closes socket.  Check if our HTTP client handles such
 * responses correctly.
 */
template<class Connection>
static void
test_no_keepalive(Context<Connection> &c)
{
    c.connection = Connection::NewClose(*c.pool, c.event_loop);
    c.connection->Request(c.pool, c,
                          HTTP_METHOD_GET, "/foo", StringMap(*c.pool),
                          nullptr,
#ifdef HAVE_EXPECT_100
                          false,
#endif
                          c, c.cancel_ptr);
    pool_unref(c.pool);
    pool_commit();

    c.WaitForResponse();

    assert(c.status == HTTP_STATUS_OK);
    assert(c.request_error == nullptr);

    /* receive the rest of the response body from the buffer */
    c.event_loop.Dispatch();

    assert(c.released);
    assert(c.body_eof);
    assert(c.body_data > 0);
    assert(c.body_error == nullptr);
}

/*
 * main
 *
 */

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

    SetupProcess();

    direct_global_init();
    const ScopeFbPoolInit fb_pool_init;

    run_all_tests<Connection>();
    run_test<Connection>(test_no_keepalive);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: streamwrap.cxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#ifndef _OSL_STREAM_WRAPPER_HXX_
#include "streamwrap.hxx"
#endif
#include <osl/file.hxx>

namespace foo
{

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::osl;

//==================================================================
//= OInputStreamWrapper
//==================================================================
//------------------------------------------------------------------
OInputStreamWrapper::OInputStreamWrapper( File& _rStream )
                 :m_pSvStream(&_rStream)
                 ,m_bSvStreamOwner(sal_False)
{
}

//------------------------------------------------------------------
OInputStreamWrapper::OInputStreamWrapper( File* pStream, sal_Bool bOwner )
                 :m_pSvStream( pStream )
                 ,m_bSvStreamOwner( bOwner )
{
}

//------------------------------------------------------------------
OInputStreamWrapper::~OInputStreamWrapper()
{
    if( m_bSvStreamOwner )
        delete m_pSvStream;

}

//------------------------------------------------------------------------------
sal_Int32 SAL_CALL OInputStreamWrapper::readBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
                throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
    checkConnected();

    if (nBytesToRead < 0)
        throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this));

    ::osl::MutexGuard aGuard( m_aMutex );

    aData.realloc(nBytesToRead);

    sal_uInt64 nRead = 0;
    m_pSvStream->read((void*)aData.getArray(), nBytesToRead,nRead);

    checkError();

    // Wenn gelesene Zeichen < MaxLength, staruno::Sequence anpassen
    if (nRead < (sal_uInt64)nBytesToRead)
        aData.realloc( static_cast< sal_Int32 >( nRead ) );

    return static_cast< sal_Int32 >( nRead );
}

//------------------------------------------------------------------------------
sal_Int32 SAL_CALL OInputStreamWrapper::readSomeBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
    checkError();

    if (nMaxBytesToRead < 0)
        throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this));

    return readBytes(aData, nMaxBytesToRead);
}

//------------------------------------------------------------------------------
void SAL_CALL OInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
    ::osl::MutexGuard aGuard( m_aMutex );
    checkError();

    m_pSvStream->setPos(osl_Pos_Current,nBytesToSkip);
    checkError();
}

//------------------------------------------------------------------------------
sal_Int32 SAL_CALL OInputStreamWrapper::available() throw( stario::NotConnectedException, staruno::RuntimeException )
{
    ::osl::MutexGuard aGuard( m_aMutex );
    checkConnected();

    sal_uInt64 nPos = 0;
    m_pSvStream->getPos(nPos);
    checkError();

    m_pSvStream->setPos(Pos_End,0);
    checkError();

    sal_uInt64 nAvailable = 0;
    m_pSvStream->getPos(nAvailable);
    nAvailable -= nPos;

    m_pSvStream->setPos(Pos_Absolut,nPos);
    checkError();

    return static_cast< sal_Int32 >( nAvailable );
}

//------------------------------------------------------------------------------
void SAL_CALL OInputStreamWrapper::closeInput() throw( stario::NotConnectedException, staruno::RuntimeException )
{
    ::osl::MutexGuard aGuard( m_aMutex );
    checkConnected();

    if (m_bSvStreamOwner)
        delete m_pSvStream;

    m_pSvStream = NULL;
}

//------------------------------------------------------------------------------
void OInputStreamWrapper::checkConnected() const
{
    if (!m_pSvStream)
        throw stario::NotConnectedException(::rtl::OUString(), const_cast<staruno::XWeak*>(static_cast<const staruno::XWeak*>(this)));
}

//------------------------------------------------------------------------------
void OInputStreamWrapper::checkError() const
{
    checkConnected();
}

//==================================================================
//= OSeekableInputStreamWrapper
//==================================================================
//------------------------------------------------------------------------------
OSeekableInputStreamWrapper::OSeekableInputStreamWrapper(File& _rStream)
    :OInputStreamWrapper(_rStream)
{
}

//------------------------------------------------------------------------------
OSeekableInputStreamWrapper::OSeekableInputStreamWrapper(File* _pStream, sal_Bool _bOwner)
    :OInputStreamWrapper(_pStream, _bOwner)
{
}

//------------------------------------------------------------------------------
Any SAL_CALL OSeekableInputStreamWrapper::queryInterface( const Type& _rType ) throw (RuntimeException)
{
    Any aReturn = OInputStreamWrapper::queryInterface(_rType);
    if (!aReturn.hasValue())
        aReturn = OSeekableInputStreamWrapper_Base::queryInterface(_rType);
    return aReturn;
}

//------------------------------------------------------------------------------
void SAL_CALL OSeekableInputStreamWrapper::acquire(  ) throw ()
{
    OInputStreamWrapper::acquire();
}

//------------------------------------------------------------------------------
void SAL_CALL OSeekableInputStreamWrapper::release(  ) throw ()
{
    OInputStreamWrapper::release();
}

//------------------------------------------------------------------------------
void SAL_CALL OSeekableInputStreamWrapper::seek( sal_Int64 _nLocation ) throw (IllegalArgumentException, IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );
    checkConnected();

    m_pSvStream->setPos(Pos_Current,(sal_uInt32)_nLocation);
    checkError();
}

//------------------------------------------------------------------------------
sal_Int64 SAL_CALL OSeekableInputStreamWrapper::getPosition(  ) throw (IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );
    checkConnected();

    sal_uInt64 nPos = 0;
    nPos = m_pSvStream->getPos(nPos);
    checkError();
    return nPos;
}

//------------------------------------------------------------------------------
sal_Int64 SAL_CALL OSeekableInputStreamWrapper::getLength(  ) throw (IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );
    checkConnected();

    sal_uInt64 nCurrentPos = 0;
    m_pSvStream->getPos(nCurrentPos);
    checkError();

    m_pSvStream->setPos(osl_Pos_End,0);
    sal_uInt64 nEndPos = 0;
    m_pSvStream->getPos(nEndPos);
    m_pSvStream->setPos(osl_Pos_Absolut,nCurrentPos);

    checkError();

    return nEndPos;
}

//==================================================================
//= OOutputStreamWrapper
//==================================================================
//------------------------------------------------------------------------------
void SAL_CALL OOutputStreamWrapper::writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
    sal_uInt64 nWritten = 0;
    rStream.write(aData.getConstArray(),aData.getLength(),nWritten);
    if (nWritten != (sal_uInt64)aData.getLength())
    {
        throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this));
    }
}

//------------------------------------------------------------------
void SAL_CALL OOutputStreamWrapper::flush() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
}

//------------------------------------------------------------------
void SAL_CALL OOutputStreamWrapper::closeOutput() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
}

} // namespace utl

<commit_msg>INTEGRATION: CWS mba30patches01 (1.4.210); FILE MERGED 2008/04/23 10:57:48 mba 1.4.210.2: RESYNC: (1.4-1.5); FILE MERGED 2008/03/18 15:48:38 mba 1.4.210.1: #i86359#: remove unused code<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: streamwrap.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#ifndef _OSL_STREAM_WRAPPER_HXX_
#include "streamwrap.hxx"
#endif
#include <osl/file.hxx>

namespace foo
{

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::lang;
using namespace ::osl;

//==================================================================
//= OOutputStreamWrapper
//==================================================================
//------------------------------------------------------------------------------
void SAL_CALL OOutputStreamWrapper::writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
    sal_uInt64 nWritten = 0;
    rStream.write(aData.getConstArray(),aData.getLength(),nWritten);
    if (nWritten != (sal_uInt64)aData.getLength())
    {
        throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this));
    }
}

//------------------------------------------------------------------
void SAL_CALL OOutputStreamWrapper::flush() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
}

//------------------------------------------------------------------
void SAL_CALL OOutputStreamWrapper::closeOutput() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException )
{
}

} // namespace utl

<|endoftext|>


<commit_before><commit_msg>Related: fdo#66400 take uppercase of first field token<commit_after><|endoftext|>


<commit_before><commit_msg>Resolves: fdo#79130 Crash in DomainMapper_Impl::CloseFieldCommand<commit_after><|endoftext|>


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

#include "GeotiffSupport.hpp"

// GDAL
#ifdef LIBPC_HAVE_GDAL
#include <geo_normalize.h>
#include <ogr_spatialref.h>
#endif

#include <sstream>
#include <boost/concept_check.hpp>

LIBPC_C_START
#ifdef __geotiff_h_

#ifdef GEO_NORMALIZE_H_INCLUDED
char LIBPC_DLL * GTIFGetOGISDefn(GTIF*, GTIFDefn*);
#endif

int LIBPC_DLL GTIFSetFromOGISDefn(GTIF*, const char*);
void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName);

#ifdef _OGR_SRS_API_H_INCLUDED
void SetGeogCSCitation(GTIF* psGTIF, OGRSpatialReference* poSRS, char* angUnitName, int nDatum, short nSpheroid);
#endif // defined _OGR_SRS_API_H_INCLUDED

#endif // defined __geotiff_h_
LIBPC_C_END

namespace libpc { namespace drivers { namespace las {

GeotiffSupport::GeotiffSupport()
    : m_gtiff(0)
    , m_tiff(0)
{
}

GeotiffSupport::~GeotiffSupport()
{
#ifdef LIBPC_SRS_ENABLED
    if (m_gtiff != 0)
    {
        GTIFFree(m_gtiff);
        m_gtiff = 0;
    }
    if (m_tiff != 0)
    {
        ST_Destroy(m_tiff);
        m_tiff = 0;
    }
#endif
}

void GeotiffSupport::resetTags()
{
    // If we already have m_gtiff and m_tiff, that is because we have
    // already called GetGTIF once before.  VLRs ultimately drive how the
    // SpatialReference is defined, not the GeoTIFF keys.
    if (m_tiff != 0 )
    {
        ST_Destroy(m_tiff);
        m_tiff = 0;
    }

    if (m_gtiff != 0 )
    {
        GTIFFree(m_gtiff);
        m_gtiff = 0;
    }

    m_tiff = ST_Create();

    return;
}

int GeotiffSupport::setKey(int tag, int count, GeotiffKeyType geotiff_key_type, void *data)
{
    return ST_SetKey(m_tiff, tag, count, (int)geotiff_key_type, data);
}

int GeotiffSupport::getKey(int tag, int *count, int *st_type, void **data_ptr) const
{
    if (m_tiff == 0) return 0;
    return ST_GetKey(m_tiff, tag, count, st_type, data_ptr);
}

void GeotiffSupport::setTags()
{
    m_gtiff = GTIFNewSimpleTags(m_tiff);
    if (!m_gtiff)
        throw std::runtime_error("The geotiff keys could not be read from VLR records");
    return;
}

std::string GeotiffSupport::getWkt(bool horizOnly, bool pretty) const
{
    GTIFDefn sGTIFDefn;
    char* pszWKT = 0;

    if (!m_gtiff)
    {
        return std::string();
    }

    if (!GTIFGetDefn(m_gtiff, &sGTIFDefn))
    {
        return std::string();
    }

    pszWKT = GTIFGetOGISDefn(m_gtiff, &sGTIFDefn );

    if (pretty) {
        OGRSpatialReference* poSRS = (OGRSpatialReference*) OSRNewSpatialReference(NULL);
        char *pszOrigWKT = pszWKT;
        poSRS->importFromWkt( &pszOrigWKT );

        CPLFree( pszWKT );
        pszWKT = NULL;
        poSRS->exportToPrettyWkt(&pszWKT, false);
        OSRDestroySpatialReference( poSRS );

    }

    if( pszWKT
        && horizOnly
        && strstr(pszWKT,"COMPD_CS") != NULL )
    {
        OGRSpatialReference* poSRS = (OGRSpatialReference*) OSRNewSpatialReference(NULL);
        char *pszOrigWKT = pszWKT;
        poSRS->importFromWkt( &pszOrigWKT );

        CPLFree( pszWKT );
        pszWKT = NULL;

        poSRS->StripVertical();
        if (pretty)
            poSRS->exportToPrettyWkt(&pszWKT, false);
        else
            poSRS->exportToWkt( &pszWKT );

        OSRDestroySpatialReference( poSRS );
    }

    if (pszWKT)
    {
        std::string tmp(pszWKT);
        CPLFree(pszWKT);
        return tmp;
    }

    return std::string();
}

void GeotiffSupport::rebuildGTIF()
{
    // If we already have m_gtiff and m_tiff, that is because we have
    // already called GetGTIF once before.  VLRs ultimately drive how the
    // SpatialReference is defined, not the GeoTIFF keys.
    if (m_tiff != 0 )
    {
        ST_Destroy(m_tiff);
        m_tiff = 0;
    }

    if (m_gtiff != 0 )
    {
        GTIFFree(m_gtiff);
        m_gtiff = 0;
    }

    m_tiff = ST_Create();

    // (here it used to read in the VLRs)

    m_gtiff = GTIFNewSimpleTags(m_tiff);
    if (!m_gtiff)
        throw std::runtime_error("The geotiff keys could not be read from VLR records");

    return;
}

void GeotiffSupport::setWkt(const std::string& v)
{
    if (!m_gtiff)
    {
        rebuildGTIF();
    }

    if (v == "")
    {
        return;
    }

    int ret = 0;
    ret = GTIFSetFromOGISDefn(m_gtiff, v.c_str());
    if (!ret)
    {
        throw std::invalid_argument("could not set m_gtiff from WKT");
    }

    ret = GTIFWriteKeys(m_gtiff);
    if (!ret)
    {
        throw std::runtime_error("The geotiff keys could not be written");
    }

    return;
}

// Utility functor with accompanying to print GeoTIFF directory.
struct geotiff_dir_printer
{
    geotiff_dir_printer() {}

    std::string output() const { return m_oss.str(); }
    std::string::size_type size() const { return m_oss.str().size(); }

    void operator()(char* data, void* aux)
    {
        ::boost::ignore_unused_variable_warning(aux);

        if (0 != data)
        {
            m_oss << data;
        }
    }

private:
    std::ostringstream m_oss;
};

static int libpcGeoTIFFPrint(char* data, void* aux)
{
    geotiff_dir_printer* printer = reinterpret_cast<geotiff_dir_printer*>(aux);
    (*printer)(data, 0);
    return static_cast<int>(printer->size());
}

std::string GeotiffSupport::getText() const
{
    if (m_gtiff == NULL)
        return std::string("");

    geotiff_dir_printer geotiff_printer;
    GTIFPrint(m_gtiff, libpcGeoTIFFPrint, &geotiff_printer);
    const std::string s = geotiff_printer.output();
    return s;
}

#if 0

void SpatialReference::setVerticalCS(boost::int32_t verticalCSType,
                                     std::string const& citation,
                                     boost::int32_t verticalDatum,
                                     boost::int32_t verticalUnits)
{
    if (!m_tiffstuff->m_gtiff)
    {
        rebuildGTIF();
    }

#ifdef LIBPC_SRS_ENABLED
    if( verticalCSType != KvUserDefined && verticalCSType > 0 )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalCSTypeGeoKey, TYPE_SHORT, 1,
                    verticalCSType );

    if( citation != "" )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalCitationGeoKey, TYPE_ASCII, 0,
                    citation.c_str() );

    if( verticalDatum > 0 && verticalDatum != KvUserDefined )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalDatumGeoKey, TYPE_SHORT, 1,
                    verticalDatum );

    if( verticalUnits > 0 && verticalUnits != KvUserDefined )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalUnitsGeoKey, TYPE_SHORT, 1,
                    verticalUnits );

    int ret = GTIFWriteKeys(m_tiffstuff->m_gtiff);
    if (!ret)
    {
        throw std::runtime_error("The geotiff keys could not be written");
    }

    // Clear WKT so it gets regenerated
    m_wkt = std::string("");

#else
    boost::ignore_unused_variable_warning(citation);
    boost::ignore_unused_variable_warning(verticalUnits);
    boost::ignore_unused_variable_warning(verticalDatum);
    boost::ignore_unused_variable_warning(verticalCSType);
#endif

    return;
}

void SpatialReference::setProj4(std::string const& v)
{
    if (!m_tiffstuff->m_gtiff)
    {
        rebuildGTIF();
    }

#ifdef LIBPC_SRS_ENABLED
    char* poWKT = 0;
    const char* poProj4 = v.c_str();

    OGRSpatialReference srs(NULL);
    if (OGRERR_NONE != srs.importFromProj4(const_cast<char *>(poProj4)))
    {
        throw std::invalid_argument("could not import proj4 into OSRSpatialReference SetProj4");
    }

    srs.exportToWkt(&poWKT);

    std::string tmp(poWKT);
    CPLFree(poWKT);

    int ret = 0;
    ret = GTIFSetFromOGISDefn( m_tiffstuff->m_gtiff, tmp.c_str() );
    if (!ret)
    {
        throw std::invalid_argument("could not set m_gtiff from Proj4");
    }

    ret = GTIFWriteKeys(m_tiffstuff->m_gtiff);
    if (!ret)
    {
        throw std::runtime_error("The geotiff keys could not be written");
    }

    GTIFDefn defn;

    if (m_tiffstuff->m_gtiff && GTIFGetDefn(m_tiffstuff->m_gtiff, &defn))
    {
        char* proj4def = GTIFGetProj4Defn(&defn);
        std::string tmp(proj4def);
        GTIFFreeMemory( proj4def );
    }
#else
    boost::ignore_unused_variable_warning(v);
#endif

    return;
}

#endif

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

#include "GeotiffSupport.hpp"

// GDAL
#ifdef LIBPC_HAVE_GDAL
#include <geo_normalize.h>
#include <ogr_spatialref.h>

#endif

#include <sstream>

#include <boost/concept_check.hpp>

LIBPC_C_START
#ifdef __geotiff_h_

#ifdef GEO_NORMALIZE_H_INCLUDED
char LIBPC_DLL * GTIFGetOGISDefn(GTIF*, GTIFDefn*);
#endif

int LIBPC_DLL GTIFSetFromOGISDefn(GTIF*, const char*);
void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName);

#ifdef _OGR_SRS_API_H_INCLUDED
void SetGeogCSCitation(GTIF* psGTIF, OGRSpatialReference* poSRS, char* angUnitName, int nDatum, short nSpheroid);
#endif // defined _OGR_SRS_API_H_INCLUDED

#endif // defined __geotiff_h_
LIBPC_C_END

namespace libpc { namespace drivers { namespace las {

GeotiffSupport::GeotiffSupport()
    : m_gtiff(0)
    , m_tiff(0)
{
}

GeotiffSupport::~GeotiffSupport()
{
#ifdef LIBPC_SRS_ENABLED
    if (m_gtiff != 0)
    {
        GTIFFree(m_gtiff);
        m_gtiff = 0;
    }
    if (m_tiff != 0)
    {
        ST_Destroy(m_tiff);
        m_tiff = 0;
    }
#endif
}

void GeotiffSupport::resetTags()
{
    // If we already have m_gtiff and m_tiff, that is because we have
    // already called GetGTIF once before.  VLRs ultimately drive how the
    // SpatialReference is defined, not the GeoTIFF keys.
    if (m_tiff != 0 )
    {
        ST_Destroy(m_tiff);
        m_tiff = 0;
    }

    if (m_gtiff != 0 )
    {
        GTIFFree(m_gtiff);
        m_gtiff = 0;
    }

    m_tiff = ST_Create();

    return;
}

int GeotiffSupport::setKey(int tag, int count, GeotiffKeyType geotiff_key_type, void *data)
{
    return ST_SetKey(m_tiff, tag, count, (int)geotiff_key_type, data);
}

int GeotiffSupport::getKey(int tag, int *count, int *st_type, void **data_ptr) const
{
    if (m_tiff == 0) return 0;
    return ST_GetKey(m_tiff, tag, count, st_type, data_ptr);
}

void GeotiffSupport::setTags()
{
    m_gtiff = GTIFNewSimpleTags(m_tiff);
    if (!m_gtiff)
        throw std::runtime_error("The geotiff keys could not be read from VLR records");
    return;
}

std::string GeotiffSupport::getWkt(bool horizOnly, bool pretty) const
{
    GTIFDefn sGTIFDefn;
    char* pszWKT = 0;

    if (!m_gtiff)
    {
        return std::string();
    }

    if (!GTIFGetDefn(m_gtiff, &sGTIFDefn))
    {
        return std::string();
    }

    pszWKT = GTIFGetOGISDefn(m_gtiff, &sGTIFDefn );

    if (pretty) {
        OGRSpatialReference* poSRS = (OGRSpatialReference*) OSRNewSpatialReference(NULL);
        char *pszOrigWKT = pszWKT;
        poSRS->importFromWkt( &pszOrigWKT );

        CPLFree( pszWKT );
        pszWKT = NULL;
        poSRS->exportToPrettyWkt(&pszWKT, false);
        OSRDestroySpatialReference( poSRS );

    }

    if( pszWKT
        && horizOnly
        && strstr(pszWKT,"COMPD_CS") != NULL )
    {
        OGRSpatialReference* poSRS = (OGRSpatialReference*) OSRNewSpatialReference(NULL);
        char *pszOrigWKT = pszWKT;
        poSRS->importFromWkt( &pszOrigWKT );

        CPLFree( pszWKT );
        pszWKT = NULL;

        poSRS->StripVertical();
        if (pretty)
            poSRS->exportToPrettyWkt(&pszWKT, false);
        else
            poSRS->exportToWkt( &pszWKT );

        OSRDestroySpatialReference( poSRS );
    }

    if (pszWKT)
    {
        std::string tmp(pszWKT);
        CPLFree(pszWKT);
        return tmp;
    }

    return std::string();
}

void GeotiffSupport::rebuildGTIF()
{
    // If we already have m_gtiff and m_tiff, that is because we have
    // already called GetGTIF once before.  VLRs ultimately drive how the
    // SpatialReference is defined, not the GeoTIFF keys.
    if (m_tiff != 0 )
    {
        ST_Destroy(m_tiff);
        m_tiff = 0;
    }

    if (m_gtiff != 0 )
    {
        GTIFFree(m_gtiff);
        m_gtiff = 0;
    }

    m_tiff = ST_Create();

    // (here it used to read in the VLRs)

    m_gtiff = GTIFNewSimpleTags(m_tiff);
    if (!m_gtiff)
        throw std::runtime_error("The geotiff keys could not be read from VLR records");

    return;
}

void GeotiffSupport::setWkt(const std::string& v)
{
    if (!m_gtiff)
    {
        rebuildGTIF();
    }

    if (v == "")
    {
        return;
    }

    int ret = 0;
    ret = GTIFSetFromOGISDefn(m_gtiff, v.c_str());
    if (!ret)
    {
        throw std::invalid_argument("could not set m_gtiff from WKT");
    }

    ret = GTIFWriteKeys(m_gtiff);
    if (!ret)
    {
        throw std::runtime_error("The geotiff keys could not be written");
    }

    return;
}

// Utility functor with accompanying to print GeoTIFF directory.
struct geotiff_dir_printer
{
    geotiff_dir_printer() {}

    std::string output() const { return m_oss.str(); }
    std::string::size_type size() const { return m_oss.str().size(); }

    void operator()(char* data, void* aux)
    {
        ::boost::ignore_unused_variable_warning(aux);

        if (0 != data)
        {
            m_oss << data;
        }
    }

private:
    std::ostringstream m_oss;
};

static int libpcGeoTIFFPrint(char* data, void* aux)
{
    geotiff_dir_printer* printer = reinterpret_cast<geotiff_dir_printer*>(aux);
    (*printer)(data, 0);
    return static_cast<int>(printer->size());
}

std::string GeotiffSupport::getText() const
{
    if (m_gtiff == NULL)
        return std::string("");

    geotiff_dir_printer geotiff_printer;
    GTIFPrint(m_gtiff, libpcGeoTIFFPrint, &geotiff_printer);
    const std::string s = geotiff_printer.output();
    return s;
}

#if 0

void SpatialReference::setVerticalCS(boost::int32_t verticalCSType,
                                     std::string const& citation,
                                     boost::int32_t verticalDatum,
                                     boost::int32_t verticalUnits)
{
    if (!m_tiffstuff->m_gtiff)
    {
        rebuildGTIF();
    }

#ifdef LIBPC_SRS_ENABLED
    if( verticalCSType != KvUserDefined && verticalCSType > 0 )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalCSTypeGeoKey, TYPE_SHORT, 1,
                    verticalCSType );

    if( citation != "" )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalCitationGeoKey, TYPE_ASCII, 0,
                    citation.c_str() );

    if( verticalDatum > 0 && verticalDatum != KvUserDefined )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalDatumGeoKey, TYPE_SHORT, 1,
                    verticalDatum );

    if( verticalUnits > 0 && verticalUnits != KvUserDefined )
        GTIFKeySet( m_tiffstuff->m_gtiff, VerticalUnitsGeoKey, TYPE_SHORT, 1,
                    verticalUnits );

    int ret = GTIFWriteKeys(m_tiffstuff->m_gtiff);
    if (!ret)
    {
        throw std::runtime_error("The geotiff keys could not be written");
    }

    // Clear WKT so it gets regenerated
    m_wkt = std::string("");

#else
    boost::ignore_unused_variable_warning(citation);
    boost::ignore_unused_variable_warning(verticalUnits);
    boost::ignore_unused_variable_warning(verticalDatum);
    boost::ignore_unused_variable_warning(verticalCSType);
#endif

    return;
}

void SpatialReference::setProj4(std::string const& v)
{
    if (!m_tiffstuff->m_gtiff)
    {
        rebuildGTIF();
    }

#ifdef LIBPC_SRS_ENABLED
    char* poWKT = 0;
    const char* poProj4 = v.c_str();

    OGRSpatialReference srs(NULL);
    if (OGRERR_NONE != srs.importFromProj4(const_cast<char *>(poProj4)))
    {
        throw std::invalid_argument("could not import proj4 into OSRSpatialReference SetProj4");
    }

    srs.exportToWkt(&poWKT);

    std::string tmp(poWKT);
    CPLFree(poWKT);

    int ret = 0;
    ret = GTIFSetFromOGISDefn( m_tiffstuff->m_gtiff, tmp.c_str() );
    if (!ret)
    {
        throw std::invalid_argument("could not set m_gtiff from Proj4");
    }

    ret = GTIFWriteKeys(m_tiffstuff->m_gtiff);
    if (!ret)
    {
        throw std::runtime_error("The geotiff keys could not be written");
    }

    GTIFDefn defn;

    if (m_tiffstuff->m_gtiff && GTIFGetDefn(m_tiffstuff->m_gtiff, &defn))
    {
        char* proj4def = GTIFGetProj4Defn(&defn);
        std::string tmp(proj4def);
        GTIFFreeMemory( proj4def );
    }
#else
    boost::ignore_unused_variable_warning(v);
#endif

    return;
}

#endif

} } } // namespaces
<|endoftext|>


<commit_before>#include "KernelProgram.h"
#ifdef _WIN32
#include <Windows.h>
#endif

namespace FLIVR
{
	bool KernelProgram::init_ = false;
	cl_device_id KernelProgram::device_ = 0;
	cl_context KernelProgram::context_ = 0;

	KernelProgram::KernelProgram(const std::string& source) :
	source_(source), program_(0), kernel_(0), queue_(0)
	{
	}

	KernelProgram::~KernelProgram()
	{
	}

	void KernelProgram::init_kernels_supported()
	{
		if (init_)
			return;

		cl_int err;
		cl_platform_id platform;

		err = clGetPlatformIDs(1, &platform, NULL);
		if (err != CL_SUCCESS)
			return;

		err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device_, NULL);
		if (err != CL_SUCCESS)
			return;

		cl_context_properties properties[] =
		{
#ifdef _WIN32
			CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
			CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
#endif
			CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
			0
		};
		context_ = clCreateContext(properties, 1, &device_, NULL, NULL, &err);
		if (err != CL_SUCCESS)
			return;

		init_ = true;
	}

	bool KernelProgram::init()
	{
		return init_;
	}

	void KernelProgram::clear()
	{
		clReleaseContext(context_);
		init_ = false;
	}

	bool KernelProgram::create(std::string &name)
	{
		cl_int err;
		const char *c_source[1];
		c_source[0] = source_.c_str();
		size_t program_size = source_.size();
		program_ = clCreateProgramWithSource(context_, 1,
			c_source, &program_size, &err);
		if (err != CL_SUCCESS)
		{
			return false;
		}

		err = clBuildProgram(program_, 0, NULL, NULL, NULL, NULL);
		info_.clear();
		if (err != CL_SUCCESS)
		{
			char *program_log;
			size_t log_size;
			clGetProgramBuildInfo(program_, device_, CL_PROGRAM_BUILD_LOG,
				0, NULL, &log_size);
			program_log = new char[log_size+1];
			program_log[log_size] = '\0';
			clGetProgramBuildInfo(program_, device_, CL_PROGRAM_BUILD_LOG,
				log_size+1, program_log, NULL);
			info_ = program_log;
			delete []program_log;
			return false;
		}

		kernel_ = clCreateKernel(program_, name.c_str(), &err);
		if (err != CL_SUCCESS)
		{
			return false;
		}

		queue_ = clCreateCommandQueue(context_, device_, 0, &err);
		if (err != CL_SUCCESS)
		{
			return false;
		}

		return true;
	}

	bool KernelProgram::valid()
	{
		return init_ && program_ && kernel_ && queue_;
	}

	void KernelProgram::destroy()
	{
		clReleaseKernel(kernel_);
		for (unsigned int i=0; i<arg_list_.size(); ++i)
			clReleaseMemObject(arg_list_[i].buffer);
		clReleaseCommandQueue(queue_);
		clReleaseProgram(program_);
	}

	void KernelProgram::execute(cl_uint dim, size_t *global_size, size_t *local_size)
	{
		if (!valid())
			return;

		cl_int err;
		glFinish();
		unsigned int i;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].size == 0)
			{
				err = clEnqueueAcquireGLObjects(queue_, 1, &(arg_list_[i].buffer), 0, NULL, NULL);
				if (err != CL_SUCCESS)
					return;
			}
		}
		err = clEnqueueNDRangeKernel(queue_, kernel_, dim, NULL, global_size,
			local_size, 0, NULL, NULL);
		if (err != CL_SUCCESS)
			return;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].size == 0)
			{
				err = clEnqueueReleaseGLObjects(queue_, 1, &(arg_list_[i].buffer), 0, NULL, NULL);
				if (err != CL_SUCCESS)
					return;
			}
		}
		clFinish(queue_);
	}

	bool KernelProgram::matchArg(Argument* arg, unsigned int& arg_index)
	{
		for (unsigned int i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].index == arg->index &&
				arg_list_[i].size == arg->size &&
				arg_list_[i].texture == arg->texture)
			{
				arg_index = i;
				return true;
			}
		}
		return false;
	}

	void KernelProgram::setKernelArgConst(int i, size_t size, void* data)
	{
		cl_int err;

		if (!data)
			return;

		err = clSetKernelArg(kernel_, i, size, data);
		if (err != CL_SUCCESS)
			return;
	}

	void KernelProgram::setKernelArgBuf(int i, cl_mem_flags flag, size_t size, void* data)
	{
		cl_int err;

		if (data)
		{
			Argument arg;
			arg.index = i;
			arg.size = size;
			arg.texture = 0;
			unsigned int index;

			if (matchArg(&arg, index))
			{
				arg.buffer = arg_list_[index].buffer;
			}
			else
			{
				cl_mem buffer = clCreateBuffer(context_, flag, size, data, &err);
				if (err != CL_SUCCESS)
					return;
				arg.buffer = buffer;
				arg_list_.push_back(arg);
			}
			err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
			if (err != CL_SUCCESS)
				return;
		}
		else
		{
			err = clSetKernelArg(kernel_, i, size, NULL);
			if (err != CL_SUCCESS)
				return;
		}
	}

	void KernelProgram::setKernelArgBufWrite(int i, cl_mem_flags flag, size_t size, void* data)
	{
		cl_int err;

		if (data)
		{
			Argument arg;
			arg.index = i;
			arg.size = size;
			arg.texture = 0;
			unsigned int index;

			if (matchArg(&arg, index))
			{
				arg.buffer = arg_list_[index].buffer;
				clReleaseMemObject(arg_list_[index].buffer);
				arg.buffer = clCreateBuffer(context_, flag, size, data, &err);
				if (err != CL_SUCCESS)
					return;
			}
			else
			{
				cl_mem buffer = clCreateBuffer(context_, flag, size, data, &err);
				if (err != CL_SUCCESS)
					return;
				arg.buffer = buffer;
				arg_list_.push_back(arg);
			}

			err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
			if (err != CL_SUCCESS)
				return;
		}
		else
		{
			err = clSetKernelArg(kernel_, i, size, NULL);
			if (err != CL_SUCCESS)
				return;
		}
	}

	void KernelProgram::setKernelArgTex2D(int i, cl_mem_flags flag, GLuint texture)
	{
		cl_int err;
		Argument arg;
		arg.index = i;
		arg.size = 0;
		arg.texture = texture;
		unsigned int index;

		if (matchArg(&arg, index))
		{
			arg.buffer = arg_list_[index].buffer;
		}
		else
		{
			cl_mem tex_buffer = clCreateFromGLTexture2D(context_, flag, GL_TEXTURE_2D, 0, texture, &err);
			if (err != CL_SUCCESS)
				return;
			arg.buffer = tex_buffer;
			arg_list_.push_back(arg);
		}
		err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
		if (err != CL_SUCCESS)
			return;
	}

	void KernelProgram::setKernelArgTex3D(int i, cl_mem_flags flag, GLuint texture)
	{
		cl_int err;
		Argument arg;
		arg.index = i;
		arg.size = 0;
		arg.texture = texture;
		unsigned int index;

		if (matchArg(&arg, index))
		{
			arg.buffer = arg_list_[index].buffer;
		}
		else
		{
			cl_mem tex_buffer = clCreateFromGLTexture3D(context_, flag, GL_TEXTURE_3D, 0, texture, &err);
			if (err != CL_SUCCESS)
				return;
			arg.buffer = tex_buffer;
			arg_list_.push_back(arg);
		}
		err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
		if (err != CL_SUCCESS)
			return;
	}

	void KernelProgram::readBuffer(int index, void* data)
	{
		bool found = false;
		unsigned int i;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].index == index)
			{
				found = true;
				break;
			}
		}
		if (found)
		{
			Argument arg = arg_list_[i];
			cl_int err;
			err = clEnqueueReadBuffer(queue_, arg.buffer, CL_TRUE, 0,
				arg.size, data, 0, NULL, NULL);
			if (err != CL_SUCCESS)
				return;
		}
	}

	void KernelProgram::writeBuffer(int index, void* pattern,
		size_t pattern_size, size_t offset, size_t size)
	{
		bool found = false;
		unsigned int i;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].index == index)
			{
				found = true;
				break;
			}
		}
		if (found)
		{
			//not supported for 1.1
			//Argument arg = arg_list_[i];
			//cl_int err;
			//err = clEnqueueFillBuffer(queue_, arg.buffer, pattern,
			//	pattern_size, offset, size, 0, NULL, NULL);
			//if (err != CL_SUCCESS)
			//	return;
		}
	}

	std::string& KernelProgram::getInfo()
	{
		return info_;
	}
}<commit_msg>opencl kernel code for mac<commit_after>#include "KernelProgram.h"
#ifdef _WIN32
#include <Windows.h>
#endif

namespace FLIVR
{
	bool KernelProgram::init_ = false;
	cl_device_id KernelProgram::device_ = 0;
	cl_context KernelProgram::context_ = 0;

	KernelProgram::KernelProgram(const std::string& source) :
	source_(source), program_(0), kernel_(0), queue_(0)
	{
	}

	KernelProgram::~KernelProgram()
	{
	}

	void KernelProgram::init_kernels_supported()
	{
		if (init_)
			return;

		cl_int err;
		cl_platform_id platform;

		err = clGetPlatformIDs(1, &platform, NULL);
		if (err != CL_SUCCESS)
			return;

		err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device_, NULL);
		if (err != CL_SUCCESS)
			return;

		cl_context_properties properties[] =
		{
#ifdef _WIN32
			CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
			CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
#endif
#ifdef _DARWIN
			CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties) kCGLShareGroup,
#endif
			CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
			0
		};
	    context_ = clCreateContext(properties, 1, &device_, NULL, NULL, &err);
		if (err != CL_SUCCESS)
			return;

		init_ = true;
	}

	bool KernelProgram::init()
	{
		return init_;
	}

	void KernelProgram::clear()
	{
		clReleaseContext(context_);
		init_ = false;
	}

	bool KernelProgram::create(std::string &name)
	{
		cl_int err;
		const char *c_source[1];
		c_source[0] = source_.c_str();
		size_t program_size = source_.size();
		program_ = clCreateProgramWithSource(context_, 1,
			c_source, &program_size, &err);
		if (err != CL_SUCCESS)
		{
			return false;
		}

		err = clBuildProgram(program_, 0, NULL, NULL, NULL, NULL);
		info_.clear();
		if (err != CL_SUCCESS)
		{
			char *program_log;
			size_t log_size;
			clGetProgramBuildInfo(program_, device_, CL_PROGRAM_BUILD_LOG,
				0, NULL, &log_size);
			program_log = new char[log_size+1];
			program_log[log_size] = '\0';
			clGetProgramBuildInfo(program_, device_, CL_PROGRAM_BUILD_LOG,
				log_size+1, program_log, NULL);
			info_ = program_log;
			delete []program_log;
			return false;
		}

		kernel_ = clCreateKernel(program_, name.c_str(), &err);
		if (err != CL_SUCCESS)
		{
			return false;
		}

		queue_ = clCreateCommandQueue(context_, device_, 0, &err);
		if (err != CL_SUCCESS)
		{
			return false;
		}

		return true;
	}

	bool KernelProgram::valid()
	{
		return init_ && program_ && kernel_ && queue_;
	}

	void KernelProgram::destroy()
	{
		clReleaseKernel(kernel_);
		for (unsigned int i=0; i<arg_list_.size(); ++i)
			clReleaseMemObject(arg_list_[i].buffer);
		clReleaseCommandQueue(queue_);
		clReleaseProgram(program_);
	}

	void KernelProgram::execute(cl_uint dim, size_t *global_size, size_t *local_size)
	{
		if (!valid())
			return;

		cl_int err;
		glFinish();
		unsigned int i;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].size == 0)
			{
				err = clEnqueueAcquireGLObjects(queue_, 1, &(arg_list_[i].buffer), 0, NULL, NULL);
				if (err != CL_SUCCESS)
					return;
			}
		}
		err = clEnqueueNDRangeKernel(queue_, kernel_, dim, NULL, global_size,
			local_size, 0, NULL, NULL);
		if (err != CL_SUCCESS)
			return;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].size == 0)
			{
				err = clEnqueueReleaseGLObjects(queue_, 1, &(arg_list_[i].buffer), 0, NULL, NULL);
				if (err != CL_SUCCESS)
					return;
			}
		}
		clFinish(queue_);
	}

	bool KernelProgram::matchArg(Argument* arg, unsigned int& arg_index)
	{
		for (unsigned int i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].index == arg->index &&
				arg_list_[i].size == arg->size &&
				arg_list_[i].texture == arg->texture)
			{
				arg_index = i;
				return true;
			}
		}
		return false;
	}

	void KernelProgram::setKernelArgConst(int i, size_t size, void* data)
	{
		cl_int err;

		if (!data)
			return;

		err = clSetKernelArg(kernel_, i, size, data);
		if (err != CL_SUCCESS)
			return;
	}

	void KernelProgram::setKernelArgBuf(int i, cl_mem_flags flag, size_t size, void* data)
	{
		cl_int err;

		if (data)
		{
			Argument arg;
			arg.index = i;
			arg.size = size;
			arg.texture = 0;
			unsigned int index;

			if (matchArg(&arg, index))
			{
				arg.buffer = arg_list_[index].buffer;
			}
			else
			{
				cl_mem buffer = clCreateBuffer(context_, flag, size, data, &err);
				if (err != CL_SUCCESS)
					return;
				arg.buffer = buffer;
				arg_list_.push_back(arg);
			}
			err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
			if (err != CL_SUCCESS)
				return;
		}
		else
		{
			err = clSetKernelArg(kernel_, i, size, NULL);
			if (err != CL_SUCCESS)
				return;
		}
	}

	void KernelProgram::setKernelArgBufWrite(int i, cl_mem_flags flag, size_t size, void* data)
	{
		cl_int err;

		if (data)
		{
			Argument arg;
			arg.index = i;
			arg.size = size;
			arg.texture = 0;
			unsigned int index;

			if (matchArg(&arg, index))
			{
				arg.buffer = arg_list_[index].buffer;
				clReleaseMemObject(arg_list_[index].buffer);
				arg.buffer = clCreateBuffer(context_, flag, size, data, &err);
				if (err != CL_SUCCESS)
					return;
			}
			else
			{
				cl_mem buffer = clCreateBuffer(context_, flag, size, data, &err);
				if (err != CL_SUCCESS)
					return;
				arg.buffer = buffer;
				arg_list_.push_back(arg);
			}

			err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
			if (err != CL_SUCCESS)
				return;
		}
		else
		{
			err = clSetKernelArg(kernel_, i, size, NULL);
			if (err != CL_SUCCESS)
				return;
		}
	}

	void KernelProgram::setKernelArgTex2D(int i, cl_mem_flags flag, GLuint texture)
	{
		cl_int err;
		Argument arg;
		arg.index = i;
		arg.size = 0;
		arg.texture = texture;
		unsigned int index;

		if (matchArg(&arg, index))
		{
			arg.buffer = arg_list_[index].buffer;
		}
		else
		{
			cl_mem tex_buffer = clCreateFromGLTexture2D(context_, flag, GL_TEXTURE_2D, 0, texture, &err);
			if (err != CL_SUCCESS)
				return;
			arg.buffer = tex_buffer;
			arg_list_.push_back(arg);
		}
		err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
		if (err != CL_SUCCESS)
			return;
	}

	void KernelProgram::setKernelArgTex3D(int i, cl_mem_flags flag, GLuint texture)
	{
		cl_int err;
		Argument arg;
		arg.index = i;
		arg.size = 0;
		arg.texture = texture;
		unsigned int index;

		if (matchArg(&arg, index))
		{
			arg.buffer = arg_list_[index].buffer;
		}
		else
		{
			cl_mem tex_buffer = clCreateFromGLTexture3D(context_, flag, GL_TEXTURE_3D, 0, texture, &err);
			if (err != CL_SUCCESS)
				return;
			arg.buffer = tex_buffer;
			arg_list_.push_back(arg);
		}
		err = clSetKernelArg(kernel_, i, sizeof(cl_mem), &(arg.buffer));
		if (err != CL_SUCCESS)
			return;
	}

	void KernelProgram::readBuffer(int index, void* data)
	{
		bool found = false;
		unsigned int i;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].index == index)
			{
				found = true;
				break;
			}
		}
		if (found)
		{
			Argument arg = arg_list_[i];
			cl_int err;
			err = clEnqueueReadBuffer(queue_, arg.buffer, CL_TRUE, 0,
				arg.size, data, 0, NULL, NULL);
			if (err != CL_SUCCESS)
				return;
		}
	}

	void KernelProgram::writeBuffer(int index, void* pattern,
		size_t pattern_size, size_t offset, size_t size)
	{
		bool found = false;
		unsigned int i;
		for (i=0; i<arg_list_.size(); ++i)
		{
			if (arg_list_[i].index == index)
			{
				found = true;
				break;
			}
		}
		if (found)
		{
			//not supported for 1.1
			//Argument arg = arg_list_[i];
			//cl_int err;
			//err = clEnqueueFillBuffer(queue_, arg.buffer, pattern,
			//	pattern_size, offset, size, 0, NULL, NULL);
			//if (err != CL_SUCCESS)
			//	return;
		}
	}

	std::string& KernelProgram::getInfo()
	{
		return info_;
	}
}<|endoftext|>