<commit_before>/*
 * Copyright 1999-2000,2004 The Apache Software Foundation.
 *
 * 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.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>
#include "ICUMsgLoader.hpp"
#include "unicode/putil.h"
#include "unicode/uloc.h"
#include "unicode/udata.h"

#include "string.h"
#include <stdio.h>
#include <stdlib.h>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Local static methods
// ---------------------------------------------------------------------------

/*
 *  Resource Data Reference.
 *
 *  The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol.
 *  The application (this *.cpp) references that symbol here, and will pass the data address to ICU, which
 *  will then  be able to fetch resources from the data.
 */

#if defined(_WIN32) || defined(WIN32)
extern "C" void U_IMPORT *XercesMessages2_6_dat;
#define BUNDLE_NAME "XercesMessages2_6"
#else
extern "C" void U_IMPORT *XercesMessages2_6_0_dat;
#define BUNDLE_NAME "XercesMessages2_6_0"
#endif

/*
 *  Tell ICU where our resource data is located in memory. The data lives in the XercesMessages dll, and we just
 *  pass the address of an exported symbol from that library to ICU.
 */
static bool setAppDataOK = false;

static void setAppData()
{
    static bool setAppDataDone = false;

    if (setAppDataDone)
    {
        return;
    }
    else
    {
        setAppDataDone = true;
        UErrorCode err = U_ZERO_ERROR;
        udata_setAppData(BUNDLE_NAME, &XercesMessages2_6_dat, &err);
        if (U_SUCCESS(err))
        {
    	    setAppDataOK = true;
        }
    }

}

// ---------------------------------------------------------------------------
//  Public Constructors and Destructor
// ---------------------------------------------------------------------------
ICUMsgLoader::ICUMsgLoader(const XMLCh* const  msgDomain)
:fLocaleBundle(0)
,fDomainBundle(0)
{
    /***
	    Validate msgDomain
    ***/
    if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain)    &&
        !XMLString::equals(msgDomain, XMLUni::fgExceptDomain)    &&
        !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain) &&
        !XMLString::equals(msgDomain, XMLUni::fgValidityDomain)   )
    {
        XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
    }

    /***
	Resolve domainName
    ***/
    int     index = XMLString::lastIndexOf(msgDomain, chForwardSlash);
    char*   domainName = XMLString::transcode(&(msgDomain[index + 1]), XMLPlatformUtils::fgMemoryManager);
    ArrayJanitor<char> jan1(domainName, XMLPlatformUtils::fgMemoryManager);

    /***
        Location resolution priority

         1. XMLMsgLoader::getNLSHome(), set by user through
            XMLPlatformUtils::Initialize(), which provides user-specified
            location where the message loader shall retrieve error messages.

         2. environment var: XERCESC_NLS_HOME

         3. path $XERCESCROOT/msg
    ***/

    char locationBuf[1024];
    memset(locationBuf, 0, sizeof locationBuf);
    const char *nlsHome = XMLMsgLoader::getNLSHome();

    if (nlsHome)
    {
    	strcpy(locationBuf, nlsHome);
        strcat(locationBuf, U_FILE_SEP_STRING);
    }
    else
    {
        nlsHome = getenv("XERCESC_NLS_HOME");
        if (nlsHome)
        {
            strcpy(locationBuf, nlsHome);
            strcat(locationBuf, U_FILE_SEP_STRING);
        }
        else
        {
            nlsHome = getenv("XERCESCROOT");
            if (nlsHome)
            {
                strcpy(locationBuf, nlsHome);
                strcat(locationBuf, U_FILE_SEP_STRING);
                strcat(locationBuf, "msg");
                strcat(locationBuf, U_FILE_SEP_STRING);
            }
            else
            {
                /***
                 leave it to ICU to decide where to search
                 for the error message.
                 ***/
                 setAppData();
            }
        }
    }

    /***
	Open the locale-specific resource bundle
    ***/
    strcat(locationBuf, BUNDLE_NAME);
    UErrorCode err = U_ZERO_ERROR;
    uloc_setDefault("en_US", &err);   // in case user-specified locale unavailable
    err = U_ZERO_ERROR;
    fLocaleBundle = ures_open(locationBuf, XMLMsgLoader::getLocale(), &err);
    if (!U_SUCCESS(err) || fLocaleBundle == NULL)
    {
    	/***
    	   in case user specified location does not work
    	   try the dll
        ***/

        if (strcmp(locationBuf, BUNDLE_NAME) !=0 )
        {
            setAppData();
            err = U_ZERO_ERROR;
            fLocaleBundle = ures_open(BUNDLE_NAME, XMLMsgLoader::getLocale(), &err);
            if (!U_SUCCESS(err) || fLocaleBundle == NULL)
            {
                 XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
            }
        }
        else
        {
            XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
        }
    }

    /***
	Open the domain specific resource bundle within
	the locale-specific resource bundle
    ***/
    err = U_ZERO_ERROR;
    fDomainBundle = ures_getByKey(fLocaleBundle, domainName, NULL, &err);
    if (!U_SUCCESS(err) || fDomainBundle == NULL)
    {
        XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
    }

}

ICUMsgLoader::~ICUMsgLoader()
{
    ures_close(fDomainBundle);
    ures_close(fLocaleBundle);
}

// ---------------------------------------------------------------------------
//  Implementation of the virtual message loader API
// ---------------------------------------------------------------------------
bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
                          ,         XMLCh* const            toFill
                          , const   unsigned int            maxChars)
{
    UErrorCode   err = U_ZERO_ERROR;
    int32_t      strLen = 0;

    // Assuming array format
    const UChar *name = ures_getStringByIndex(fDomainBundle, (int32_t)msgToLoad-1, &strLen, &err);

    if (!U_SUCCESS(err) || (name == NULL))
    {
        return false;
    }

    int retStrLen = strLen > (int32_t)maxChars ? maxChars : strLen;

    if (sizeof(UChar)==sizeof(XMLCh))
    {
        XMLString::moveChars(toFill, (XMLCh*)name, retStrLen);
        toFill[retStrLen] = (XMLCh) 0;
    }
    else
    {
        XMLCh* retStr = toFill;
        const UChar *srcPtr = name;

        while (retStrLen--)
           *retStr++ = *srcPtr++;

        *retStr = 0;
    }

    return true;
}

bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const unsigned int            maxChars
                            , const XMLCh* const            repText1
                            , const XMLCh* const            repText2
                            , const XMLCh* const            repText3
                            , const XMLCh* const            repText4
                            , MemoryManager* const          manager   )
{
    // Call the other version to load up the message
    if (!loadMsg(msgToLoad, toFill, maxChars))
        return false;

    // And do the token replacement
    XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
    return true;
}

bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const unsigned int            maxChars
                            , const char* const             repText1
                            , const char* const             repText2
                            , const char* const             repText3
                            , const char* const             repText4
                            , MemoryManager * const         manager)
{
    //
    //  Transcode the provided parameters and call the other version,
    //  which will do the replacement work.
    //
    XMLCh* tmp1 = 0;
    XMLCh* tmp2 = 0;
    XMLCh* tmp3 = 0;
    XMLCh* tmp4 = 0;

    bool bRet = false;
    if (repText1)
        tmp1 = XMLString::transcode(repText1, manager);
    if (repText2)
        tmp2 = XMLString::transcode(repText2, manager);
    if (repText3)
        tmp3 = XMLString::transcode(repText3, manager);
    if (repText4)
        tmp4 = XMLString::transcode(repText4, manager);

    bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);

    if (tmp1)
        manager->deallocate(tmp1);//delete [] tmp1;
    if (tmp2)
        manager->deallocate(tmp2);//delete [] tmp2;
    if (tmp3)
        manager->deallocate(tmp3);//delete [] tmp3;
    if (tmp4)
        manager->deallocate(tmp4);//delete [] tmp4;

    return bRet;
}

XERCES_CPP_NAMESPACE_END
<commit_msg>Make it compile on Unix<commit_after>/*
 * Copyright 1999-2000,2004 The Apache Software Foundation.
 *
 * 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.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>
#include "ICUMsgLoader.hpp"
#include "unicode/putil.h"
#include "unicode/uloc.h"
#include "unicode/udata.h"

#include "string.h"
#include <stdio.h>
#include <stdlib.h>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Local static methods
// ---------------------------------------------------------------------------

/*
 *  Resource Data Reference.
 *
 *  The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol.
 *  The application (this *.cpp) references that symbol here, and will pass the data address to ICU, which
 *  will then  be able to fetch resources from the data.
 */

#if defined(_WIN32) || defined(WIN32)
#define ENTRY_POINT XercesMessages3_0_dat
#define BUNDLE_NAME "XercesMessages3_0"
#else
#define ENTRY_POINT XercesMessages3_0_0_dat
#define BUNDLE_NAME "XercesMessages3_0_0"
#endif
extern "C" void U_IMPORT *ENTRY_POINT;

/*
 *  Tell ICU where our resource data is located in memory. The data lives in the XercesMessages dll, and we just
 *  pass the address of an exported symbol from that library to ICU.
 */
static bool setAppDataOK = false;

static void setAppData()
{
    static bool setAppDataDone = false;

    if (setAppDataDone)
    {
        return;
    }
    else
    {
        setAppDataDone = true;
        UErrorCode err = U_ZERO_ERROR;
        udata_setAppData(BUNDLE_NAME, &ENTRY_POINT, &err);
        if (U_SUCCESS(err))
        {
    	    setAppDataOK = true;
        }
    }

}

// ---------------------------------------------------------------------------
//  Public Constructors and Destructor
// ---------------------------------------------------------------------------
ICUMsgLoader::ICUMsgLoader(const XMLCh* const  msgDomain)
:fLocaleBundle(0)
,fDomainBundle(0)
{
    /***
	    Validate msgDomain
    ***/
    if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain)    &&
        !XMLString::equals(msgDomain, XMLUni::fgExceptDomain)    &&
        !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain) &&
        !XMLString::equals(msgDomain, XMLUni::fgValidityDomain)   )
    {
        XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
    }

    /***
	Resolve domainName
    ***/
    int     index = XMLString::lastIndexOf(msgDomain, chForwardSlash);
    char*   domainName = XMLString::transcode(&(msgDomain[index + 1]), XMLPlatformUtils::fgMemoryManager);
    ArrayJanitor<char> jan1(domainName, XMLPlatformUtils::fgMemoryManager);

    /***
        Location resolution priority

         1. XMLMsgLoader::getNLSHome(), set by user through
            XMLPlatformUtils::Initialize(), which provides user-specified
            location where the message loader shall retrieve error messages.

         2. environment var: XERCESC_NLS_HOME

         3. path $XERCESCROOT/msg
    ***/

    char locationBuf[1024];
    memset(locationBuf, 0, sizeof locationBuf);
    const char *nlsHome = XMLMsgLoader::getNLSHome();

    if (nlsHome)
    {
    	strcpy(locationBuf, nlsHome);
        strcat(locationBuf, U_FILE_SEP_STRING);
    }
    else
    {
        nlsHome = getenv("XERCESC_NLS_HOME");
        if (nlsHome)
        {
            strcpy(locationBuf, nlsHome);
            strcat(locationBuf, U_FILE_SEP_STRING);
        }
        else
        {
            nlsHome = getenv("XERCESCROOT");
            if (nlsHome)
            {
                strcpy(locationBuf, nlsHome);
                strcat(locationBuf, U_FILE_SEP_STRING);
                strcat(locationBuf, "msg");
                strcat(locationBuf, U_FILE_SEP_STRING);
            }
            else
            {
                /***
                 leave it to ICU to decide where to search
                 for the error message.
                 ***/
                 setAppData();
            }
        }
    }

    /***
	Open the locale-specific resource bundle
    ***/
    strcat(locationBuf, BUNDLE_NAME);
    UErrorCode err = U_ZERO_ERROR;
    uloc_setDefault("en_US", &err);   // in case user-specified locale unavailable
    err = U_ZERO_ERROR;
    fLocaleBundle = ures_open(locationBuf, XMLMsgLoader::getLocale(), &err);
    if (!U_SUCCESS(err) || fLocaleBundle == NULL)
    {
    	/***
    	   in case user specified location does not work
    	   try the dll
        ***/

        if (strcmp(locationBuf, BUNDLE_NAME) !=0 )
        {
            setAppData();
            err = U_ZERO_ERROR;
            fLocaleBundle = ures_open(BUNDLE_NAME, XMLMsgLoader::getLocale(), &err);
            if (!U_SUCCESS(err) || fLocaleBundle == NULL)
            {
                 XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
            }
        }
        else
        {
            XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
        }
    }

    /***
	Open the domain specific resource bundle within
	the locale-specific resource bundle
    ***/
    err = U_ZERO_ERROR;
    fDomainBundle = ures_getByKey(fLocaleBundle, domainName, NULL, &err);
    if (!U_SUCCESS(err) || fDomainBundle == NULL)
    {
        XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
    }

}

ICUMsgLoader::~ICUMsgLoader()
{
    ures_close(fDomainBundle);
    ures_close(fLocaleBundle);
}

// ---------------------------------------------------------------------------
//  Implementation of the virtual message loader API
// ---------------------------------------------------------------------------
bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
                          ,         XMLCh* const            toFill
                          , const   unsigned int            maxChars)
{
    UErrorCode   err = U_ZERO_ERROR;
    int32_t      strLen = 0;

    // Assuming array format
    const UChar *name = ures_getStringByIndex(fDomainBundle, (int32_t)msgToLoad-1, &strLen, &err);

    if (!U_SUCCESS(err) || (name == NULL))
    {
        return false;
    }

    int retStrLen = strLen > (int32_t)maxChars ? maxChars : strLen;

    if (sizeof(UChar)==sizeof(XMLCh))
    {
        XMLString::moveChars(toFill, (XMLCh*)name, retStrLen);
        toFill[retStrLen] = (XMLCh) 0;
    }
    else
    {
        XMLCh* retStr = toFill;
        const UChar *srcPtr = name;

        while (retStrLen--)
           *retStr++ = *srcPtr++;

        *retStr = 0;
    }

    return true;
}

bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const unsigned int            maxChars
                            , const XMLCh* const            repText1
                            , const XMLCh* const            repText2
                            , const XMLCh* const            repText3
                            , const XMLCh* const            repText4
                            , MemoryManager* const          manager   )
{
    // Call the other version to load up the message
    if (!loadMsg(msgToLoad, toFill, maxChars))
        return false;

    // And do the token replacement
    XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
    return true;
}

bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const unsigned int            maxChars
                            , const char* const             repText1
                            , const char* const             repText2
                            , const char* const             repText3
                            , const char* const             repText4
                            , MemoryManager * const         manager)
{
    //
    //  Transcode the provided parameters and call the other version,
    //  which will do the replacement work.
    //
    XMLCh* tmp1 = 0;
    XMLCh* tmp2 = 0;
    XMLCh* tmp3 = 0;
    XMLCh* tmp4 = 0;

    bool bRet = false;
    if (repText1)
        tmp1 = XMLString::transcode(repText1, manager);
    if (repText2)
        tmp2 = XMLString::transcode(repText2, manager);
    if (repText3)
        tmp3 = XMLString::transcode(repText3, manager);
    if (repText4)
        tmp4 = XMLString::transcode(repText4, manager);

    bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);

    if (tmp1)
        manager->deallocate(tmp1);//delete [] tmp1;
    if (tmp2)
        manager->deallocate(tmp2);//delete [] tmp2;
    if (tmp3)
        manager->deallocate(tmp3);//delete [] tmp3;
    if (tmp4)
        manager->deallocate(tmp4);//delete [] tmp4;

    return bRet;
}

XERCES_CPP_NAMESPACE_END
<|endoftext|>


<commit_before><commit_msg>Make JitCache thread safe<commit_after><|endoftext|>


<commit_before>#include "SysControl.h"
#include "ControlsApp.h"
#include "ControlsXPad360.h"
#include "Engine.h"
#include "App.h"

//ƽַ̨
#ifdef _WIN32
#pragma execution_character_set("utf-8")
#endif

using namespace MathLib;

class CSysControlLocal : public CSysControl
{
public:
	CSysControlLocal();
    virtual ~CSysControlLocal();

	virtual void Init();	//ɫҪʼɫҪʼ
	virtual void Update(float ifps);
	virtual void Shutdown();

	virtual int GetState(int state);		//״̬״̬״̬ӵ״̬ȵȡ
	virtual int ClearState(int state);

	virtual float GetMouseDX();
	virtual float GetMouseDY();

	virtual void SetMouseGrab(int g);		//Ƿʾ
	virtual int GetMouseGrab();			//ȡ״̬ʾػǲʾ״̬

	virtual void SetControlMode(ControlMode mode);			//ģʽ
	virtual ControlMode GetControlMode() const;				//ȡģʽ

private:
	void Update_Mouse(float ifps);
	void Update_Keyboard(float ifps);
	void Update_XPad360(float ifps);

	CControlsApp        *m_pControlsApp;		//Ϸƶ
	CControlsXPad360    *m_pControlsXPad360;
	ControlMode         m_nControlMode;			//ģʽ

	int                 m_nOldMouseX;			//һX
	int                 m_nOldMouseY;			//һY

	CObjectGui          *m_pTest3DUI;
	CWidgetLabel        *m_pTestMessageLabel;

};

CSysControlLocal::CSysControlLocal()
{

}
CSysControlLocal::~CSysControlLocal()
{

}

void CSysControlLocal::Init()
{
	m_pControlsApp = new CControlsApp;
	m_pControlsXPad360 = new CControlsXPad360(0);

	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);

	SetControlMode(CONTROL_KEYBORAD_MOUSE);

	m_pTest3DUI = new CObjectGui(2.0f, 1.0f, "data/core/gui/");
	m_pTest3DUI->SetMouseShow(0);
	m_pTest3DUI->SetBackground(1);
	m_pTest3DUI->SetBackgroundColor(vec4(1.0f, 0.0f, 0.0f, 1.0f));

	m_pTest3DUI->SetScreenSize(800, 400);
	m_pTest3DUI->SetControlDistance(1000.0f);
	m_pTest3DUI->CreateMaterial("gui_base");	 //show in game

	m_pTest3DUI->SetWorldTransform(Translate(0.0f, 0.0f, 2.0f) * MakeRotationFromZY(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f)));

	m_pTestMessageLabel = new CWidgetLabel(m_pTest3DUI->GetGui());	//ʼֱǩ
	m_pTest3DUI->GetGui()->AddChild(m_pTestMessageLabel, CGui::ALIGN_CENTER);
	m_pTestMessageLabel->SetFontColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

	m_pTestMessageLabel->SetFontSize(80);		//С
	m_pTestMessageLabel->SetFontOutline(1);		//
	m_pTestMessageLabel->SetText("\nһа\nǧѩ\nŲﴬ");

	void CSysControlLocal::Update(float ifps)
	{
		Update_Mouse(ifps);
		Update_Keyboard(ifps);
		Update_XPad360(ifps);
	}

	m_nOldMouseX = 0;
	m_nOldMouseY = 0;
}
void CSysControlLocal::Shutdown()
{
	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);
}

<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "SysControl.h"
#include "ControlsApp.h"
#include "ControlsXPad360.h"
#include "Engine.h"
#include "App.h"

//ƽַ̨
#ifdef _WIN32
#pragma execution_character_set("utf-8")
#endif

using namespace MathLib;

class CSysControlLocal : public CSysControl
{
public:
	CSysControlLocal();
    virtual ~CSysControlLocal();

	virtual void Init();	//ɫҪʼɫҪʼ
	virtual void Update(float ifps);
	virtual void Shutdown();

	virtual int GetState(int state);		//״̬״̬״̬ӵ״̬ȵȡ
	virtual int ClearState(int state);

	virtual float GetMouseDX();
	virtual float GetMouseDY();

	virtual void SetMouseGrab(int g);		//Ƿʾ
	virtual int GetMouseGrab();			//ȡ״̬ʾػǲʾ״̬

	virtual void SetControlMode(ControlMode mode);			//ģʽ
	virtual ControlMode GetControlMode() const;				//ȡģʽ

private:
	void Update_Mouse(float ifps);
	void Update_Keyboard(float ifps);
	void Update_XPad360(float ifps);

	CControlsApp        *m_pControlsApp;		//Ϸƶ
	CControlsXPad360    *m_pControlsXPad360;
	ControlMode         m_nControlMode;			//ģʽ

	int                 m_nOldMouseX;			//һX
	int                 m_nOldMouseY;			//һY

	CObjectGui          *m_pTest3DUI;
	CWidgetLabel        *m_pTestMessageLabel;

};

CSysControlLocal::CSysControlLocal()
{

}
CSysControlLocal::~CSysControlLocal()
{

}

void CSysControlLocal::Init()
{
	m_pControlsApp = new CControlsApp;
	m_pControlsXPad360 = new CControlsXPad360(0);

	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);

	SetControlMode(CONTROL_KEYBORAD_MOUSE);

	m_pTest3DUI = new CObjectGui(2.0f, 1.0f, "data/core/gui/");
	m_pTest3DUI->SetMouseShow(0);
	m_pTest3DUI->SetBackground(1);
	m_pTest3DUI->SetBackgroundColor(vec4(1.0f, 0.0f, 0.0f, 1.0f));

	m_pTest3DUI->SetScreenSize(800, 400);
	m_pTest3DUI->SetControlDistance(1000.0f);
	m_pTest3DUI->CreateMaterial("gui_base");	 //show in game

	m_pTest3DUI->SetWorldTransform(Translate(0.0f, 0.0f, 2.0f) * MakeRotationFromZY(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f)));

	m_pTestMessageLabel = new CWidgetLabel(m_pTest3DUI->GetGui());	//ʼֱǩ
	m_pTest3DUI->GetGui()->AddChild(m_pTestMessageLabel, CGui::ALIGN_CENTER);
	m_pTestMessageLabel->SetFontColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

	m_pTestMessageLabel->SetFontSize(80);		//С
	m_pTestMessageLabel->SetFontOutline(1);		//
	m_pTestMessageLabel->SetText("\nһа\nǧѩ\nŲﴬ");

	void CSysControlLocal::Update(float ifps)
	{
		Update_Mouse(ifps);
		Update_Keyboard(ifps);
		Update_XPad360(ifps);
	}

	m_nOldMouseX = 0;
	m_nOldMouseY = 0;
}
void CSysControlLocal::Shutdown()
{
	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);
	delete m_pControlsApp;
	m_pControlsApp = NULL;
	delete m_pControlsXPad360;
	m_pControlsXPad360 = NULL;

}

<|endoftext|>


<commit_before>#include <nan.h>
extern "C" {
#include <expat.h>
}

using namespace v8;
using namespace node;

class Parser : public ObjectWrap {
public:
  static void Initialize(Handle<Object> target)
  {
    NanScope();
    Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);

    t->InstanceTemplate()->SetInternalFieldCount(1);

    NODE_SET_PROTOTYPE_METHOD(t, "parse", Parse);
    NODE_SET_PROTOTYPE_METHOD(t, "setEncoding", SetEncoding);
    NODE_SET_PROTOTYPE_METHOD(t, "setUnknownEncoding", SetUnknownEncoding);
    NODE_SET_PROTOTYPE_METHOD(t, "getError", GetError);
    NODE_SET_PROTOTYPE_METHOD(t, "stop", Stop);
    NODE_SET_PROTOTYPE_METHOD(t, "resume", Resume);
    NODE_SET_PROTOTYPE_METHOD(t, "reset", Reset);
    NODE_SET_PROTOTYPE_METHOD(t, "getCurrentLineNumber", GetCurrentLineNumber);
    NODE_SET_PROTOTYPE_METHOD(t, "getCurrentColumnNumber", GetCurrentColumnNumber);
    NODE_SET_PROTOTYPE_METHOD(t, "getCurrentByteIndex", GetCurrentByteIndex);

    target->Set(NanNew("Parser"), t->GetFunction());
  }

protected:
  /*** Constructor ***/

  static NAN_METHOD(New)
  {
    NanScope();
    XML_Char *encoding = NULL;
    if (args.Length() == 1 && args[0]->IsString())
      {
        encoding = new XML_Char[32];
        NanRawString(args[0], Nan::ASCII, NULL, encoding, 32, 0);
      }

    Parser *parser = new Parser(encoding);
    if (encoding)
      delete[] encoding;
    parser->Wrap(args.This());
    NanReturnValue(args.This());
  }

  Parser(const XML_Char *encoding)
    : ObjectWrap()
  {
    parser = XML_ParserCreate(encoding);
    assert(parser != NULL);

    attachHandlers();
  }

  ~Parser()
  {
    XML_ParserFree(parser);
  }

  void attachHandlers()
  {
    XML_SetUserData(parser, this);
    XML_SetElementHandler(parser, StartElement, EndElement);
    XML_SetCharacterDataHandler(parser, Text);
    XML_SetCdataSectionHandler(parser, StartCdata, EndCdata);
    XML_SetProcessingInstructionHandler(parser, ProcessingInstruction);
    XML_SetCommentHandler(parser, Comment);
    XML_SetXmlDeclHandler(parser, XmlDecl);
    XML_SetEntityDeclHandler(parser, EntityDecl);
    XML_SetUnknownEncodingHandler(parser, UnknownEncoding, this);
  }

  /*** parse() ***/

  static NAN_METHOD(Parse)
  {
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    NanScope();
    Local<String> str;
    int isFinal = 0;

    /* Argument 2: isFinal :: Bool */
    if (args.Length() >= 2)
      {
        isFinal = args[1]->IsTrue();
      }

    /* Argument 1: buf :: String or Buffer */
    if (args.Length() >= 1 && args[0]->IsString())
      {
        str = args[0]->ToString();
        NanReturnValue(parser->parseString(**str, isFinal) ? NanTrue() : NanFalse());
      }
    else if (args.Length() >= 1 && args[0]->IsObject())
      {
        Local<Object> obj = args[0]->ToObject();
        if (Buffer::HasInstance(obj))
        {
          NanReturnValue(parser->parseBuffer(obj, isFinal) ? NanTrue() : NanFalse());
        }
        else
        {
          NanThrowTypeError("Parse buffer must be String or Buffer");
          NanReturnUndefined();
        }
      }
    else {
      NanThrowTypeError("Parse buffer must be String or Buffer");
      NanReturnUndefined();
    }
  }

  /** Parse a v8 String by first writing it to the expat parser's
      buffer */
  bool parseString(String &str, int isFinal)
  {
    int len = str.Utf8Length();
    if (len == 0)
      return true;

    void *buf = XML_GetBuffer(parser, len);
    assert(buf != NULL);
    assert(str.WriteUtf8(static_cast<char *>(buf), len) == len);

    return XML_ParseBuffer(parser, len, isFinal) != XML_STATUS_ERROR;
  }

  /** Parse a node.js Buffer directly */
  bool parseBuffer(Local<Object> buffer, int isFinal)
  {
    return XML_Parse(parser, Buffer::Data(buffer), Buffer::Length(buffer), isFinal) != XML_STATUS_ERROR;
  }

  /*** setEncoding() ***/

  static NAN_METHOD(SetEncoding)
  {
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    NanScope();

    if (args.Length() == 1 && args[0]->IsString())
      {
        XML_Char *encoding = new XML_Char[32];
        NanRawString(args[0], Nan::ASCII, NULL, encoding, 32, 0);

        int status = parser->setEncoding(encoding);

        delete[] encoding;

        NanReturnValue(status ? NanTrue() : NanFalse());
      }
    else
      NanReturnValue(NanFalse());
  }

  int setEncoding(XML_Char *encoding)
  {
    return XML_SetEncoding(parser, encoding) != 0;
  }

  /*** getError() ***/

  static NAN_METHOD(GetError)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    const XML_LChar *error = parser->getError();
    if (error)
      NanReturnValue(NanNew(error));
    else
      NanReturnValue(NanNull());
  }

  /*** stop() ***/

  static NAN_METHOD(Stop)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    int status = parser->stop();

    NanReturnValue(status ? NanTrue() : NanFalse());
  }

  int stop()
  {
    return XML_StopParser(parser, XML_TRUE) != 0;
  }

  /*** resume() ***/

  static NAN_METHOD(Resume)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    int status = parser->resume();

    NanReturnValue(status ? NanTrue() : NanFalse());
  }

  int resume()
  {
    return XML_ResumeParser(parser) != 0;
  }

  static NAN_METHOD(Reset)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    XML_Char *encoding = NULL;
    if (args.Length() == 1 && args[0]->IsString())
      {
        encoding = new XML_Char[32];
        NanRawString(args[0], Nan::ASCII, NULL, encoding, 32, 0);
      }

    int status = parser->reset(encoding);
    if (status)
      parser->attachHandlers();
    NanReturnValue(status ? NanTrue() : NanFalse());
  }

  int reset(XML_Char *encoding)
  {
      return XML_ParserReset(parser, encoding) != 0;
  }
  const XML_LChar *getError()
  {
    enum XML_Error code;
    code = XML_GetErrorCode(parser);
    return XML_ErrorString(code);
  }

  static NAN_METHOD(GetCurrentLineNumber)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    NanReturnValue(NanNew(parser->getCurrentLineNumber()));
  }

  uint32_t getCurrentLineNumber()
  {
    return XML_GetCurrentLineNumber(parser);
  }

  static NAN_METHOD(GetCurrentColumnNumber)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    NanReturnValue(NanNew(parser->getCurrentColumnNumber()));
  }

  uint32_t getCurrentColumnNumber()
  {
    return XML_GetCurrentColumnNumber(parser);
  }

  static NAN_METHOD(GetCurrentByteIndex)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    NanReturnValue(NanNew(parser->getCurrentByteIndex()));
  }

  int32_t getCurrentByteIndex()
  {
    return XML_GetCurrentByteIndex(parser);
  }

private:
  /* expat instance */
  XML_Parser parser;

  /* no default ctor */
  Parser();

  /*** SAX callbacks ***/
  /* Should a local HandleScope be used in those callbacks? */

  static void StartElement(void *userData,
                           const XML_Char *name, const XML_Char **atts)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Collect atts into JS object */
    Local<Object> attr = NanNew<Object>();
    for(const XML_Char **atts1 = atts; *atts1; atts1 += 2)
      attr->Set(NanNew(atts1[0]), NanNew(atts1[1]));

    /* Trigger event */
    Handle<Value> argv[3] = { NanNew("startElement"),
                              NanNew(name),
                              attr };
    parser->Emit(3, argv);
  }

  static void EndElement(void *userData,
                         const XML_Char *name)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[2] = { NanNew("endElement"), NanNew(name) };
    parser->Emit(2, argv);
  }

  static void StartCdata(void *userData)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[1] = { NanNew("startCdata") };
    parser->Emit(1, argv);
  }

  static void EndCdata(void *userData)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[1] = { NanNew("endCdata") };
    parser->Emit(1, argv);
  }

  static void Text(void *userData,
                   const XML_Char *s, int len)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[2] = { NanNew("text"),
                              NanNew(s, len) };
    parser->Emit(2, argv);
  }

  static void ProcessingInstruction(void *userData,
                                    const XML_Char *target, const XML_Char *data)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[3] = { NanNew("processingInstruction"),
                              NanNew(target),
                              NanNew(data) };
    parser->Emit(3, argv);
  }

  static void Comment(void *userData,
                      const XML_Char *data)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[2] = { NanNew("comment"), NanNew(data) };
    parser->Emit(2, argv);
  }

  static void XmlDecl(void *userData,
                      const XML_Char *version, const XML_Char *encoding,
                      int standalone)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Local<Value> argv[4];

                    argv[0] = NanNew("xmlDecl");
    if (version)    argv[1] = NanNew(version);
    else            argv[1] = NanNull();
    if (encoding)   argv[2] = NanNew(encoding);
    else            argv[2] = NanNull();
    if (standalone) argv[3] = NanTrue();
    else            argv[3] = NanFalse();

    parser->Emit(4, argv);
  }

  static void EntityDecl(void *userData, const XML_Char *entityName, int is_parameter_entity,
                         const XML_Char *value, int value_length, const XML_Char *base,
                         const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Local<Value> argv[8];

                             argv[0] = NanNew("entityDecl");
    if (entityName)          argv[1] = NanNew(entityName);
    else                     argv[1] = NanNull();
    if (is_parameter_entity) argv[2] = NanTrue();
    else                     argv[2] = NanFalse();
    if (value)               argv[3] = NanNew(value, value_length);
    else                     argv[3] = NanNull();
    if (base)                argv[4] = NanNew(base);
    else                     argv[4] = NanNull();
    if (systemId)            argv[5] = NanNew(systemId);
    else                     argv[5] = NanNull();
    if (publicId)            argv[6] = NanNew(publicId);
    else                     argv[6] = NanNull();
    if (notationName)        argv[7] = NanNew(notationName);
    else                     argv[7] = NanNull();

    parser->Emit(8, argv);
  }

  XML_Encoding *xmlEncodingInfo;

  static int UnknownEncoding(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(encodingHandlerData);

    /* Trigger event */
    parser->xmlEncodingInfo = info;
    Local<Value> argv[2];

              argv[0] = NanNew("unknownEncoding");
    if (name) argv[1] = NanNew(name);
    else      argv[1] = NanNull();

    parser->Emit(2, argv);

    /* Did no event handler invoke setUnknownEncoding()? */
    if (parser->xmlEncodingInfo) {
      parser->xmlEncodingInfo = NULL;
      return XML_STATUS_ERROR;
    } else {
      return XML_STATUS_OK;
    }
  }

  /**
   * Fills xmlEncodingInfo
   */
  static NAN_METHOD(SetUnknownEncoding)
  {
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    NanScope();

    if (!parser->xmlEncodingInfo)
      NanThrowError("setUnknownEncoding() must be synchronously invoked from an unknownEncoding event handler");

    if (args.Length() >= 1 && args[0]->IsArray()) {
      Local<Array> map = args[0].As<Array>();
      /* Copy map */
      for(int i = 0; i < 256; i++) {
        Local<Value> m = map->Get(NanNew(i));
        if (m->IsInt32())
          parser->xmlEncodingInfo->map[i] = m->Int32Value();
        else
          NanThrowTypeError("UnknownEncoding map must consist of 256 ints");
      }
    } else
      NanThrowTypeError("SetUnknownEncoding expects a map array");

    parser->xmlEncodingInfo = NULL;
    NanReturnUndefined();
  }

  void Emit(int argc, Handle<Value> argv[])
  {
    NanScope();

    Handle<Object> handle = NanObjectWrapHandle(this);
    Local<Function> emit = handle->Get(NanNew("emit")).As<Function>();
    emit->Call(handle, argc, argv);
  }
};

extern "C" {
  static void init (Handle<Object> target)
  {
    Parser::Initialize(target);
  }
  //Changed the name cause I couldn't load the module with - in their names
  NODE_MODULE(node_expat, init);
};

<commit_msg>update string usage to nan 1.3.0 style<commit_after>#include <nan.h>
extern "C" {
#include <expat.h>
}

using namespace v8;
using namespace node;

class Parser : public ObjectWrap {
public:
  static void Initialize(Handle<Object> target)
  {
    NanScope();
    Local<FunctionTemplate> t = NanNew<FunctionTemplate>(New);

    t->InstanceTemplate()->SetInternalFieldCount(1);

    NODE_SET_PROTOTYPE_METHOD(t, "parse", Parse);
    NODE_SET_PROTOTYPE_METHOD(t, "setEncoding", SetEncoding);
    NODE_SET_PROTOTYPE_METHOD(t, "setUnknownEncoding", SetUnknownEncoding);
    NODE_SET_PROTOTYPE_METHOD(t, "getError", GetError);
    NODE_SET_PROTOTYPE_METHOD(t, "stop", Stop);
    NODE_SET_PROTOTYPE_METHOD(t, "resume", Resume);
    NODE_SET_PROTOTYPE_METHOD(t, "reset", Reset);
    NODE_SET_PROTOTYPE_METHOD(t, "getCurrentLineNumber", GetCurrentLineNumber);
    NODE_SET_PROTOTYPE_METHOD(t, "getCurrentColumnNumber", GetCurrentColumnNumber);
    NODE_SET_PROTOTYPE_METHOD(t, "getCurrentByteIndex", GetCurrentByteIndex);

    target->Set(NanNew("Parser"), t->GetFunction());
  }

protected:
  /*** Constructor ***/

  static NAN_METHOD(New)
  {
    NanScope();
    XML_Char *encoding = NULL;
    if (args.Length() == 1 && args[0]->IsString())
      {
        NanAsciiString encodingArg(args[0]);
        encoding = new XML_Char[encodingArg.length() + 1];
        strcpy(encoding, *encodingArg);
      }

    Parser *parser = new Parser(encoding);
    if (encoding)
      delete[] encoding;
    parser->Wrap(args.This());
    NanReturnValue(args.This());
  }

  Parser(const XML_Char *encoding)
    : ObjectWrap()
  {
    parser = XML_ParserCreate(encoding);
    assert(parser != NULL);

    attachHandlers();
  }

  ~Parser()
  {
    XML_ParserFree(parser);
  }

  void attachHandlers()
  {
    XML_SetUserData(parser, this);
    XML_SetElementHandler(parser, StartElement, EndElement);
    XML_SetCharacterDataHandler(parser, Text);
    XML_SetCdataSectionHandler(parser, StartCdata, EndCdata);
    XML_SetProcessingInstructionHandler(parser, ProcessingInstruction);
    XML_SetCommentHandler(parser, Comment);
    XML_SetXmlDeclHandler(parser, XmlDecl);
    XML_SetEntityDeclHandler(parser, EntityDecl);
    XML_SetUnknownEncodingHandler(parser, UnknownEncoding, this);
  }

  /*** parse() ***/

  static NAN_METHOD(Parse)
  {
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    NanScope();
    Local<String> str;
    int isFinal = 0;

    /* Argument 2: isFinal :: Bool */
    if (args.Length() >= 2)
      {
        isFinal = args[1]->IsTrue();
      }

    /* Argument 1: buf :: String or Buffer */
    if (args.Length() >= 1 && args[0]->IsString())
      {
        str = args[0]->ToString();
        NanReturnValue(parser->parseString(**str, isFinal) ? NanTrue() : NanFalse());
      }
    else if (args.Length() >= 1 && args[0]->IsObject())
      {
        Local<Object> obj = args[0]->ToObject();
        if (Buffer::HasInstance(obj))
        {
          NanReturnValue(parser->parseBuffer(obj, isFinal) ? NanTrue() : NanFalse());
        }
        else
        {
          NanThrowTypeError("Parse buffer must be String or Buffer");
          NanReturnUndefined();
        }
      }
    else {
      NanThrowTypeError("Parse buffer must be String or Buffer");
      NanReturnUndefined();
    }
  }

  /** Parse a v8 String by first writing it to the expat parser's
      buffer */
  bool parseString(String &str, int isFinal)
  {
    int len = str.Utf8Length();
    if (len == 0)
      return true;

    void *buf = XML_GetBuffer(parser, len);
    assert(buf != NULL);
    assert(str.WriteUtf8(static_cast<char *>(buf), len) == len);

    return XML_ParseBuffer(parser, len, isFinal) != XML_STATUS_ERROR;
  }

  /** Parse a node.js Buffer directly */
  bool parseBuffer(Local<Object> buffer, int isFinal)
  {
    return XML_Parse(parser, Buffer::Data(buffer), Buffer::Length(buffer), isFinal) != XML_STATUS_ERROR;
  }

  /*** setEncoding() ***/

  static NAN_METHOD(SetEncoding)
  {
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    NanScope();

    if (args.Length() == 1 && args[0]->IsString())
      {
        NanAsciiString encoding(args[0]);
        int status = parser->setEncoding(*encoding);

        NanReturnValue(status ? NanTrue() : NanFalse());
      }
    else
      NanReturnValue(NanFalse());
  }

  int setEncoding(XML_Char *encoding)
  {
    return XML_SetEncoding(parser, encoding) != 0;
  }

  /*** getError() ***/

  static NAN_METHOD(GetError)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    const XML_LChar *error = parser->getError();
    if (error)
      NanReturnValue(NanNew(error));
    else
      NanReturnValue(NanNull());
  }

  /*** stop() ***/

  static NAN_METHOD(Stop)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    int status = parser->stop();

    NanReturnValue(status ? NanTrue() : NanFalse());
  }

  int stop()
  {
    return XML_StopParser(parser, XML_TRUE) != 0;
  }

  /*** resume() ***/

  static NAN_METHOD(Resume)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    int status = parser->resume();

    NanReturnValue(status ? NanTrue() : NanFalse());
  }

  int resume()
  {
    return XML_ResumeParser(parser) != 0;
  }

  static NAN_METHOD(Reset)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    XML_Char *encoding = NULL;
    if (args.Length() == 1 && args[0]->IsString())
      {
        NanAsciiString encodingArg(args[0]);
        encoding = new XML_Char[encodingArg.length() + 1];
        strcpy(encoding, *encodingArg);
      }

    int status = parser->reset(encoding);
    if (encoding)
      delete[] encoding;
    if (status)
      parser->attachHandlers();
    NanReturnValue(status ? NanTrue() : NanFalse());
  }

  int reset(XML_Char *encoding)
  {
      return XML_ParserReset(parser, encoding) != 0;
  }
  const XML_LChar *getError()
  {
    enum XML_Error code;
    code = XML_GetErrorCode(parser);
    return XML_ErrorString(code);
  }

  static NAN_METHOD(GetCurrentLineNumber)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    NanReturnValue(NanNew(parser->getCurrentLineNumber()));
  }

  uint32_t getCurrentLineNumber()
  {
    return XML_GetCurrentLineNumber(parser);
  }

  static NAN_METHOD(GetCurrentColumnNumber)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    NanReturnValue(NanNew(parser->getCurrentColumnNumber()));
  }

  uint32_t getCurrentColumnNumber()
  {
    return XML_GetCurrentColumnNumber(parser);
  }

  static NAN_METHOD(GetCurrentByteIndex)
  {
    NanScope();
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());

    NanReturnValue(NanNew(parser->getCurrentByteIndex()));
  }

  int32_t getCurrentByteIndex()
  {
    return XML_GetCurrentByteIndex(parser);
  }

private:
  /* expat instance */
  XML_Parser parser;

  /* no default ctor */
  Parser();

  /*** SAX callbacks ***/
  /* Should a local HandleScope be used in those callbacks? */

  static void StartElement(void *userData,
                           const XML_Char *name, const XML_Char **atts)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Collect atts into JS object */
    Local<Object> attr = NanNew<Object>();
    for(const XML_Char **atts1 = atts; *atts1; atts1 += 2)
      attr->Set(NanNew(atts1[0]), NanNew(atts1[1]));

    /* Trigger event */
    Handle<Value> argv[3] = { NanNew("startElement"),
                              NanNew(name),
                              attr };
    parser->Emit(3, argv);
  }

  static void EndElement(void *userData,
                         const XML_Char *name)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[2] = { NanNew("endElement"), NanNew(name) };
    parser->Emit(2, argv);
  }

  static void StartCdata(void *userData)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[1] = { NanNew("startCdata") };
    parser->Emit(1, argv);
  }

  static void EndCdata(void *userData)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[1] = { NanNew("endCdata") };
    parser->Emit(1, argv);
  }

  static void Text(void *userData,
                   const XML_Char *s, int len)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[2] = { NanNew("text"),
                              NanNew(s, len) };
    parser->Emit(2, argv);
  }

  static void ProcessingInstruction(void *userData,
                                    const XML_Char *target, const XML_Char *data)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[3] = { NanNew("processingInstruction"),
                              NanNew(target),
                              NanNew(data) };
    parser->Emit(3, argv);
  }

  static void Comment(void *userData,
                      const XML_Char *data)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Handle<Value> argv[2] = { NanNew("comment"), NanNew(data) };
    parser->Emit(2, argv);
  }

  static void XmlDecl(void *userData,
                      const XML_Char *version, const XML_Char *encoding,
                      int standalone)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Local<Value> argv[4];

                    argv[0] = NanNew("xmlDecl");
    if (version)    argv[1] = NanNew(version);
    else            argv[1] = NanNull();
    if (encoding)   argv[2] = NanNew(encoding);
    else            argv[2] = NanNull();
    if (standalone) argv[3] = NanTrue();
    else            argv[3] = NanFalse();

    parser->Emit(4, argv);
  }

  static void EntityDecl(void *userData, const XML_Char *entityName, int is_parameter_entity,
                         const XML_Char *value, int value_length, const XML_Char *base,
                         const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(userData);

    /* Trigger event */
    Local<Value> argv[8];

                             argv[0] = NanNew("entityDecl");
    if (entityName)          argv[1] = NanNew(entityName);
    else                     argv[1] = NanNull();
    if (is_parameter_entity) argv[2] = NanTrue();
    else                     argv[2] = NanFalse();
    if (value)               argv[3] = NanNew(value, value_length);
    else                     argv[3] = NanNull();
    if (base)                argv[4] = NanNew(base);
    else                     argv[4] = NanNull();
    if (systemId)            argv[5] = NanNew(systemId);
    else                     argv[5] = NanNull();
    if (publicId)            argv[6] = NanNew(publicId);
    else                     argv[6] = NanNull();
    if (notationName)        argv[7] = NanNew(notationName);
    else                     argv[7] = NanNull();

    parser->Emit(8, argv);
  }

  XML_Encoding *xmlEncodingInfo;

  static int UnknownEncoding(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info)
  {
    NanScope();
    Parser *parser = reinterpret_cast<Parser *>(encodingHandlerData);

    /* Trigger event */
    parser->xmlEncodingInfo = info;
    Local<Value> argv[2];

              argv[0] = NanNew("unknownEncoding");
    if (name) argv[1] = NanNew(name);
    else      argv[1] = NanNull();

    parser->Emit(2, argv);

    /* Did no event handler invoke setUnknownEncoding()? */
    if (parser->xmlEncodingInfo) {
      parser->xmlEncodingInfo = NULL;
      return XML_STATUS_ERROR;
    } else {
      return XML_STATUS_OK;
    }
  }

  /**
   * Fills xmlEncodingInfo
   */
  static NAN_METHOD(SetUnknownEncoding)
  {
    Parser *parser = ObjectWrap::Unwrap<Parser>(args.This());
    NanScope();

    if (!parser->xmlEncodingInfo)
      NanThrowError("setUnknownEncoding() must be synchronously invoked from an unknownEncoding event handler");

    if (args.Length() >= 1 && args[0]->IsArray()) {
      Local<Array> map = args[0].As<Array>();
      /* Copy map */
      for(int i = 0; i < 256; i++) {
        Local<Value> m = map->Get(NanNew(i));
        if (m->IsInt32())
          parser->xmlEncodingInfo->map[i] = m->Int32Value();
        else
          NanThrowTypeError("UnknownEncoding map must consist of 256 ints");
      }
    } else
      NanThrowTypeError("SetUnknownEncoding expects a map array");

    parser->xmlEncodingInfo = NULL;
    NanReturnUndefined();
  }

  void Emit(int argc, Handle<Value> argv[])
  {
    NanScope();

    Handle<Object> handle = NanObjectWrapHandle(this);
    Local<Function> emit = handle->Get(NanNew("emit")).As<Function>();
    emit->Call(handle, argc, argv);
  }
};

extern "C" {
  static void init (Handle<Object> target)
  {
    Parser::Initialize(target);
  }
  //Changed the name cause I couldn't load the module with - in their names
  NODE_MODULE(node_expat, init);
};

<|endoftext|>


<commit_before>#ifndef Nodes_Node_h
#define Nodes_Node_h
#include <functional>
#include <vector>
#include "../types.hh"

namespace doanimate
{
	namespace nodes
	{
		class Node
		{
			public:
			const bool has_ui_operations;

			Node(const bool has_ui_operations)
			: has_ui_operations(has_ui_operations)
			{
			}

			virtual void update() = 0;

			virtual std::vector<types::Value>& get_inputs() = 0;

			virtual const std::vector<types::Value>& get_outputs() = 0;

			virtual const std::vector<types::TypeInfo>& get_input_type_infos() = 0;

			virtual const std::vector<std::string>& get_input_names() = 0;

			virtual const std::vector<types::TypeInfo>& get_output_type_infos() = 0;

			virtual const std::vector<std::string>& get_output_names() = 0;

			virtual void run_ui_operations()
			{}
		};

		class DefaultNode : public Node
		{
			protected:
			using imp_t = std::function<
				std::vector<types::Value>(std::vector<types::Value>)
			>;

			imp_t implementation;

			const std::vector<types::TypeInfo> input_type_infos;

			const std::vector<std::string> input_names;

			const std::vector<types::TypeInfo> output_type_infos;

			const std::vector<std::string> output_names;

			std::vector<types::Value> inputs;

			std::vector<types::Value> outputs;

			public:
			DefaultNode(
				imp_t implementation,
				decltype(input_type_infos) input_type_infos,
				decltype(input_names) input_names,
				decltype(output_type_infos) output_type_infos,
				decltype(output_names) output_names,
				decltype(inputs) default_inputs
			)
			: Node(false),
			  implementation(implementation),
			  input_type_infos(input_type_infos),
			  input_names(input_names),
			  output_type_infos(output_type_infos),
			  output_names(output_names),
			  inputs(default_inputs)
			{}

			DefaultNode(
				decltype(implementation) implementation,
				decltype(input_type_infos) input_type_infos,
				decltype(input_names) input_names,
				decltype(output_type_infos) output_type_infos,
				decltype(output_names) output_names
			)
			: DefaultNode(
				implementation,
				input_type_infos,
				input_names,
				output_type_infos,
				output_names,
				decltype(inputs)(input_type_infos.size(), false)
			)
			{}

			virtual void update();

			virtual std::vector<types::Value>& get_inputs();

			virtual const std::vector<types::Value>& get_outputs();

			virtual const std::vector<types::TypeInfo>& get_input_type_infos();

			virtual const std::vector<std::string>& get_input_names();

			virtual const std::vector<types::TypeInfo>& get_output_type_infos();

			virtual const std::vector<std::string>& get_output_names();
		};
	}
}
#endif
<commit_msg>Fixed formatting error in node.hh<commit_after>#ifndef Nodes_Node_h
#define Nodes_Node_h
#include <functional>
#include <vector>
#include "../types.hh"

namespace doanimate
{
	namespace nodes
	{
		class Node
		{
			public:
			const bool has_ui_operations;

			Node(const bool has_ui_operations)
			: has_ui_operations(has_ui_operations)
			{}

			virtual void update() = 0;

			virtual std::vector<types::Value>& get_inputs() = 0;

			virtual const std::vector<types::Value>& get_outputs() = 0;

			virtual const std::vector<types::TypeInfo>& get_input_type_infos() = 0;

			virtual const std::vector<std::string>& get_input_names() = 0;

			virtual const std::vector<types::TypeInfo>& get_output_type_infos() = 0;

			virtual const std::vector<std::string>& get_output_names() = 0;

			virtual void run_ui_operations()
			{}
		};

		class DefaultNode : public Node
		{
			protected:
			using imp_t = std::function<
				std::vector<types::Value>(std::vector<types::Value>)
			>;

			imp_t implementation;

			const std::vector<types::TypeInfo> input_type_infos;

			const std::vector<std::string> input_names;

			const std::vector<types::TypeInfo> output_type_infos;

			const std::vector<std::string> output_names;

			std::vector<types::Value> inputs;

			std::vector<types::Value> outputs;

			public:
			DefaultNode(
				imp_t implementation,
				decltype(input_type_infos) input_type_infos,
				decltype(input_names) input_names,
				decltype(output_type_infos) output_type_infos,
				decltype(output_names) output_names,
				decltype(inputs) default_inputs
			)
			: Node(false),
			  implementation(implementation),
			  input_type_infos(input_type_infos),
			  input_names(input_names),
			  output_type_infos(output_type_infos),
			  output_names(output_names),
			  inputs(default_inputs)
			{}

			DefaultNode(
				decltype(implementation) implementation,
				decltype(input_type_infos) input_type_infos,
				decltype(input_names) input_names,
				decltype(output_type_infos) output_type_infos,
				decltype(output_names) output_names
			)
			: DefaultNode(
				implementation,
				input_type_infos,
				input_names,
				output_type_infos,
				output_names,
				decltype(inputs)(input_type_infos.size(), false)
			)
			{}

			virtual void update();

			virtual std::vector<types::Value>& get_inputs();

			virtual const std::vector<types::Value>& get_outputs();

			virtual const std::vector<types::TypeInfo>& get_input_type_infos();

			virtual const std::vector<std::string>& get_input_names();

			virtual const std::vector<types::TypeInfo>& get_output_type_infos();

			virtual const std::vector<std::string>& get_output_names();
		};
	}
}
#endif
<|endoftext|>


<commit_before>/*************************************************************************/
/*  os_linuxbsd.cpp                                                      */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "os_linuxbsd.h"

#include "core/os/dir_access.h"
#include "main/main.h"

#ifdef X11_ENABLED
#include "display_server_x11.h"
#endif

#ifdef HAVE_MNTENT
#include <mntent.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <dlfcn.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void OS_LinuxBSD::initialize() {
	crash_handler.initialize();

	OS_Unix::initialize_core();
}

void OS_LinuxBSD::initialize_joypads() {
#ifdef JOYDEV_ENABLED
	joypad = memnew(JoypadLinux(Input::get_singleton()));
#endif
}

String OS_LinuxBSD::get_unique_id() const {
	static String machine_id;
	if (machine_id.empty()) {
		if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
			while (machine_id.empty() && !f->eof_reached()) {
				machine_id = f->get_line().strip_edges();
			}
			f->close();
			memdelete(f);
		}
	}
	return machine_id;
}

void OS_LinuxBSD::finalize() {
	if (main_loop) {
		memdelete(main_loop);
	}
	main_loop = nullptr;

#ifdef ALSAMIDI_ENABLED
	driver_alsamidi.close();
#endif

#ifdef JOYDEV_ENABLED
	if (joypad) {
		memdelete(joypad);
	}
#endif
}

MainLoop *OS_LinuxBSD::get_main_loop() const {
	return main_loop;
}

void OS_LinuxBSD::delete_main_loop() {
	if (main_loop) {
		memdelete(main_loop);
	}
	main_loop = nullptr;
}

void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) {
	main_loop = p_main_loop;
}

String OS_LinuxBSD::get_name() const {
#ifdef __linux__
	return "Linux";
#elif defined(__FreeBSD__)
	return "FreeBSD";
#elif defined(__NetBSD__)
	return "NetBSD";
#else
	return "BSD";
#endif
}

Error OS_LinuxBSD::shell_open(String p_uri) {
	Error ok;
	List<String> args;
	args.push_back(p_uri);
	ok = execute("xdg-open", args, false);
	if (ok == OK) {
		return OK;
	}
	ok = execute("gnome-open", args, false);
	if (ok == OK) {
		return OK;
	}
	ok = execute("kde-open", args, false);
	return ok;
}

bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
	return p_feature == "pc";
}

String OS_LinuxBSD::get_config_path() const {
	if (has_environment("XDG_CONFIG_HOME")) {
		return get_environment("XDG_CONFIG_HOME");
	} else if (has_environment("HOME")) {
		return get_environment("HOME").plus_file(".config");
	} else {
		return ".";
	}
}

String OS_LinuxBSD::get_data_path() const {
	if (has_environment("XDG_DATA_HOME")) {
		return get_environment("XDG_DATA_HOME");
	} else if (has_environment("HOME")) {
		return get_environment("HOME").plus_file(".local/share");
	} else {
		return get_config_path();
	}
}

String OS_LinuxBSD::get_cache_path() const {
	if (has_environment("XDG_CACHE_HOME")) {
		return get_environment("XDG_CACHE_HOME");
	} else if (has_environment("HOME")) {
		return get_environment("HOME").plus_file(".cache");
	} else {
		return get_config_path();
	}
}

String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
	String xdgparam;

	switch (p_dir) {
		case SYSTEM_DIR_DESKTOP: {
			xdgparam = "DESKTOP";
		} break;
		case SYSTEM_DIR_DCIM: {
			xdgparam = "PICTURES";

		} break;
		case SYSTEM_DIR_DOCUMENTS: {
			xdgparam = "DOCUMENTS";

		} break;
		case SYSTEM_DIR_DOWNLOADS: {
			xdgparam = "DOWNLOAD";

		} break;
		case SYSTEM_DIR_MOVIES: {
			xdgparam = "VIDEOS";

		} break;
		case SYSTEM_DIR_MUSIC: {
			xdgparam = "MUSIC";

		} break;
		case SYSTEM_DIR_PICTURES: {
			xdgparam = "PICTURES";

		} break;
		case SYSTEM_DIR_RINGTONES: {
			xdgparam = "MUSIC";

		} break;
	}

	String pipe;
	List<String> arg;
	arg.push_back(xdgparam);
	Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, nullptr, &pipe);
	if (err != OK) {
		return ".";
	}
	return pipe.strip_edges();
}

void OS_LinuxBSD::run() {
	force_quit = false;

	if (!main_loop) {
		return;
	}

	main_loop->init();

	//uint64_t last_ticks=get_ticks_usec();

	//int frames=0;
	//uint64_t frame=0;

	while (!force_quit) {
		DisplayServer::get_singleton()->process_events(); // get rid of pending events
#ifdef JOYDEV_ENABLED
		joypad->process_joypads();
#endif
		if (Main::iteration()) {
			break;
		}
	};

	main_loop->finish();
}

void OS_LinuxBSD::disable_crash_handler() {
	crash_handler.disable();
}

bool OS_LinuxBSD::is_disable_crash_handler() const {
	return crash_handler.is_disabled();
}

static String get_mountpoint(const String &p_path) {
	struct stat s;
	if (stat(p_path.utf8().get_data(), &s)) {
		return "";
	}

#ifdef HAVE_MNTENT
	dev_t dev = s.st_dev;
	FILE *fd = setmntent("/proc/mounts", "r");
	if (!fd) {
		return "";
	}

	struct mntent mnt;
	char buf[1024];
	size_t buflen = 1024;
	while (getmntent_r(fd, &mnt, buf, buflen)) {
		if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) {
			endmntent(fd);
			return String(mnt.mnt_dir);
		}
	}

	endmntent(fd);
#endif
	return "";
}

Error OS_LinuxBSD::move_to_trash(const String &p_path) {
	String trash_can = "";
	String mnt = get_mountpoint(p_path);

	// If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
	if (mnt != "") {
		String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
		struct stat s;
		if (!stat(path.utf8().get_data(), &s)) {
			trash_can = path;
		}
	}

	// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
	if (trash_can == "") {
		char *dhome = getenv("XDG_DATA_HOME");
		if (dhome) {
			trash_can = String(dhome) + "/Trash/files";
		}
	}

	// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
	if (trash_can == "") {
		char *home = getenv("HOME");
		if (home) {
			trash_can = String(home) + "/.local/share/Trash/files";
		}
	}

	// Issue an error if none of the previous locations is appropriate for the trash can.
	if (trash_can == "") {
		ERR_PRINT("move_to_trash: Could not determine the trash can location");
		return FAILED;
	}

	// Create needed directories for decided trash can location.
	DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	Error err = dir_access->make_dir_recursive(trash_can);
	memdelete(dir_access);

	// Issue an error if trash can is not created proprely.
	if (err != OK) {
		ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
		return err;
	}

	// The trash can is successfully created, now move the given resource to it.
	// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
	List<String> mv_args;
	mv_args.push_back(p_path);
	mv_args.push_back(trash_can);
	int retval;
	err = execute("mv", mv_args, true, nullptr, nullptr, &retval);

	// Issue an error if "mv" failed to move the given resource to the trash can.
	if (err != OK || retval != 0) {
		ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
		return FAILED;
	}

	return OK;
}

OS_LinuxBSD::OS_LinuxBSD() {
	main_loop = nullptr;
	force_quit = false;

#ifdef PULSEAUDIO_ENABLED
	AudioDriverManager::add_driver(&driver_pulseaudio);
#endif

#ifdef ALSA_ENABLED
	AudioDriverManager::add_driver(&driver_alsa);
#endif

#ifdef X11_ENABLED
	DisplayServerX11::register_x11_driver();
#endif
}
<commit_msg>Changed shell_open behaviour<commit_after>/*************************************************************************/
/*  os_linuxbsd.cpp                                                      */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "os_linuxbsd.h"

#include "core/os/dir_access.h"
#include "main/main.h"

#ifdef X11_ENABLED
#include "display_server_x11.h"
#endif

#ifdef HAVE_MNTENT
#include <mntent.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <dlfcn.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void OS_LinuxBSD::initialize() {
	crash_handler.initialize();

	OS_Unix::initialize_core();
}

void OS_LinuxBSD::initialize_joypads() {
#ifdef JOYDEV_ENABLED
	joypad = memnew(JoypadLinux(Input::get_singleton()));
#endif
}

String OS_LinuxBSD::get_unique_id() const {
	static String machine_id;
	if (machine_id.empty()) {
		if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
			while (machine_id.empty() && !f->eof_reached()) {
				machine_id = f->get_line().strip_edges();
			}
			f->close();
			memdelete(f);
		}
	}
	return machine_id;
}

void OS_LinuxBSD::finalize() {
	if (main_loop) {
		memdelete(main_loop);
	}
	main_loop = nullptr;

#ifdef ALSAMIDI_ENABLED
	driver_alsamidi.close();
#endif

#ifdef JOYDEV_ENABLED
	if (joypad) {
		memdelete(joypad);
	}
#endif
}

MainLoop *OS_LinuxBSD::get_main_loop() const {
	return main_loop;
}

void OS_LinuxBSD::delete_main_loop() {
	if (main_loop) {
		memdelete(main_loop);
	}
	main_loop = nullptr;
}

void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) {
	main_loop = p_main_loop;
}

String OS_LinuxBSD::get_name() const {
#ifdef __linux__
	return "Linux";
#elif defined(__FreeBSD__)
	return "FreeBSD";
#elif defined(__NetBSD__)
	return "NetBSD";
#else
	return "BSD";
#endif
}

Error OS_LinuxBSD::shell_open(String p_uri) {
	Error ok;
	int err_code;
	List<String> args;
	args.push_back(p_uri);

	// Agnostic
	ok = execute("xdg-open", args, true, nullptr, nullptr, &err_code);
	if (ok == OK && !err_code) {
		return OK;
	} else if (err_code == 2) {
		return ERR_FILE_NOT_FOUND;
	}
	// GNOME
	args.push_front("open"); // The command is `gio open`, so we need to add it to args
	ok = execute("gio", args, true, nullptr, nullptr, &err_code);
	if (ok == OK && !err_code) {
		return OK;
	} else if (err_code == 2) {
		return ERR_FILE_NOT_FOUND;
	}
	args.pop_front();
	ok = execute("gvfs-open", args, true, nullptr, nullptr, &err_code);
	if (ok == OK && !err_code) {
		return OK;
	} else if (err_code == 2) {
		return ERR_FILE_NOT_FOUND;
	}
	// KDE
	ok = execute("kde-open5", args, true, nullptr, nullptr, &err_code);
	if (ok == OK && !err_code) {
		return OK;
	}
	ok = execute("kde-open", args, true, nullptr, nullptr, &err_code);
	return !err_code ? ok : FAILED;
}

bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
	return p_feature == "pc";
}

String OS_LinuxBSD::get_config_path() const {
	if (has_environment("XDG_CONFIG_HOME")) {
		return get_environment("XDG_CONFIG_HOME");
	} else if (has_environment("HOME")) {
		return get_environment("HOME").plus_file(".config");
	} else {
		return ".";
	}
}

String OS_LinuxBSD::get_data_path() const {
	if (has_environment("XDG_DATA_HOME")) {
		return get_environment("XDG_DATA_HOME");
	} else if (has_environment("HOME")) {
		return get_environment("HOME").plus_file(".local/share");
	} else {
		return get_config_path();
	}
}

String OS_LinuxBSD::get_cache_path() const {
	if (has_environment("XDG_CACHE_HOME")) {
		return get_environment("XDG_CACHE_HOME");
	} else if (has_environment("HOME")) {
		return get_environment("HOME").plus_file(".cache");
	} else {
		return get_config_path();
	}
}

String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const {
	String xdgparam;

	switch (p_dir) {
		case SYSTEM_DIR_DESKTOP: {
			xdgparam = "DESKTOP";
		} break;
		case SYSTEM_DIR_DCIM: {
			xdgparam = "PICTURES";

		} break;
		case SYSTEM_DIR_DOCUMENTS: {
			xdgparam = "DOCUMENTS";

		} break;
		case SYSTEM_DIR_DOWNLOADS: {
			xdgparam = "DOWNLOAD";

		} break;
		case SYSTEM_DIR_MOVIES: {
			xdgparam = "VIDEOS";

		} break;
		case SYSTEM_DIR_MUSIC: {
			xdgparam = "MUSIC";

		} break;
		case SYSTEM_DIR_PICTURES: {
			xdgparam = "PICTURES";

		} break;
		case SYSTEM_DIR_RINGTONES: {
			xdgparam = "MUSIC";

		} break;
	}

	String pipe;
	List<String> arg;
	arg.push_back(xdgparam);
	Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, nullptr, &pipe);
	if (err != OK) {
		return ".";
	}
	return pipe.strip_edges();
}

void OS_LinuxBSD::run() {
	force_quit = false;

	if (!main_loop) {
		return;
	}

	main_loop->init();

	//uint64_t last_ticks=get_ticks_usec();

	//int frames=0;
	//uint64_t frame=0;

	while (!force_quit) {
		DisplayServer::get_singleton()->process_events(); // get rid of pending events
#ifdef JOYDEV_ENABLED
		joypad->process_joypads();
#endif
		if (Main::iteration()) {
			break;
		}
	};

	main_loop->finish();
}

void OS_LinuxBSD::disable_crash_handler() {
	crash_handler.disable();
}

bool OS_LinuxBSD::is_disable_crash_handler() const {
	return crash_handler.is_disabled();
}

static String get_mountpoint(const String &p_path) {
	struct stat s;
	if (stat(p_path.utf8().get_data(), &s)) {
		return "";
	}

#ifdef HAVE_MNTENT
	dev_t dev = s.st_dev;
	FILE *fd = setmntent("/proc/mounts", "r");
	if (!fd) {
		return "";
	}

	struct mntent mnt;
	char buf[1024];
	size_t buflen = 1024;
	while (getmntent_r(fd, &mnt, buf, buflen)) {
		if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) {
			endmntent(fd);
			return String(mnt.mnt_dir);
		}
	}

	endmntent(fd);
#endif
	return "";
}

Error OS_LinuxBSD::move_to_trash(const String &p_path) {
	String trash_can = "";
	String mnt = get_mountpoint(p_path);

	// If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can.
	if (mnt != "") {
		String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
		struct stat s;
		if (!stat(path.utf8().get_data(), &s)) {
			trash_can = path;
		}
	}

	// Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can.
	if (trash_can == "") {
		char *dhome = getenv("XDG_DATA_HOME");
		if (dhome) {
			trash_can = String(dhome) + "/Trash/files";
		}
	}

	// Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can.
	if (trash_can == "") {
		char *home = getenv("HOME");
		if (home) {
			trash_can = String(home) + "/.local/share/Trash/files";
		}
	}

	// Issue an error if none of the previous locations is appropriate for the trash can.
	if (trash_can == "") {
		ERR_PRINT("move_to_trash: Could not determine the trash can location");
		return FAILED;
	}

	// Create needed directories for decided trash can location.
	DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
	Error err = dir_access->make_dir_recursive(trash_can);
	memdelete(dir_access);

	// Issue an error if trash can is not created proprely.
	if (err != OK) {
		ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\"");
		return err;
	}

	// The trash can is successfully created, now move the given resource to it.
	// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
	List<String> mv_args;
	mv_args.push_back(p_path);
	mv_args.push_back(trash_can);
	int retval;
	err = execute("mv", mv_args, true, nullptr, nullptr, &retval);

	// Issue an error if "mv" failed to move the given resource to the trash can.
	if (err != OK || retval != 0) {
		ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\"");
		return FAILED;
	}

	return OK;
}

OS_LinuxBSD::OS_LinuxBSD() {
	main_loop = nullptr;
	force_quit = false;

#ifdef PULSEAUDIO_ENABLED
	AudioDriverManager::add_driver(&driver_pulseaudio);
#endif

#ifdef ALSA_ENABLED
	AudioDriverManager::add_driver(&driver_alsa);
#endif

#ifdef X11_ENABLED
	DisplayServerX11::register_x11_driver();
#endif
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2006-2019, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "platform/mbed_power_mgmt.h"
#include "platform/CriticalSectionLock.h"
#include "platform/internal/SysTimer.h"
#include "platform/internal/mbed_os_timer.h"
#include "us_ticker_api.h"
#include "lp_ticker_api.h"
#include "mbed_critical.h"
#include "mbed_error.h"
#include <new>

/* This provides the marshalling point for a system global SysTimer, which
 * is used to provide:
 * - timed sleeps (for default idle hook in RTOS tickless mode, or non-RTOS sleeps)
 * - regular ticks for RTOS
 * - absolute system timing (directly for non-RTOS, or indirectly via RTOS tick count)
 */

namespace mbed {
namespace internal {

OsTimer *os_timer;

namespace {
uint64_t os_timer_data[(sizeof(OsTimer) + 7) / 8];
}

OsTimer *init_os_timer()
{
    // Do not use SingletonPtr since this relies on the RTOS.
    // Locking not required as it will be first called during
    // OS init, or else we're a non-RTOS single-threaded setup.
    if (!os_timer) {
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER
        os_timer = new (os_timer_data) OsTimer(get_lp_ticker_data());
#elif DEVICE_USTICKER
        os_timer = new (os_timer_data) OsTimer(get_us_ticker_data());
#else
        MBED_ERROR("OS timer not available");
#endif
    }

    return os_timer;
}

/* These traits classes are designed to permit chunks of code to be
 * omitted - in particular eliminating timers. However, we don't want
 * to cause template bloat, so don't have too many traits variants.
 */

/* Optionally timed operation, with optional predicate */
struct timed_predicate_op {
    timed_predicate_op(OsClock::time_point t) : wake_time(t), orig_predicate(NULL), orig_handle(NULL)
    {
        init_os_timer();
    }

    timed_predicate_op(OsClock::time_point t, bool (*wake_predicate)(void *), void *wake_predicate_handle) : wake_time(t), orig_predicate(wake_predicate), orig_handle(wake_predicate_handle)
    {
        init_os_timer();
    }

    ~timed_predicate_op()
    {
        // Make sure wake timer is cancelled. (It may or may not be, depending on
        // why we woke).
        os_timer->cancel_wake();
    }

    bool wake_condition() const
    {
        return (orig_predicate && orig_predicate(orig_handle)) || os_timer->wake_time_passed();
    }

    void sleep_prepare()
    {
        if (wake_time != wake_time.max()) {
            OsClock::set_wake_time(wake_time);
        }
    }

    bool sleep_prepared()
    {
        return wake_time == wake_time.max() || os_timer->wake_time_set();
    }

private:
    OsClock::time_point wake_time;
    bool (*orig_predicate)(void *);
    void *orig_handle;
};

/* Untimed operation with predicate */
struct untimed_op {
    untimed_op(bool (*wake_predicate)(void *), void *wake_predicate_handle) : orig_predicate(wake_predicate), orig_handle(wake_predicate_handle)
    {
    }

    bool wake_condition() const
    {
        return orig_predicate(orig_handle);
    }

    void sleep_prepare()
    {
    }

    bool sleep_prepared()
    {
        return true;
    }

private:
    bool (*orig_predicate)(void *);
    void *orig_handle;
};

/* We require that this is called from thread context, outside a critical section,
 * and the kernel already suspended if an RTOS, meaning we don't have to worry
 * about any potential threading issues.
 *
 * The wake predicate will be called from both outside and inside a critical
 * section, so appropriate atomic care must be taken.
 */
template <class OpT>
void do_sleep_operation(OpT &op)
{
    // We assume the ticker is not already in use - without RTOS, it
    // is never used, with RTOS, it will have been disabled with OS_Tick_Disable
    while (!op.wake_condition()) {
        // Set (or re-set) the wake time - outside a critical section, as
        // it could take long enough to cause UART data loss on some platforms.
        op.sleep_prepare();

        // If no target sleep function, nothing else to do - just keep
        // rechecking the wake condition.
#if DEVICE_SLEEP
        // Now we need to enter the critical section for the race-free sleep
        {
            CriticalSectionLock lock;

            // Recheck wake conditions before starting sleep, avoiding race
            if (op.wake_condition()) {
                break;
            }

            // It's possible that an intermediate wake interrupt occurred
            // between "set_wake_time" and the critical lock - only sleep
            // if we see that the timer is armed or we don't need it. Otherwise,
            // we go round to set the timer again.
            if (op.sleep_prepared()) {
                // Enter HAL sleep (normal or deep)
                sleep();
            }
        }

        // Ensure interrupts get a chance to fire, which allows new result from
        // wake_predicate() and wake_time_passed()
        __ISB();
#endif
    }
}

/* We require that this is called from thread context, outside a critical section,
 * and the kernel already suspended if an RTOS, meaning we don't have to worry
 * about any potential threading issues.
 *
 * The wake predicate will be called from both outside and inside a critical
 * section, so appropriate atomic care must be taken.
 */
OsClock::time_point do_timed_sleep_absolute(OsClock::time_point wake_time, bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    {
        timed_predicate_op op(wake_time, wake_predicate, wake_predicate_handle);
        do_sleep_operation(op);
    }

    return OsClock::now_with_init_done();
}

#if MBED_CONF_RTOS_PRESENT
/* The 32-bit limit is part of the API - we will always wake within 2^32 ticks */
/* This version is tuned for RTOS use, where the RTOS needs to know the time spent sleeping */
/* Note that unlike do_timed_sleep_relative_or_forever it does not do a tick update on entry; */
/* it assumes the caller has been using the ticker, and is passing a delay relative to the */
/* time point of the ticks it has acknowledged. */
OsClock::duration_u32 do_timed_sleep_relative_to_acknowledged_ticks(OsClock::duration_u32 wake_delay, bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    // When running with RTOS, the requested delay will be based on the kernel's tick count.
    // If it missed a tick as entering idle, we should reflect that by basing the start time
    // on its current idea of time - OsClock::acknowledged_ticks().
    // Example: OS acknowledged tick count = 100, our reported tick count = 101, requested delay = 50
    // We need to schedule wake for tick 150, report 50 ticks back to our caller, and
    // clear the unacknowledged tick count.
    OsClock::time_point sleep_start = OsClock::acknowledged_ticks();

    OsClock::time_point sleep_finish = do_timed_sleep_absolute(sleep_start + wake_delay, wake_predicate, wake_predicate_handle);

    return sleep_finish - sleep_start;
}

#else

void do_untimed_sleep(bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    untimed_op op(wake_predicate, wake_predicate_handle);

    do_sleep_operation(op);
}

/* max() delay is treated as "wait forever" */
/* This version is tuned for non-RTOS use, where we must update the tick count, */
/* don't need to return sleep time, and waiting forever is possible */
void do_timed_sleep_relative_or_forever(OsClock::duration_u32 wake_delay, bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    // Special-case 0 delay, to save multiple callers having to do it. Just call the predicate once.
    if (wake_delay == wake_delay.zero()) {
        if (wake_predicate) {
            wake_predicate(wake_predicate_handle);
        }
        return;
    }

    OsClock::time_point wake_time;
    if (wake_delay == OsClock::duration_u32::max()) {
        wake_time = OsClock::time_point::max();
    } else {
        wake_time = OsClock::now() + wake_delay;
    }
    /* Always use timed_predicate_op here to save pulling in two templates */
    timed_predicate_op op(wake_time, wake_predicate, wake_predicate_handle);
    do_sleep_operation(op);
}

#endif

} // namespace internal
} // namespace mbed
<commit_msg>Fix MBED_ERROR call in init_os_timer<commit_after>/*
 * Copyright (c) 2006-2019, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "platform/mbed_power_mgmt.h"
#include "platform/CriticalSectionLock.h"
#include "platform/internal/SysTimer.h"
#include "platform/internal/mbed_os_timer.h"
#include "us_ticker_api.h"
#include "lp_ticker_api.h"
#include "mbed_critical.h"
#include "mbed_error.h"
#include <new>

/* This provides the marshalling point for a system global SysTimer, which
 * is used to provide:
 * - timed sleeps (for default idle hook in RTOS tickless mode, or non-RTOS sleeps)
 * - regular ticks for RTOS
 * - absolute system timing (directly for non-RTOS, or indirectly via RTOS tick count)
 */

namespace mbed {
namespace internal {

OsTimer *os_timer;

namespace {
uint64_t os_timer_data[(sizeof(OsTimer) + 7) / 8];
}

OsTimer *init_os_timer()
{
    // Do not use SingletonPtr since this relies on the RTOS.
    // Locking not required as it will be first called during
    // OS init, or else we're a non-RTOS single-threaded setup.
    if (!os_timer) {
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER
        os_timer = new (os_timer_data) OsTimer(get_lp_ticker_data());
#elif DEVICE_USTICKER
        os_timer = new (os_timer_data) OsTimer(get_us_ticker_data());
#else
        MBED_ERROR(
            MBED_MAKE_ERROR(
                MBED_MODULE_PLATFORM,
                MBED_ERROR_CODE_CONFIG_UNSUPPORTED),
            "OS timer not available");
#endif
    }

    return os_timer;
}

/* These traits classes are designed to permit chunks of code to be
 * omitted - in particular eliminating timers. However, we don't want
 * to cause template bloat, so don't have too many traits variants.
 */

/* Optionally timed operation, with optional predicate */
struct timed_predicate_op {
    timed_predicate_op(OsClock::time_point t) : wake_time(t), orig_predicate(NULL), orig_handle(NULL)
    {
        init_os_timer();
    }

    timed_predicate_op(OsClock::time_point t, bool (*wake_predicate)(void *), void *wake_predicate_handle) : wake_time(t), orig_predicate(wake_predicate), orig_handle(wake_predicate_handle)
    {
        init_os_timer();
    }

    ~timed_predicate_op()
    {
        // Make sure wake timer is cancelled. (It may or may not be, depending on
        // why we woke).
        os_timer->cancel_wake();
    }

    bool wake_condition() const
    {
        return (orig_predicate && orig_predicate(orig_handle)) || os_timer->wake_time_passed();
    }

    void sleep_prepare()
    {
        if (wake_time != wake_time.max()) {
            OsClock::set_wake_time(wake_time);
        }
    }

    bool sleep_prepared()
    {
        return wake_time == wake_time.max() || os_timer->wake_time_set();
    }

private:
    OsClock::time_point wake_time;
    bool (*orig_predicate)(void *);
    void *orig_handle;
};

/* Untimed operation with predicate */
struct untimed_op {
    untimed_op(bool (*wake_predicate)(void *), void *wake_predicate_handle) : orig_predicate(wake_predicate), orig_handle(wake_predicate_handle)
    {
    }

    bool wake_condition() const
    {
        return orig_predicate(orig_handle);
    }

    void sleep_prepare()
    {
    }

    bool sleep_prepared()
    {
        return true;
    }

private:
    bool (*orig_predicate)(void *);
    void *orig_handle;
};

/* We require that this is called from thread context, outside a critical section,
 * and the kernel already suspended if an RTOS, meaning we don't have to worry
 * about any potential threading issues.
 *
 * The wake predicate will be called from both outside and inside a critical
 * section, so appropriate atomic care must be taken.
 */
template <class OpT>
void do_sleep_operation(OpT &op)
{
    // We assume the ticker is not already in use - without RTOS, it
    // is never used, with RTOS, it will have been disabled with OS_Tick_Disable
    while (!op.wake_condition()) {
        // Set (or re-set) the wake time - outside a critical section, as
        // it could take long enough to cause UART data loss on some platforms.
        op.sleep_prepare();

        // If no target sleep function, nothing else to do - just keep
        // rechecking the wake condition.
#if DEVICE_SLEEP
        // Now we need to enter the critical section for the race-free sleep
        {
            CriticalSectionLock lock;

            // Recheck wake conditions before starting sleep, avoiding race
            if (op.wake_condition()) {
                break;
            }

            // It's possible that an intermediate wake interrupt occurred
            // between "set_wake_time" and the critical lock - only sleep
            // if we see that the timer is armed or we don't need it. Otherwise,
            // we go round to set the timer again.
            if (op.sleep_prepared()) {
                // Enter HAL sleep (normal or deep)
                sleep();
            }
        }

        // Ensure interrupts get a chance to fire, which allows new result from
        // wake_predicate() and wake_time_passed()
        __ISB();
#endif
    }
}

/* We require that this is called from thread context, outside a critical section,
 * and the kernel already suspended if an RTOS, meaning we don't have to worry
 * about any potential threading issues.
 *
 * The wake predicate will be called from both outside and inside a critical
 * section, so appropriate atomic care must be taken.
 */
OsClock::time_point do_timed_sleep_absolute(OsClock::time_point wake_time, bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    {
        timed_predicate_op op(wake_time, wake_predicate, wake_predicate_handle);
        do_sleep_operation(op);
    }

    return OsClock::now_with_init_done();
}

#if MBED_CONF_RTOS_PRESENT
/* The 32-bit limit is part of the API - we will always wake within 2^32 ticks */
/* This version is tuned for RTOS use, where the RTOS needs to know the time spent sleeping */
/* Note that unlike do_timed_sleep_relative_or_forever it does not do a tick update on entry; */
/* it assumes the caller has been using the ticker, and is passing a delay relative to the */
/* time point of the ticks it has acknowledged. */
OsClock::duration_u32 do_timed_sleep_relative_to_acknowledged_ticks(OsClock::duration_u32 wake_delay, bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    // When running with RTOS, the requested delay will be based on the kernel's tick count.
    // If it missed a tick as entering idle, we should reflect that by basing the start time
    // on its current idea of time - OsClock::acknowledged_ticks().
    // Example: OS acknowledged tick count = 100, our reported tick count = 101, requested delay = 50
    // We need to schedule wake for tick 150, report 50 ticks back to our caller, and
    // clear the unacknowledged tick count.
    OsClock::time_point sleep_start = OsClock::acknowledged_ticks();

    OsClock::time_point sleep_finish = do_timed_sleep_absolute(sleep_start + wake_delay, wake_predicate, wake_predicate_handle);

    return sleep_finish - sleep_start;
}

#else

void do_untimed_sleep(bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    untimed_op op(wake_predicate, wake_predicate_handle);

    do_sleep_operation(op);
}

/* max() delay is treated as "wait forever" */
/* This version is tuned for non-RTOS use, where we must update the tick count, */
/* don't need to return sleep time, and waiting forever is possible */
void do_timed_sleep_relative_or_forever(OsClock::duration_u32 wake_delay, bool (*wake_predicate)(void *), void *wake_predicate_handle)
{
    // Special-case 0 delay, to save multiple callers having to do it. Just call the predicate once.
    if (wake_delay == wake_delay.zero()) {
        if (wake_predicate) {
            wake_predicate(wake_predicate_handle);
        }
        return;
    }

    OsClock::time_point wake_time;
    if (wake_delay == OsClock::duration_u32::max()) {
        wake_time = OsClock::time_point::max();
    } else {
        wake_time = OsClock::now() + wake_delay;
    }
    /* Always use timed_predicate_op here to save pulling in two templates */
    timed_predicate_op op(wake_time, wake_predicate, wake_predicate_handle);
    do_sleep_operation(op);
}

#endif

} // namespace internal
} // namespace mbed
<|endoftext|>