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

#include "uno/environment.hxx"

#include "cppu/EnvDcp.hxx"
#include "cppu/Enterable.hxx"

#include "rtl/instance.hxx"

#include "osl/thread.h"
#include "osl/mutex.hxx"

#include <boost/unordered_map.hpp>

using namespace com::sun::star;

struct SAL_DLLPRIVATE oslThreadIdentifier_equal
{
    bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const;
};

bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const
{
    bool result = s1 == s2;

    return result;
}

struct SAL_DLLPRIVATE oslThreadIdentifier_hash
{
    size_t operator()(oslThreadIdentifier s1) const;
};

size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const
{
    return s1;
}

typedef ::boost::unordered_map<oslThreadIdentifier,
                        uno_Environment *,
                        oslThreadIdentifier_hash,
                        oslThreadIdentifier_equal>  ThreadMap;

namespace
{
    struct s_threadMap_mutex : public rtl::Static< osl::Mutex, s_threadMap_mutex > {};
    struct s_threadMap : public rtl::Static< ThreadMap, s_threadMap > {};
}

static rtl::OUString s_uno_envDcp(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO));

static void s_setCurrent(uno_Environment * pEnv)
{
    oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL);

    osl::MutexGuard guard(s_threadMap_mutex::get());
    ThreadMap &rThreadMap = s_threadMap::get();
    if (pEnv)
        rThreadMap[threadId] = pEnv;

    else
    {
        ThreadMap::iterator iEnv = rThreadMap.find(threadId);
        rThreadMap.erase(iEnv);
    }
}

static uno_Environment * s_getCurrent(void)
{
    uno_Environment * pEnv = NULL;

    oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL);

    osl::MutexGuard guard(s_threadMap_mutex::get());
    ThreadMap &rThreadMap = s_threadMap::get();
    ThreadMap::iterator iEnv = rThreadMap.find(threadId);
    if(iEnv != rThreadMap.end())
        pEnv = iEnv->second;

    return pEnv;
}

extern "C" void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName)
    SAL_THROW_EXTERN_C()
{
    if (*ppEnv)
    {
        (*ppEnv)->release(*ppEnv);
        *ppEnv = NULL;
    }

    rtl::OUString currPurpose;

    uno_Environment * pCurrEnv = s_getCurrent();
    if (pCurrEnv) // no environment means no purpose
        currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);

    if (pTypeName && rtl_uString_getLength(pTypeName))
    {
        rtl::OUString envDcp(pTypeName);
        envDcp += currPurpose;

        uno_getEnvironment(ppEnv, envDcp.pData, NULL);
    }
    else
    {
        if (pCurrEnv)
        {
            *ppEnv = pCurrEnv;
            (*ppEnv)->acquire(*ppEnv);
        }
        else
            uno_getEnvironment(ppEnv, s_uno_envDcp.pData, NULL);

    }
}

static rtl::OUString s_getPrefix(rtl::OUString const & str1, rtl::OUString const & str2)
{
    sal_Int32 nIndex1 = 0;
    sal_Int32 nIndex2 = 0;
    sal_Int32 sim = 0;

    rtl::OUString token1;
    rtl::OUString token2;

    do
    {
        token1 = str1.getToken(0, ':', nIndex1);
        token2 = str2.getToken(0, ':', nIndex2);

        if (token1.equals(token2))
            sim += token1.getLength() + 1;
    }
    while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2));

    rtl::OUString result;

    if (sim)
        result = str1.copy(0, sim - 1);

    return result;
}

static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv)
{
    int res = 0;

    rtl::OUString nextPurpose;

    rtl::OUString currPurpose;
    if (pCurrEnv)
        currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);

    rtl::OUString targetPurpose;
    if (pTargetEnv)
        targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName);

    rtl::OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose));
    if (currPurpose.getLength() > intermPurpose.getLength())
    {
        sal_Int32 idx = currPurpose.lastIndexOf(':');
        nextPurpose = currPurpose.copy(0, idx);

        res = -1;
    }
    else if (intermPurpose.getLength() < targetPurpose.getLength())
    {
        sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1);
        if (idx == -1)
            nextPurpose = targetPurpose;

        else
            nextPurpose = targetPurpose.copy(0, idx);

        res = 1;
    }

    if (nextPurpose.getLength())
    {
        rtl::OUString next_envDcp(s_uno_envDcp);
        next_envDcp += nextPurpose;

        uno_getEnvironment(ppEnv, next_envDcp.pData, NULL);
    }
    else
    {
        if (*ppEnv)
            (*ppEnv)->release(*ppEnv);

        *ppEnv = NULL;
    }

    return res;
}

extern "C" { static void s_pull(va_list * pParam)
{
    uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
    va_list       * pXparam = va_arg(*pParam, va_list *);

    pCallee(pXparam);
}}

static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
{
    cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
    if (pEnterable)
        pEnterable->callInto(s_pull, pCallee, pParam);

    else
        pCallee(pParam);
}

static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
{
    va_list param;

    va_start(param, pCallee);
    s_callInto_v(pEnv, pCallee, &param);
    va_end(param);
}

static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
{
    cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
    if (pEnterable)
        pEnterable->callOut_v(pCallee, pParam);

    else
        pCallee(pParam);
}

static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
{
    va_list param;

    va_start(param, pCallee);
    s_callOut_v(pEnv, pCallee, &param);
    va_end(param);
}

static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *);

extern "C" { static void s_environment_invoke_vv(va_list * pParam)
{
    uno_Environment * pCurrEnv    = va_arg(*pParam, uno_Environment *);
    uno_Environment * pTargetEnv  = va_arg(*pParam, uno_Environment *);
    uno_EnvCallee   * pCallee     = va_arg(*pParam, uno_EnvCallee *);
    va_list         * pXparam     = va_arg(*pParam, va_list *);

    s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam);
}}

static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
{
    uno_Environment * pNextEnv = NULL;
    switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv))
    {
    case -1:
        s_setCurrent(pNextEnv);
        s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
        s_setCurrent(pCurrEnv);
        break;

    case 0: {
        uno_Environment * hld = s_getCurrent();
        s_setCurrent(pCurrEnv);
        pCallee(pParam);
        s_setCurrent(hld);
    }
        break;

    case 1:
        s_setCurrent(pNextEnv);
        s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
        s_setCurrent(pCurrEnv);
        break;
    }

    if (pNextEnv)
        pNextEnv->release(pNextEnv);
}

extern "C" void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
    SAL_THROW_EXTERN_C()
{
    s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam);
}

extern "C" void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
    SAL_THROW_EXTERN_C()
{
    va_list param;

    va_start(param, pCallee);
    uno_Environment_invoke_v(pEnv, pCallee, &param);
    va_end(param);
}

extern "C" void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv)
    SAL_THROW_EXTERN_C()
{
    uno_Environment * pNextEnv = NULL;
    uno_Environment * pCurrEnv = s_getCurrent();

    int res;
    while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0)
    {
        cppu::Enterable * pEnterable;

        switch(res)
        {
        case -1:
            pEnterable = reinterpret_cast<cppu::Enterable *>(pCurrEnv->pReserved);
            if (pEnterable)
                pEnterable->leave();
            pCurrEnv->release(pCurrEnv);
            break;

        case 1:
            pNextEnv->acquire(pNextEnv);
            pEnterable = reinterpret_cast<cppu::Enterable *>(pNextEnv->pReserved);
            if (pEnterable)
                pEnterable->enter();
            break;
        }

        s_setCurrent(pNextEnv);
        pCurrEnv = pNextEnv;
    }
}

int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason)
    SAL_THROW_EXTERN_C()
{
    int result = 1;

    rtl::OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName));
    if (typeName.equals(s_uno_envDcp))
    {
        cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
        if (pEnterable)
            result = pEnterable->isValid((rtl::OUString *)pReason);
    }
    else
    {
        rtl::OUString envDcp(s_uno_envDcp);
        envDcp += cppu::EnvDcp::getPurpose(pEnv->pTypeName);

        uno::Environment env(envDcp);

        result = env.isValid((rtl::OUString *)pReason);
    }

    return result;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>don't crash trying to erase one past end<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "uno/environment.hxx"

#include "cppu/EnvDcp.hxx"
#include "cppu/Enterable.hxx"

#include "rtl/instance.hxx"

#include "osl/thread.h"
#include "osl/mutex.hxx"

#include <boost/unordered_map.hpp>

using namespace com::sun::star;

struct SAL_DLLPRIVATE oslThreadIdentifier_equal
{
    bool operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const;
};

bool oslThreadIdentifier_equal::operator()(oslThreadIdentifier s1, oslThreadIdentifier s2) const
{
    bool result = s1 == s2;

    return result;
}

struct SAL_DLLPRIVATE oslThreadIdentifier_hash
{
    size_t operator()(oslThreadIdentifier s1) const;
};

size_t oslThreadIdentifier_hash::operator()(oslThreadIdentifier s1) const
{
    return s1;
}

typedef ::boost::unordered_map<oslThreadIdentifier,
                        uno_Environment *,
                        oslThreadIdentifier_hash,
                        oslThreadIdentifier_equal>  ThreadMap;

namespace
{
    struct s_threadMap_mutex : public rtl::Static< osl::Mutex, s_threadMap_mutex > {};
    struct s_threadMap : public rtl::Static< ThreadMap, s_threadMap > {};
}

static rtl::OUString s_uno_envDcp(RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO));

static void s_setCurrent(uno_Environment * pEnv)
{
    oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL);

    osl::MutexGuard guard(s_threadMap_mutex::get());
    ThreadMap &rThreadMap = s_threadMap::get();
    if (pEnv)
        rThreadMap[threadId] = pEnv;

    else
        rThreadMap.erase(threadId);
}

static uno_Environment * s_getCurrent(void)
{
    uno_Environment * pEnv = NULL;

    oslThreadIdentifier threadId = osl_getThreadIdentifier(NULL);

    osl::MutexGuard guard(s_threadMap_mutex::get());
    ThreadMap &rThreadMap = s_threadMap::get();
    ThreadMap::iterator iEnv = rThreadMap.find(threadId);
    if(iEnv != rThreadMap.end())
        pEnv = iEnv->second;

    return pEnv;
}

extern "C" void SAL_CALL uno_getCurrentEnvironment(uno_Environment ** ppEnv, rtl_uString * pTypeName)
    SAL_THROW_EXTERN_C()
{
    if (*ppEnv)
    {
        (*ppEnv)->release(*ppEnv);
        *ppEnv = NULL;
    }

    rtl::OUString currPurpose;

    uno_Environment * pCurrEnv = s_getCurrent();
    if (pCurrEnv) // no environment means no purpose
        currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);

    if (pTypeName && rtl_uString_getLength(pTypeName))
    {
        rtl::OUString envDcp(pTypeName);
        envDcp += currPurpose;

        uno_getEnvironment(ppEnv, envDcp.pData, NULL);
    }
    else
    {
        if (pCurrEnv)
        {
            *ppEnv = pCurrEnv;
            (*ppEnv)->acquire(*ppEnv);
        }
        else
            uno_getEnvironment(ppEnv, s_uno_envDcp.pData, NULL);

    }
}

static rtl::OUString s_getPrefix(rtl::OUString const & str1, rtl::OUString const & str2)
{
    sal_Int32 nIndex1 = 0;
    sal_Int32 nIndex2 = 0;
    sal_Int32 sim = 0;

    rtl::OUString token1;
    rtl::OUString token2;

    do
    {
        token1 = str1.getToken(0, ':', nIndex1);
        token2 = str2.getToken(0, ':', nIndex2);

        if (token1.equals(token2))
            sim += token1.getLength() + 1;
    }
    while(nIndex1 == nIndex2 && nIndex1 >= 0 && token1.equals(token2));

    rtl::OUString result;

    if (sim)
        result = str1.copy(0, sim - 1);

    return result;
}

static int s_getNextEnv(uno_Environment ** ppEnv, uno_Environment * pCurrEnv, uno_Environment * pTargetEnv)
{
    int res = 0;

    rtl::OUString nextPurpose;

    rtl::OUString currPurpose;
    if (pCurrEnv)
        currPurpose = cppu::EnvDcp::getPurpose(pCurrEnv->pTypeName);

    rtl::OUString targetPurpose;
    if (pTargetEnv)
        targetPurpose = cppu::EnvDcp::getPurpose(pTargetEnv->pTypeName);

    rtl::OUString intermPurpose(s_getPrefix(currPurpose, targetPurpose));
    if (currPurpose.getLength() > intermPurpose.getLength())
    {
        sal_Int32 idx = currPurpose.lastIndexOf(':');
        nextPurpose = currPurpose.copy(0, idx);

        res = -1;
    }
    else if (intermPurpose.getLength() < targetPurpose.getLength())
    {
        sal_Int32 idx = targetPurpose.indexOf(':', intermPurpose.getLength() + 1);
        if (idx == -1)
            nextPurpose = targetPurpose;

        else
            nextPurpose = targetPurpose.copy(0, idx);

        res = 1;
    }

    if (nextPurpose.getLength())
    {
        rtl::OUString next_envDcp(s_uno_envDcp);
        next_envDcp += nextPurpose;

        uno_getEnvironment(ppEnv, next_envDcp.pData, NULL);
    }
    else
    {
        if (*ppEnv)
            (*ppEnv)->release(*ppEnv);

        *ppEnv = NULL;
    }

    return res;
}

extern "C" { static void s_pull(va_list * pParam)
{
    uno_EnvCallee * pCallee = va_arg(*pParam, uno_EnvCallee *);
    va_list       * pXparam = va_arg(*pParam, va_list *);

    pCallee(pXparam);
}}

static void s_callInto_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
{
    cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
    if (pEnterable)
        pEnterable->callInto(s_pull, pCallee, pParam);

    else
        pCallee(pParam);
}

static void s_callInto(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
{
    va_list param;

    va_start(param, pCallee);
    s_callInto_v(pEnv, pCallee, &param);
    va_end(param);
}

static void s_callOut_v(uno_Environment * pEnv, uno_EnvCallee * pCallee, va_list * pParam)
{
    cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
    if (pEnterable)
        pEnterable->callOut_v(pCallee, pParam);

    else
        pCallee(pParam);
}

static void s_callOut(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
{
    va_list param;

    va_start(param, pCallee);
    s_callOut_v(pEnv, pCallee, &param);
    va_end(param);
}

static void s_environment_invoke_v(uno_Environment *, uno_Environment *, uno_EnvCallee *, va_list *);

extern "C" { static void s_environment_invoke_vv(va_list * pParam)
{
    uno_Environment * pCurrEnv    = va_arg(*pParam, uno_Environment *);
    uno_Environment * pTargetEnv  = va_arg(*pParam, uno_Environment *);
    uno_EnvCallee   * pCallee     = va_arg(*pParam, uno_EnvCallee *);
    va_list         * pXparam     = va_arg(*pParam, va_list *);

    s_environment_invoke_v(pCurrEnv, pTargetEnv, pCallee, pXparam);
}}

static void s_environment_invoke_v(uno_Environment * pCurrEnv, uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
{
    uno_Environment * pNextEnv = NULL;
    switch(s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv))
    {
    case -1:
        s_setCurrent(pNextEnv);
        s_callOut(pCurrEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
        s_setCurrent(pCurrEnv);
        break;

    case 0: {
        uno_Environment * hld = s_getCurrent();
        s_setCurrent(pCurrEnv);
        pCallee(pParam);
        s_setCurrent(hld);
    }
        break;

    case 1:
        s_setCurrent(pNextEnv);
        s_callInto(pNextEnv, s_environment_invoke_vv, pNextEnv, pTargetEnv, pCallee, pParam);
        s_setCurrent(pCurrEnv);
        break;
    }

    if (pNextEnv)
        pNextEnv->release(pNextEnv);
}

extern "C" void SAL_CALL uno_Environment_invoke_v(uno_Environment * pTargetEnv, uno_EnvCallee * pCallee, va_list * pParam)
    SAL_THROW_EXTERN_C()
{
    s_environment_invoke_v(s_getCurrent(), pTargetEnv, pCallee, pParam);
}

extern "C" void SAL_CALL uno_Environment_invoke(uno_Environment * pEnv, uno_EnvCallee * pCallee, ...)
    SAL_THROW_EXTERN_C()
{
    va_list param;

    va_start(param, pCallee);
    uno_Environment_invoke_v(pEnv, pCallee, &param);
    va_end(param);
}

extern "C" void SAL_CALL uno_Environment_enter(uno_Environment * pTargetEnv)
    SAL_THROW_EXTERN_C()
{
    uno_Environment * pNextEnv = NULL;
    uno_Environment * pCurrEnv = s_getCurrent();

    int res;
    while ( (res = s_getNextEnv(&pNextEnv, pCurrEnv, pTargetEnv)) != 0)
    {
        cppu::Enterable * pEnterable;

        switch(res)
        {
        case -1:
            pEnterable = reinterpret_cast<cppu::Enterable *>(pCurrEnv->pReserved);
            if (pEnterable)
                pEnterable->leave();
            pCurrEnv->release(pCurrEnv);
            break;

        case 1:
            pNextEnv->acquire(pNextEnv);
            pEnterable = reinterpret_cast<cppu::Enterable *>(pNextEnv->pReserved);
            if (pEnterable)
                pEnterable->enter();
            break;
        }

        s_setCurrent(pNextEnv);
        pCurrEnv = pNextEnv;
    }
}

int SAL_CALL uno_Environment_isValid(uno_Environment * pEnv, rtl_uString ** pReason)
    SAL_THROW_EXTERN_C()
{
    int result = 1;

    rtl::OUString typeName(cppu::EnvDcp::getTypeName(pEnv->pTypeName));
    if (typeName.equals(s_uno_envDcp))
    {
        cppu::Enterable * pEnterable = reinterpret_cast<cppu::Enterable *>(pEnv->pReserved);
        if (pEnterable)
            result = pEnterable->isValid((rtl::OUString *)pReason);
    }
    else
    {
        rtl::OUString envDcp(s_uno_envDcp);
        envDcp += cppu::EnvDcp::getPurpose(pEnv->pTypeName);

        uno::Environment env(envDcp);

        result = env.isValid((rtl::OUString *)pReason);
    }

    return result;
}

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


<commit_before>/*
 * (C) Copyright 2016 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <gst/gst.h>
#include <MediaPipelineImplFactory.hpp>
#include "MediaPipelineImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <DotGraph.hpp>
#include <GstreamerDotDetails.hpp>
#include <SignalHandler.hpp>
#include "kmselement.h"

#define GST_CAT_DEFAULT kurento_media_pipeline_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoMediaPipelineImpl"

namespace kurento
{

void
MediaPipelineImpl::log_bus_issue(GstBin *bin, GstMessage *msg,
    gboolean is_error)
{
  GstDebugLevel log_level = is_error ? GST_LEVEL_ERROR : GST_LEVEL_WARNING;

  GError *err = NULL;
  gchar *dbg_info = NULL;
  gst_message_parse_error (msg, &err, &dbg_info);

  GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, log_level, NULL,
      "Element '%s' bus code %d: %s", GST_OBJECT_NAME (msg->src), err->code,
      err->message);
  GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, log_level, NULL,
      "Debugging info: %s", ((dbg_info) ? dbg_info : "None"));

  std::string errorMessage (err->message);
  if (dbg_info) {
    errorMessage += " (" + std::string (dbg_info) + ")";
  }

  try {
    gint code = err->code;
    Error error (shared_from_this(), errorMessage, code,
                 "UNEXPECTED_PIPELINE_ERROR");

    signalError (error);
  } catch (std::bad_weak_ptr &e) {
  }

  gchar *dot_name = g_strdup_printf ("%s_bus_%d", GST_DEFAULT_NAME, err->code);
  GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (bin, GST_DEBUG_GRAPH_SHOW_ALL, dot_name);
  g_free(dot_name);

  g_error_free (err);
  g_free (dbg_info);
}

void
MediaPipelineImpl::busMessage (GstMessage *message)
{
  switch (GST_MESSAGE_TYPE (message)) {
  case GST_MESSAGE_ERROR:
    log_bus_issue (GST_BIN (pipeline), message, TRUE);
    break;
  case GST_MESSAGE_WARNING:
    log_bus_issue (GST_BIN (pipeline), message, FALSE);
    break;
  default:
    break;
  }
}

void MediaPipelineImpl::postConstructor ()
{
  GstBus *bus;

  MediaObjectImpl::postConstructor ();

  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline) );
  gst_bus_add_signal_watch (bus);
  busMessageHandler = register_signal_handler (G_OBJECT (bus), "message",
                      std::function <void (GstBus *, GstMessage *) > (std::bind (
                            &MediaPipelineImpl::busMessage, this,
                            std::placeholders::_2) ),
                      std::dynamic_pointer_cast<MediaPipelineImpl>
                      (shared_from_this() ) );
  g_object_unref (bus);
}

MediaPipelineImpl::MediaPipelineImpl (const boost::property_tree::ptree &config)
  : MediaObjectImpl (config)
{
  GstClock *clock;

  pipeline = gst_pipeline_new (NULL);

  if (pipeline == NULL) {
    throw KurentoException (MEDIA_OBJECT_NOT_AVAILABLE,
                            "Cannot create gstreamer pipeline");
  }

  clock = gst_system_clock_obtain ();
  gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
  g_object_unref (clock);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  busMessageHandler = 0;
}

MediaPipelineImpl::~MediaPipelineImpl ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline) );

  gst_element_set_state (pipeline, GST_STATE_NULL);

  if (busMessageHandler > 0) {
    unregister_signal_handler (bus, busMessageHandler);
  }

  gst_bus_remove_signal_watch (bus);
  g_object_unref (bus);
  g_object_unref (pipeline);
}

std::string MediaPipelineImpl::getGstreamerDot (
  std::shared_ptr<GstreamerDotDetails> details)
{
  return generateDotGraph (GST_BIN (pipeline), details);
}

std::string MediaPipelineImpl::getGstreamerDot()
{
  return generateDotGraph (GST_BIN (pipeline),
                           std::shared_ptr <GstreamerDotDetails> (new GstreamerDotDetails (
                                 GstreamerDotDetails::SHOW_VERBOSE) ) );
}

bool
MediaPipelineImpl::getLatencyStats ()
{
  std::unique_lock <std::recursive_mutex> lock (recMutex);
  return latencyStats;
}

void
MediaPipelineImpl::setLatencyStats (bool latencyStats)
{
  GstIterator *it;
  gboolean done = FALSE;
  GValue item = G_VALUE_INIT;
  std::unique_lock <std::recursive_mutex> lock (recMutex);

  if (this->latencyStats == latencyStats) {
    return;
  }

  this->latencyStats = latencyStats;
  it = gst_bin_iterate_elements (GST_BIN (pipeline) );

  while (!done) {
    switch (gst_iterator_next (it, &item) ) {
    case GST_ITERATOR_OK: {
      GstElement *element = GST_ELEMENT (g_value_get_object (&item) );

      if (KMS_IS_ELEMENT (element) ) {
        g_object_set (element, "media-stats", latencyStats, NULL);
      }

      g_value_reset (&item);
      break;
    }

    case GST_ITERATOR_RESYNC:
      gst_iterator_resync (it);
      break;

    case GST_ITERATOR_ERROR:
    case GST_ITERATOR_DONE:
      done = TRUE;
      break;
    }
  }

  g_value_unset (&item);
  gst_iterator_free (it);
}

bool
MediaPipelineImpl::addElement (GstElement *element)
{
  std::unique_lock <std::recursive_mutex> lock (recMutex);
  bool ret;

  if (KMS_IS_ELEMENT (element) ) {
    g_object_set (element, "media-stats", latencyStats, NULL);
  }

  ret = gst_bin_add (GST_BIN (pipeline), element);

  if (ret) {
    gst_element_sync_state_with_parent (element);
  }

  return ret;
}

MediaObjectImpl *
MediaPipelineImplFactory::createObject (const boost::property_tree::ptree &pt)
const
{
  return new MediaPipelineImpl (pt);
}

MediaPipelineImpl::StaticConstructor MediaPipelineImpl::staticConstructor;

MediaPipelineImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<commit_msg>MediaPipelineImpl: Fix NULL dereferencing<commit_after>/*
 * (C) Copyright 2016 Kurento (http://kurento.org/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <gst/gst.h>
#include <MediaPipelineImplFactory.hpp>
#include "MediaPipelineImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <DotGraph.hpp>
#include <GstreamerDotDetails.hpp>
#include <SignalHandler.hpp>
#include "kmselement.h"

#define GST_CAT_DEFAULT kurento_media_pipeline_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoMediaPipelineImpl"

namespace kurento
{

void
MediaPipelineImpl::log_bus_issue(GstBin *bin, GstMessage *msg,
    gboolean is_error)
{
  GstDebugLevel log_level = is_error ? GST_LEVEL_ERROR : GST_LEVEL_WARNING;

  GError *err = NULL;
  gchar *dbg_info = NULL;
  gst_message_parse_error (msg, &err, &dbg_info);

  gint err_code = (err ? err->code : -1);
  gchar *err_msg = (err ? g_strdup (err->message) : g_strdup ("None"));

  GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, log_level, NULL,
      "Element '%s' bus code %d: %s", GST_OBJECT_NAME (msg->src), err_code,
      err_msg);
  GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, log_level, NULL,
      "Debugging info: %s", ((dbg_info) ? dbg_info : "None"));

  std::string errorMessage (err_msg);
  if (dbg_info) {
    errorMessage += " (" + std::string (dbg_info) + ")";
  }

  try {
    gint code = err_code;
    Error error (shared_from_this(), errorMessage, code,
                 "UNEXPECTED_PIPELINE_ERROR");

    signalError (error);
  } catch (std::bad_weak_ptr &e) {
  }

  gchar *dot_name = g_strdup_printf ("%s_bus_%d", GST_DEFAULT_NAME, err_code);
  GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (bin, GST_DEBUG_GRAPH_SHOW_ALL, dot_name);
  g_free(dot_name);

  g_error_free (err);
  g_free (dbg_info);
  g_free (err_msg);
}

void
MediaPipelineImpl::busMessage (GstMessage *message)
{
  switch (GST_MESSAGE_TYPE (message)) {
  case GST_MESSAGE_ERROR:
    log_bus_issue (GST_BIN (pipeline), message, TRUE);
    break;
  case GST_MESSAGE_WARNING:
    log_bus_issue (GST_BIN (pipeline), message, FALSE);
    break;
  default:
    break;
  }
}

void MediaPipelineImpl::postConstructor ()
{
  GstBus *bus;

  MediaObjectImpl::postConstructor ();

  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline) );
  gst_bus_add_signal_watch (bus);
  busMessageHandler = register_signal_handler (G_OBJECT (bus), "message",
                      std::function <void (GstBus *, GstMessage *) > (std::bind (
                            &MediaPipelineImpl::busMessage, this,
                            std::placeholders::_2) ),
                      std::dynamic_pointer_cast<MediaPipelineImpl>
                      (shared_from_this() ) );
  g_object_unref (bus);
}

MediaPipelineImpl::MediaPipelineImpl (const boost::property_tree::ptree &config)
  : MediaObjectImpl (config)
{
  GstClock *clock;

  pipeline = gst_pipeline_new (NULL);

  if (pipeline == NULL) {
    throw KurentoException (MEDIA_OBJECT_NOT_AVAILABLE,
                            "Cannot create gstreamer pipeline");
  }

  clock = gst_system_clock_obtain ();
  gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
  g_object_unref (clock);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  busMessageHandler = 0;
}

MediaPipelineImpl::~MediaPipelineImpl ()
{
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline) );

  gst_element_set_state (pipeline, GST_STATE_NULL);

  if (busMessageHandler > 0) {
    unregister_signal_handler (bus, busMessageHandler);
  }

  gst_bus_remove_signal_watch (bus);
  g_object_unref (bus);
  g_object_unref (pipeline);
}

std::string MediaPipelineImpl::getGstreamerDot (
  std::shared_ptr<GstreamerDotDetails> details)
{
  return generateDotGraph (GST_BIN (pipeline), details);
}

std::string MediaPipelineImpl::getGstreamerDot()
{
  return generateDotGraph (GST_BIN (pipeline),
                           std::shared_ptr <GstreamerDotDetails> (new GstreamerDotDetails (
                                 GstreamerDotDetails::SHOW_VERBOSE) ) );
}

bool
MediaPipelineImpl::getLatencyStats ()
{
  std::unique_lock <std::recursive_mutex> lock (recMutex);
  return latencyStats;
}

void
MediaPipelineImpl::setLatencyStats (bool latencyStats)
{
  GstIterator *it;
  gboolean done = FALSE;
  GValue item = G_VALUE_INIT;
  std::unique_lock <std::recursive_mutex> lock (recMutex);

  if (this->latencyStats == latencyStats) {
    return;
  }

  this->latencyStats = latencyStats;
  it = gst_bin_iterate_elements (GST_BIN (pipeline) );

  while (!done) {
    switch (gst_iterator_next (it, &item) ) {
    case GST_ITERATOR_OK: {
      GstElement *element = GST_ELEMENT (g_value_get_object (&item) );

      if (KMS_IS_ELEMENT (element) ) {
        g_object_set (element, "media-stats", latencyStats, NULL);
      }

      g_value_reset (&item);
      break;
    }

    case GST_ITERATOR_RESYNC:
      gst_iterator_resync (it);
      break;

    case GST_ITERATOR_ERROR:
    case GST_ITERATOR_DONE:
      done = TRUE;
      break;
    }
  }

  g_value_unset (&item);
  gst_iterator_free (it);
}

bool
MediaPipelineImpl::addElement (GstElement *element)
{
  std::unique_lock <std::recursive_mutex> lock (recMutex);
  bool ret;

  if (KMS_IS_ELEMENT (element) ) {
    g_object_set (element, "media-stats", latencyStats, NULL);
  }

  ret = gst_bin_add (GST_BIN (pipeline), element);

  if (ret) {
    gst_element_sync_state_with_parent (element);
  }

  return ret;
}

MediaObjectImpl *
MediaPipelineImplFactory::createObject (const boost::property_tree::ptree &pt)
const
{
  return new MediaPipelineImpl (pt);
}

MediaPipelineImpl::StaticConstructor MediaPipelineImpl::staticConstructor;

MediaPipelineImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<|endoftext|>


<commit_before><commit_msg>Fix build breakage on Windows.<commit_after><|endoftext|>


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

#include <cusp/array1d.h>
#include <cusp/array2d.h>

#include <cusp/system/detail/adl/format_utils.h>
#include <cusp/system/detail/generic/format_utils.h>

namespace cusp
{

template <typename DerivedPolicy, typename Matrix, typename Array>
void extract_diagonal(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                      const Matrix& A, Array& output)
{
    using cusp::system::detail::generic::extract_diagonal;

    typedef typename Matrix::format Format;

    Format format;

    output.resize(thrust::min(A.num_rows, A.num_cols));

    // dispatch on matrix format
    extract_diagonal(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                     A, output, format);
}

template <typename Matrix, typename Array>
void extract_diagonal(const Matrix& A, Array& output)
{
    using thrust::system::detail::generic::select_system;

    typedef typename Matrix::memory_space System1;
    typedef typename Array::memory_space  System2;

    System1 system1;
    System2 system2;

    cusp::extract_diagonal(select_system(system1,system2), A, output);
}

template <typename DerivedPolicy, typename OffsetArray, typename IndexArray>
void offsets_to_indices(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                        const OffsetArray& offsets, IndexArray& indices)
{
    using cusp::system::detail::generic::offsets_to_indices;

    offsets_to_indices(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                       offsets, indices);
}

template <typename OffsetArray, typename IndexArray>
void offsets_to_indices(const OffsetArray& offsets, IndexArray& indices)
{
    using thrust::system::detail::generic::select_system;

    typedef typename IndexArray::memory_space  System1;
    typedef typename OffsetArray::memory_space System2;

    System1 system1;
    System2 system2;

    cusp::offsets_to_indices(select_system(system1,system2), offsets, indices);
}

template <typename DerivedPolicy, typename IndexArray, typename OffsetArray>
void indices_to_offsets(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                        const IndexArray& indices, OffsetArray& offsets)
{
    using cusp::system::detail::generic::indices_to_offsets;

    indices_to_offsets(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                       indices, offsets);
}

template <typename IndexArray, typename OffsetArray>
void indices_to_offsets(const IndexArray& indices, OffsetArray& offsets)
{
    using thrust::system::detail::generic::select_system;

    typedef typename IndexArray::memory_space  System1;
    typedef typename OffsetArray::memory_space System2;

    System1 system1;
    System2 system2;

    cusp::indices_to_offsets(select_system(system1,system2), indices, offsets);
}

template <typename DerivedPolicy, typename ArrayType1, typename ArrayType2>
size_t count_diagonals(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                       const size_t num_rows,
                       const size_t num_cols,
                       const ArrayType1& row_indices,
                       const ArrayType2& column_indices)
{
    using cusp::system::detail::generic::count_diagonals;

    return count_diagonals(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                           num_rows, num_cols, row_indices, column_indices);
}

template <typename ArrayType1, typename ArrayType2>
size_t count_diagonals(const size_t num_rows,
                       const size_t num_cols,
                       const ArrayType1& row_indices,
                       const ArrayType2& column_indices)
{
    using thrust::system::detail::generic::select_system;

    typedef typename ArrayType1::memory_space System1;
    typedef typename ArrayType2::memory_space System2;

    System1 system1;
    System2 system2;

    return cusp::count_diagonals(select_system(system1,system2), num_rows, num_cols, row_indices, column_indices);
}

template <typename DerivedPolicy, typename ArrayType>
size_t compute_max_entries_per_row(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                                   const ArrayType& row_offsets)
{
    using cusp::system::detail::generic::count_diagonals;

    return compute_max_entries_per_row(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                                       row_offsets);
}

template <typename ArrayType>
size_t compute_max_entries_per_row(const ArrayType& row_offsets)
{
    using thrust::system::detail::generic::select_system;

    typedef typename ArrayType::memory_space System;

    System system;

    return cusp::compute_max_entries_per_row(select_system(system), row_offsets);
}

template <typename DerivedPolicy, typename ArrayType>
size_t compute_optimal_entries_per_row(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                                       const ArrayType& row_offsets,
                                       float relative_speed,
                                       size_t breakeven_threshold)
{
    using cusp::system::detail::generic::compute_optimal_entries_per_row;

    return compute_optimal_entries_per_row(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                                           row_offsets, relative_speed, breakeven_threshold);
}

template <typename ArrayType>
size_t compute_optimal_entries_per_row(const ArrayType& row_offsets,
                                       float relative_speed,
                                       size_t breakeven_threshold)
{
    using thrust::system::detail::generic::select_system;

    typedef typename ArrayType::memory_space System;

    System system;

    return cusp::compute_optimal_entries_per_row(select_system(system), row_offsets, relative_speed, breakeven_threshold);
}

} // end namespace cusp

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

#include <cusp/array1d.h>
#include <cusp/array2d.h>

#include <cusp/system/detail/adl/format_utils.h>
#include <cusp/system/detail/generic/format_utils.h>

namespace cusp
{

template <typename DerivedPolicy, typename Matrix, typename Array>
void extract_diagonal(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                      const Matrix& A, Array& output)
{
    using cusp::system::detail::generic::extract_diagonal;

    typedef typename Matrix::format Format;

    Format format;

    output.resize(thrust::min(A.num_rows, A.num_cols));

    // dispatch on matrix format
    extract_diagonal(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                     A, output, format);
}

template <typename Matrix, typename Array>
void extract_diagonal(const Matrix& A, Array& output)
{
    using thrust::system::detail::generic::select_system;

    typedef typename Matrix::memory_space System1;
    typedef typename Array::memory_space  System2;

    System1 system1;
    System2 system2;

    cusp::extract_diagonal(select_system(system1,system2), A, output);
}

template <typename DerivedPolicy, typename OffsetArray, typename IndexArray>
void offsets_to_indices(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                        const OffsetArray& offsets, IndexArray& indices)
{
    using cusp::system::detail::generic::offsets_to_indices;

    offsets_to_indices(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                       offsets, indices);
}

template <typename OffsetArray, typename IndexArray>
void offsets_to_indices(const OffsetArray& offsets, IndexArray& indices)
{
    using thrust::system::detail::generic::select_system;

    typedef typename IndexArray::memory_space  System1;
    typedef typename OffsetArray::memory_space System2;

    System1 system1;
    System2 system2;

    cusp::offsets_to_indices(select_system(system1,system2), offsets, indices);
}

template <typename DerivedPolicy, typename IndexArray, typename OffsetArray>
void indices_to_offsets(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                        const IndexArray& indices, OffsetArray& offsets)
{
    using cusp::system::detail::generic::indices_to_offsets;

    indices_to_offsets(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                       indices, offsets);
}

template <typename IndexArray, typename OffsetArray>
void indices_to_offsets(const IndexArray& indices, OffsetArray& offsets)
{
    using thrust::system::detail::generic::select_system;

    typedef typename IndexArray::memory_space  System1;
    typedef typename OffsetArray::memory_space System2;

    System1 system1;
    System2 system2;

    cusp::indices_to_offsets(select_system(system1,system2), indices, offsets);
}

template <typename DerivedPolicy, typename ArrayType1, typename ArrayType2>
size_t count_diagonals(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                       const size_t num_rows,
                       const size_t num_cols,
                       const ArrayType1& row_indices,
                       const ArrayType2& column_indices)
{
    using cusp::system::detail::generic::count_diagonals;

    return count_diagonals(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                           num_rows, num_cols, row_indices, column_indices);
}

template <typename ArrayType1, typename ArrayType2>
size_t count_diagonals(const size_t num_rows,
                       const size_t num_cols,
                       const ArrayType1& row_indices,
                       const ArrayType2& column_indices)
{
    using thrust::system::detail::generic::select_system;

    typedef typename ArrayType1::memory_space System1;
    typedef typename ArrayType2::memory_space System2;

    System1 system1;
    System2 system2;

    return cusp::count_diagonals(select_system(system1,system2), num_rows, num_cols, row_indices, column_indices);
}

template <typename DerivedPolicy, typename ArrayType>
size_t compute_max_entries_per_row(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                                   const ArrayType& row_offsets)
{
    using cusp::system::detail::generic::compute_max_entries_per_row;

    return compute_max_entries_per_row(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                                       row_offsets);
}

template <typename ArrayType>
size_t compute_max_entries_per_row(const ArrayType& row_offsets)
{
    using thrust::system::detail::generic::select_system;

    typedef typename ArrayType::memory_space System;

    System system;

    return cusp::compute_max_entries_per_row(select_system(system), row_offsets);
}

template <typename DerivedPolicy, typename ArrayType>
size_t compute_optimal_entries_per_row(const thrust::detail::execution_policy_base<DerivedPolicy> &exec,
                                       const ArrayType& row_offsets,
                                       float relative_speed,
                                       size_t breakeven_threshold)
{
    using cusp::system::detail::generic::compute_optimal_entries_per_row;

    return compute_optimal_entries_per_row(thrust::detail::derived_cast(thrust::detail::strip_const(exec)),
                                           row_offsets, relative_speed, breakeven_threshold);
}

template <typename ArrayType>
size_t compute_optimal_entries_per_row(const ArrayType& row_offsets,
                                       float relative_speed,
                                       size_t breakeven_threshold)
{
    using thrust::system::detail::generic::select_system;

    typedef typename ArrayType::memory_space System;

    System system;

    return cusp::compute_optimal_entries_per_row(select_system(system), row_offsets, relative_speed, breakeven_threshold);
}

} // end namespace cusp

<|endoftext|>


<commit_before>
// INCLUDE FILES
#include "PuzzlesConfig.h"

#include <aknutils.h>
#include <coemain.h>
#include "CGameView.h"
#include "CGameContainer.h"
#include "PuzzlesAppUi.h"

#include <string.h>

extern "C" {
#include "puzzles.h"
}

#include "_puzzles.inc.h"

// ============================ MEMBER FUNCTIONS ===============================

struct blitter {
    CFbsBitmap *bitmap;
    CBitmapDevice *bd;
    CBitmapContext *gc;
};

// -----------------------------------------------------------------------------
// CGameView::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CGameView* CGameView::NewL(CGameContainer *aGameContainer) {
    CGameView* self = CGameView::NewLC(aGameContainer);
    CleanupStack::Pop(self);
    return self;
}

// -----------------------------------------------------------------------------
// CGameView::NewLC()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CGameView* CGameView::NewLC(CGameContainer *aGameContainer) {
    CGameView* self = new (ELeave) CGameView;
    CleanupStack::PushL(self);
    self->ConstructL(aGameContainer);
    return self;
}

// -----------------------------------------------------------------------------
// CGameView::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CGameView::ConstructL(CGameContainer *aGameContainer) {
    iGameContainer = aGameContainer;
    iLastFont = NULL;

    // Create a window for this application view
    SetContainerWindowL(*aGameContainer);

    EnableDragEvents();

    iGameSize.iWidth = 0;
    iGameSize.iHeight = 0;

    iVirtualScreen = new (ELeave) CFbsBitmap;
    User::LeaveIfError(iVirtualScreen->Create(TSize(0, 0), iCoeEnv->ScreenDevice()->DisplayMode()));
    iBitmapDevice = CFbsBitmapDevice::NewL(iVirtualScreen);
    User::LeaveIfError(iBitmapDevice->CreateBitmapContext(iBC));

    TFileName fFont;
    TFileName fFixedFont;

    fFont.Copy(KFont);
    fFixedFont.Copy(KFixedFont);

    CompleteWithAppPath(fFont);
    CompleteWithAppPath(fFixedFont);

    // load fonts
    User::LeaveIfError(iBitmapDevice->AddFile(fFont, iFontID));
    User::LeaveIfError(iBitmapDevice->AddFile(fFixedFont, iFixedFontID));
}

// -----------------------------------------------------------------------------
// CGameView::CGameView()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CGameView::CGameView() {
    // No implementation required
}

// -----------------------------------------------------------------------------
// CGameView::~CGameView()
// Destructor.
// -----------------------------------------------------------------------------
//
CGameView::~CGameView() {
    if (iVirtualScreen) {
        ReleaseFont();

        if (iBitmapDevice) {
            iBitmapDevice->RemoveFile(iFixedFontID);
            iBitmapDevice->RemoveFile(iFontID);
        }

        delete iBC;
        delete iBitmapDevice;
        delete iVirtualScreen;
    }
}

bool CGameView::SetGameSize(const TSize& aSize) {
    TSize size = Rect().Size();
    iGamePos.iX = (size.iWidth - aSize.iWidth) >> 1;
    iGamePos.iY = (size.iHeight - aSize.iHeight) >> 1;

    if (iGameSize != aSize) {
        ReleaseFont();
        delete iBC;

        iGameSize = aSize;

        User::LeaveIfError(iVirtualScreen->Resize(aSize));
        User::LeaveIfError(iBitmapDevice->Resize(aSize));
        User::LeaveIfError(iBitmapDevice->CreateBitmapContext(iBC));

        iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
        iBC->SetBrushColor(KRgbWhite);
        iBC->Clear();

        return true;
    }

    return false;
}

// -----------------------------------------------------------------------------
// CGameView::HandlePointerEventL()
// Called by framework to handle pointer touch events.
// Note: although this method is compatible with earlier SDKs,
// it will not be called in SDKs without Touch support.
// -----------------------------------------------------------------------------
//
#ifdef ENABLE_TOUCH_UI
void CGameView::HandlePointerEventL(const TPointerEvent& aPointerEvent) {
    iGameContainer->HandleGamePointerEventL(aPointerEvent, iGamePos);
}
#endif

void CGameView::SetupFont(int fonttype, int fontsize) {
    if (iLastFont && (fonttype != iLastFontType || fontsize != iLastFontSize)) {
        ReleaseFont();
    }

    if (!iLastFont) {
        _LIT(KVera, "Bitstream Vera Sans");
        _LIT(KVeraFixed, "Bitstream Vera Sans Mono");

        const TDesC *name;

        if (fonttype == FONT_FIXED) {
            name = &KVeraFixed;
        } else {
            name = &KVera;
        }

        TFontSpec fontSpec(*name, fontsize);
        fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
        iBitmapDevice->GetNearestFontInPixels(iLastFont, fontSpec);

        iBC->UseFont(iLastFont);

        iLastFontType = fonttype;
        iLastFontSize = fontsize;
    }
}
void CGameView::ReleaseFont() {
    if (iLastFont) {
        iBC->DiscardFont();
        iBitmapDevice->ReleaseFont(iLastFont);
        iLastFont = NULL;
    }
}

#define GOOD_XY(x, y) \
    ((x) >= 0 && (x) < iGameSize.iWidth && (y) >= 0 && (y) < iGameSize.iHeight)
#define CHECK_XY(x, y) \
    if (!GOOD_XY(x, y)) return;
#define CHECK_XYWH(x, y, w, h) \
    if (!GOOD_XY(x, y) || !GOOD_XY(x + w - 1, y + h - 1)) return;
#define CHECK2_XY(x1, y1, x2, y2) \
    if (!GOOD_XY(x1, y1) || !GOOD_XY(x2, y2)) return;

void CGameView::DrawText(
    int x, int y,
    int fonttype, int fontsize,
    int align, int colour,
    char *text
) {
    CHECK_XY(x, y);

    SetupFont(fonttype, fontsize);

    TBuf<32> buf;
    HBufC *hText = NULL;
    TPtrC8 pText((TUint8*)text);
    int w;

	if (pText.Length() > buf.MaxLength()) {
	    hText = HBufC::NewL(pText.Length() + 1);
	    hText->Des().Copy(pText);

        w = iLastFont->TextWidthInPixels(hText->Des());
	} else {
	    buf.Copy(pText);
        w = iLastFont->TextWidthInPixels(buf);
	}

    if (align & ALIGN_VCENTRE) {
        y = y + iLastFont->AscentInPixels() / 2 + 1;
    }
    if (align & ALIGN_HCENTRE) {
        x = x - w / 2 + 1;
    }
    if (align & ALIGN_HRIGHT) {
        x = x - w;
    }

    iBC->SetPenColor(iGameContainer->MapColour(colour));

    if (hText != NULL) {
        iBC->DrawText(hText->Des(), TPoint(x, y));
        delete hText;
    } else {
        iBC->DrawText(buf, TPoint(x, y));
    }
}
void CGameView::DrawRect(int x, int y, int w, int h, int colour) {
    CHECK_XYWH(x, y, w, h);

    iBC->SetPenStyle(CGraphicsContext::ENullPen);
    iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBC->SetBrushColor(iGameContainer->MapColour(colour));
    iBC->DrawRect(TRect(TPoint(x, y), TSize(w, h)));
}
void CGameView::DrawLine(int x1, int y1, int x2, int y2, int colour) {
    CHECK2_XY(x1, y1, x2, y2);

    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(colour));
    iBC->DrawLine(TPoint(x1, y1), TPoint(x2, y2));
}
void CGameView::DrawThickLine(float thickness, float x1, float y1, float x2, float y2, int colour) {
    CHECK2_XY(x1, y1, x2, y2);

    int thick = (int)((thickness - 1) / 2 + 0.5) * 2 + 1;

    iBC->SetPenSize(TSize(thick, thick));
    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(colour));
    iBC->DrawLine(TPoint(x1, y1), TPoint(x2, y2));

    iBC->SetPenSize(TSize(1, 1));
}
void CGameView::DrawPolygon(
    int *coords, int npoints,
    int fillcolour, int outlinecolour
) {
    int i;
    for (i = 0; i < npoints; ++i) {
        if (!GOOD_XY(coords[i*2], coords[i*2+1])) {
            return;
        }
    }

    TPoint *points = new TPoint[npoints];

    for (i = 0; i < npoints; ++i) {
        points[i] = TPoint(coords[i*2], coords[i*2+1]);
    }

    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(outlinecolour));
    iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBC->SetBrushColor(iGameContainer->MapColour(fillcolour));
    iBC->DrawPolygon(points, (TInt)npoints, CGraphicsContext::EAlternate);

    delete [] points;
}
void CGameView::DrawCircle(
    int cx, int cy, int radius,
    int fillcolour,
    int outlinecolour
) {
    CHECK2_XY(cx, cy, cx+radius-1, cy+radius-1);

    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(outlinecolour));
    iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBC->SetBrushColor(iGameContainer->MapColour(fillcolour));
    iBC->DrawEllipse(TRect(cx - radius, cy - radius, cx + radius + 1, cy + radius + 1));
}
void CGameView::Clip(int x, int y, int w, int h) {
    iBC->SetClippingRect(TRect(TPoint(x, y), TSize(w, h)));
}
void CGameView::Unclip() {
    iBC->CancelClippingRect();
}
void CGameView::StartDraw() {
    iBC->SetPenSize(TSize(1, 1));
}
void CGameView::DrawUpdate(int /* x */, int /* y */, int /* w */, int /* h */) {
    //DrawNow(TRect(TPoint(x, y) + iGamePos, TSize(w, h)));
}
void CGameView::EndDraw() {
    ReleaseFont();
    Unclip();

    DrawDeferred();
}
blitter *CGameView::BlitterNew(int w, int h) {
    blitter *bl = snew(blitter);
    bl->bitmap = new (ELeave) CFbsBitmap;
    User::LeaveIfError(bl->bitmap->Create(TSize(w, h), iVirtualScreen->DisplayMode()));
    bl->bd = CFbsBitmapDevice::NewL(bl->bitmap);
    bl->bd->CreateBitmapContext(bl->gc);
    return bl;
}
void CGameView::BlitterFree(blitter *bl) {
    delete bl->gc;
    delete bl->bd;
    delete bl->bitmap;
    sfree(bl);
}
void CGameView::BlitterSave(blitter *bl, int x, int y) {
    bl->gc->BitBlt(
        TPoint(0, 0),
        iVirtualScreen,
        TRect(TPoint(x, y), bl->bitmap->SizeInPixels())
    );
}
void CGameView::BlitterLoad(blitter *bl, int x, int y) {
    iBC->BitBlt(TPoint(x, y), bl->bitmap);
}

// -----------------------------------------------------------------------------
// CGameView::Draw()
// Draws the display.
// -----------------------------------------------------------------------------
//
void CGameView::Draw(const TRect& /* aRect */) const {
    // Get the standard graphics context
    CWindowGc& gc = SystemGc();

    if (iVirtualScreen) {
        TRect gameRect(TPoint(), iGameSize);

        gc.BitBlt(
            iGamePos,
            iVirtualScreen,
            gameRect
        );

        // draw a rectangle around the board area to make
        // the limits visible to the user

        gc.SetPenSize(TSize(1, 1));
        gc.SetPenColor(KRgbBlack);
        gc.SetPenStyle(CGraphicsContext::ESolidPen);
        gc.SetBrushStyle(CGraphicsContext::ENullBrush);

        gameRect.Move(iGamePos);
        gameRect.Grow(1, 1);
        gc.DrawRect(gameRect);
    }
}

// End of File
<commit_msg>revert the changes to text drawing (when centering vertically or horizontally)<commit_after>
// INCLUDE FILES
#include "PuzzlesConfig.h"

#include <aknutils.h>
#include <coemain.h>
#include "CGameView.h"
#include "CGameContainer.h"
#include "PuzzlesAppUi.h"

#include <string.h>

extern "C" {
#include "puzzles.h"
}

#include "_puzzles.inc.h"

// ============================ MEMBER FUNCTIONS ===============================

struct blitter {
    CFbsBitmap *bitmap;
    CBitmapDevice *bd;
    CBitmapContext *gc;
};

// -----------------------------------------------------------------------------
// CGameView::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CGameView* CGameView::NewL(CGameContainer *aGameContainer) {
    CGameView* self = CGameView::NewLC(aGameContainer);
    CleanupStack::Pop(self);
    return self;
}

// -----------------------------------------------------------------------------
// CGameView::NewLC()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CGameView* CGameView::NewLC(CGameContainer *aGameContainer) {
    CGameView* self = new (ELeave) CGameView;
    CleanupStack::PushL(self);
    self->ConstructL(aGameContainer);
    return self;
}

// -----------------------------------------------------------------------------
// CGameView::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CGameView::ConstructL(CGameContainer *aGameContainer) {
    iGameContainer = aGameContainer;
    iLastFont = NULL;

    // Create a window for this application view
    SetContainerWindowL(*aGameContainer);

    EnableDragEvents();

    iGameSize.iWidth = 0;
    iGameSize.iHeight = 0;

    iVirtualScreen = new (ELeave) CFbsBitmap;
    User::LeaveIfError(iVirtualScreen->Create(TSize(0, 0), iCoeEnv->ScreenDevice()->DisplayMode()));
    iBitmapDevice = CFbsBitmapDevice::NewL(iVirtualScreen);
    User::LeaveIfError(iBitmapDevice->CreateBitmapContext(iBC));

    TFileName fFont;
    TFileName fFixedFont;

    fFont.Copy(KFont);
    fFixedFont.Copy(KFixedFont);

    CompleteWithAppPath(fFont);
    CompleteWithAppPath(fFixedFont);

    // load fonts
    User::LeaveIfError(iBitmapDevice->AddFile(fFont, iFontID));
    User::LeaveIfError(iBitmapDevice->AddFile(fFixedFont, iFixedFontID));
}

// -----------------------------------------------------------------------------
// CGameView::CGameView()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CGameView::CGameView() {
    // No implementation required
}

// -----------------------------------------------------------------------------
// CGameView::~CGameView()
// Destructor.
// -----------------------------------------------------------------------------
//
CGameView::~CGameView() {
    if (iVirtualScreen) {
        ReleaseFont();

        if (iBitmapDevice) {
            iBitmapDevice->RemoveFile(iFixedFontID);
            iBitmapDevice->RemoveFile(iFontID);
        }

        delete iBC;
        delete iBitmapDevice;
        delete iVirtualScreen;
    }
}

bool CGameView::SetGameSize(const TSize& aSize) {
    TSize size = Rect().Size();
    iGamePos.iX = (size.iWidth - aSize.iWidth) >> 1;
    iGamePos.iY = (size.iHeight - aSize.iHeight) >> 1;

    if (iGameSize != aSize) {
        ReleaseFont();
        delete iBC;

        iGameSize = aSize;

        User::LeaveIfError(iVirtualScreen->Resize(aSize));
        User::LeaveIfError(iBitmapDevice->Resize(aSize));
        User::LeaveIfError(iBitmapDevice->CreateBitmapContext(iBC));

        iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
        iBC->SetBrushColor(KRgbWhite);
        iBC->Clear();

        return true;
    }

    return false;
}

// -----------------------------------------------------------------------------
// CGameView::HandlePointerEventL()
// Called by framework to handle pointer touch events.
// Note: although this method is compatible with earlier SDKs,
// it will not be called in SDKs without Touch support.
// -----------------------------------------------------------------------------
//
#ifdef ENABLE_TOUCH_UI
void CGameView::HandlePointerEventL(const TPointerEvent& aPointerEvent) {
    iGameContainer->HandleGamePointerEventL(aPointerEvent, iGamePos);
}
#endif

void CGameView::SetupFont(int fonttype, int fontsize) {
    if (iLastFont && (fonttype != iLastFontType || fontsize != iLastFontSize)) {
        ReleaseFont();
    }

    if (!iLastFont) {
        _LIT(KVera, "Bitstream Vera Sans");
        _LIT(KVeraFixed, "Bitstream Vera Sans Mono");

        const TDesC *name;

        if (fonttype == FONT_FIXED) {
            name = &KVeraFixed;
        } else {
            name = &KVera;
        }

        TFontSpec fontSpec(*name, fontsize);
        fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
        iBitmapDevice->GetNearestFontInPixels(iLastFont, fontSpec);

        iBC->UseFont(iLastFont);

        iLastFontType = fonttype;
        iLastFontSize = fontsize;
    }
}
void CGameView::ReleaseFont() {
    if (iLastFont) {
        iBC->DiscardFont();
        iBitmapDevice->ReleaseFont(iLastFont);
        iLastFont = NULL;
    }
}

#define GOOD_XY(x, y) \
    ((x) >= 0 && (x) < iGameSize.iWidth && (y) >= 0 && (y) < iGameSize.iHeight)
#define CHECK_XY(x, y) \
    if (!GOOD_XY(x, y)) return;
#define CHECK_XYWH(x, y, w, h) \
    if (!GOOD_XY(x, y) || !GOOD_XY(x + w - 1, y + h - 1)) return;
#define CHECK2_XY(x1, y1, x2, y2) \
    if (!GOOD_XY(x1, y1) || !GOOD_XY(x2, y2)) return;

void CGameView::DrawText(
    int x, int y,
    int fonttype, int fontsize,
    int align, int colour,
    char *text
) {
    CHECK_XY(x, y);

    SetupFont(fonttype, fontsize);

    TBuf<32> buf;
    HBufC *hText = NULL;
    TPtrC8 pText((TUint8*)text);
    int w;

	if (pText.Length() > buf.MaxLength()) {
	    hText = HBufC::NewL(pText.Length() + 1);
	    hText->Des().Copy(pText);

        w = iLastFont->TextWidthInPixels(hText->Des());
	} else {
	    buf.Copy(pText);
        w = iLastFont->TextWidthInPixels(buf);
	}

    if (align & ALIGN_VCENTRE) {
        y = y + iLastFont->AscentInPixels() / 2;
    }
    if (align & ALIGN_HCENTRE) {
        x = x - w / 2;
    }
    if (align & ALIGN_HRIGHT) {
        x = x - w;
    }

    iBC->SetPenColor(iGameContainer->MapColour(colour));

    if (hText != NULL) {
        iBC->DrawText(hText->Des(), TPoint(x, y));
        delete hText;
    } else {
        iBC->DrawText(buf, TPoint(x, y));
    }
}
void CGameView::DrawRect(int x, int y, int w, int h, int colour) {
    CHECK_XYWH(x, y, w, h);

    iBC->SetPenStyle(CGraphicsContext::ENullPen);
    iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBC->SetBrushColor(iGameContainer->MapColour(colour));
    iBC->DrawRect(TRect(TPoint(x, y), TSize(w, h)));
}
void CGameView::DrawLine(int x1, int y1, int x2, int y2, int colour) {
    CHECK2_XY(x1, y1, x2, y2);

    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(colour));
    iBC->DrawLine(TPoint(x1, y1), TPoint(x2, y2));
}
void CGameView::DrawThickLine(float thickness, float x1, float y1, float x2, float y2, int colour) {
    CHECK2_XY(x1, y1, x2, y2);

    int thick = (int)((thickness - 1) / 2 + 0.5) * 2 + 1;

    iBC->SetPenSize(TSize(thick, thick));
    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(colour));
    iBC->DrawLine(TPoint(x1, y1), TPoint(x2, y2));

    iBC->SetPenSize(TSize(1, 1));
}
void CGameView::DrawPolygon(
    int *coords, int npoints,
    int fillcolour, int outlinecolour
) {
    int i;
    for (i = 0; i < npoints; ++i) {
        if (!GOOD_XY(coords[i*2], coords[i*2+1])) {
            return;
        }
    }

    TPoint *points = new TPoint[npoints];

    for (i = 0; i < npoints; ++i) {
        points[i] = TPoint(coords[i*2], coords[i*2+1]);
    }

    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(outlinecolour));
    iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBC->SetBrushColor(iGameContainer->MapColour(fillcolour));
    iBC->DrawPolygon(points, (TInt)npoints, CGraphicsContext::EAlternate);

    delete [] points;
}
void CGameView::DrawCircle(
    int cx, int cy, int radius,
    int fillcolour,
    int outlinecolour
) {
    CHECK2_XY(cx, cy, cx+radius-1, cy+radius-1);

    iBC->SetPenStyle(CGraphicsContext::ESolidPen);
    iBC->SetPenColor(iGameContainer->MapColour(outlinecolour));
    iBC->SetBrushStyle(CGraphicsContext::ESolidBrush);
    iBC->SetBrushColor(iGameContainer->MapColour(fillcolour));
    iBC->DrawEllipse(TRect(cx - radius, cy - radius, cx + radius + 1, cy + radius + 1));
}
void CGameView::Clip(int x, int y, int w, int h) {
    iBC->SetClippingRect(TRect(TPoint(x, y), TSize(w, h)));
}
void CGameView::Unclip() {
    iBC->CancelClippingRect();
}
void CGameView::StartDraw() {
    iBC->SetPenSize(TSize(1, 1));
}
void CGameView::DrawUpdate(int /* x */, int /* y */, int /* w */, int /* h */) {
    //DrawNow(TRect(TPoint(x, y) + iGamePos, TSize(w, h)));
}
void CGameView::EndDraw() {
    ReleaseFont();
    Unclip();

    DrawDeferred();
}
blitter *CGameView::BlitterNew(int w, int h) {
    blitter *bl = snew(blitter);
    bl->bitmap = new (ELeave) CFbsBitmap;
    User::LeaveIfError(bl->bitmap->Create(TSize(w, h), iVirtualScreen->DisplayMode()));
    bl->bd = CFbsBitmapDevice::NewL(bl->bitmap);
    bl->bd->CreateBitmapContext(bl->gc);
    return bl;
}
void CGameView::BlitterFree(blitter *bl) {
    delete bl->gc;
    delete bl->bd;
    delete bl->bitmap;
    sfree(bl);
}
void CGameView::BlitterSave(blitter *bl, int x, int y) {
    bl->gc->BitBlt(
        TPoint(0, 0),
        iVirtualScreen,
        TRect(TPoint(x, y), bl->bitmap->SizeInPixels())
    );
}
void CGameView::BlitterLoad(blitter *bl, int x, int y) {
    iBC->BitBlt(TPoint(x, y), bl->bitmap);
}

// -----------------------------------------------------------------------------
// CGameView::Draw()
// Draws the display.
// -----------------------------------------------------------------------------
//
void CGameView::Draw(const TRect& /* aRect */) const {
    // Get the standard graphics context
    CWindowGc& gc = SystemGc();

    if (iVirtualScreen) {
        TRect gameRect(TPoint(), iGameSize);

        gc.BitBlt(
            iGamePos,
            iVirtualScreen,
            gameRect
        );

        // draw a rectangle around the board area to make
        // the limits visible to the user

        gc.SetPenSize(TSize(1, 1));
        gc.SetPenColor(KRgbBlack);
        gc.SetPenStyle(CGraphicsContext::ESolidPen);
        gc.SetBrushStyle(CGraphicsContext::ENullBrush);

        gameRect.Move(iGamePos);
        gameRect.Grow(1, 1);
        gc.DrawRect(gameRect);
    }
}

// End of File
<|endoftext|>


<commit_before>//===-- Language.cpp -------------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <functional>
#include <map>
#include <mutex>

#include "lldb/Target/Language.h"

#include "lldb/Host/Mutex.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Stream.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

typedef std::unique_ptr<Language> LanguageUP;
typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;

static LanguagesMap&
GetLanguagesMap ()
{
    static LanguagesMap *g_map = nullptr;
    static std::once_flag g_initialize;

    std::call_once(g_initialize, [] {
        g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global destructor chain
    });

    return *g_map;
}
static Mutex&
GetLanguagesMutex ()
{
    static Mutex *g_mutex = nullptr;
    static std::once_flag g_initialize;

    std::call_once(g_initialize, [] {
        g_mutex = new Mutex(); // NOTE: INTENTIONAL LEAK due to global destructor chain
    });

    return *g_mutex;
}

Language*
Language::FindPlugin (lldb::LanguageType language)
{
    Mutex::Locker locker(GetLanguagesMutex());
    LanguagesMap& map(GetLanguagesMap());
    auto iter = map.find(language), end = map.end();
    if (iter != end)
        return iter->second.get();

    Language *language_ptr = nullptr;
    LanguageCreateInstance create_callback;

    for (uint32_t idx = 0;
         (create_callback = PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
         ++idx)
    {
        language_ptr = create_callback(language);

        if (language_ptr)
        {
            map[language] = std::unique_ptr<Language>(language_ptr);
            return language_ptr;
        }
    }

    return nullptr;
}

void
Language::ForEach (std::function<bool(Language*)> callback)
{
    Mutex::Locker locker(GetLanguagesMutex());
    LanguagesMap& map(GetLanguagesMap());
    for (const auto& entry : map)
    {
        if (!callback(entry.second.get()))
            break;
    }
}

bool
Language::IsTopLevelFunction (Function& function)
{
    return false;
}

lldb::TypeCategoryImplSP
Language::GetFormatters ()
{
    return nullptr;
}

HardcodedFormatters::HardcodedFormatFinder
Language::GetHardcodedFormats ()
{
    return {};
}

HardcodedFormatters::HardcodedSummaryFinder
Language::GetHardcodedSummaries ()
{
    return {};
}

HardcodedFormatters::HardcodedSyntheticFinder
Language::GetHardcodedSynthetics ()
{
    return {};
}

HardcodedFormatters::HardcodedValidatorFinder
Language::GetHardcodedValidators ()
{
    return {};
}

std::vector<ConstString>
Language::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
{
    return {};
}

lldb_private::formatters::StringPrinter::EscapingHelper
Language::GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType elem_type)
{
    return StringPrinter::GetDefaultEscapingHelper(elem_type);
}

struct language_name_pair {
    const char *name;
    LanguageType type;
};

struct language_name_pair language_names[] =
{
    // To allow GetNameForLanguageType to be a simple array lookup, the first
    // part of this array must follow enum LanguageType exactly.
    {   "unknown",          eLanguageTypeUnknown        },
    {   "c89",              eLanguageTypeC89            },
    {   "c",                eLanguageTypeC              },
    {   "ada83",            eLanguageTypeAda83          },
    {   "c++",              eLanguageTypeC_plus_plus    },
    {   "cobol74",          eLanguageTypeCobol74        },
    {   "cobol85",          eLanguageTypeCobol85        },
    {   "fortran77",        eLanguageTypeFortran77      },
    {   "fortran90",        eLanguageTypeFortran90      },
    {   "pascal83",         eLanguageTypePascal83       },
    {   "modula2",          eLanguageTypeModula2        },
    {   "java",             eLanguageTypeJava           },
    {   "c99",              eLanguageTypeC99            },
    {   "ada95",            eLanguageTypeAda95          },
    {   "fortran95",        eLanguageTypeFortran95      },
    {   "pli",              eLanguageTypePLI            },
    {   "objective-c",      eLanguageTypeObjC           },
    {   "objective-c++",    eLanguageTypeObjC_plus_plus },
    {   "upc",              eLanguageTypeUPC            },
    {   "d",                eLanguageTypeD              },
    {   "python",           eLanguageTypePython         },
    {   "opencl",           eLanguageTypeOpenCL         },
    {   "go",               eLanguageTypeGo             },
    {   "modula3",          eLanguageTypeModula3        },
    {   "haskell",          eLanguageTypeHaskell        },
    {   "c++03",            eLanguageTypeC_plus_plus_03 },
    {   "c++11",            eLanguageTypeC_plus_plus_11 },
    {   "ocaml",            eLanguageTypeOCaml          },
    {   "rust",             eLanguageTypeRust           },
    {   "c11",              eLanguageTypeC11            },
    {   "swift",            eLanguageTypeSwift          },
    {   "julia",            eLanguageTypeJulia          },
    {   "dylan",            eLanguageTypeDylan          },
    {   "c++14",            eLanguageTypeC_plus_plus_14 },
    {   "fortran03",        eLanguageTypeFortran03      },
    {   "fortran08",        eLanguageTypeFortran08      },
    // Vendor Extensions
    {   "mipsassem",        eLanguageTypeMipsAssembler  },
    {   "renderscript",     eLanguageTypeExtRenderScript},
    // Now synonyms, in arbitrary order
    {   "objc",             eLanguageTypeObjC           },
    {   "objc++",           eLanguageTypeObjC_plus_plus },
    {   "pascal",           eLanguageTypePascal83       }
};

static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);

LanguageType
Language::GetLanguageTypeFromString (const char *string)
{
    for (uint32_t i = 0; i < num_languages; i++)
    {
        if (strcasecmp (language_names[i].name, string) == 0)
            return (LanguageType) language_names[i].type;
    }
    return eLanguageTypeUnknown;
}

const char *
Language::GetNameForLanguageType (LanguageType language)
{
    if (language < num_languages)
        return language_names[language].name;
    else
        return language_names[eLanguageTypeUnknown].name;
}

void
Language::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
{
    for (uint32_t i = 1; i < num_languages; i++)
    {
        s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
    }
}

void
Language::ForAllLanguages (std::function<bool(lldb::LanguageType)> callback)
{
    for (uint32_t i = 1; i < num_languages; i++)
    {
        if (!callback(language_names[i].type))
            break;
    }
}

bool
Language::LanguageIsCPlusPlus (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypeC_plus_plus:
        case eLanguageTypeC_plus_plus_03:
        case eLanguageTypeC_plus_plus_11:
        case eLanguageTypeC_plus_plus_14:
            return true;
        default:
            return false;
    }
}

bool
Language::LanguageIsObjC (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypeObjC:
        case eLanguageTypeObjC_plus_plus:
            return true;
        default:
            return false;
    }
}

bool
Language::LanguageIsC (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypeC:
        case eLanguageTypeC89:
        case eLanguageTypeC99:
        case eLanguageTypeC11:
            return true;
        default:
            return false;
    }
}

bool
Language::LanguageIsPascal (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypePascal83:
            return true;
        default:
            return false;
    }
}

void
Language::GetLanguagesSupportingTypeSystems (std::set<lldb::LanguageType> &languages,
                                             std::set<lldb::LanguageType> &languages_for_expressions)
{
    uint32_t idx = 0;

    while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++))
    {
        (*enumerate)(languages, languages_for_expressions);
    }
}

void
Language::GetLanguagesSupportingREPLs (std::set<lldb::LanguageType> &languages)
{
    uint32_t idx = 0;

    while (REPLEnumerateSupportedLanguages enumerate = PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(idx++))
    {
        (*enumerate)(languages);
    }
}

std::unique_ptr<Language::TypeScavenger>
Language::GetTypeScavenger ()
{
    return nullptr;
}

size_t
Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,
                               const char *key,
                               ResultSet &results,
                               bool append)
{
    if (!exe_scope || !exe_scope->CalculateTarget().get())
        return false;

    if (!key || !key[0])
        return false;

    if (!append)
        results.clear();

    size_t old_size = results.size();

    if (this->Find_Impl(exe_scope, key, results))
        return results.size() - old_size;
    return 0;
}

bool
Language::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
                                    std::string& prefix, std::string& suffix)
{
    return false;
}

DumpValueObjectOptions::DeclPrintingHelper
Language::GetDeclPrintingHelper ()
{
    return nullptr;
}

LazyBool
Language::IsLogicalTrue (ValueObject& valobj,
                         Error& error)
{
    return eLazyBoolCalculate;
}

bool
Language::IsNilReference (ValueObject& valobj)
{
    return false;
}

bool
Language::IsUninitializedReference (ValueObject& valobj)
{
    return false;
}

bool
Language::GetFunctionDisplayName (const SymbolContext *sc,
                                  const ExecutionContext *exe_ctx,
                                  FunctionNameRepresentation representation,
                                  Stream& s)
{
    return false;
}

void
Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s)
{
    GetDefaultExceptionResolverDescription(catch_on, throw_on, s);
}

void
Language::GetDefaultExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s)
{
       s.Printf ("Exception breakpoint (catch: %s throw: %s)",
                 catch_on ? "on" : "off",
                 throw_on ? "on" : "off");
}
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
Language::Language()
{
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
Language::~Language()
{
}
<commit_msg>Fix formatting for last commit.<commit_after>//===-- Language.cpp -------------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <functional>
#include <map>
#include <mutex>

#include "lldb/Target/Language.h"

#include "lldb/Host/Mutex.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Stream.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

typedef std::unique_ptr<Language> LanguageUP;
typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;

static LanguagesMap&
GetLanguagesMap ()
{
    static LanguagesMap *g_map = nullptr;
    static std::once_flag g_initialize;

    std::call_once(g_initialize, [] {
        g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global destructor chain
    });

    return *g_map;
}
static Mutex&
GetLanguagesMutex ()
{
    static Mutex *g_mutex = nullptr;
    static std::once_flag g_initialize;

    std::call_once(g_initialize, [] {
        g_mutex = new Mutex(); // NOTE: INTENTIONAL LEAK due to global destructor chain
    });

    return *g_mutex;
}

Language*
Language::FindPlugin (lldb::LanguageType language)
{
    Mutex::Locker locker(GetLanguagesMutex());
    LanguagesMap& map(GetLanguagesMap());
    auto iter = map.find(language), end = map.end();
    if (iter != end)
        return iter->second.get();

    Language *language_ptr = nullptr;
    LanguageCreateInstance create_callback;

    for (uint32_t idx = 0;
         (create_callback = PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
         ++idx)
    {
        language_ptr = create_callback(language);

        if (language_ptr)
        {
            map[language] = std::unique_ptr<Language>(language_ptr);
            return language_ptr;
        }
    }

    return nullptr;
}

void
Language::ForEach (std::function<bool(Language*)> callback)
{
    Mutex::Locker locker(GetLanguagesMutex());
    LanguagesMap& map(GetLanguagesMap());
    for (const auto& entry : map)
    {
        if (!callback(entry.second.get()))
            break;
    }
}

bool
Language::IsTopLevelFunction (Function& function)
{
    return false;
}

lldb::TypeCategoryImplSP
Language::GetFormatters ()
{
    return nullptr;
}

HardcodedFormatters::HardcodedFormatFinder
Language::GetHardcodedFormats ()
{
    return {};
}

HardcodedFormatters::HardcodedSummaryFinder
Language::GetHardcodedSummaries ()
{
    return {};
}

HardcodedFormatters::HardcodedSyntheticFinder
Language::GetHardcodedSynthetics ()
{
    return {};
}

HardcodedFormatters::HardcodedValidatorFinder
Language::GetHardcodedValidators ()
{
    return {};
}

std::vector<ConstString>
Language::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
{
    return {};
}

lldb_private::formatters::StringPrinter::EscapingHelper
Language::GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType elem_type)
{
    return StringPrinter::GetDefaultEscapingHelper(elem_type);
}

struct language_name_pair {
    const char *name;
    LanguageType type;
};

struct language_name_pair language_names[] =
{
    // To allow GetNameForLanguageType to be a simple array lookup, the first
    // part of this array must follow enum LanguageType exactly.
    {   "unknown",          eLanguageTypeUnknown        },
    {   "c89",              eLanguageTypeC89            },
    {   "c",                eLanguageTypeC              },
    {   "ada83",            eLanguageTypeAda83          },
    {   "c++",              eLanguageTypeC_plus_plus    },
    {   "cobol74",          eLanguageTypeCobol74        },
    {   "cobol85",          eLanguageTypeCobol85        },
    {   "fortran77",        eLanguageTypeFortran77      },
    {   "fortran90",        eLanguageTypeFortran90      },
    {   "pascal83",         eLanguageTypePascal83       },
    {   "modula2",          eLanguageTypeModula2        },
    {   "java",             eLanguageTypeJava           },
    {   "c99",              eLanguageTypeC99            },
    {   "ada95",            eLanguageTypeAda95          },
    {   "fortran95",        eLanguageTypeFortran95      },
    {   "pli",              eLanguageTypePLI            },
    {   "objective-c",      eLanguageTypeObjC           },
    {   "objective-c++",    eLanguageTypeObjC_plus_plus },
    {   "upc",              eLanguageTypeUPC            },
    {   "d",                eLanguageTypeD              },
    {   "python",           eLanguageTypePython         },
    {   "opencl",           eLanguageTypeOpenCL         },
    {   "go",               eLanguageTypeGo             },
    {   "modula3",          eLanguageTypeModula3        },
    {   "haskell",          eLanguageTypeHaskell        },
    {   "c++03",            eLanguageTypeC_plus_plus_03 },
    {   "c++11",            eLanguageTypeC_plus_plus_11 },
    {   "ocaml",            eLanguageTypeOCaml          },
    {   "rust",             eLanguageTypeRust           },
    {   "c11",              eLanguageTypeC11            },
    {   "swift",            eLanguageTypeSwift          },
    {   "julia",            eLanguageTypeJulia          },
    {   "dylan",            eLanguageTypeDylan          },
    {   "c++14",            eLanguageTypeC_plus_plus_14 },
    {   "fortran03",        eLanguageTypeFortran03      },
    {   "fortran08",        eLanguageTypeFortran08      },
    // Vendor Extensions
    {   "mipsassem",        eLanguageTypeMipsAssembler  },
    {   "renderscript",     eLanguageTypeExtRenderScript},
    // Now synonyms, in arbitrary order
    {   "objc",             eLanguageTypeObjC           },
    {   "objc++",           eLanguageTypeObjC_plus_plus },
    {   "pascal",           eLanguageTypePascal83       }
};

static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);

LanguageType
Language::GetLanguageTypeFromString (const char *string)
{
    for (uint32_t i = 0; i < num_languages; i++)
    {
        if (strcasecmp (language_names[i].name, string) == 0)
            return (LanguageType) language_names[i].type;
    }
    return eLanguageTypeUnknown;
}

const char *
Language::GetNameForLanguageType (LanguageType language)
{
    if (language < num_languages)
        return language_names[language].name;
    else
        return language_names[eLanguageTypeUnknown].name;
}

void
Language::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
{
    for (uint32_t i = 1; i < num_languages; i++)
    {
        s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
    }
}

void
Language::ForAllLanguages (std::function<bool(lldb::LanguageType)> callback)
{
    for (uint32_t i = 1; i < num_languages; i++)
    {
        if (!callback(language_names[i].type))
            break;
    }
}

bool
Language::LanguageIsCPlusPlus (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypeC_plus_plus:
        case eLanguageTypeC_plus_plus_03:
        case eLanguageTypeC_plus_plus_11:
        case eLanguageTypeC_plus_plus_14:
            return true;
        default:
            return false;
    }
}

bool
Language::LanguageIsObjC (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypeObjC:
        case eLanguageTypeObjC_plus_plus:
            return true;
        default:
            return false;
    }
}

bool
Language::LanguageIsC (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypeC:
        case eLanguageTypeC89:
        case eLanguageTypeC99:
        case eLanguageTypeC11:
            return true;
        default:
            return false;
    }
}

bool
Language::LanguageIsPascal (LanguageType language)
{
    switch (language)
    {
        case eLanguageTypePascal83:
            return true;
        default:
            return false;
    }
}

void
Language::GetLanguagesSupportingTypeSystems (std::set<lldb::LanguageType> &languages,
                                             std::set<lldb::LanguageType> &languages_for_expressions)
{
    uint32_t idx = 0;

    while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++))
    {
        (*enumerate)(languages, languages_for_expressions);
    }
}

void
Language::GetLanguagesSupportingREPLs (std::set<lldb::LanguageType> &languages)
{
    uint32_t idx = 0;

    while (REPLEnumerateSupportedLanguages enumerate = PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(idx++))
    {
        (*enumerate)(languages);
    }
}

std::unique_ptr<Language::TypeScavenger>
Language::GetTypeScavenger ()
{
    return nullptr;
}

size_t
Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,
                               const char *key,
                               ResultSet &results,
                               bool append)
{
    if (!exe_scope || !exe_scope->CalculateTarget().get())
        return false;

    if (!key || !key[0])
        return false;

    if (!append)
        results.clear();

    size_t old_size = results.size();

    if (this->Find_Impl(exe_scope, key, results))
        return results.size() - old_size;
    return 0;
}

bool
Language::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
                                    std::string& prefix, std::string& suffix)
{
    return false;
}

DumpValueObjectOptions::DeclPrintingHelper
Language::GetDeclPrintingHelper ()
{
    return nullptr;
}

LazyBool
Language::IsLogicalTrue (ValueObject& valobj,
                         Error& error)
{
    return eLazyBoolCalculate;
}

bool
Language::IsNilReference (ValueObject& valobj)
{
    return false;
}

bool
Language::IsUninitializedReference (ValueObject& valobj)
{
    return false;
}

bool
Language::GetFunctionDisplayName (const SymbolContext *sc,
                                  const ExecutionContext *exe_ctx,
                                  FunctionNameRepresentation representation,
                                  Stream& s)
{
    return false;
}

void
Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s)
{
    GetDefaultExceptionResolverDescription(catch_on, throw_on, s);
}

void
Language::GetDefaultExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s)
{
     s.Printf ("Exception breakpoint (catch: %s throw: %s)",
               catch_on ? "on" : "off",
               throw_on ? "on" : "off");
}
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
Language::Language()
{
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
Language::~Language()
{
}
<|endoftext|>


<commit_before>
//@HEADER
// ***************************************************
//
// HPCG: High Performance Conjugate Gradient Benchmark
//
// Contact:
// Michael A. Heroux ( maherou@sandia.gov)
// Jack Dongarra     (dongarra@eecs.utk.edu)
// Piotr Luszczek    (luszczek@eecs.utk.edu)
//
// ***************************************************
//@HEADER

/*!
 @file TestNorms.cpp

 HPCG routine
 */

#include <cmath>
#include "TestNorms.hpp"

/*!
  Computes the mean and standard deviation of the array of norm results.

  @param[in] testnorms_data data structure with the results of norm test

  @return Returns 0 upon success or non-zero otherwise
*/
int TestNorms(TestNormsData * testnorms_data) {

  // Compute mean
  double mean = 0.0;
  for (int i= 0; i<testnorms_data->samples; ++i) mean += testnorms_data->values[i];
  testnorms_data->mean = (mean/((double)testnorms_data->samples));

  // Compute variance
  double sumdiff = 0.0;
  for (int i= 0; i<testnorms_data->samples; ++i) sumdiff += (testnorms_data->values[i] - mean) * (testnorms_data->values[i] - mean);
  testnorms_data->variance = (sumdiff/((double)testnorms_data->samples));

  // Determine if variation is sufficiently small to declare success
  testnorms_data->pass = (testnorms_data->variance<1.0e-6);

  return 0;
}
<commit_msg>Fixed an error introduced when the testnorms_data struct was added.  The  non-struct variable mean was being used to compute the variance, but it  was not properly scaled (since scaling was being done on the  testnorm_data->mean version).<commit_after>
//@HEADER
// ***************************************************
//
// HPCG: High Performance Conjugate Gradient Benchmark
//
// Contact:
// Michael A. Heroux ( maherou@sandia.gov)
// Jack Dongarra     (dongarra@eecs.utk.edu)
// Piotr Luszczek    (luszczek@eecs.utk.edu)
//
// ***************************************************
//@HEADER

/*!
 @file TestNorms.cpp

 HPCG routine
 */

#include <cmath>
#include "TestNorms.hpp"

/*!
  Computes the mean and standard deviation of the array of norm results.

  @param[in] testnorms_data data structure with the results of norm test

  @return Returns 0 upon success or non-zero otherwise
*/
int TestNorms(TestNormsData * testnorms_data) {

  // Compute mean
  double mean = 0.0;
  for (int i= 0; i<testnorms_data->samples; ++i) mean += testnorms_data->values[i];
  testnorms_data->mean = (mean/((double)testnorms_data->samples));

  // Compute variance
  double sumdiff = 0.0;
  mean = testnorms_data->mean;
  for (int i= 0; i<testnorms_data->samples; ++i) sumdiff += (testnorms_data->values[i] - mean) * (testnorms_data->values[i] - mean);
  testnorms_data->variance = (sumdiff/((double)testnorms_data->samples));

  // Determine if variation is sufficiently small to declare success
  testnorms_data->pass = (testnorms_data->variance<1.0e-6);

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>shutdown improvements to avoid erasing while holding the port lock<commit_after><|endoftext|>