mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2026-01-10 23:56:54 +00:00
初始化
This commit is contained in:
59
cocos2d-x/tools/simulator/libsimulator/lib/AppEvent.cpp
Executable file
59
cocos2d-x/tools/simulator/libsimulator/lib/AppEvent.cpp
Executable file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// AppEvent.cpp
|
||||
// Simulator
|
||||
//
|
||||
//
|
||||
|
||||
#include "AppEvent.h"
|
||||
|
||||
AppEvent::AppEvent(const std::string& eventName, int type)
|
||||
: CustomEvent()
|
||||
, _eventName(eventName)
|
||||
{
|
||||
name = eventName;
|
||||
setEventType(type);
|
||||
}
|
||||
|
||||
void AppEvent::setEventType(int type)
|
||||
{
|
||||
_eventType = type;
|
||||
}
|
||||
int AppEvent::getEventType()
|
||||
{
|
||||
return _eventType;
|
||||
}
|
||||
|
||||
void AppEvent::setDataString(std::string data)
|
||||
{
|
||||
_dataString = data;
|
||||
}
|
||||
|
||||
std::string AppEvent::getDataString()
|
||||
{
|
||||
return _dataString;
|
||||
}
|
||||
74
cocos2d-x/tools/simulator/libsimulator/lib/AppEvent.h
Executable file
74
cocos2d-x/tools/simulator/libsimulator/lib/AppEvent.h
Executable file
@@ -0,0 +1,74 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// AppEvent.h
|
||||
// Simulator
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __Simulator__AppEvent__
|
||||
#define __Simulator__AppEvent__
|
||||
|
||||
#include <string>
|
||||
#include "cocos2d.h"
|
||||
|
||||
// encode / decode json
|
||||
#include "json/document.h"
|
||||
#include "json/stringbuffer.h"
|
||||
#include "json/writer.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
#include "cocos/scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "cocos/scripting/js-bindings/event/CustomEventTypes.h"
|
||||
|
||||
enum
|
||||
{
|
||||
APP_EVENT_MENU = 1,
|
||||
APP_EVENT_DROP = 2
|
||||
};
|
||||
|
||||
#define kAppEventName "APP.EVENT"
|
||||
|
||||
class CC_LIBSIM_DLL AppEvent : public cocos2d::CustomEvent
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
AppEvent(const std::string& eventName, int type);
|
||||
|
||||
/** Gets event name */
|
||||
inline const std::string& getEventName() const { return _eventName; };
|
||||
|
||||
void setEventType(int type);
|
||||
int getEventType();
|
||||
void setDataString(std::string data);
|
||||
std::string getDataString();
|
||||
protected:
|
||||
std::string _eventName;
|
||||
std::string _dataString;
|
||||
int _eventType;
|
||||
};
|
||||
|
||||
#endif /* defined(__Simulator__AppEvent__) */
|
||||
98
cocos2d-x/tools/simulator/libsimulator/lib/AppLang.cpp
Executable file
98
cocos2d-x/tools/simulator/libsimulator/lib/AppLang.cpp
Executable file
@@ -0,0 +1,98 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// AppLang.cpp
|
||||
// Simulator
|
||||
//
|
||||
|
||||
#include "AppLang.h"
|
||||
|
||||
AppLang::AppLang()
|
||||
: _hasInit(false)
|
||||
{
|
||||
_localizationFileName = "lang";
|
||||
}
|
||||
|
||||
void AppLang::readLocalizationFile()
|
||||
{
|
||||
if (!_hasInit)
|
||||
{
|
||||
_hasInit = true;
|
||||
|
||||
auto fileUtils = cocos2d::FileUtils::getInstance();
|
||||
|
||||
if (!fileUtils->isFileExist(_localizationFileName))
|
||||
{
|
||||
cocos2d::log("[WARNING]:not find %s", _localizationFileName.c_str());
|
||||
return;
|
||||
}
|
||||
auto fullFilePath = fileUtils->fullPathForFilename(_localizationFileName);
|
||||
std::string fileContent = cocos2d::FileUtils::getInstance()->getStringFromFile(fullFilePath);
|
||||
if(fileContent.empty())
|
||||
return;
|
||||
|
||||
if (_docRootjson.Parse<0>(fileContent.c_str()).HasParseError())
|
||||
{
|
||||
cocos2d::log("[WARNING]:read json file %s failed because of %d", _localizationFileName.c_str(), _docRootjson.GetParseError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppLang* AppLang::getInstance()
|
||||
{
|
||||
static AppLang *lang = nullptr;
|
||||
if (!lang)
|
||||
{
|
||||
lang = new AppLang;
|
||||
lang->readLocalizationFile();
|
||||
}
|
||||
return lang;
|
||||
}
|
||||
|
||||
std::string AppLang::getString(const std::string &lang, const std::string &key)
|
||||
{
|
||||
std::string tmpKey = key;
|
||||
const char *ckey = tmpKey.c_str();
|
||||
|
||||
std::string tmpLang = lang;
|
||||
const char *langKey = tmpLang.c_str();
|
||||
|
||||
if (!_docRootjson.IsObject())
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
if (_docRootjson.HasMember(langKey))
|
||||
{
|
||||
const rapidjson::Value& v = _docRootjson[langKey];
|
||||
if (v.HasMember(ckey))
|
||||
{
|
||||
return v[ckey].GetString();
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
59
cocos2d-x/tools/simulator/libsimulator/lib/AppLang.h
Executable file
59
cocos2d-x/tools/simulator/libsimulator/lib/AppLang.h
Executable file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// AppLang.h
|
||||
// Simulator
|
||||
//
|
||||
|
||||
#ifndef __Simulator__AppLang__
|
||||
#define __Simulator__AppLang__
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include <map>
|
||||
|
||||
#include "json/document.h"
|
||||
#include "DeviceEx.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
class CC_LIBSIM_DLL AppLang
|
||||
{
|
||||
public:
|
||||
static AppLang* getInstance();
|
||||
|
||||
std::string getString(const std::string &lang, const std::string& key);
|
||||
|
||||
protected:
|
||||
AppLang();
|
||||
void readLocalizationFile();
|
||||
|
||||
bool _hasInit;
|
||||
std::string _localizationFileName;
|
||||
rapidjson::Document _docRootjson;
|
||||
};
|
||||
|
||||
#define tr(key) AppLang::getInstance()->getString(player::DeviceEx::getInstance()->getCurrentUILangName(), key)
|
||||
|
||||
#endif /* defined(__Simulator__AppLang__) */
|
||||
52
cocos2d-x/tools/simulator/libsimulator/lib/DeviceEx.h
Executable file
52
cocos2d-x/tools/simulator/libsimulator/lib/DeviceEx.h
Executable file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "PlayerMacros.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class CC_LIBSIM_DLL DeviceEx
|
||||
{
|
||||
public:
|
||||
static DeviceEx *getInstance();
|
||||
|
||||
std::string getCurrentUILangName();
|
||||
std::string getUserGUID();
|
||||
|
||||
private:
|
||||
DeviceEx();
|
||||
void init();
|
||||
void makeUILangName();
|
||||
std::string makeUserGUID();
|
||||
|
||||
std::string _uiLangName;
|
||||
std::string _userGUID;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
62
cocos2d-x/tools/simulator/libsimulator/lib/PlayerEditBoxServiceProtocol.h
Executable file
62
cocos2d-x/tools/simulator/libsimulator/lib/PlayerEditBoxServiceProtocol.h
Executable file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_EDITBOX_SERVICE_PROTOCOL_H_
|
||||
#define __PLAYER_EDITBOX_SERVICE_PROTOCOL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerEditBoxServiceProtocol : public PlayerServiceProtocol
|
||||
{
|
||||
public:
|
||||
static const int FORMAT_NONE = 0;
|
||||
static const int FORMAT_NUMBER = 1;
|
||||
|
||||
virtual void showSingleLineEditBox(const cocos2d::Rect &rect) = 0;
|
||||
virtual void showMultiLineEditBox(const cocos2d::Rect &rect) = 0;
|
||||
virtual void hide() = 0;
|
||||
|
||||
virtual void setText(const std::string &text) = 0;
|
||||
virtual void setFont(const std::string &name, int size) = 0;
|
||||
virtual void setFontColor(const cocos2d::Color3B &color) = 0;
|
||||
virtual void setFormator(int formator) = 0;
|
||||
|
||||
void registerHandler(int handler) { _handler = handler; }
|
||||
int getHandler() { return _handler; }
|
||||
|
||||
protected:
|
||||
int _handler;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_EDITBOX_SERVICE_PROTOCOL_H_
|
||||
58
cocos2d-x/tools/simulator/libsimulator/lib/PlayerFileDialogServiceProtocol.h
Executable file
58
cocos2d-x/tools/simulator/libsimulator/lib/PlayerFileDialogServiceProtocol.h
Executable file
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_FILE_DIALOG_SERVICE_PROTOCOL_H_
|
||||
#define __PLAYER_FILE_DIALOG_SERVICE_PROTOCOL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerFileDialogServiceProtocol : public PlayerServiceProtocol
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* extensions = "Lua Script File|*.lua;JSON File|*.json";
|
||||
*/
|
||||
virtual std::string openFile(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const = 0;
|
||||
virtual std::vector<std::string> openMultiple(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const = 0;
|
||||
virtual std::string saveFile(const std::string &title,
|
||||
const std::string &path) const = 0;
|
||||
virtual std::string openDirectory(const std::string &title,
|
||||
const std::string &directory) const = 0;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_FILE_DIALOG_SERVICE_PROTOCOL_H_
|
||||
34
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMacros.h
Executable file
34
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMacros.h
Executable file
@@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MACROS_H_
|
||||
#define __PLAYER_MACROS_H_
|
||||
|
||||
#define PLAYER_NS_BEGIN namespace player {
|
||||
#define PLAYER_NS_END }
|
||||
#define USING_PLAYER_NS using namespace player;
|
||||
|
||||
#endif // __PLAYER_MACROS_H_
|
||||
78
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMenuServiceProtocol.cpp
Executable file
78
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMenuServiceProtocol.cpp
Executable file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerMenuServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerMenuItem::PlayerMenuItem()
|
||||
: _order(0)
|
||||
, _isGroup(false)
|
||||
, _isEnabled(true)
|
||||
, _isChecked(false)
|
||||
{
|
||||
}
|
||||
|
||||
PlayerMenuItem::~PlayerMenuItem()
|
||||
{
|
||||
}
|
||||
|
||||
std::string PlayerMenuItem::getMenuId() const
|
||||
{
|
||||
return _menuId;
|
||||
}
|
||||
|
||||
std::string PlayerMenuItem::getTitle() const
|
||||
{
|
||||
return _title;
|
||||
}
|
||||
|
||||
int PlayerMenuItem::getOrder() const
|
||||
{
|
||||
return _order;
|
||||
}
|
||||
|
||||
bool PlayerMenuItem::isGroup() const
|
||||
{
|
||||
return _isGroup;
|
||||
}
|
||||
|
||||
bool PlayerMenuItem::isEnabled() const
|
||||
{
|
||||
return _isEnabled;
|
||||
}
|
||||
|
||||
bool PlayerMenuItem::isChecked() const
|
||||
{
|
||||
return _isChecked;
|
||||
}
|
||||
|
||||
std::string PlayerMenuItem::getShortcut() const
|
||||
{
|
||||
return _shortcut;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
92
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMenuServiceProtocol.h
Executable file
92
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMenuServiceProtocol.h
Executable file
@@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MENU_SERVICE_PROTOCOL_H
|
||||
#define __PLAYER_MENU_SERVICE_PROTOCOL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerServiceProtocol.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
#define kPlayerSuperModifyKey "super"
|
||||
#define kPlayerShiftModifyKey "shift"
|
||||
#define kPlayerCtrlModifyKey "ctrl"
|
||||
#define kPlayerAltModifyKey "alt"
|
||||
|
||||
class CC_LIBSIM_DLL PlayerMenuItem : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
virtual ~PlayerMenuItem();
|
||||
|
||||
std::string getMenuId() const;
|
||||
std::string getTitle() const;
|
||||
int getOrder() const;
|
||||
bool isGroup() const;
|
||||
bool isEnabled() const;
|
||||
bool isChecked() const;
|
||||
std::string getShortcut() const;
|
||||
|
||||
virtual void setTitle(const std::string &title) = 0;
|
||||
virtual void setEnabled(bool enabled) = 0;
|
||||
virtual void setChecked(bool checked) = 0;
|
||||
virtual void setShortcut(const std::string &shortcut) = 0;
|
||||
|
||||
protected:
|
||||
PlayerMenuItem();
|
||||
|
||||
std::string _menuId;
|
||||
std::string _title;
|
||||
int _order;
|
||||
bool _isGroup;
|
||||
bool _isEnabled;
|
||||
bool _isChecked; // ignored when isGroup = true
|
||||
std::string _shortcut; // ignored when isGroup = true
|
||||
};
|
||||
|
||||
class PlayerMenuServiceProtocol : public PlayerServiceProtocol
|
||||
{
|
||||
public:
|
||||
static const int MAX_ORDER = 9999;
|
||||
|
||||
virtual PlayerMenuItem *addItem(const std::string &menuId,
|
||||
const std::string &title,
|
||||
const std::string &parentId,
|
||||
int order = MAX_ORDER) = 0;
|
||||
virtual PlayerMenuItem *addItem(const std::string &menuId,
|
||||
const std::string &title) = 0;
|
||||
virtual PlayerMenuItem *getItem(const std::string &menuId) = 0;
|
||||
virtual bool removeItem(const std::string &menuId) = 0;
|
||||
virtual void setMenuBarEnabled(bool enabled) = 0;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MENU_SERVICE_PROTOCOL_H
|
||||
60
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMessageBoxServiceProtocol.h
Executable file
60
cocos2d-x/tools/simulator/libsimulator/lib/PlayerMessageBoxServiceProtocol.h
Executable file
@@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MESSAGEBOX_SERVICE_PROTOCOL_H
|
||||
#define __PLAYER_MESSAGEBOX_SERVICE_PROTOCOL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerMessageBoxServiceProtocol : public PlayerServiceProtocol
|
||||
{
|
||||
public:
|
||||
static const int BUTTONS_OK = 0;
|
||||
static const int BUTTONS_OK_CANCEL = 1;
|
||||
static const int BUTTONS_YES_NO = 2;
|
||||
static const int BUTTONS_YES_NO_CANCEL = 3;
|
||||
|
||||
static const int BUTTON_OK = 0;
|
||||
static const int BUTTON_CANCEL = 1;
|
||||
static const int BUTTON_YES = 2;
|
||||
static const int BUTTON_NO = 3;
|
||||
|
||||
// Show a message box, return index of user clicked button
|
||||
//
|
||||
// @return int first button index is 0
|
||||
virtual int showMessageBox(const std::string &title,
|
||||
const std::string &message,
|
||||
int buttonsType = BUTTONS_OK) = 0;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MESSAGEBOX_SERVICE_PROTOCOL_H
|
||||
65
cocos2d-x/tools/simulator/libsimulator/lib/PlayerProtocol.cpp
Executable file
65
cocos2d-x/tools/simulator/libsimulator/lib/PlayerProtocol.cpp
Executable file
@@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerProtocol.h"
|
||||
#include "base/ccMacros.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerProtocol *PlayerProtocol::_instance = nullptr;
|
||||
|
||||
PlayerProtocol::PlayerProtocol()
|
||||
{
|
||||
CCASSERT(_instance == nullptr, "CAN NOT CREATE MORE PLAYER INSTANCE");
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
PlayerProtocol::~PlayerProtocol()
|
||||
{
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
PlayerProtocol *PlayerProtocol::getInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void PlayerProtocol::purgeInstance()
|
||||
{
|
||||
if (_instance) delete _instance;
|
||||
}
|
||||
|
||||
void PlayerProtocol::setPlayerSettings(const PlayerSettings &settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
PlayerSettings PlayerProtocol::getPlayerSettings() const
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
72
cocos2d-x/tools/simulator/libsimulator/lib/PlayerProtocol.h
Executable file
72
cocos2d-x/tools/simulator/libsimulator/lib/PlayerProtocol.h
Executable file
@@ -0,0 +1,72 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_PROTOCOL_H_
|
||||
#define __PLAYER_PROTOCOL_H_
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerSettings.h"
|
||||
|
||||
#include "PlayerFileDialogServiceProtocol.h"
|
||||
#include "PlayerMessageBoxServiceProtocol.h"
|
||||
#include "PlayerMenuServiceProtocol.h"
|
||||
#include "PlayerEditBoxServiceProtocol.h"
|
||||
#include "PlayerTaskServiceProtocol.h"
|
||||
|
||||
#include "ProjectConfig/ProjectConfig.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class CC_LIBSIM_DLL PlayerProtocol
|
||||
{
|
||||
public:
|
||||
virtual ~PlayerProtocol();
|
||||
|
||||
static PlayerProtocol *getInstance();
|
||||
static void purgeInstance();
|
||||
|
||||
void setPlayerSettings(const PlayerSettings &settings);
|
||||
PlayerSettings getPlayerSettings() const;
|
||||
|
||||
virtual PlayerFileDialogServiceProtocol *getFileDialogService() = 0; // implemented in platform related source files
|
||||
virtual PlayerMessageBoxServiceProtocol *getMessageBoxService() = 0;
|
||||
virtual PlayerMenuServiceProtocol *getMenuService() = 0;
|
||||
// virtual PlayerEditBoxServiceProtocol *getEditBoxService() = 0;
|
||||
virtual PlayerTaskServiceProtocol *getTaskService() = 0;
|
||||
|
||||
protected:
|
||||
PlayerProtocol(); // avoid create instance from outside
|
||||
|
||||
PlayerSettings _settings;
|
||||
|
||||
private:
|
||||
static PlayerProtocol *_instance;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_PROTOCOL_H_
|
||||
31
cocos2d-x/tools/simulator/libsimulator/lib/PlayerServiceProtocol.cpp
Executable file
31
cocos2d-x/tools/simulator/libsimulator/lib/PlayerServiceProtocol.cpp
Executable file
@@ -0,0 +1,31 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PLAYER_NS_END
|
||||
42
cocos2d-x/tools/simulator/libsimulator/lib/PlayerServiceProtocol.h
Executable file
42
cocos2d-x/tools/simulator/libsimulator/lib/PlayerServiceProtocol.h
Executable file
@@ -0,0 +1,42 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_SERVICE_PROTOCOL_H_
|
||||
#define __PLAYER_SERVICE_PROTOCOL_H_
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerServiceProtocol
|
||||
{
|
||||
public:
|
||||
virtual ~PlayerServiceProtocol() {};
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_SERVICE_PROTOCOL_H_
|
||||
27
cocos2d-x/tools/simulator/libsimulator/lib/PlayerSettings.cpp
Executable file
27
cocos2d-x/tools/simulator/libsimulator/lib/PlayerSettings.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerSettings.h"
|
||||
50
cocos2d-x/tools/simulator/libsimulator/lib/PlayerSettings.h
Executable file
50
cocos2d-x/tools/simulator/libsimulator/lib/PlayerSettings.h
Executable file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_SETTINGS_H_
|
||||
#define __PLAYER_SETTINGS_H_
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerSettings
|
||||
{
|
||||
public:
|
||||
PlayerSettings()
|
||||
: openLastProject(false)
|
||||
, offsetX(0)
|
||||
, offsetY(0)
|
||||
{}
|
||||
|
||||
bool openLastProject;
|
||||
int offsetX;
|
||||
int offsetY;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_SETTINGS_H_
|
||||
93
cocos2d-x/tools/simulator/libsimulator/lib/PlayerTaskServiceProtocol.cpp
Executable file
93
cocos2d-x/tools/simulator/libsimulator/lib/PlayerTaskServiceProtocol.cpp
Executable file
@@ -0,0 +1,93 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerTaskServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
std::string PlayerTask::getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
std::string PlayerTask::getExecutePath() const
|
||||
{
|
||||
return _executePath;
|
||||
}
|
||||
|
||||
std::string PlayerTask::getCommandLineArguments() const
|
||||
{
|
||||
return _commandLineArguments;
|
||||
}
|
||||
|
||||
std::string PlayerTask::getOutput() const
|
||||
{
|
||||
return _output;
|
||||
}
|
||||
|
||||
int PlayerTask::getState() const
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
|
||||
bool PlayerTask::isIdle() const
|
||||
{
|
||||
return _state == STATE_IDLE;
|
||||
}
|
||||
|
||||
bool PlayerTask::isRunning() const
|
||||
{
|
||||
return _state == STATE_RUNNING;
|
||||
}
|
||||
|
||||
bool PlayerTask::isCompleted() const
|
||||
{
|
||||
return _state == STATE_COMPLETED;
|
||||
}
|
||||
|
||||
float PlayerTask::getLifetime() const
|
||||
{
|
||||
return _lifetime;
|
||||
}
|
||||
|
||||
int PlayerTask::getResultCode() const
|
||||
{
|
||||
return _resultCode;
|
||||
}
|
||||
|
||||
PlayerTask::PlayerTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments)
|
||||
: _name(name)
|
||||
, _executePath(executePath)
|
||||
, _commandLineArguments(commandLineArguments)
|
||||
, _state(STATE_IDLE)
|
||||
, _lifetime(0)
|
||||
, _resultCode(0)
|
||||
{
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
88
cocos2d-x/tools/simulator/libsimulator/lib/PlayerTaskServiceProtocol.h
Executable file
88
cocos2d-x/tools/simulator/libsimulator/lib/PlayerTaskServiceProtocol.h
Executable file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_TASK_SERVICE_PROTOCOL_H
|
||||
#define __PLAYER_TASK_SERVICE_PROTOCOL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerTask : public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
static const int STATE_IDLE = 0;
|
||||
static const int STATE_RUNNING = 1;
|
||||
static const int STATE_COMPLETED = 2;
|
||||
|
||||
virtual ~PlayerTask() {};
|
||||
|
||||
std::string getName() const;
|
||||
std::string getExecutePath() const;
|
||||
std::string getCommandLineArguments() const;
|
||||
std::string getOutput() const;
|
||||
int getState() const;
|
||||
bool isIdle() const;
|
||||
bool isRunning() const;
|
||||
bool isCompleted() const;
|
||||
float getLifetime() const;
|
||||
int getResultCode() const;
|
||||
|
||||
virtual bool run() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void runInTerminal() = 0;
|
||||
|
||||
protected:
|
||||
PlayerTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
|
||||
std::string _name;
|
||||
std::string _executePath;
|
||||
std::string _commandLineArguments;
|
||||
std::string _output;
|
||||
float _lifetime;
|
||||
int _state;
|
||||
int _resultCode;
|
||||
};
|
||||
|
||||
class PlayerTaskServiceProtocol : public PlayerServiceProtocol
|
||||
{
|
||||
public:
|
||||
virtual PlayerTask *createTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments) = 0;
|
||||
virtual PlayerTask *getTask(const std::string &name) = 0;
|
||||
virtual void removeTask(const std::string &name) = 0;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_TASK_SERVICE_PROTOCOL_H
|
||||
27
cocos2d-x/tools/simulator/libsimulator/lib/PlayerUtils.cpp
Executable file
27
cocos2d-x/tools/simulator/libsimulator/lib/PlayerUtils.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerUtils.h"
|
||||
61
cocos2d-x/tools/simulator/libsimulator/lib/PlayerUtils.h
Executable file
61
cocos2d-x/tools/simulator/libsimulator/lib/PlayerUtils.h
Executable file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_UTILS_H_
|
||||
#define __PLAYER_UTILS_H_
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
template<class T>
|
||||
vector<T> splitString(T str, T pattern)
|
||||
{
|
||||
vector<T> result;
|
||||
str += pattern;
|
||||
size_t size = str.size();
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
size_t pos = str.find(pattern, i);
|
||||
if (pos < size)
|
||||
{
|
||||
T s = str.substr(i, pos - i);
|
||||
result.push_back(s);
|
||||
i = pos + pattern.size() - 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_UTILS_H_
|
||||
816
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/ProjectConfig.cpp
Executable file
816
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/ProjectConfig.cpp
Executable file
@@ -0,0 +1,816 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 <sstream>
|
||||
|
||||
#include "ProjectConfig/ProjectConfig.h"
|
||||
#include "ProjectConfig/SimulatorConfig.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#define DIRECTORY_SEPARATOR "\\"
|
||||
#define DIRECTORY_SEPARATOR_CHAR '\\'
|
||||
#else
|
||||
#define DIRECTORY_SEPARATOR "/"
|
||||
#define DIRECTORY_SEPARATOR_CHAR '/'
|
||||
#endif
|
||||
|
||||
static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
elems.push_back(item);
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
|
||||
static std::vector<std::string> split(const std::string &s, char delim) {
|
||||
std::vector<std::string> elems;
|
||||
split(s, delim, elems);
|
||||
return elems;
|
||||
}
|
||||
|
||||
ProjectConfig::ProjectConfig()
|
||||
: _scriptFile("")
|
||||
, _writablePath("")
|
||||
, _packagePath("")
|
||||
, _frameSize(960, 640)
|
||||
, _frameScale(1.0f)
|
||||
, _showConsole(false)
|
||||
, _loadPrecompiledFramework(false)
|
||||
, _writeDebugLogToFile(false)
|
||||
, _windowOffset(0, 0)
|
||||
, _debuggerType(kCCRuntimeDebuggerNone)
|
||||
, _isAppMenu(true)
|
||||
, _isResizeWindow(false)
|
||||
, _isRetinaDisplay(false)
|
||||
, _debugLogFile("debug.log")
|
||||
, _consolePort(kProjectConfigConsolePort)
|
||||
, _fileUploadPort(kProjectConfigUploadPort)
|
||||
, _bindAddress("")
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
|
||||
string ProjectConfig::getProjectDir() const
|
||||
{
|
||||
return _projectDir;
|
||||
}
|
||||
|
||||
void ProjectConfig::setProjectDir(const string &projectDir)
|
||||
{
|
||||
_projectDir = projectDir;
|
||||
normalize();
|
||||
}
|
||||
|
||||
string ProjectConfig::getScriptFile() const
|
||||
{
|
||||
return _scriptFile;
|
||||
}
|
||||
|
||||
string ProjectConfig::getScriptFileRealPath() const
|
||||
{
|
||||
return replaceProjectDirToFullPath(_scriptFile);
|
||||
}
|
||||
|
||||
void ProjectConfig::setScriptFile(const string &scriptFile)
|
||||
{
|
||||
_scriptFile = scriptFile;
|
||||
normalize();
|
||||
}
|
||||
|
||||
string ProjectConfig::getWritablePath() const
|
||||
{
|
||||
return _writablePath;
|
||||
}
|
||||
|
||||
string ProjectConfig::getWritableRealPath() const
|
||||
{
|
||||
return replaceProjectDirToFullPath(_writablePath);
|
||||
}
|
||||
|
||||
void ProjectConfig::setWritablePath(const string &writablePath)
|
||||
{
|
||||
_writablePath = writablePath;
|
||||
normalize();
|
||||
}
|
||||
|
||||
string ProjectConfig::getPackagePath() const
|
||||
{
|
||||
return _packagePath;
|
||||
}
|
||||
|
||||
string ProjectConfig::getNormalizedPackagePath() const
|
||||
{
|
||||
// replace $(PROJDIR)
|
||||
auto path = _packagePath;
|
||||
auto pos = string::npos;
|
||||
while ((pos = path.find("$(PROJDIR)")) != string::npos)
|
||||
{
|
||||
path = path.substr(0, pos) + _projectDir + path.substr(pos + 10);
|
||||
}
|
||||
auto len = path.length();
|
||||
if (len && path[len - 1] != ';')
|
||||
{
|
||||
path.append(";");
|
||||
}
|
||||
path.append(";");
|
||||
SimulatorConfig::makeNormalizePath(&path, "/");
|
||||
return path;
|
||||
}
|
||||
|
||||
void ProjectConfig::setPackagePath(const string &packagePath)
|
||||
{
|
||||
_packagePath = packagePath;
|
||||
}
|
||||
|
||||
void ProjectConfig::addPackagePath(const string &packagePath)
|
||||
{
|
||||
if (packagePath.length())
|
||||
{
|
||||
if (_packagePath.length())
|
||||
{
|
||||
_packagePath.append(";");
|
||||
}
|
||||
_packagePath.append(packagePath);
|
||||
normalize();
|
||||
}
|
||||
}
|
||||
|
||||
vector<string> ProjectConfig::getPackagePathArray() const
|
||||
{
|
||||
vector<string> arr;
|
||||
|
||||
size_t pos = string::npos;
|
||||
size_t prev = 0;
|
||||
while ((pos = _packagePath.find_first_of(";", pos + 1)) != string::npos)
|
||||
{
|
||||
auto path = _packagePath.substr(prev, pos - prev);
|
||||
if (path.length() > 0) arr.push_back(path);
|
||||
prev = pos + 1;
|
||||
}
|
||||
auto path = _packagePath.substr(prev);
|
||||
if (path.length() > 0) arr.push_back(path);
|
||||
return arr;
|
||||
}
|
||||
|
||||
cocos2d::Size ProjectConfig::getFrameSize() const
|
||||
{
|
||||
return _frameSize;
|
||||
}
|
||||
|
||||
void ProjectConfig::setFrameSize(const cocos2d::Size &frameSize)
|
||||
{
|
||||
if (frameSize.width > 0 && frameSize.height > 0)
|
||||
{
|
||||
_frameSize = frameSize;
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectConfig::isLandscapeFrame() const
|
||||
{
|
||||
return _frameSize.width > _frameSize.height;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isPortraitFrame() const
|
||||
{
|
||||
return _frameSize.width < _frameSize.height;
|
||||
}
|
||||
|
||||
void ProjectConfig::changeFrameOrientation()
|
||||
{
|
||||
float w = _frameSize.width;
|
||||
_frameSize.width = _frameSize.height;
|
||||
_frameSize.height = w;
|
||||
}
|
||||
|
||||
void ProjectConfig::changeFrameOrientationToPortait()
|
||||
{
|
||||
if (isLandscapeFrame()) changeFrameOrientation();
|
||||
}
|
||||
|
||||
void ProjectConfig::changeFrameOrientationToLandscape()
|
||||
{
|
||||
if (!isLandscapeFrame()) changeFrameOrientation();
|
||||
}
|
||||
|
||||
float ProjectConfig::getFrameScale() const
|
||||
{
|
||||
return _frameScale;
|
||||
}
|
||||
|
||||
void ProjectConfig::setFrameScale(float frameScale)
|
||||
{
|
||||
if (frameScale > 0)
|
||||
{
|
||||
_frameScale = frameScale;
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectConfig::isShowConsole() const
|
||||
{
|
||||
return _showConsole;
|
||||
}
|
||||
|
||||
void ProjectConfig::setShowConsole(bool showConsole)
|
||||
{
|
||||
_showConsole = showConsole;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isLoadPrecompiledFramework() const
|
||||
{
|
||||
return _loadPrecompiledFramework;
|
||||
}
|
||||
|
||||
void ProjectConfig::setLoadPrecompiledFramework(bool load)
|
||||
{
|
||||
_loadPrecompiledFramework = load;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isWriteDebugLogToFile() const
|
||||
{
|
||||
return _writeDebugLogToFile;
|
||||
}
|
||||
|
||||
void ProjectConfig::setWriteDebugLogToFile(bool writeDebugLogToFile)
|
||||
{
|
||||
_writeDebugLogToFile = writeDebugLogToFile;
|
||||
}
|
||||
|
||||
void ProjectConfig::setDebugLogFilePath(const std::string &logFile)
|
||||
{
|
||||
_debugLogFile = logFile;
|
||||
}
|
||||
string ProjectConfig::getDebugLogFilePath() const
|
||||
{
|
||||
if (isAbsolutePath(_debugLogFile)) return _debugLogFile;
|
||||
|
||||
auto path(getProjectDir());
|
||||
path.append(_debugLogFile);
|
||||
return path;
|
||||
}
|
||||
|
||||
cocos2d::Vec2 ProjectConfig::getWindowOffset() const
|
||||
{
|
||||
return _windowOffset;
|
||||
}
|
||||
|
||||
void ProjectConfig::setWindowOffset(const cocos2d::Vec2 &windowOffset)
|
||||
{
|
||||
_windowOffset = windowOffset;
|
||||
}
|
||||
|
||||
int ProjectConfig::getDebuggerType() const
|
||||
{
|
||||
return _debuggerType;
|
||||
}
|
||||
|
||||
void ProjectConfig::setDebuggerType(int debuggerType)
|
||||
{
|
||||
_debuggerType = debuggerType;
|
||||
}
|
||||
|
||||
void ProjectConfig::parseCommandLine(const vector<string> &args)
|
||||
{
|
||||
auto it = args.begin();
|
||||
while (it != args.end())
|
||||
{
|
||||
string arg = *it;
|
||||
|
||||
if (arg.compare("-workdir") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
setProjectDir(*it);
|
||||
if (_writablePath.length() == 0) setWritablePath(*it);
|
||||
}
|
||||
else if (arg.compare("-writable-path") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
setWritablePath(*it);
|
||||
}
|
||||
else if (arg.compare("-entry") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
setScriptFile(*it);
|
||||
}
|
||||
else if (arg.compare("-landscape") == 0)
|
||||
{
|
||||
setFrameSize(cocos2d::Size(DEFAULT_HEIGHT, DEFAULT_WIDTH));
|
||||
}
|
||||
else if (arg.compare("-portrait") == 0)
|
||||
{
|
||||
setFrameSize(cocos2d::Size(DEFAULT_WIDTH, DEFAULT_HEIGHT));
|
||||
}
|
||||
else if (arg.compare("-resolution") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
const string& sizeStr(*it);
|
||||
size_t pos = sizeStr.find('x');
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
if (pos != sizeStr.npos && pos > 0)
|
||||
{
|
||||
string widthStr, heightStr;
|
||||
widthStr.assign(sizeStr, 0, pos);
|
||||
heightStr.assign(sizeStr, pos + 1, sizeStr.length() - pos);
|
||||
width = atoi(widthStr.c_str());
|
||||
height = atoi(heightStr.c_str());
|
||||
setFrameSize(cocos2d::Size(width, height));
|
||||
}
|
||||
}
|
||||
else if (arg.compare("-scale") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
float scale = atof((*it).c_str());
|
||||
setFrameScale(scale);
|
||||
}
|
||||
else if (arg.compare("-write-debug-log") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
setDebugLogFilePath((*it));
|
||||
setWriteDebugLogToFile(true);
|
||||
}
|
||||
else if (arg.compare("-console") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
if ((*it).compare("enable") == 0)
|
||||
{
|
||||
setShowConsole(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setShowConsole(false);
|
||||
}
|
||||
}
|
||||
else if (arg.compare("-position") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
const string& posStr(*it);
|
||||
size_t pos = posStr.find(',');
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
if (pos != posStr.npos && pos > 0)
|
||||
{
|
||||
string xStr, yStr;
|
||||
xStr.assign(posStr, 0, pos);
|
||||
yStr.assign(posStr, pos + 1, posStr.length() - pos);
|
||||
x = atoi(xStr.c_str());
|
||||
y = atoi(yStr.c_str());
|
||||
setWindowOffset(cocos2d::Vec2(x, y));
|
||||
}
|
||||
}
|
||||
else if (arg.compare("-debugger") == 0)
|
||||
{
|
||||
++it;
|
||||
if (it == args.end()) break;
|
||||
if ((*it).compare("codeide") == 0)
|
||||
{
|
||||
setDebuggerType(kCCRuntimeDebuggerCodeIDE);
|
||||
}
|
||||
else if ((*it).compare("studio") == 0)
|
||||
{
|
||||
setDebuggerType(kCCRuntimeDebuggerStudio);
|
||||
}
|
||||
}
|
||||
else if (arg.compare("-app-menu") == 0)
|
||||
{
|
||||
_isAppMenu = true;
|
||||
}
|
||||
else if (arg.compare("-resize-window") == 0)
|
||||
{
|
||||
_isResizeWindow = true;
|
||||
}
|
||||
else if (arg.compare("-retina-display") == 0)
|
||||
{
|
||||
_isRetinaDisplay = true;
|
||||
}
|
||||
else if (arg.compare("-port") == 0)
|
||||
{
|
||||
CCLOG("REFINE:");
|
||||
}
|
||||
else if (arg.compare("-listen") == 0)
|
||||
{
|
||||
++it;
|
||||
setBindAddress((*it));
|
||||
}
|
||||
else if (arg.compare("-search-path") == 0)
|
||||
{
|
||||
++it;
|
||||
vector<string> pathes = split((*it), ';');
|
||||
setSearchPath(pathes);
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
string ProjectConfig::makeCommandLine(unsigned int mask /* = kProjectConfigAll */) const
|
||||
{
|
||||
stringstream buff;
|
||||
|
||||
vector<string> commands = makeCommandLineVector(mask);
|
||||
for (auto &cmd : commands)
|
||||
{
|
||||
buff << " " << cmd;
|
||||
}
|
||||
|
||||
string result = buff.str();
|
||||
while (result.at(0) == ' ')
|
||||
{
|
||||
result = result.assign(result, 1, result.length());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<string> ProjectConfig::makeCommandLineVector(unsigned int mask /* = kProjectConfigAll */) const
|
||||
{
|
||||
vector<string> ret;
|
||||
|
||||
stringstream buff;
|
||||
|
||||
if (mask & kProjectConfigProjectDir)
|
||||
{
|
||||
auto path = getProjectDir();
|
||||
if (path.length())
|
||||
{
|
||||
ret.push_back("-workdir");
|
||||
ret.push_back(dealWithSpaceWithPath(path));
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigScriptFile)
|
||||
{
|
||||
auto path = getScriptFileRealPath();
|
||||
if (path.length())
|
||||
{
|
||||
ret.push_back("-entry");
|
||||
ret.push_back(dealWithSpaceWithPath(path));
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigWritablePath)
|
||||
{
|
||||
auto path = getWritableRealPath();
|
||||
if (path.length())
|
||||
{
|
||||
ret.push_back("-writable-path");
|
||||
ret.push_back(dealWithSpaceWithPath(path));
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigFrameSize)
|
||||
{
|
||||
buff.str("");
|
||||
buff << (int)getFrameSize().width;
|
||||
buff << "x";
|
||||
buff << (int)getFrameSize().height;
|
||||
|
||||
ret.push_back("-resolution");
|
||||
ret.push_back(buff.str());
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigFrameScale)
|
||||
{
|
||||
if (getFrameScale() < 1.0f)
|
||||
{
|
||||
buff.str("");
|
||||
buff.precision(2);
|
||||
buff << getFrameScale();
|
||||
|
||||
ret.push_back("-scale");
|
||||
ret.push_back(buff.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigWriteDebugLogToFile)
|
||||
{
|
||||
if (isWriteDebugLogToFile())
|
||||
{
|
||||
ret.push_back("-write-debug-log");
|
||||
ret.push_back(getDebugLogFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigShowConsole)
|
||||
{
|
||||
if (isShowConsole())
|
||||
{
|
||||
ret.push_back("-console");
|
||||
ret.push_back("enable");
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.push_back("-console");
|
||||
ret.push_back("disable");
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigWindowOffset)
|
||||
{
|
||||
if (_windowOffset.x != 0 && _windowOffset.y != 0)
|
||||
{
|
||||
buff.str("");
|
||||
buff << (int)_windowOffset.x;
|
||||
buff << ",";
|
||||
buff << (int)_windowOffset.y;
|
||||
buff << "";
|
||||
|
||||
ret.push_back("-position");
|
||||
ret.push_back(buff.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigDebugger)
|
||||
{
|
||||
switch (getDebuggerType())
|
||||
{
|
||||
case kCCRuntimeDebuggerCodeIDE:
|
||||
ret.push_back("-debugger");
|
||||
ret.push_back("codeide");
|
||||
break;
|
||||
case kCCRuntimeDebuggerStudio:
|
||||
ret.push_back("-debugger");
|
||||
ret.push_back("studio");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigListen)
|
||||
{
|
||||
if (!_bindAddress.empty())
|
||||
{
|
||||
ret.push_back("-listen");
|
||||
ret.push_back(_bindAddress);
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & kProjectConfigSearchPath)
|
||||
{
|
||||
if (_searchPath.size() > 0)
|
||||
{
|
||||
stringstream pathbuff;
|
||||
for (auto &path : _searchPath)
|
||||
{
|
||||
pathbuff << dealWithSpaceWithPath(path) << ";";
|
||||
}
|
||||
string pathArgs = pathbuff.str();
|
||||
pathArgs[pathArgs.length()-1] = '\0';
|
||||
|
||||
ret.push_back("-search-path");
|
||||
ret.push_back(pathArgs);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ProjectConfig::setConsolePort(int port)
|
||||
{
|
||||
_consolePort = port;
|
||||
}
|
||||
|
||||
int ProjectConfig::getConsolePort()
|
||||
{
|
||||
return _consolePort;
|
||||
}
|
||||
|
||||
void ProjectConfig::setFileUploadPort(int port)
|
||||
{
|
||||
_fileUploadPort = port;
|
||||
}
|
||||
|
||||
int ProjectConfig::getFileUploadPort()
|
||||
{
|
||||
return _fileUploadPort;
|
||||
}
|
||||
|
||||
void ProjectConfig::setBindAddress(const std::string &address)
|
||||
{
|
||||
_bindAddress = address;
|
||||
}
|
||||
|
||||
const std::string &ProjectConfig::getBindAddress() const
|
||||
{
|
||||
return _bindAddress;
|
||||
}
|
||||
|
||||
void ProjectConfig::setSearchPath(const vector<string> &args)
|
||||
{
|
||||
_searchPath = args;
|
||||
}
|
||||
|
||||
const vector<string> &ProjectConfig::getSearchPath() const
|
||||
{
|
||||
return _searchPath;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isAppMenu() const
|
||||
{
|
||||
return _isAppMenu;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isResizeWindow() const
|
||||
{
|
||||
return _isResizeWindow;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isRetinaDisplay() const
|
||||
{
|
||||
return _isRetinaDisplay;
|
||||
}
|
||||
|
||||
bool ProjectConfig::validate() const
|
||||
{
|
||||
auto utils = cocos2d::FileUtils::getInstance();
|
||||
if (!utils->isDirectoryExist(_projectDir)) return false;
|
||||
if (!utils->isDirectoryExist(getWritableRealPath())) return false;
|
||||
if (!utils->isFileExist(getScriptFileRealPath())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProjectConfig::dump()
|
||||
{
|
||||
CCLOG("Project Config:");
|
||||
CCLOG(" project dir: %s", _projectDir.c_str());
|
||||
CCLOG(" writable path: %s", _writablePath.length() ? _writablePath.c_str() : "-");
|
||||
CCLOG(" script file: %s", _scriptFile.c_str());
|
||||
CCLOG(" frame size: %0.0f x %0.0f", _frameSize.width, _frameSize.height);
|
||||
CCLOG(" frame scale: %0.2f", _frameScale);
|
||||
CCLOG(" show console: %s", _showConsole ? "YES" : "NO");
|
||||
CCLOG(" write debug log: %s (%s)", _writeDebugLogToFile ? getDebugLogFilePath().c_str() : "NO",
|
||||
_writeDebugLogToFile ? getDebugLogFilePath().c_str() : "");
|
||||
CCLOG(" listen: %s", _bindAddress.c_str());
|
||||
|
||||
if (_debuggerType == kCCRuntimeDebuggerLDT)
|
||||
{
|
||||
CCLOG(" debugger: Eclipse LDT");
|
||||
}
|
||||
else if (_debuggerType == kCCRuntimeDebuggerCodeIDE)
|
||||
{
|
||||
CCLOG(" debugger: Cocos Code IDE");
|
||||
}
|
||||
else if (_debuggerType == kCCRuntimeDebuggerStudio)
|
||||
{
|
||||
CCLOG(" debugger: Cocos Studio");
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG(" debugger: none");
|
||||
}
|
||||
|
||||
CCLOG(" add searching path:");
|
||||
for (auto &path : _searchPath)
|
||||
{
|
||||
CCLOG(" %s", path.c_str());
|
||||
}
|
||||
|
||||
CCLOG("\n\n");
|
||||
}
|
||||
|
||||
void ProjectConfig::normalize()
|
||||
{
|
||||
SimulatorConfig::makeNormalizePath(&_projectDir);
|
||||
SimulatorConfig::makeNormalizePath(&_scriptFile);
|
||||
SimulatorConfig::makeNormalizePath(&_writablePath);
|
||||
SimulatorConfig::makeNormalizePath(&_packagePath);
|
||||
|
||||
// projectDir
|
||||
size_t len = _projectDir.length();
|
||||
if (len > 0 && _projectDir[len - 1] != DIRECTORY_SEPARATOR_CHAR)
|
||||
{
|
||||
_projectDir.append(DIRECTORY_SEPARATOR);
|
||||
len++;
|
||||
}
|
||||
|
||||
// writablePath
|
||||
if (len > 0 && _writablePath.length() == 0)
|
||||
{
|
||||
_writablePath = _projectDir;
|
||||
}
|
||||
len = _writablePath.length();
|
||||
if (len > 0 && _writablePath[len - 1] != DIRECTORY_SEPARATOR_CHAR)
|
||||
{
|
||||
_writablePath.append(DIRECTORY_SEPARATOR);
|
||||
}
|
||||
_writablePath = replaceProjectDirToMacro(_writablePath);
|
||||
|
||||
// scriptFile
|
||||
_scriptFile = replaceProjectDirToMacro(_scriptFile);
|
||||
|
||||
// package.path
|
||||
vector<string> arr = getPackagePathArray();
|
||||
_packagePath = string("");
|
||||
for (auto it = arr.begin(); it != arr.end(); ++it)
|
||||
{
|
||||
string path = replaceProjectDirToMacro(*it);
|
||||
_packagePath.append(path);
|
||||
_packagePath.append(";");
|
||||
}
|
||||
if (_packagePath.length() > 0 && _packagePath[_packagePath.length() - 1] == ';')
|
||||
{
|
||||
_packagePath = _packagePath.substr(0, _packagePath.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
string ProjectConfig::replaceProjectDirToMacro(const string &path) const
|
||||
{
|
||||
if (!isAbsolutePath(path))
|
||||
{
|
||||
if (path.compare(0, 10, "$(PROJDIR)") == 0) return path;
|
||||
string result("$(PROJDIR)");
|
||||
result.append(DIRECTORY_SEPARATOR);
|
||||
result.append(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
string result = path;
|
||||
size_t len = _projectDir.length();
|
||||
if (len > 0 && result.compare(0, len, _projectDir) == 0)
|
||||
{
|
||||
result = "$(PROJDIR)";
|
||||
result.append(DIRECTORY_SEPARATOR);
|
||||
result.append(path.substr(len));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string ProjectConfig::replaceProjectDirToFullPath(const string &path) const
|
||||
{
|
||||
if (isAbsolutePath(path)) return path;
|
||||
|
||||
if (path.length() == 0) return _projectDir;
|
||||
|
||||
string result = path;
|
||||
if (path.compare(0, 10, "$(PROJDIR)") == 0)
|
||||
{
|
||||
result = _projectDir;
|
||||
string suffix = path.substr(10);
|
||||
if (suffix[0] == DIRECTORY_SEPARATOR_CHAR)
|
||||
{
|
||||
suffix = suffix.substr(1);
|
||||
}
|
||||
result.append(suffix);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ProjectConfig::isAbsolutePath(const string &path) const
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR_CHAR == '/')
|
||||
{
|
||||
return path.length() > 0 && path[0] == '/';
|
||||
}
|
||||
return path.length() > 2 && path[1] == ':';
|
||||
}
|
||||
|
||||
string ProjectConfig::dealWithSpaceWithPath(const string &path) const
|
||||
{
|
||||
#if defined(_WINDOWS)
|
||||
string ret("\"");
|
||||
ret += path;
|
||||
if (path[path.length() - 1] == '\\')
|
||||
{
|
||||
ret += "\\";
|
||||
}
|
||||
ret += "\"";
|
||||
return ret;
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
174
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/ProjectConfig.h
Executable file
174
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/ProjectConfig.h
Executable file
@@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PROJECT_CONFIG_H_
|
||||
#define __PROJECT_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
#define kCCRuntimeDebuggerNone 0
|
||||
#define kCCRuntimeDebuggerLDT 1
|
||||
#define kCCRuntimeDebuggerCodeIDE 2
|
||||
#define kCCRuntimeDebuggerStudio 3
|
||||
|
||||
#define kProjectConfigProjectDir 1 // -workdir "PATH"
|
||||
#define kProjectConfigScriptFile 2 // -script "FILENAME"
|
||||
#define kProjectConfigPackagePath 4 // -package.path "PATH;PATH"
|
||||
#define kProjectConfigWritablePath 8 // -writable "PATH"
|
||||
#define kProjectConfigFrameSize 16 // -size 960x640
|
||||
#define kProjectConfigFrameScale 32 // -scale 1.0
|
||||
#define kProjectConfigShowConsole 64 // -console, -disable-console
|
||||
#define kProjectConfigLoadPrecompiledFramework 128 // -load-framework, -disable-load-framework
|
||||
#define kProjectConfigWriteDebugLogToFile 256 // -write-debug-log, -disable-write-debug-log
|
||||
#define kProjectConfigWindowOffset 512 // -offset {0,0}
|
||||
#define kProjectConfigDebugger 1024 // -debugger-ldt, -debugger-codeide, -disable-debugger
|
||||
#define kProjectConfigListen 2048 //
|
||||
#define kProjectConfigSearchPath 4096 //
|
||||
|
||||
#define kProjectConfigOpenRecent (kProjectConfigProjectDir | kProjectConfigScriptFile | kProjectConfigPackagePath | kProjectConfigWritablePath | kProjectConfigFrameSize | kProjectConfigFrameScale | kProjectConfigShowConsole | kProjectConfigLoadPrecompiledFramework | kProjectConfigWriteDebugLogToFile)
|
||||
|
||||
#define kProjectConfigAll (kProjectConfigProjectDir | kProjectConfigScriptFile | kProjectConfigPackagePath | kProjectConfigWritablePath | kProjectConfigFrameSize | kProjectConfigFrameScale | kProjectConfigShowConsole | kProjectConfigLoadPrecompiledFramework | kProjectConfigWriteDebugLogToFile | kProjectConfigWindowOffset | kProjectConfigDebugger | kProjectConfigListen | kProjectConfigSearchPath)
|
||||
|
||||
|
||||
#define kProjectConfigConsolePort 6010
|
||||
#define kProjectConfigUploadPort 6020
|
||||
#define kProjectConfigDebugPort 5086
|
||||
|
||||
class CC_LIBSIM_DLL ProjectConfig
|
||||
{
|
||||
public:
|
||||
ProjectConfig();
|
||||
|
||||
static const int DEFAULT_WIDTH = 640;
|
||||
static const int DEFAULT_HEIGHT = 960;
|
||||
|
||||
string getProjectDir() const;
|
||||
void setProjectDir(const string &projectDir);
|
||||
|
||||
string getScriptFile() const;
|
||||
string getScriptFileRealPath() const;
|
||||
void setScriptFile(const string &scriptFile);
|
||||
|
||||
string getWritablePath() const;
|
||||
string getWritableRealPath() const;
|
||||
void setWritablePath(const string &writablePath);
|
||||
|
||||
string getPackagePath() const;
|
||||
string getNormalizedPackagePath() const;
|
||||
void setPackagePath(const string &packagePath);
|
||||
void addPackagePath(const string &packagePath);
|
||||
vector<string> getPackagePathArray() const;
|
||||
|
||||
cocos2d::Size getFrameSize() const;
|
||||
void setFrameSize(const cocos2d::Size &frameSize);
|
||||
bool isLandscapeFrame() const;
|
||||
bool isPortraitFrame() const;
|
||||
void changeFrameOrientation();
|
||||
void changeFrameOrientationToPortait();
|
||||
void changeFrameOrientationToLandscape();
|
||||
|
||||
float getFrameScale() const;
|
||||
void setFrameScale(float frameScale);
|
||||
|
||||
bool isShowConsole() const;
|
||||
void setShowConsole(bool showConsole);
|
||||
|
||||
bool isLoadPrecompiledFramework() const;
|
||||
void setLoadPrecompiledFramework(bool load);
|
||||
|
||||
bool isWriteDebugLogToFile() const;
|
||||
void setWriteDebugLogToFile(bool writeDebugLogToFile);
|
||||
void setDebugLogFilePath(const std::string &logFile);
|
||||
string getDebugLogFilePath() const;
|
||||
|
||||
cocos2d::Vec2 getWindowOffset() const;
|
||||
void setWindowOffset(const cocos2d::Vec2 &windowOffset);
|
||||
|
||||
int getDebuggerType() const;
|
||||
void setDebuggerType(int debuggerType);
|
||||
|
||||
void parseCommandLine(const vector<string> &args);
|
||||
string makeCommandLine(unsigned int mask = kProjectConfigAll) const;
|
||||
vector<string> makeCommandLineVector(unsigned int mask = kProjectConfigAll) const;
|
||||
|
||||
void setConsolePort(int port);
|
||||
int getConsolePort();
|
||||
void setFileUploadPort(int port);
|
||||
int getFileUploadPort();
|
||||
// @address: 127.0.0.1
|
||||
void setBindAddress(const std::string &address);
|
||||
const std::string &getBindAddress() const;
|
||||
void setSearchPath(const vector<string> &args);
|
||||
const vector<string> &getSearchPath() const;
|
||||
|
||||
bool isAppMenu() const;
|
||||
bool isResizeWindow() const;
|
||||
bool isRetinaDisplay() const;
|
||||
|
||||
bool validate() const;
|
||||
void dump();
|
||||
|
||||
private:
|
||||
string _projectDir;
|
||||
string _scriptFile;
|
||||
string _packagePath;
|
||||
string _writablePath;
|
||||
cocos2d::Size _frameSize;
|
||||
float _frameScale;
|
||||
bool _showConsole;
|
||||
bool _loadPrecompiledFramework;
|
||||
bool _writeDebugLogToFile;
|
||||
bool _restartProcess;
|
||||
cocos2d::Vec2 _windowOffset;
|
||||
int _debuggerType;
|
||||
bool _isAppMenu;
|
||||
bool _isResizeWindow;
|
||||
bool _isRetinaDisplay;
|
||||
string _debugLogFile;
|
||||
int _consolePort;
|
||||
int _fileUploadPort;
|
||||
string _bindAddress;
|
||||
vector<string> _searchPath;
|
||||
|
||||
void normalize();
|
||||
string replaceProjectDirToMacro(const string &path) const;
|
||||
string replaceProjectDirToFullPath(const string &path) const;
|
||||
bool isAbsolutePath(const string &path) const;
|
||||
|
||||
/**
|
||||
* windows : Y:\Documents\CocosProjects\Cocos Project\ -> "Y:\Documents\CocosProjects\Cocos Project\\"
|
||||
* other : return @path
|
||||
*/
|
||||
string dealWithSpaceWithPath(const string &path) const;
|
||||
};
|
||||
|
||||
#endif // __PROJECT_CONFIG_H_
|
||||
109
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/SimulatorConfig.cpp
Executable file
109
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/SimulatorConfig.cpp
Executable file
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "SimulatorConfig.h"
|
||||
#include <sstream>
|
||||
|
||||
SimulatorConfig *SimulatorConfig::_instance = NULL;
|
||||
|
||||
SimulatorConfig *SimulatorConfig::getInstance()
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
_instance = new SimulatorConfig();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
SimulatorConfig::SimulatorConfig()
|
||||
{
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPhone 5 (640x1136)", 640, 1136));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPhone 6 (750x1334)", 750, 1334));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPhone 6Plus (1242x2208)", 1242, 2208));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPhone 7 (750x1334)", 750, 1334));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPhone 7Plus (1242x2208)", 1242, 2208));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPhone X (750x2436)", 750, 2436));
|
||||
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPad (2048x1536)", 2048, 1536));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPad Air 2 (1536x2048)", 1536, 2048));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPad Pro 10.5-inch (1668x2224)", 1668, 2224));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Apple iPad Pro 12.9-inch (2048x2732)", 2048, 2732));
|
||||
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Huawei P9 (1080x1920)", 1080, 1920));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Huawei Mate9 Pro (1440x2560)", 1440, 2560));
|
||||
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Google Nexus 5 (1080x2880)", 1080, 2880));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Google Nexus 5X (1079x1919)", 1079, 1919));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Google Nexus 6 (1442x2562)", 1442, 2562));
|
||||
_screenSizeArray.push_back(SimulatorScreenSize("Google Nexus 7 (1920x1200)", 1920, 1200));
|
||||
}
|
||||
|
||||
int SimulatorConfig::getScreenSizeCount() const
|
||||
{
|
||||
return (int)_screenSizeArray.size();
|
||||
}
|
||||
|
||||
SimulatorScreenSize SimulatorConfig::getScreenSize(int index) const
|
||||
{
|
||||
return _screenSizeArray.at(index);
|
||||
}
|
||||
|
||||
int SimulatorConfig::checkScreenSize(const cocos2d::Size &size) const
|
||||
{
|
||||
int width = size.width;
|
||||
int height = size.height;
|
||||
|
||||
if (width > height)
|
||||
{
|
||||
int w = width;
|
||||
width = height;
|
||||
height = w;
|
||||
}
|
||||
|
||||
int count = (int)_screenSizeArray.size();
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const SimulatorScreenSize &size = _screenSizeArray[i];
|
||||
if (size.width == width && size.height == height)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// helper
|
||||
|
||||
void SimulatorConfig::makeNormalizePath(string *path, const char *directorySeparator/* = NULL*/)
|
||||
{
|
||||
if (!directorySeparator) directorySeparator = DIRECTORY_SEPARATOR;
|
||||
size_t pos = std::string::npos;
|
||||
while ((pos = path->find_first_of("/\\", pos + 1)) != std::string::npos)
|
||||
{
|
||||
path->replace(pos, 1, directorySeparator);
|
||||
}
|
||||
}
|
||||
83
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/SimulatorConfig.h
Executable file
83
cocos2d-x/tools/simulator/libsimulator/lib/ProjectConfig/SimulatorConfig.h
Executable file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __SIMULATOR_CONFIG_H_
|
||||
#define __SIMULATOR_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#define DIRECTORY_SEPARATOR "\\"
|
||||
#define DIRECTORY_SEPARATOR_CHAR '\\'
|
||||
#else
|
||||
#define DIRECTORY_SEPARATOR "/"
|
||||
#define DIRECTORY_SEPARATOR_CHAR '/'
|
||||
#endif
|
||||
|
||||
typedef struct _SimulatorScreenSize {
|
||||
string title;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
_SimulatorScreenSize(const string &title_, int width_, int height_)
|
||||
{
|
||||
title = title_;
|
||||
width = width_;
|
||||
height = height_;
|
||||
}
|
||||
} SimulatorScreenSize;
|
||||
|
||||
typedef vector<SimulatorScreenSize> ScreenSizeArray;
|
||||
typedef ScreenSizeArray::iterator ScreenSizeArrayIterator;
|
||||
|
||||
class CC_LIBSIM_DLL SimulatorConfig
|
||||
{
|
||||
public:
|
||||
static SimulatorConfig *getInstance();
|
||||
|
||||
// predefined screen size
|
||||
int getScreenSizeCount() const;
|
||||
SimulatorScreenSize getScreenSize(int index) const;
|
||||
int checkScreenSize(const cocos2d::Size &size) const;
|
||||
|
||||
// helper
|
||||
static void makeNormalizePath(string *path, const char *directorySeparator = NULL);
|
||||
|
||||
private:
|
||||
SimulatorConfig();
|
||||
|
||||
static SimulatorConfig *_instance;
|
||||
|
||||
ScreenSizeArray _screenSizeArray;
|
||||
};
|
||||
|
||||
#endif // __SIMULATOR_CONFIG_H_
|
||||
55
cocos2d-x/tools/simulator/libsimulator/lib/SimulatorExport.h
Executable file
55
cocos2d-x/tools/simulator/libsimulator/lib/SimulatorExport.h
Executable file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if (defined(WIN32) && defined(_WINDOWS)) || defined(WINRT) || defined(WP8)
|
||||
#ifdef __MINGW32__
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(_USRLIBSIMSTATIC)
|
||||
#define CC_LIBSIM_DLL
|
||||
#else
|
||||
#if defined(_USRLIBSIMDLL)
|
||||
#define CC_LIBSIM_DLL __declspec(dllexport)
|
||||
#else /* use a DLL library */
|
||||
#define CC_LIBSIM_DLL __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define NULL pointer value */
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(_SHARED_)
|
||||
#define CC_LIBSIM_DLL __attribute__((visibility("default")))
|
||||
#else
|
||||
#define CC_LIBSIM_DLL
|
||||
#endif
|
||||
39
cocos2d-x/tools/simulator/libsimulator/lib/cocos2dx_extra.h
Executable file
39
cocos2d-x/tools/simulator/libsimulator/lib/cocos2dx_extra.h
Executable file
@@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __COCOS2D_X_EXTRA_H_
|
||||
#define __COCOS2D_X_EXTRA_H_
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define NS_CC_EXTRA_BEGIN namespace cocos2d { namespace extra {
|
||||
#define NS_CC_EXTRA_END }}
|
||||
#define USING_NS_CC_EXTRA using namespace cocos2d::extra
|
||||
|
||||
#endif /* __COCOS2D_X_EXTRA_H_ */
|
||||
579
cocos2d-x/tools/simulator/libsimulator/lib/network/CCHTTPRequest.cpp
Executable file
579
cocos2d-x/tools/simulator/libsimulator/lib/network/CCHTTPRequest.cpp
Executable file
@@ -0,0 +1,579 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "network/CCHTTPRequest.h"
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
}
|
||||
#include "CCLuaEngine.h"
|
||||
#endif
|
||||
#include <sstream>
|
||||
|
||||
|
||||
NS_CC_EXTRA_BEGIN
|
||||
|
||||
unsigned int HTTPRequest::s_id = 0;
|
||||
|
||||
HTTPRequest *HTTPRequest::createWithUrl(HTTPRequestDelegate *delegate,
|
||||
const char *url,
|
||||
int method)
|
||||
{
|
||||
HTTPRequest *request = new HTTPRequest();
|
||||
request->initWithDelegate(delegate, url, method);
|
||||
request->autorelease();
|
||||
return request;
|
||||
}
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
HTTPRequest *HTTPRequest::createWithUrlLua(LUA_FUNCTION listener,
|
||||
const char *url,
|
||||
int method)
|
||||
{
|
||||
HTTPRequest *request = new HTTPRequest();
|
||||
request->initWithListener(listener, url, method);
|
||||
request->autorelease();
|
||||
return request;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool HTTPRequest::initWithDelegate(HTTPRequestDelegate *delegate, const char *url, int method)
|
||||
{
|
||||
_delegate = delegate;
|
||||
return initWithUrl(url, method);
|
||||
}
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
bool HTTPRequest::initWithListener(LUA_FUNCTION listener, const char *url, int method)
|
||||
{
|
||||
_listener = listener;
|
||||
return initWithUrl(url, method);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool HTTPRequest::initWithUrl(const char *url, int method)
|
||||
{
|
||||
CCASSERT(url, "HTTPRequest::initWithUrl() - invalid url");
|
||||
_curl = curl_easy_init();
|
||||
curl_easy_setopt(_curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(_curl, CURLOPT_USERAGENT, "libcurl");
|
||||
curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT);
|
||||
curl_easy_setopt(_curl, CURLOPT_TIMEOUT, DEFAULT_TIMEOUT);
|
||||
curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1L);
|
||||
|
||||
if (method == kCCHTTPRequestMethodPOST)
|
||||
{
|
||||
curl_easy_setopt(_curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(_curl, CURLOPT_COPYPOSTFIELDS, "");
|
||||
}
|
||||
|
||||
++s_id;
|
||||
// CCLOG("HTTPRequest[0x%04x] - create request with url: %s", s_id, url);
|
||||
return true;
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest(void)
|
||||
{
|
||||
cleanup();
|
||||
if (_listener)
|
||||
{
|
||||
#if (CC_LUA_ENGINE_ENABLED > 0)
|
||||
LuaEngine::getInstance()->removeScriptHandler(_listener);
|
||||
#endif
|
||||
}
|
||||
// CCLOG("HTTPRequest[0x%04x] - request removed", s_id);
|
||||
}
|
||||
|
||||
void HTTPRequest::setRequestUrl(const char *url)
|
||||
{
|
||||
CCASSERT(url, "HTTPRequest::setRequestUrl() - invalid url");
|
||||
_url = url;
|
||||
curl_easy_setopt(_curl, CURLOPT_URL, _url.c_str());
|
||||
}
|
||||
|
||||
const string HTTPRequest::getRequestUrl(void)
|
||||
{
|
||||
return _url;
|
||||
}
|
||||
|
||||
void HTTPRequest::addRequestHeader(const char *header)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::addRequestHeader() - request not idle");
|
||||
CCASSERT(header, "HTTPRequest::addRequestHeader() - invalid header");
|
||||
_headers.push_back(string(header));
|
||||
}
|
||||
|
||||
void HTTPRequest::addPOSTValue(const char *key, const char *value)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::addPOSTValue() - request not idle");
|
||||
CCASSERT(key, "HTTPRequest::addPOSTValue() - invalid key");
|
||||
_postFields[string(key)] = string(value ? value : "");
|
||||
}
|
||||
|
||||
void HTTPRequest::setPOSTData(const char *data)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::setPOSTData() - request not idle");
|
||||
CCASSERT(data, "HTTPRequest::setPOSTData() - invalid post data");
|
||||
_postFields.clear();
|
||||
curl_easy_setopt(_curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(_curl, CURLOPT_COPYPOSTFIELDS, data);
|
||||
}
|
||||
|
||||
void HTTPRequest::addFormFile(const char *name, const char *filePath, const char *contentType)
|
||||
{
|
||||
curl_formadd(&_formPost, &_lastPost,
|
||||
CURLFORM_COPYNAME, name,
|
||||
CURLFORM_FILE, filePath,
|
||||
CURLFORM_CONTENTTYPE, contentType,
|
||||
CURLFORM_END);
|
||||
//CCLOG("addFormFile %s %s %s", name, filePath, contentType);
|
||||
}
|
||||
|
||||
void HTTPRequest::addFormContents(const char *name, const char *value)
|
||||
{
|
||||
curl_formadd(&_formPost, &_lastPost,
|
||||
CURLFORM_COPYNAME, name,
|
||||
CURLFORM_COPYCONTENTS, value,
|
||||
CURLFORM_END);
|
||||
//CCLOG("addFormContents %s %s", name, value);
|
||||
}
|
||||
|
||||
void HTTPRequest::setCookieString(const char *cookie)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::setAcceptEncoding() - request not idle");
|
||||
curl_easy_setopt(_curl, CURLOPT_COOKIE, cookie ? cookie : "");
|
||||
}
|
||||
|
||||
const string HTTPRequest::getCookieString(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "HTTPRequest::getResponseData() - request not completed");
|
||||
return _responseCookies;
|
||||
}
|
||||
|
||||
void HTTPRequest::setAcceptEncoding(int acceptEncoding)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::setAcceptEncoding() - request not idle");
|
||||
switch (acceptEncoding)
|
||||
{
|
||||
case kCCHTTPRequestAcceptEncodingGzip:
|
||||
curl_easy_setopt(_curl, CURLOPT_ACCEPT_ENCODING, "gzip");
|
||||
break;
|
||||
|
||||
case kCCHTTPRequestAcceptEncodingDeflate:
|
||||
curl_easy_setopt(_curl, CURLOPT_ACCEPT_ENCODING, "deflate");
|
||||
break;
|
||||
|
||||
default:
|
||||
curl_easy_setopt(_curl, CURLOPT_ACCEPT_ENCODING, "identity");
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::setTimeout(int timeout)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::setTimeout() - request not idle");
|
||||
curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, timeout);
|
||||
curl_easy_setopt(_curl, CURLOPT_TIMEOUT, timeout);
|
||||
}
|
||||
|
||||
bool HTTPRequest::start(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateIdle, "HTTPRequest::start() - request not idle");
|
||||
|
||||
_state = kCCHTTPRequestStateInProgress;
|
||||
_curlState = kCCHTTPRequestCURLStateBusy;
|
||||
retain();
|
||||
|
||||
curl_easy_setopt(_curl, CURLOPT_HTTP_CONTENT_DECODING, 1);
|
||||
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, writeDataCURL);
|
||||
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, this);
|
||||
curl_easy_setopt(_curl, CURLOPT_HEADERFUNCTION, writeHeaderCURL);
|
||||
curl_easy_setopt(_curl, CURLOPT_WRITEHEADER, this);
|
||||
curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, false);
|
||||
curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, progressCURL);
|
||||
curl_easy_setopt(_curl, CURLOPT_PROGRESSDATA, this);
|
||||
curl_easy_setopt(_curl, CURLOPT_COOKIEFILE, "");
|
||||
|
||||
#ifdef _WINDOWS_
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
|
||||
std::thread worker(requestCURL, this);
|
||||
worker.detach();
|
||||
|
||||
#else
|
||||
CreateThread(NULL, // default security attributes
|
||||
0, // use default stack size
|
||||
requestCURL, // thread function name
|
||||
this, // argument to thread function
|
||||
0, // use default creation flags
|
||||
NULL);
|
||||
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WP8
|
||||
|
||||
#else
|
||||
pthread_create(&_thread, NULL, requestCURL, this);
|
||||
pthread_detach(_thread);
|
||||
#endif
|
||||
|
||||
// Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false);
|
||||
// CCLOG("HTTPRequest[0x%04x] - request start", s_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HTTPRequest::cancel(void)
|
||||
{
|
||||
_delegate = NULL;
|
||||
if (_state == kCCHTTPRequestStateIdle || _state == kCCHTTPRequestStateInProgress)
|
||||
{
|
||||
_state = kCCHTTPRequestStateCancelled;
|
||||
}
|
||||
}
|
||||
|
||||
int HTTPRequest::getState(void)
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
|
||||
int HTTPRequest::getResponseStatusCode(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "Request not completed");
|
||||
return _responseCode;
|
||||
}
|
||||
|
||||
const HTTPRequestHeaders &HTTPRequest::getResponseHeaders(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "HTTPRequest::getResponseHeaders() - request not completed");
|
||||
return _responseHeaders;
|
||||
}
|
||||
|
||||
const string HTTPRequest::getResponseHeadersString()
|
||||
{
|
||||
string buf;
|
||||
for (HTTPRequestHeadersIterator it = _responseHeaders.begin(); it != _responseHeaders.end(); ++it)
|
||||
{
|
||||
buf.append(*it);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
const string HTTPRequest::getResponseString(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "HTTPRequest::getResponseString() - request not completed");
|
||||
return string(_responseBuffer ? static_cast<char*>(_responseBuffer) : "");
|
||||
}
|
||||
|
||||
void *HTTPRequest::getResponseData(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "HTTPRequest::getResponseData() - request not completed");
|
||||
void *buff = malloc(_responseDataLength);
|
||||
memcpy(buff, _responseBuffer, _responseDataLength);
|
||||
return buff;
|
||||
}
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
LUA_STRING HTTPRequest::getResponseDataLua(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "HTTPRequest::getResponseDataLua() - request not completed");
|
||||
LuaStack *stack = LuaEngine::getInstance()->getLuaStack();
|
||||
stack->clean();
|
||||
stack->pushString(static_cast<char*>(_responseBuffer), (int)_responseDataLength);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int HTTPRequest::getResponseDataLength(void)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "Request not completed");
|
||||
return (int)_responseDataLength;
|
||||
}
|
||||
|
||||
size_t HTTPRequest::saveResponseData(const char *filename)
|
||||
{
|
||||
CCASSERT(_state == kCCHTTPRequestStateCompleted, "HTTPRequest::saveResponseData() - request not completed");
|
||||
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
CCASSERT(fp, "HTTPRequest::saveResponseData() - open file failure");
|
||||
|
||||
size_t writedBytes = _responseDataLength;
|
||||
if (writedBytes > 0)
|
||||
{
|
||||
fwrite(_responseBuffer, _responseDataLength, 1, fp);
|
||||
}
|
||||
fclose(fp);
|
||||
return writedBytes;
|
||||
}
|
||||
|
||||
int HTTPRequest::getErrorCode(void)
|
||||
{
|
||||
return _errorCode;
|
||||
}
|
||||
|
||||
const string HTTPRequest::getErrorMessage(void)
|
||||
{
|
||||
return _errorMessage;
|
||||
}
|
||||
|
||||
HTTPRequestDelegate* HTTPRequest::getDelegate(void)
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
void HTTPRequest::checkCURLState(float dt)
|
||||
{
|
||||
CC_UNUSED_PARAM(dt);
|
||||
if (_curlState != kCCHTTPRequestCURLStateBusy)
|
||||
{
|
||||
// Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
|
||||
release();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::update(float dt)
|
||||
{
|
||||
if (_state == kCCHTTPRequestStateInProgress)
|
||||
{
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
if (_listener)
|
||||
{
|
||||
LuaValueDict dict;
|
||||
|
||||
dict["name"] = LuaValue::stringValue("progress");
|
||||
dict["total"] = LuaValue::intValue((int)_dltotal);
|
||||
dict["dltotal"] = LuaValue::intValue((int)_dlnow);
|
||||
dict["request"] = LuaValue::ccobjectValue(this, "HTTPRequest");
|
||||
|
||||
LuaStack *stack = LuaEngine::getInstance()->getLuaStack();
|
||||
stack->clean();
|
||||
stack->pushLuaValueDict(dict);
|
||||
stack->executeFunctionByHandler(_listener, 1);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
|
||||
if (_curlState != kCCHTTPRequestCURLStateIdle)
|
||||
{
|
||||
// Director::getInstance()->getScheduler()->schedule(schedule_selector(HTTPRequest::checkCURLState), this, 0, false);
|
||||
}
|
||||
|
||||
if (_state == kCCHTTPRequestStateCompleted)
|
||||
{
|
||||
// CCLOG("HTTPRequest[0x%04x] - request completed", s_id);
|
||||
if (_delegate) _delegate->requestFinished(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// CCLOG("HTTPRequest[0x%04x] - request failed", s_id);
|
||||
if (_delegate) _delegate->requestFailed(this);
|
||||
}
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
if (_listener)
|
||||
{
|
||||
LuaValueDict dict;
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case kCCHTTPRequestStateCompleted:
|
||||
dict["name"] = LuaValue::stringValue("completed");
|
||||
break;
|
||||
|
||||
case kCCHTTPRequestStateCancelled:
|
||||
dict["name"] = LuaValue::stringValue("cancelled");
|
||||
break;
|
||||
|
||||
case kCCHTTPRequestStateFailed:
|
||||
dict["name"] = LuaValue::stringValue("failed");
|
||||
break;
|
||||
|
||||
default:
|
||||
dict["name"] = LuaValue::stringValue("unknown");
|
||||
}
|
||||
dict["request"] = LuaValue::ccobjectValue(this, "HTTPRequest");
|
||||
LuaStack *stack = LuaEngine::getInstance()->getLuaStack();
|
||||
stack->clean();
|
||||
stack->pushLuaValueDict(dict);
|
||||
stack->executeFunctionByHandler(_listener, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// instance callback
|
||||
|
||||
void HTTPRequest::onRequest(void)
|
||||
{
|
||||
if (_postFields.size() > 0)
|
||||
{
|
||||
curl_easy_setopt(_curl, CURLOPT_POST, 1L);
|
||||
stringbuf buf;
|
||||
for (Fields::iterator it = _postFields.begin(); it != _postFields.end(); ++it)
|
||||
{
|
||||
char *part = curl_easy_escape(_curl, it->first.c_str(), 0);
|
||||
buf.sputn(part, strlen(part));
|
||||
buf.sputc('=');
|
||||
curl_free(part);
|
||||
|
||||
part = curl_easy_escape(_curl, it->second.c_str(), 0);
|
||||
buf.sputn(part, strlen(part));
|
||||
curl_free(part);
|
||||
|
||||
buf.sputc('&');
|
||||
}
|
||||
curl_easy_setopt(_curl, CURLOPT_COPYPOSTFIELDS, buf.str().c_str());
|
||||
}
|
||||
|
||||
struct curl_slist *chunk = NULL;
|
||||
for (HTTPRequestHeadersIterator it = _headers.begin(); it != _headers.end(); ++it)
|
||||
{
|
||||
chunk = curl_slist_append(chunk, (*it).c_str());
|
||||
}
|
||||
|
||||
if (_formPost)
|
||||
{
|
||||
curl_easy_setopt(_curl, CURLOPT_HTTPPOST, _formPost);
|
||||
}
|
||||
|
||||
curl_slist *cookies = NULL;
|
||||
curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, chunk);
|
||||
CURLcode code = curl_easy_perform(_curl);
|
||||
curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &_responseCode);
|
||||
curl_easy_getinfo(_curl, CURLINFO_COOKIELIST, &cookies);
|
||||
|
||||
if (cookies)
|
||||
{
|
||||
struct curl_slist *nc = cookies;
|
||||
stringbuf buf;
|
||||
while (nc)
|
||||
{
|
||||
buf.sputn(nc->data, strlen(nc->data));
|
||||
buf.sputc('\n');
|
||||
nc = nc->next;
|
||||
}
|
||||
_responseCookies = buf.str();
|
||||
curl_slist_free_all(cookies);
|
||||
cookies = NULL;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(_curl);
|
||||
_curl = NULL;
|
||||
if (_formPost)
|
||||
{
|
||||
curl_formfree(_formPost);
|
||||
_formPost = NULL;
|
||||
}
|
||||
curl_slist_free_all(chunk);
|
||||
|
||||
_errorCode = code;
|
||||
_errorMessage = (code == CURLE_OK) ? "" : curl_easy_strerror(code);
|
||||
_state = (code == CURLE_OK) ? kCCHTTPRequestStateCompleted : kCCHTTPRequestStateFailed;
|
||||
_curlState = kCCHTTPRequestCURLStateClosed;
|
||||
}
|
||||
|
||||
size_t HTTPRequest::onWriteData(void *buffer, size_t bytes)
|
||||
{
|
||||
if (_responseDataLength + bytes + 1 > _responseBufferLength)
|
||||
{
|
||||
_responseBufferLength += BUFFER_CHUNK_SIZE;
|
||||
_responseBuffer = realloc(_responseBuffer, _responseBufferLength);
|
||||
}
|
||||
|
||||
memcpy(static_cast<char*>(_responseBuffer) + _responseDataLength, buffer, bytes);
|
||||
_responseDataLength += bytes;
|
||||
static_cast<char*>(_responseBuffer)[_responseDataLength] = 0;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t HTTPRequest::onWriteHeader(void *buffer, size_t bytes)
|
||||
{
|
||||
char *headerBuffer = new char[bytes + 1];
|
||||
headerBuffer[bytes] = 0;
|
||||
memcpy(headerBuffer, buffer, bytes);
|
||||
_responseHeaders.push_back(string(headerBuffer));
|
||||
delete []headerBuffer;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int HTTPRequest::onProgress(double dltotal, double dlnow, double ultotal, double ulnow)
|
||||
{
|
||||
_dltotal = dltotal;
|
||||
_dlnow = dlnow;
|
||||
_ultotal = ultotal;
|
||||
_ulnow = ulnow;
|
||||
|
||||
return _state == kCCHTTPRequestStateCancelled ? 1: 0;
|
||||
}
|
||||
|
||||
void HTTPRequest::cleanup(void)
|
||||
{
|
||||
_state = kCCHTTPRequestStateCleared;
|
||||
_responseBufferLength = 0;
|
||||
_responseDataLength = 0;
|
||||
if (_responseBuffer)
|
||||
{
|
||||
free(_responseBuffer);
|
||||
_responseBuffer = NULL;
|
||||
}
|
||||
if (_curl)
|
||||
{
|
||||
curl_easy_cleanup(_curl);
|
||||
_curl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// curl callback
|
||||
|
||||
#ifdef _WINDOWS_
|
||||
DWORD WINAPI HTTPRequest::requestCURL(LPVOID userdata)
|
||||
{
|
||||
static_cast<HTTPRequest*>(userdata)->onRequest();
|
||||
return 0;
|
||||
}
|
||||
#else // _WINDOWS_
|
||||
void *HTTPRequest::requestCURL(void *userdata)
|
||||
{
|
||||
static_cast<HTTPRequest*>(userdata)->onRequest();
|
||||
return NULL;
|
||||
}
|
||||
#endif // _WINDOWS_
|
||||
|
||||
size_t HTTPRequest::writeDataCURL(void *buffer, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
return static_cast<HTTPRequest*>(userdata)->onWriteData(buffer, size *nmemb);
|
||||
}
|
||||
|
||||
size_t HTTPRequest::writeHeaderCURL(void *buffer, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
return static_cast<HTTPRequest*>(userdata)->onWriteHeader(buffer, size *nmemb);
|
||||
}
|
||||
|
||||
int HTTPRequest::progressCURL(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow)
|
||||
{
|
||||
return static_cast<HTTPRequest*>(userdata)->onProgress(dltotal, dlnow, ultotal, ulnow);
|
||||
}
|
||||
|
||||
NS_CC_EXTRA_END
|
||||
250
cocos2d-x/tools/simulator/libsimulator/lib/network/CCHTTPRequest.h
Executable file
250
cocos2d-x/tools/simulator/libsimulator/lib/network/CCHTTPRequest.h
Executable file
@@ -0,0 +1,250 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __CC_HTTP_REQUEST_H_
|
||||
#define __CC_HTTP_REQUEST_H_
|
||||
|
||||
#include "cocos2dx_extra.h"
|
||||
#include "cocos2d.h"
|
||||
#include "network/CCHTTPRequestDelegate.h"
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
#include "CCLuaEngine.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS_
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "curl/curl.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
NS_CC_EXTRA_BEGIN
|
||||
|
||||
#define kCCHTTPRequestMethodGET 0
|
||||
#define kCCHTTPRequestMethodPOST 1
|
||||
|
||||
#define kCCHTTPRequestAcceptEncodingIdentity 0
|
||||
#define kCCHTTPRequestAcceptEncodingGzip 1
|
||||
#define kCCHTTPRequestAcceptEncodingDeflate 2
|
||||
|
||||
#define kCCHTTPRequestStateIdle 0
|
||||
#define kCCHTTPRequestStateCleared 1
|
||||
#define kCCHTTPRequestStateInProgress 2
|
||||
#define kCCHTTPRequestStateCompleted 3
|
||||
#define kCCHTTPRequestStateCancelled 4
|
||||
#define kCCHTTPRequestStateFailed 5
|
||||
|
||||
#define kCCHTTPRequestCURLStateIdle 0
|
||||
#define kCCHTTPRequestCURLStateBusy 1
|
||||
#define kCCHTTPRequestCURLStateClosed 2
|
||||
|
||||
typedef vector<string> HTTPRequestHeaders;
|
||||
typedef HTTPRequestHeaders::iterator HTTPRequestHeadersIterator;
|
||||
|
||||
class HTTPRequest : public Ref
|
||||
{
|
||||
public:
|
||||
static HTTPRequest *createWithUrl(HTTPRequestDelegate *delegate,
|
||||
const char *url,
|
||||
int method = kCCHTTPRequestMethodGET);
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
static HTTPRequest* createWithUrlLua(LUA_FUNCTION listener,
|
||||
const char *url,
|
||||
int method = kCCHTTPRequestMethodGET);
|
||||
#endif
|
||||
|
||||
~HTTPRequest(void);
|
||||
|
||||
/** @brief Set request url. */
|
||||
void setRequestUrl(const char *url);
|
||||
|
||||
/** @brief Get request url. */
|
||||
const string getRequestUrl(void);
|
||||
|
||||
/** @brief Add a custom header to the request. */
|
||||
void addRequestHeader(const char *header);
|
||||
|
||||
/** @brief Add a POST variable to the request, POST only. */
|
||||
void addPOSTValue(const char *key, const char *value);
|
||||
|
||||
/** @brief Set POST data to the request body, POST only. */
|
||||
void setPOSTData(const char *data);
|
||||
|
||||
|
||||
void addFormFile(const char *name, const char *filePath, const char *fileType="application/octet-stream");
|
||||
void addFormContents(const char *name, const char *value);
|
||||
|
||||
/** @brief Set/Get cookie string. */
|
||||
void setCookieString(const char *cookie);
|
||||
const string getCookieString(void);
|
||||
|
||||
/** @brief Set accept encoding. */
|
||||
void setAcceptEncoding(int acceptEncoding);
|
||||
|
||||
/** @brief Number of seconds to wait before timing out - default is 10. */
|
||||
void setTimeout(int timeout);
|
||||
|
||||
/** @brief Execute an asynchronous request. */
|
||||
bool start(void);
|
||||
|
||||
/** @brief Cancel an asynchronous request, clearing all delegates first. */
|
||||
void cancel(void);
|
||||
|
||||
/** @brief Get the request state. */
|
||||
int getState(void);
|
||||
|
||||
/** @brief Return HTTP status code. */
|
||||
int getResponseStatusCode(void);
|
||||
|
||||
/** @brief Return HTTP response headers. */
|
||||
const HTTPRequestHeaders &getResponseHeaders(void);
|
||||
const string getResponseHeadersString(void);
|
||||
|
||||
/** @brief Returns the contents of the result. */
|
||||
const string getResponseString(void);
|
||||
|
||||
/** @brief Alloc memory block, return response data. use free() release memory block */
|
||||
void *getResponseData(void);
|
||||
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
LUA_STRING getResponseDataLua(void);
|
||||
#endif
|
||||
|
||||
/** @brief Get response data length (bytes). */
|
||||
int getResponseDataLength(void);
|
||||
|
||||
/** @brief Save response data to file. */
|
||||
size_t saveResponseData(const char *filename);
|
||||
|
||||
/** @brief Get error code. */
|
||||
int getErrorCode(void);
|
||||
|
||||
/** @brief Get error message. */
|
||||
const string getErrorMessage(void);
|
||||
|
||||
/** @brief Return HTTPRequestDelegate delegate. */
|
||||
HTTPRequestDelegate* getDelegate(void);
|
||||
|
||||
/** @brief timer function. */
|
||||
void checkCURLState(float dt);
|
||||
virtual void update(float dt);
|
||||
|
||||
private:
|
||||
HTTPRequest(void)
|
||||
: _delegate(NULL)
|
||||
, _listener(0)
|
||||
, _state(kCCHTTPRequestStateIdle)
|
||||
, _errorCode(0)
|
||||
, _responseCode(0)
|
||||
, _responseBuffer(NULL)
|
||||
, _responseBufferLength(0)
|
||||
, _responseDataLength(0)
|
||||
, _curlState(kCCHTTPRequestCURLStateIdle)
|
||||
, _formPost(NULL)
|
||||
, _lastPost(NULL)
|
||||
, _dltotal(0)
|
||||
, _dlnow(0)
|
||||
, _ultotal(0)
|
||||
, _ulnow(0)
|
||||
{
|
||||
}
|
||||
bool initWithDelegate(HTTPRequestDelegate* delegate, const char *url, int method);
|
||||
#if CC_LUA_ENGINE_ENABLED > 0
|
||||
bool initWithListener(LUA_FUNCTION listener, const char *url, int method);
|
||||
#endif
|
||||
bool initWithUrl(const char *url, int method);
|
||||
|
||||
enum {
|
||||
DEFAULT_TIMEOUT = 10, // 10 seconds
|
||||
BUFFER_CHUNK_SIZE = 32768, // 32 KB
|
||||
};
|
||||
|
||||
static unsigned int s_id;
|
||||
string _url;
|
||||
HTTPRequestDelegate* _delegate;
|
||||
int _listener;
|
||||
int _curlState;
|
||||
|
||||
CURL *_curl;
|
||||
curl_httppost *_formPost;
|
||||
curl_httppost *_lastPost;
|
||||
|
||||
int _state;
|
||||
int _errorCode;
|
||||
string _errorMessage;
|
||||
|
||||
// request
|
||||
typedef map<string, string> Fields;
|
||||
Fields _postFields;
|
||||
HTTPRequestHeaders _headers;
|
||||
|
||||
// response
|
||||
int _responseCode;
|
||||
HTTPRequestHeaders _responseHeaders;
|
||||
void *_responseBuffer;
|
||||
size_t _responseBufferLength;
|
||||
size_t _responseDataLength;
|
||||
string _responseCookies;
|
||||
|
||||
double _dltotal;
|
||||
double _dlnow;
|
||||
double _ultotal;
|
||||
double _ulnow;
|
||||
|
||||
// private methods
|
||||
void cleanup(void);
|
||||
void cleanupRawResponseBuff(void);
|
||||
|
||||
// instance callback
|
||||
void onRequest(void);
|
||||
size_t onWriteData(void *buffer, size_t bytes);
|
||||
size_t onWriteHeader(void *buffer, size_t bytes);
|
||||
int onProgress(double dltotal, double dlnow, double ultotal, double ulnow);
|
||||
|
||||
// curl callback
|
||||
#ifdef _WINDOWS_
|
||||
static DWORD WINAPI requestCURL(LPVOID userdata);
|
||||
#else
|
||||
pthread_t _thread;
|
||||
static void *requestCURL(void *userdata);
|
||||
#endif
|
||||
static size_t writeDataCURL(void *buffer, size_t size, size_t nmemb, void *userdata);
|
||||
static size_t writeHeaderCURL(void *buffer, size_t size, size_t nmemb, void *userdata);
|
||||
static int progressCURL(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow);
|
||||
};
|
||||
|
||||
NS_CC_EXTRA_END
|
||||
|
||||
#endif /* __CC_HTTP_REQUEST_H_ */
|
||||
45
cocos2d-x/tools/simulator/libsimulator/lib/network/CCHTTPRequestDelegate.h
Executable file
45
cocos2d-x/tools/simulator/libsimulator/lib/network/CCHTTPRequestDelegate.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __CC_EXTENSION_CCHTTP_REQUEST_DELEGATE_H_
|
||||
#define __CC_EXTENSION_CCHTTP_REQUEST_DELEGATE_H_
|
||||
|
||||
#include "cocos2dx_extra.h"
|
||||
|
||||
NS_CC_EXTRA_BEGIN
|
||||
|
||||
class HTTPRequest;
|
||||
|
||||
class HTTPRequestDelegate
|
||||
{
|
||||
public:
|
||||
virtual void requestFinished(HTTPRequest* request) {}
|
||||
virtual void requestFailed(HTTPRequest* request) {}
|
||||
};
|
||||
|
||||
NS_CC_EXTRA_END
|
||||
|
||||
#endif // __CC_EXTENSION_CCHTTP_REQUEST_DELEGATE_H_
|
||||
95
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/DeviceEx-mac.mm
Executable file
95
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/DeviceEx-mac.mm
Executable file
@@ -0,0 +1,95 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "DeviceEx.h"
|
||||
|
||||
#import "openudid/OpenUDIDMac.h"
|
||||
|
||||
using namespace std;
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
DeviceEx *DeviceEx::getInstance()
|
||||
{
|
||||
static DeviceEx *instance = NULL;
|
||||
if (!instance)
|
||||
{
|
||||
instance = new DeviceEx();
|
||||
instance->init();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::string DeviceEx::getCurrentUILangName()
|
||||
{
|
||||
return _uiLangName;
|
||||
}
|
||||
|
||||
std::string DeviceEx::getUserGUID()
|
||||
{
|
||||
return _userGUID;
|
||||
}
|
||||
|
||||
|
||||
////////// private //////////
|
||||
|
||||
DeviceEx::DeviceEx()
|
||||
: _uiLangName("en")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeviceEx::init()
|
||||
{
|
||||
makeUILangName();
|
||||
makeUserGUID();
|
||||
}
|
||||
|
||||
void DeviceEx::makeUILangName()
|
||||
{
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *languages = [defs objectForKey:@"AppleLanguages"];
|
||||
if ([languages count] > 0)
|
||||
{
|
||||
NSString *lang = [languages objectAtIndex:0];
|
||||
_uiLangName = lang.UTF8String;
|
||||
}
|
||||
}
|
||||
|
||||
std::string DeviceEx::makeUserGUID()
|
||||
{
|
||||
if (_userGUID.length() <= 0)
|
||||
{
|
||||
_userGUID = string([[OpenUDIDMac value] cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
|
||||
if (_userGUID.length() <= 0)
|
||||
{
|
||||
_userGUID = "guid-fixed-1234567890";
|
||||
}
|
||||
}
|
||||
|
||||
return _userGUID;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
//
|
||||
// EditBoxServiceMac.h
|
||||
// player
|
||||
//
|
||||
|
||||
#ifndef __player__EditBoxServiceMac__
|
||||
#define __player__EditBoxServiceMac__
|
||||
|
||||
#include "PlayerEditBoxServiceProtocol.h"
|
||||
|
||||
|
||||
@interface EditBoxServiceImplMac : NSObject <NSTextFieldDelegate>
|
||||
{
|
||||
NSTextField* textField_;
|
||||
void* editBox_;
|
||||
BOOL editState_;
|
||||
NSMutableDictionary* placeholderAttributes_;
|
||||
}
|
||||
|
||||
@property(nonatomic, retain) NSTextField* textField;
|
||||
@property(nonatomic, retain) NSMutableDictionary* placeholderAttributes;
|
||||
@property(nonatomic, readonly, getter = isEditState) BOOL editState;
|
||||
@property(nonatomic, assign) void* editBox;
|
||||
|
||||
-(id) initWithFrame: (NSRect) frameRect editBox: (void*) editBox;
|
||||
-(void) doAnimationWhenKeyboardMoveWithDuration:(float)duration distance:(float)distance;
|
||||
-(void) setPosition:(NSPoint) pos;
|
||||
-(void) setContentSize:(NSSize) size;
|
||||
-(void) visit;
|
||||
-(void) openKeyboard;
|
||||
-(void) closeKeyboard;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
class PlayerEditBoxServiceMac : public PlayerEditBoxServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerEditBoxServiceMac();
|
||||
virtual ~PlayerEditBoxServiceMac();
|
||||
|
||||
// overwrite
|
||||
virtual void showSingleLineEditBox(const cocos2d::Rect &rect) ;
|
||||
virtual void showMultiLineEditBox(const cocos2d::Rect &rect) ;
|
||||
virtual void hide() ;
|
||||
|
||||
virtual void setText(const std::string &text);
|
||||
virtual void setFont(const std::string &name, int size);
|
||||
virtual void setFontColor(const cocos2d::Color3B &color);
|
||||
|
||||
virtual void setFormator(int formator);
|
||||
private:
|
||||
void show();
|
||||
|
||||
private:
|
||||
EditBoxServiceImplMac* _sysEdit;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,256 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerEditBoxServiceMac.h"
|
||||
|
||||
#include "cocos2d.h"
|
||||
#if (CC_LUA_ENGINE_ENABLED > 0)
|
||||
#include "CCLuaEngine.h"
|
||||
#endif
|
||||
#include "glfw3native.h"
|
||||
|
||||
// internal
|
||||
|
||||
@implementation EditBoxServiceImplMac
|
||||
|
||||
@synthesize textField = textField_;
|
||||
@synthesize placeholderAttributes = placeholderAttributes_;
|
||||
@synthesize editState = editState_;
|
||||
@synthesize editBox = editBox_;
|
||||
|
||||
- (id) getNSWindow
|
||||
{
|
||||
// auto glview = cocos2d::Director::getInstance()->getOpenGLView();
|
||||
// return glview->getCocoaWindow();
|
||||
CCLOG("- (id) getNSWindow");
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
[textField_ removeFromSuperview];
|
||||
[textField_ release];
|
||||
|
||||
[placeholderAttributes_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(id) initWithFrame: (NSRect) frameRect editBox: (void*) editBox
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
editState_ = NO;
|
||||
self.textField = [[[NSTextField alloc] initWithFrame:frameRect] autorelease];
|
||||
|
||||
NSColor *newColor = [NSColor colorWithCalibratedRed:255 / 255.0f green:0 blue:0 alpha:1.0f];
|
||||
self.textField.textColor = newColor;
|
||||
|
||||
NSFont *font = [NSFont systemFontOfSize:10]; //REFINE: need to delete hard code here.
|
||||
textField_.font = font;
|
||||
|
||||
[self setupTextField:textField_];
|
||||
|
||||
self.editBox = editBox;
|
||||
self.placeholderAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
font, NSFontAttributeName,
|
||||
[NSColor grayColor], NSForegroundColorAttributeName,
|
||||
nil];
|
||||
|
||||
[[[self getNSWindow] contentView] addSubview:textField_];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(onTextDidChanged:)
|
||||
name:NSControlTextDidEndEditingNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)onTextDidChanged:(NSNotification *) notification
|
||||
{
|
||||
// hide first
|
||||
[self.textField setHidden:YES];
|
||||
|
||||
#if (CC_LUA_ENGINE_ENABLED > 0)
|
||||
player::PlayerEditBoxServiceMac *macEditBox = static_cast<player::PlayerEditBoxServiceMac *>(self.editBox);
|
||||
auto luaStack = cocos2d::LuaEngine::getInstance()->getLuaStack();
|
||||
|
||||
luaStack->pushString([self.textField.stringValue UTF8String]);
|
||||
luaStack->executeFunctionByHandler(macEditBox->getHandler(), 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setupTextField:(NSTextField *)textField
|
||||
{
|
||||
[textField setTextColor:[NSColor whiteColor]];
|
||||
[textField setBackgroundColor:[NSColor clearColor]];
|
||||
[textField setBordered:NO];
|
||||
[textField setHidden:NO];
|
||||
[textField setWantsLayer:YES];
|
||||
[textField setDelegate:self];
|
||||
}
|
||||
|
||||
-(void) doAnimationWhenKeyboardMoveWithDuration:(float)duration distance:(float)distance
|
||||
{
|
||||
[[[self getNSWindow] contentView] doAnimationWhenKeyboardMoveWithDuration:duration distance:distance];
|
||||
}
|
||||
|
||||
-(void) setPosition:(NSPoint) pos
|
||||
{
|
||||
NSRect frame = [textField_ frame];
|
||||
frame.origin = pos;
|
||||
[textField_ setFrame:frame];
|
||||
}
|
||||
|
||||
-(void) setContentSize:(NSSize) size
|
||||
{
|
||||
[self.textField setFrameSize:size];
|
||||
}
|
||||
|
||||
-(void) visit
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
-(void) openKeyboard
|
||||
{
|
||||
if ([textField_ superview]) {
|
||||
[textField_ becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) closeKeyboard
|
||||
{
|
||||
if ([textField_ superview]) {
|
||||
[textField_ resignFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(NSTextField *)sender
|
||||
{
|
||||
if (sender == textField_) {
|
||||
[sender resignFirstResponder];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void)animationSelector
|
||||
{
|
||||
}
|
||||
|
||||
- (BOOL) control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
PLAYER_NS_BEGIN;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PlayerEditBoxServiceMac::PlayerEditBoxServiceMac()
|
||||
{
|
||||
_handler = 0;
|
||||
NSRect rect = NSMakeRect(0, 0, 100, 20);
|
||||
_sysEdit = [[EditBoxServiceImplMac alloc] initWithFrame:rect editBox:this];
|
||||
}
|
||||
|
||||
PlayerEditBoxServiceMac::~PlayerEditBoxServiceMac()
|
||||
{
|
||||
[_sysEdit release];
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::showSingleLineEditBox(const cocos2d::Rect &rect)
|
||||
{
|
||||
[[_sysEdit.textField cell] setLineBreakMode:NSLineBreakByTruncatingTail];
|
||||
[[_sysEdit.textField cell] setTruncatesLastVisibleLine:YES];
|
||||
|
||||
[_sysEdit setPosition:NSMakePoint(rect.origin.x, rect.origin.y)];
|
||||
[_sysEdit setContentSize:NSMakeSize(rect.size.width, rect.size.height)];
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::showMultiLineEditBox(const cocos2d::Rect &rect)
|
||||
{
|
||||
[[_sysEdit.textField cell] setLineBreakMode:NSLineBreakByCharWrapping];
|
||||
[[_sysEdit.textField cell] setTruncatesLastVisibleLine:NO];
|
||||
|
||||
[_sysEdit setPosition:NSMakePoint(rect.origin.x, rect.origin.y)];
|
||||
[_sysEdit setContentSize:NSMakeSize(rect.size.width, rect.size.height)];
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::setText(const std::string &text)
|
||||
{
|
||||
_sysEdit.textField.stringValue = [NSString stringWithUTF8String:text.c_str()];
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::setFont(const std::string &name, int size)
|
||||
{
|
||||
NSString *fntName = [NSString stringWithUTF8String:name.c_str()];
|
||||
NSFont *textFont = [NSFont fontWithName:fntName size:size];
|
||||
if (textFont != nil)
|
||||
{
|
||||
[_sysEdit.textField setFont:textFont];
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::setFontColor(const cocos2d::Color3B &color)
|
||||
{
|
||||
NSColor *textColor = [NSColor colorWithCalibratedRed:color.r / 255.0f green:color.g / 255.0f blue:color.b / 255.0f alpha:1.0f];
|
||||
_sysEdit.textField.textColor = textColor;
|
||||
}
|
||||
|
||||
// hide editbox
|
||||
void PlayerEditBoxServiceMac::hide()
|
||||
{
|
||||
[_sysEdit.textField setHidden:YES];
|
||||
[_sysEdit closeKeyboard];
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::show()
|
||||
{
|
||||
[_sysEdit.textField setHidden:NO];
|
||||
[_sysEdit openKeyboard];
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceMac::setFormator(int formator)
|
||||
{
|
||||
CCLOG("Not support yet.");
|
||||
}
|
||||
|
||||
PLAYER_NS_END;
|
||||
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __PLAY_FILE_DIALOG_SERVICE_MAC_H
|
||||
#define __PLAY_FILE_DIALOG_SERVICE_MAC_H
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerFileDialogServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerFileDialogServiceMac : public PlayerFileDialogServiceProtocol
|
||||
{
|
||||
public:
|
||||
virtual std::string openFile(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const;
|
||||
|
||||
virtual std::vector<std::string> openMultiple(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const;
|
||||
|
||||
virtual std::string saveFile(const std::string &title,
|
||||
const std::string &path) const;
|
||||
|
||||
virtual std::string openDirectory(const std::string &title,
|
||||
const std::string &directory)const;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAY_FILE_DIALOG_SERVICE_MAC_H
|
||||
@@ -0,0 +1,199 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerFileDialogServiceMac.h"
|
||||
|
||||
#include "glfw3.h"
|
||||
#include "glfw3native.h"
|
||||
|
||||
#define VALIDATE_FRAMEBUFFER { \
|
||||
NSOpenGLContext *__context = glfwGetNSGLContext(glfwGetCurrentContext()); \
|
||||
[__context makeCurrentContext]; \
|
||||
}
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
std::string PlayerFileDialogServiceMac::openFile(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const
|
||||
{
|
||||
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
|
||||
[openDlg setTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[openDlg setCanChooseDirectories:NO];
|
||||
[openDlg setCanChooseFiles:YES];
|
||||
[openDlg setCanHide:YES];
|
||||
[openDlg setCanCreateDirectories:NO];
|
||||
[openDlg setCanSelectHiddenExtension:NO];
|
||||
[openDlg setAllowsMultipleSelection:NO];
|
||||
|
||||
if (directory.length()) {
|
||||
[openDlg setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory.c_str()]]];
|
||||
}
|
||||
|
||||
if (extensions.length())
|
||||
{
|
||||
NSMutableArray *fileTypes = [NSMutableArray array];
|
||||
|
||||
NSString *buff = [NSString stringWithUTF8String:extensions.c_str()];
|
||||
NSArray *extensionArray = [buff componentsSeparatedByString:@";"];
|
||||
|
||||
for (NSString *oneExtension in extensionArray) {
|
||||
NSArray *tmpData = [oneExtension componentsSeparatedByString:@"|"];
|
||||
if ([tmpData count] > 1)
|
||||
{
|
||||
NSString *suffixString = [tmpData objectAtIndex:1];
|
||||
suffixString = [suffixString stringByReplacingOccurrencesOfString:@"*." withString:@""];
|
||||
[fileTypes addObjectsFromArray:[suffixString componentsSeparatedByString:@","]];
|
||||
}
|
||||
}
|
||||
|
||||
[openDlg setAllowedFileTypes:fileTypes];
|
||||
}
|
||||
|
||||
std::string filePath;
|
||||
if ([openDlg runModal] == NSFileHandlingPanelOKButton)
|
||||
{
|
||||
NSURL *url = [openDlg.URLs objectAtIndex:0];
|
||||
filePath = [[url path] UTF8String];
|
||||
}
|
||||
|
||||
[openDlg close];
|
||||
VALIDATE_FRAMEBUFFER
|
||||
return filePath;
|
||||
}
|
||||
|
||||
std::string PlayerFileDialogServiceMac::openDirectory( const std::string &title,
|
||||
const std::string &directory) const
|
||||
{
|
||||
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
|
||||
[openDlg setTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[openDlg setCanChooseDirectories:YES];
|
||||
[openDlg setCanChooseFiles:NO];
|
||||
[openDlg setCanHide:YES];
|
||||
[openDlg setCanCreateDirectories:NO];
|
||||
[openDlg setCanSelectHiddenExtension:NO];
|
||||
[openDlg setAllowsMultipleSelection:NO];
|
||||
|
||||
if (directory.length()) {
|
||||
[openDlg setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory.c_str()]]];
|
||||
}
|
||||
|
||||
std::string path;
|
||||
if ([openDlg runModal] == NSFileHandlingPanelOKButton)
|
||||
{
|
||||
NSURL *url = [openDlg.URLs objectAtIndex:0];
|
||||
path = [[url path] UTF8String];
|
||||
}
|
||||
|
||||
[openDlg close];
|
||||
VALIDATE_FRAMEBUFFER
|
||||
return path;
|
||||
}
|
||||
|
||||
std::vector<std::string> PlayerFileDialogServiceMac::openMultiple( const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const
|
||||
{
|
||||
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
|
||||
[openDlg setTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[openDlg setCanChooseDirectories:YES];
|
||||
[openDlg setCanChooseFiles:YES];
|
||||
[openDlg setCanHide:YES];
|
||||
[openDlg setCanCreateDirectories:NO];
|
||||
[openDlg setCanSelectHiddenExtension:NO];
|
||||
[openDlg setAllowsMultipleSelection:YES];
|
||||
|
||||
if (directory.length()) {
|
||||
[openDlg setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory.c_str()]]];
|
||||
}
|
||||
|
||||
if (extensions.length())
|
||||
{
|
||||
NSMutableArray *fileTypes = [NSMutableArray array];
|
||||
|
||||
NSString *buff = [NSString stringWithUTF8String:extensions.c_str()];
|
||||
NSArray *extensionArray = [buff componentsSeparatedByString:@";"];
|
||||
|
||||
for (NSString *oneExtension in extensionArray) {
|
||||
NSArray *tmpData = [oneExtension componentsSeparatedByString:@"|"];
|
||||
if ([tmpData count] > 1)
|
||||
{
|
||||
NSString *suffixString = [tmpData objectAtIndex:1];
|
||||
suffixString = [suffixString stringByReplacingOccurrencesOfString:@"*." withString:@""];
|
||||
[fileTypes addObjectsFromArray:[suffixString componentsSeparatedByString:@","]];
|
||||
}
|
||||
}
|
||||
|
||||
[openDlg setAllowedFileTypes:fileTypes];
|
||||
}
|
||||
|
||||
std::vector<std::string> pathes;
|
||||
if ([openDlg runModal] == NSFileHandlingPanelOKButton)
|
||||
{
|
||||
for (NSURL *url in openDlg.URLs) {
|
||||
pathes.push_back([[url path] UTF8String]);
|
||||
}
|
||||
}
|
||||
|
||||
[openDlg close];
|
||||
VALIDATE_FRAMEBUFFER
|
||||
return pathes;
|
||||
}
|
||||
|
||||
std::string PlayerFileDialogServiceMac::saveFile(const std::string &title,
|
||||
const std::string &path) const
|
||||
{
|
||||
NSSavePanel* saveDlg = [NSSavePanel savePanel];
|
||||
[saveDlg setTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[saveDlg setCanHide:YES];
|
||||
[saveDlg setCanCreateDirectories:NO];
|
||||
[saveDlg setCanSelectHiddenExtension:NO];
|
||||
|
||||
|
||||
// set directory
|
||||
NSString *tempPath = [NSString stringWithUTF8String:path.c_str()];
|
||||
NSString *directory = [tempPath stringByDeletingLastPathComponent];
|
||||
if (directory)
|
||||
{
|
||||
[saveDlg setDirectoryURL:[NSURL fileURLWithPath:directory]];
|
||||
}
|
||||
|
||||
// set filename
|
||||
[saveDlg setNameFieldStringValue:[tempPath lastPathComponent]];
|
||||
|
||||
std::string filePath;
|
||||
if ([saveDlg runModal] == NSFileHandlingPanelOKButton)
|
||||
{
|
||||
NSURL *url = saveDlg.URL;
|
||||
filePath = [[url path] UTF8String];
|
||||
}
|
||||
|
||||
[saveDlg close];
|
||||
VALIDATE_FRAMEBUFFER
|
||||
return filePath;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
68
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMac.h
Executable file
68
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMac.h
Executable file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MAC_H_
|
||||
#define __PLAYER_MAC_H_
|
||||
|
||||
#include "PlayerProtocol.h"
|
||||
|
||||
//#include "PlayerEditBoxServiceMac.h"
|
||||
#include "PlayerFileDialogServiceMac.h"
|
||||
#include "PlayerMenuServiceMac.h"
|
||||
#include "PlayerMessageBoxServiceMac.h"
|
||||
#include "PlayerTaskServiceMac.h"
|
||||
|
||||
#include "PlayerUtils.h"
|
||||
|
||||
#include "ProjectConfig/ProjectConfig.h"
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerMac : public PlayerProtocol
|
||||
{
|
||||
public:
|
||||
static PlayerMac *create();
|
||||
virtual ~PlayerMac();
|
||||
|
||||
virtual PlayerFileDialogServiceProtocol *getFileDialogService();
|
||||
virtual PlayerMessageBoxServiceProtocol *getMessageBoxService();
|
||||
virtual PlayerMenuServiceProtocol *getMenuService();
|
||||
// virtual PlayerEditBoxServiceProtocol *getEditBoxService();
|
||||
virtual PlayerTaskServiceProtocol *getTaskService();
|
||||
|
||||
protected:
|
||||
PlayerMac();
|
||||
|
||||
PlayerMenuServiceMac *_menuService;
|
||||
PlayerMessageBoxServiceMac *_messageBoxService;
|
||||
PlayerFileDialogServiceMac *_fileDialogService;
|
||||
// PlayerEditBoxServiceMac *_editBoxService;
|
||||
PlayerTaskServiceMac *_taskService;
|
||||
id _appController;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MAC_H_
|
||||
107
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMac.mm
Executable file
107
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMac.mm
Executable file
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerMac.h"
|
||||
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
using namespace cocos2d;
|
||||
|
||||
PlayerMac* PlayerMac::create()
|
||||
{
|
||||
return new PlayerMac();
|
||||
}
|
||||
|
||||
|
||||
PlayerMac::PlayerMac()
|
||||
: PlayerProtocol()
|
||||
, _fileDialogService(nullptr)
|
||||
, _messageBoxService(nullptr)
|
||||
, _menuService(nullptr)
|
||||
//, _editBoxService(nullptr)
|
||||
, _appController(nullptr)
|
||||
, _taskService(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PlayerMac::~PlayerMac()
|
||||
{
|
||||
CC_SAFE_DELETE(_fileDialogService);
|
||||
CC_SAFE_DELETE(_fileDialogService);
|
||||
CC_SAFE_DELETE(_messageBoxService);
|
||||
CC_SAFE_DELETE(_menuService);
|
||||
// CC_SAFE_DELETE(_editBoxService);
|
||||
CC_SAFE_DELETE(_taskService);
|
||||
}
|
||||
|
||||
PlayerFileDialogServiceProtocol *PlayerMac::getFileDialogService()
|
||||
{
|
||||
if (!_fileDialogService)
|
||||
{
|
||||
_fileDialogService = new PlayerFileDialogServiceMac();
|
||||
}
|
||||
return _fileDialogService;
|
||||
}
|
||||
|
||||
PlayerMessageBoxServiceProtocol *PlayerMac::getMessageBoxService()
|
||||
{
|
||||
if (!_messageBoxService)
|
||||
{
|
||||
_messageBoxService = new PlayerMessageBoxServiceMac();
|
||||
}
|
||||
return _messageBoxService;
|
||||
}
|
||||
|
||||
PlayerMenuServiceProtocol *PlayerMac::getMenuService()
|
||||
{
|
||||
if (!_menuService)
|
||||
{
|
||||
_menuService = new PlayerMenuServiceMac();
|
||||
}
|
||||
return _menuService;
|
||||
}
|
||||
|
||||
//PlayerEditBoxServiceProtocol *PlayerMac::getEditBoxService()
|
||||
//{
|
||||
// if (!_editBoxService)
|
||||
// {
|
||||
// _editBoxService = new PlayerEditBoxServiceMac();
|
||||
// }
|
||||
// return _editBoxService;
|
||||
//}
|
||||
|
||||
PlayerTaskServiceProtocol *PlayerMac::getTaskService()
|
||||
{
|
||||
if (!_taskService)
|
||||
{
|
||||
_taskService = new PlayerTaskServiceMac();
|
||||
}
|
||||
return _taskService;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
107
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMenuServiceMac.h
Executable file
107
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMenuServiceMac.h
Executable file
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MENU_SERVICE_MAC_H_
|
||||
#define __PLAYER_MENU_SERVICE_MAC_H_
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerMenuServiceProtocol.h"
|
||||
|
||||
//
|
||||
// Menu item Helper
|
||||
//
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
class PlayerMenuItemMac;
|
||||
PLAYER_NS_END
|
||||
|
||||
@interface NNMenuItem : NSMenuItem <NSMenuDelegate>
|
||||
{
|
||||
int scriptHandler;
|
||||
player::PlayerMenuItemMac *macMenuItem;
|
||||
}
|
||||
@property (nonatomic) int scriptHandler;
|
||||
@property (nonatomic) const player::PlayerMenuItemMac *macMenuItem;
|
||||
|
||||
+(id) createMenuItem:(const player::PlayerMenuItemMac *) macMenuItem;
|
||||
@end
|
||||
|
||||
|
||||
//
|
||||
// PlayerMenuItemMac
|
||||
//
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerMenuItemMac : public PlayerMenuItem
|
||||
{
|
||||
public:
|
||||
static PlayerMenuItemMac *create(const std::string &menuId, const std::string &title);
|
||||
virtual ~PlayerMenuItemMac();
|
||||
|
||||
virtual void setTitle(const std::string &title);
|
||||
virtual void setEnabled(bool enabled);
|
||||
virtual void setChecked(bool checked);
|
||||
virtual void setShortcut(const std::string &shortcut);
|
||||
|
||||
protected:
|
||||
PlayerMenuItemMac();
|
||||
|
||||
PlayerMenuItemMac *_parent;
|
||||
NNMenuItem *_menuItem;
|
||||
NSMenu *_menu;
|
||||
cocos2d::Vector<PlayerMenuItemMac*> _children;
|
||||
|
||||
friend class PlayerMenuServiceMac;
|
||||
};
|
||||
|
||||
class PlayerMenuServiceMac : public PlayerMenuServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerMenuServiceMac();
|
||||
virtual ~PlayerMenuServiceMac();
|
||||
|
||||
virtual PlayerMenuItem *addItem(const std::string &menuId, const std::string &title, const std::string &parentId, int order = MAX_ORDER);
|
||||
virtual PlayerMenuItem *addItem(const std::string &menuId, const std::string &title);
|
||||
virtual PlayerMenuItem *getItem(const std::string &menuId);
|
||||
virtual bool removeItem(const std::string &menuId);
|
||||
virtual void setMenuBarEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
bool removeItemInternal(const std::string &menuId, bool isUpdateChildrenOrder);
|
||||
void updateChildrenOrder(PlayerMenuItemMac *parent);
|
||||
|
||||
private:
|
||||
PlayerMenuItemMac _root;
|
||||
std::unordered_map<std::string, PlayerMenuItemMac*> _items;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MENU_SERVICE_MAC_H_
|
||||
393
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMenuServiceMac.mm
Executable file
393
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerMenuServiceMac.mm
Executable file
@@ -0,0 +1,393 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerMenuServiceMac.h"
|
||||
#include "PlayerUtils.h"
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "AppEvent.h"
|
||||
|
||||
/////////////////////////////////////// menu helper //////////////////////////////////////////////
|
||||
static bool __G_IS_MENUBAR_ENABLED__ = true; // WTF
|
||||
|
||||
@implementation NNMenuItem
|
||||
@synthesize scriptHandler;
|
||||
@synthesize macMenuItem;
|
||||
|
||||
+(id) createMenuItem:(const player::PlayerMenuItemMac *) macMenuItem
|
||||
{
|
||||
if (macMenuItem->getTitle().compare("-") == 0)
|
||||
{
|
||||
return [NSMenuItem separatorItem];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [[[NNMenuItem alloc] initWithMenuItem:macMenuItem] autorelease];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-(id) initWithMenuItem:(const player::PlayerMenuItemMac *) menuItem
|
||||
{
|
||||
NSString *title = [NSString stringWithUTF8String:menuItem->getTitle().c_str()];
|
||||
title = [title stringByReplacingOccurrencesOfString:@"&" withString:@""];
|
||||
if ([super initWithTitle:title action:@selector(onClicked:) keyEquivalent:@""])
|
||||
{
|
||||
self.target = self;
|
||||
}
|
||||
|
||||
self.macMenuItem = menuItem;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) setShortcut:(std::string) shortcut
|
||||
{
|
||||
std::vector <std::string> fields = player::splitString(shortcut, std::string("+"));
|
||||
|
||||
NSUInteger mask = [self keyEquivalentModifierMask];
|
||||
for (auto cut : fields)
|
||||
{
|
||||
if (cut == kPlayerSuperModifyKey)
|
||||
{
|
||||
mask |= NSCommandKeyMask;
|
||||
}
|
||||
else if (cut == kPlayerShiftModifyKey)
|
||||
{
|
||||
mask |= NSShiftKeyMask;
|
||||
}
|
||||
else if (cut == kPlayerCtrlModifyKey)
|
||||
{
|
||||
mask |= NSControlKeyMask;
|
||||
}
|
||||
else if (cut == kPlayerAltModifyKey)
|
||||
{
|
||||
mask |= NSAlternateKeyMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cut.length() == 1)
|
||||
{
|
||||
[self setKeyEquivalent:[NSString stringWithUTF8String:cut.c_str()]];
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("[modifyItem] shortcut (%s) is invalid.", shortcut.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mask != 0)
|
||||
{
|
||||
[self setKeyEquivalentModifierMask:mask];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) onClicked:(id)sender
|
||||
{
|
||||
AppEvent event(kAppEventName, APP_EVENT_MENU);
|
||||
|
||||
std::stringstream buf;
|
||||
buf << "{\"data\":\"" << self.macMenuItem->getMenuId().c_str() << "\"";
|
||||
buf << ",\"name\":" << "\"menuClicked\"" << "}";
|
||||
event.setDataString(buf.str());
|
||||
event.args[0].ptrVal = (void*)self.macMenuItem;
|
||||
cocos2d::EventDispatcher::dispatchCustomEvent(event);
|
||||
}
|
||||
|
||||
-(BOOL) validateMenuItem:(NSMenuItem *)menuItem
|
||||
{
|
||||
return __G_IS_MENUBAR_ENABLED__;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
//
|
||||
|
||||
PlayerMenuItemMac *PlayerMenuItemMac::create(const std::string &menuId, const std::string &title)
|
||||
{
|
||||
PlayerMenuItemMac *item = new PlayerMenuItemMac();
|
||||
item->_menuId = menuId;
|
||||
item->_title = title;
|
||||
item->autorelease();
|
||||
return item;
|
||||
}
|
||||
|
||||
PlayerMenuItemMac::PlayerMenuItemMac()
|
||||
: _parent(nullptr)
|
||||
, _menuItem(nullptr)
|
||||
, _menu(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PlayerMenuItemMac::~PlayerMenuItemMac()
|
||||
{
|
||||
CC_SAFE_RELEASE(_parent);
|
||||
if (_menuItem)
|
||||
{
|
||||
[_parent->_menu removeItem:_menuItem];
|
||||
}
|
||||
|
||||
CCLOG("PlayerMenuItemWin::~PlayerMenuItemWin() - %s", _menuId.c_str());
|
||||
}
|
||||
|
||||
void PlayerMenuItemMac::setTitle(const std::string &title)
|
||||
{
|
||||
if (title.length() == 0)
|
||||
{
|
||||
CCLOG("MenuServiceWin::setTitle() - can not set menu title to empty, menu id (%s)", _menuId.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
_menuItem.title = [NSString stringWithUTF8String:title.c_str()];
|
||||
if (_menu)
|
||||
{
|
||||
_menu.title = _menuItem.title;
|
||||
}
|
||||
|
||||
_title = title;
|
||||
}
|
||||
|
||||
void PlayerMenuItemMac::setEnabled(bool enabled)
|
||||
{
|
||||
_isEnabled = enabled;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
[_menuItem setAction:@selector(onClicked:)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_menuItem setAction:nil];
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMenuItemMac::setChecked(bool checked)
|
||||
{
|
||||
_isChecked = checked;
|
||||
[_menuItem setState:checked ? NSOnState : NSOffState];
|
||||
}
|
||||
|
||||
void PlayerMenuItemMac::setShortcut(const std::string &shortcut)
|
||||
{
|
||||
_shortcut = shortcut;
|
||||
[_menuItem setShortcut:shortcut];
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PlayerMenuServiceMac::PlayerMenuServiceMac()
|
||||
{
|
||||
// @REFINE: build menu with **EDIT** menu
|
||||
|
||||
NSApplication *thisApp = [NSApplication sharedApplication];
|
||||
_root._menu = [thisApp mainMenu];
|
||||
}
|
||||
|
||||
PlayerMenuServiceMac::~PlayerMenuServiceMac()
|
||||
{
|
||||
cocos2d::log("~PlayerMenuServiceMac");
|
||||
_items.clear();
|
||||
}
|
||||
|
||||
PlayerMenuItem* PlayerMenuServiceMac::addItem(const std::string &menuId, const std::string &title,
|
||||
const std::string &parentId, int order)
|
||||
{
|
||||
if (menuId.length() == 0 || title.length() == 0)
|
||||
{
|
||||
CCLOG("PlayerMenuServiceMac::addItem() - menuId and title must is non-empty");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check menu id is exists
|
||||
if (_items.find(menuId) != _items.end())
|
||||
{
|
||||
CCLOG("PlayerMenuServiceMac::addItem() - menu id (%s) is exists", menuId.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// set parent
|
||||
PlayerMenuItemMac *parent = &_root;
|
||||
if (parentId.length())
|
||||
{
|
||||
// query parent menu
|
||||
auto it = _items.find(parentId);
|
||||
if (it != _items.end())
|
||||
{
|
||||
parent = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parent->_menu)
|
||||
{
|
||||
NSMenu *nsmenu = [[NSMenu alloc] initWithTitle:[parent->_menuItem title]];
|
||||
[parent->_parent->_menu setSubmenu:nsmenu forItem:parent->_menuItem];
|
||||
parent->_menu = nsmenu;
|
||||
parent->_isGroup = true;
|
||||
}
|
||||
|
||||
|
||||
// create new menu item
|
||||
PlayerMenuItemMac *item = PlayerMenuItemMac::create(menuId, title);
|
||||
item->_parent = parent;
|
||||
item->_parent->retain();
|
||||
|
||||
// check new menu item position
|
||||
int childSize = (int) [parent->_menu itemArray].count;
|
||||
childSize = (int) parent->_children.size();
|
||||
if (order > childSize)
|
||||
{
|
||||
order = childSize;
|
||||
}
|
||||
else if (order < 0)
|
||||
{
|
||||
order = 0;
|
||||
}
|
||||
|
||||
|
||||
// add menu item to menu bar
|
||||
int newIndex = order;
|
||||
if (parent == &_root)
|
||||
{
|
||||
newIndex += 1;
|
||||
}
|
||||
NNMenuItem *newItem = [NNMenuItem createMenuItem:item];
|
||||
[parent->_menu insertItem:newItem atIndex:newIndex];
|
||||
item->_menuItem = newItem;
|
||||
|
||||
|
||||
// update menu state
|
||||
parent->_children.insert(order, item);
|
||||
_items[item->_menuId] = item;
|
||||
updateChildrenOrder(parent);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
PlayerMenuItem* PlayerMenuServiceMac::addItem(const std::string &menuId, const std::string &title)
|
||||
{
|
||||
return addItem(menuId, title, "");
|
||||
}
|
||||
|
||||
PlayerMenuItem* PlayerMenuServiceMac::getItem(const std::string &menuId)
|
||||
{
|
||||
auto it = _items.find(menuId);
|
||||
if (it == _items.end())
|
||||
{
|
||||
CCLOG("MenuServiceWin::getItem() - Invalid menu id (%s)", menuId.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool PlayerMenuServiceMac::removeItem(const std::string &menuId)
|
||||
{
|
||||
return removeItemInternal(menuId, true);;
|
||||
}
|
||||
|
||||
void PlayerMenuServiceMac::setMenuBarEnabled(bool enabled)
|
||||
{
|
||||
__G_IS_MENUBAR_ENABLED__ = enabled;
|
||||
}
|
||||
|
||||
#pragma mark - private -
|
||||
|
||||
bool PlayerMenuServiceMac::removeItemInternal(const std::string &menuId, bool isUpdateChildrenOrder)
|
||||
{
|
||||
auto it = _items.find(menuId);
|
||||
if (it == _items.end())
|
||||
{
|
||||
CCLOG("MenuServiceWin::removeItem() - Invalid menu id (%s)", menuId.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
PlayerMenuItemMac *item = it->second;
|
||||
if (item->_children.size() == 0)
|
||||
{
|
||||
// remove item from parent
|
||||
bool removed = false;
|
||||
auto *theChildren = &item->_parent->_children;
|
||||
for (auto it = theChildren->begin(); it != theChildren->end(); ++it)
|
||||
{
|
||||
if ((*it)->_menuItem == item->_menuItem)
|
||||
{
|
||||
theChildren->erase(it);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!removed)
|
||||
{
|
||||
CCLOG("MenuServiceWin::removeItem() - remove menu item (%s) failed, not found command id from parent->children", item->_menuId.c_str());
|
||||
}
|
||||
|
||||
// remove menu id mapping
|
||||
_items.erase(menuId);
|
||||
if (isUpdateChildrenOrder)
|
||||
{
|
||||
updateChildrenOrder(item->_parent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove all children
|
||||
while (item->_children.size() != 0)
|
||||
{
|
||||
PlayerMenuItemMac *child = *item->_children.begin();
|
||||
if (!removeItemInternal(child->_menuId.c_str(), false))
|
||||
{
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return removeItemInternal(menuId, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlayerMenuServiceMac::updateChildrenOrder(PlayerMenuItemMac *parent)
|
||||
{
|
||||
auto *children = &parent->_children;
|
||||
int order = 0;
|
||||
for (auto it = children->begin(); it != children->end(); ++it)
|
||||
{
|
||||
(*it)->_order = order;
|
||||
order++;
|
||||
}
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MessageBoxServiceMac_h
|
||||
#define __PLAYER_MessageBoxServiceMac_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerMessageBoxServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerMessageBoxServiceMac : public PlayerMessageBoxServiceProtocol
|
||||
{
|
||||
public:
|
||||
virtual int showMessageBox(const std::string &title,
|
||||
const std::string &message,
|
||||
int buttonsType = BUTTONS_OK);
|
||||
protected:
|
||||
struct MessageBoxInfo
|
||||
{
|
||||
std::string title;
|
||||
const int buttonId;
|
||||
};
|
||||
std::vector<MessageBoxInfo> getTitles(int buttons);
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MessageBoxServiceMac_h
|
||||
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerMessageBoxServiceMac.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
int PlayerMessageBoxServiceMac::showMessageBox(const std::string &title,
|
||||
const std::string &message,
|
||||
int buttonsType)
|
||||
{
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
|
||||
auto titles = getTitles(buttonsType);
|
||||
for (auto& title : titles)
|
||||
{
|
||||
[alert addButtonWithTitle:[NSString stringWithUTF8String:title.title.c_str()]];
|
||||
}
|
||||
|
||||
[alert setMessageText:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[alert setInformativeText:[NSString stringWithUTF8String:message.c_str()]];
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
|
||||
int index = (int)[alert runModal] - NSAlertFirstButtonReturn;
|
||||
return titles.at(index).buttonId;
|
||||
}
|
||||
|
||||
std::vector<PlayerMessageBoxServiceMac::MessageBoxInfo> PlayerMessageBoxServiceMac::getTitles(int buttons)
|
||||
{
|
||||
std::vector<PlayerMessageBoxServiceMac::MessageBoxInfo> titles;
|
||||
|
||||
switch (buttons) {
|
||||
case BUTTONS_OK:
|
||||
titles.push_back({"OK", BUTTON_OK});
|
||||
break;
|
||||
|
||||
case BUTTONS_OK_CANCEL:
|
||||
titles.push_back({"OK", BUTTON_OK});
|
||||
titles.push_back({"Cancel", BUTTON_CANCEL});
|
||||
break;
|
||||
|
||||
case BUTTONS_YES_NO:
|
||||
titles.push_back({"Yes", BUTTON_YES});
|
||||
titles.push_back({"No", BUTTON_NO});
|
||||
break;
|
||||
|
||||
case BUTTONS_YES_NO_CANCEL:
|
||||
titles.push_back({"Yes", BUTTON_YES});
|
||||
titles.push_back({"No", BUTTON_NO});
|
||||
titles.push_back({"Cancel", BUTTON_CANCEL});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
105
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerTaskServiceMac.h
Executable file
105
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerTaskServiceMac.h
Executable file
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_TASK_SERVICE_MAC_H_
|
||||
#define __PLAYER_TASK_SERVICE_MAC_H_
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "PlayerTaskServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
class PlayerTaskMac;
|
||||
PLAYER_NS_END
|
||||
|
||||
@interface PlayerTaskPrivate : NSObject
|
||||
{
|
||||
NSFileHandle *fileHandle;
|
||||
|
||||
NSTask *_buildTask;
|
||||
BOOL _isRunning;
|
||||
int _exitCode;
|
||||
NSString *_output;
|
||||
}
|
||||
|
||||
@property (assign) NSTask *buildTask;
|
||||
@property (assign) BOOL isRunning;
|
||||
@property (assign) int exitCode;
|
||||
@property (retain) NSString *output;
|
||||
|
||||
- (void) runScriptAsyn:(NSString *)absScriptPath withArguments:(NSArray *) arguments;
|
||||
@end
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerTaskMac : public PlayerTask
|
||||
{
|
||||
public:
|
||||
static PlayerTaskMac *create(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
|
||||
virtual ~PlayerTaskMac();
|
||||
|
||||
virtual bool run();
|
||||
virtual void stop();
|
||||
virtual void runInTerminal();
|
||||
|
||||
// check task status
|
||||
virtual void update(float dt);
|
||||
|
||||
void appendOutput(const char *data);
|
||||
protected:
|
||||
PlayerTaskMac(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
|
||||
void cleanup();
|
||||
std::u16string makeCommandLine() const;
|
||||
|
||||
PlayerTaskPrivate *_taskPrivate;
|
||||
};
|
||||
|
||||
class PlayerTaskServiceMac : public PlayerTaskServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerTaskServiceMac();
|
||||
virtual ~PlayerTaskServiceMac();
|
||||
|
||||
virtual PlayerTask *createTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
virtual PlayerTask *getTask(const std::string &name);
|
||||
virtual void removeTask(const std::string &name);
|
||||
|
||||
protected:
|
||||
cocos2d::Map<std::string, PlayerTaskMac*> _tasks;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
|
||||
#endif // __PLAYER_TASK_SERVICE_MAC_H_
|
||||
271
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerTaskServiceMac.mm
Executable file
271
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/PlayerTaskServiceMac.mm
Executable file
@@ -0,0 +1,271 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerTaskServiceMac.h"
|
||||
|
||||
@implementation PlayerTaskPrivate
|
||||
|
||||
@synthesize buildTask = _buildTask;
|
||||
@synthesize isRunning = _isRunning;
|
||||
@synthesize exitCode = _exitCode;
|
||||
@synthesize output = _output;
|
||||
|
||||
-(id) init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_isRunning = NO;
|
||||
_exitCode = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) dealloc
|
||||
{
|
||||
[_output release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ...
|
||||
{
|
||||
NSMethodSignature *signature = [self methodSignatureForSelector:selector];
|
||||
|
||||
// setup the invocation
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
invocation.target = self;
|
||||
invocation.selector = selector;
|
||||
|
||||
// associate the arguments
|
||||
va_list objects;
|
||||
va_start(objects, object);
|
||||
unsigned int objectCounter = 2;
|
||||
for (id obj = object; obj != nil; obj = va_arg(objects, id))
|
||||
{
|
||||
[invocation setArgument:&obj atIndex:objectCounter++];
|
||||
}
|
||||
va_end(objects);
|
||||
|
||||
// make sure to invoke on a background queue
|
||||
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithInvocation:invocation];
|
||||
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
|
||||
[backgroundQueue addOperation:operation];
|
||||
}
|
||||
|
||||
- (void) runScriptAsyn:(NSString *)absScriptPath withArguments:(NSArray *) arguments
|
||||
{
|
||||
_isRunning = YES;
|
||||
[self performSelectorInBackground:@selector(runScriptSync:withArguments:)
|
||||
withObjects:absScriptPath, arguments, nil];
|
||||
}
|
||||
|
||||
- (void) runScriptSync:(NSString *)absScriptPath withArguments:(NSArray *)arguments
|
||||
{
|
||||
if (!absScriptPath)
|
||||
{
|
||||
CCLOG("Please check your script (%s)", absScriptPath.UTF8String);
|
||||
return ;
|
||||
}
|
||||
|
||||
_buildTask = [[NSTask alloc] init];
|
||||
[_buildTask setLaunchPath:absScriptPath];
|
||||
|
||||
if (!arguments)
|
||||
{
|
||||
arguments = [NSArray array];
|
||||
}
|
||||
[_buildTask setArguments:arguments];
|
||||
|
||||
//
|
||||
NSPipe *pipe;
|
||||
pipe = [NSPipe pipe];
|
||||
[_buildTask setStandardOutput: pipe];
|
||||
|
||||
fileHandle = [pipe fileHandleForReading];
|
||||
|
||||
//
|
||||
[_buildTask launch];
|
||||
[_buildTask waitUntilExit];
|
||||
|
||||
NSData *data;
|
||||
data = [fileHandle readDataToEndOfFile];
|
||||
|
||||
_output = [[NSString alloc] initWithData: data
|
||||
encoding: NSUTF8StringEncoding];
|
||||
_isRunning = NO;
|
||||
_exitCode = [_buildTask terminationStatus];
|
||||
|
||||
[fileHandle closeFile];
|
||||
[_buildTask release];
|
||||
_buildTask = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerTaskMac *PlayerTaskMac::create(const std::string &name, const std::string &executePath, const std::string &commandLineArguments)
|
||||
{
|
||||
PlayerTaskMac *task = new PlayerTaskMac(name, executePath, commandLineArguments);
|
||||
task->autorelease();
|
||||
return task;
|
||||
}
|
||||
|
||||
PlayerTaskMac::PlayerTaskMac(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments)
|
||||
: PlayerTask(name, executePath, commandLineArguments)
|
||||
{
|
||||
_taskPrivate = [[PlayerTaskPrivate alloc] init];
|
||||
}
|
||||
|
||||
PlayerTaskMac::~PlayerTaskMac()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
bool PlayerTaskMac::run()
|
||||
{
|
||||
if (!isIdle())
|
||||
{
|
||||
CCLOG("PlayerTaskMac::run() - task is not idle");
|
||||
return false;
|
||||
}
|
||||
|
||||
NSString *commandLine = [NSString stringWithCString:_commandLineArguments.c_str()
|
||||
encoding:NSUTF8StringEncoding];
|
||||
[_taskPrivate runScriptAsyn:[NSString stringWithUTF8String:_executePath.data()]
|
||||
withArguments:[NSMutableArray arrayWithArray:[commandLine componentsSeparatedByString:@" "]]];
|
||||
_state = STATE_RUNNING;
|
||||
|
||||
// cocos2d::Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerTaskMac::runInTerminal()
|
||||
{
|
||||
NSString *s = [NSString stringWithFormat:
|
||||
@"tell application \"Terminal\" to do script \"%s %s\"", _executePath.c_str(), _commandLineArguments.c_str()];
|
||||
|
||||
NSAppleScript *as = [[NSAppleScript alloc] initWithSource: s];
|
||||
[as executeAndReturnError:nil];
|
||||
}
|
||||
|
||||
void PlayerTaskMac::stop()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void PlayerTaskMac::update(float dt)
|
||||
{
|
||||
_lifetime += dt;
|
||||
|
||||
if (_taskPrivate.isRunning)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
// cocos2d::Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void PlayerTaskMac::appendOutput(const char *data)
|
||||
{
|
||||
_output.append(data);
|
||||
}
|
||||
|
||||
void PlayerTaskMac::cleanup()
|
||||
{
|
||||
|
||||
_state = STATE_COMPLETED;
|
||||
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:_taskPrivate];
|
||||
[_taskPrivate.buildTask interrupt];
|
||||
|
||||
_resultCode = _taskPrivate.exitCode;
|
||||
_output.append(_taskPrivate.output.UTF8String);
|
||||
|
||||
[_taskPrivate release];
|
||||
_taskPrivate = nil;
|
||||
CCLOG("\nCMD: (exit code: %d) %s", _resultCode, _output.c_str());
|
||||
|
||||
// cocos2d::Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(_name);
|
||||
}
|
||||
|
||||
std::u16string PlayerTaskMac::makeCommandLine() const
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf << "\"";
|
||||
buf << _executePath;
|
||||
buf << "\" ";
|
||||
buf << _commandLineArguments;
|
||||
|
||||
std::u16string u16command;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(buf.str(), u16command);
|
||||
return u16command;
|
||||
}
|
||||
|
||||
PlayerTaskServiceMac::PlayerTaskServiceMac()
|
||||
{
|
||||
}
|
||||
|
||||
PlayerTaskServiceMac::~PlayerTaskServiceMac()
|
||||
{
|
||||
for (auto it = _tasks.begin(); it != _tasks.end(); ++it)
|
||||
{
|
||||
it->second->stop();
|
||||
}
|
||||
}
|
||||
|
||||
PlayerTask *PlayerTaskServiceMac::createTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments)
|
||||
{
|
||||
CCASSERT(_tasks.find(name) == _tasks.end(), "Task already exists.");
|
||||
PlayerTaskMac *task = PlayerTaskMac::create(name, executePath, commandLineArguments);
|
||||
_tasks.insert(name, task);
|
||||
return task;
|
||||
}
|
||||
|
||||
PlayerTask *PlayerTaskServiceMac::getTask(const std::string &name)
|
||||
{
|
||||
auto it = _tasks.find(name);
|
||||
return it != _tasks.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
void PlayerTaskServiceMac::removeTask(const std::string &name)
|
||||
{
|
||||
auto it = _tasks.find(name);
|
||||
if (it != _tasks.end())
|
||||
{
|
||||
if (!it->second->isCompleted())
|
||||
{
|
||||
it->second->stop();
|
||||
}
|
||||
_tasks.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
71
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/Runtime_ios-mac.mm
Executable file
71
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/Runtime_ios-mac.mm
Executable file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 <ifaddrs.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ConfigParser.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
string getIPAddress()
|
||||
{
|
||||
BOOL success;
|
||||
struct ifaddrs * addrs;
|
||||
const struct ifaddrs * cursor;
|
||||
|
||||
// customized by user
|
||||
auto &bindAddress = ConfigParser::getInstance()->getBindAddress();
|
||||
if (bindAddress.length() > 0)
|
||||
{
|
||||
return bindAddress;
|
||||
}
|
||||
|
||||
success = getifaddrs(&addrs) == 0;
|
||||
if (success) {
|
||||
cursor = addrs;
|
||||
while (cursor != NULL) {
|
||||
// the second test keeps from picking up the loopback address
|
||||
if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0)
|
||||
{
|
||||
NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
|
||||
if ([name rangeOfString:@"en" options:NSCaseInsensitiveSearch].length > 0) {
|
||||
string ipaddr = [[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)]UTF8String];
|
||||
if (!ipaddr.empty()) {
|
||||
return ipaddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor = cursor->ifa_next;
|
||||
}
|
||||
freeifaddrs(addrs);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// OpenUDID.h
|
||||
// openudid
|
||||
//
|
||||
// initiated by Yann Lechelle (cofounder @Appsfire) on 8/28/11.
|
||||
// Copyright 2011 OpenUDID.org
|
||||
//
|
||||
// Main branches
|
||||
// iOS code: https://github.com/ylechelle/OpenUDID
|
||||
//
|
||||
|
||||
/*
|
||||
!!! IMPORTANT !!!
|
||||
|
||||
IF YOU ARE GOING TO INTEGRATE OpenUDID INSIDE A (STATIC) LIBRARY,
|
||||
PLEASE MAKE SURE YOU REFACTOR THE OpenUDID CLASS WITH A PREFIX OF YOUR OWN,
|
||||
E.G. ACME_OpenUDID. THIS WILL AVOID CONFUSION BY DEVELOPERS WHO ARE ALSO
|
||||
USING OpenUDID IN THEIR OWN CODE.
|
||||
|
||||
!!! IMPORTANT !!!
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
http://en.wikipedia.org/wiki/Zlib_License
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//
|
||||
// Usage:
|
||||
// #include "OpenUDID.h"
|
||||
// NSString* openUDID = [OpenUDID value];
|
||||
//
|
||||
|
||||
#define kOpenUDIDErrorNone 0
|
||||
#define kOpenUDIDErrorOptedOut 1
|
||||
#define kOpenUDIDErrorCompromised 2
|
||||
|
||||
@interface OpenUDIDMac : NSObject {
|
||||
}
|
||||
+ (NSString*) value;
|
||||
+ (NSString*) valueWithError:(NSError**)error;
|
||||
+ (void) setOptOut:(BOOL)optOutValue;
|
||||
|
||||
@end
|
||||
383
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/openudid/OpenUDIDMac.m
Executable file
383
cocos2d-x/tools/simulator/libsimulator/lib/platform/mac/openudid/OpenUDIDMac.m
Executable file
@@ -0,0 +1,383 @@
|
||||
//
|
||||
// OpenUDIDMac.m
|
||||
// openudid
|
||||
//
|
||||
// initiated by Yann Lechelle (cofounder @Appsfire) on 8/28/11.
|
||||
// Copyright 2011 OpenUDID.org
|
||||
//
|
||||
// Initiators/root branches
|
||||
// iOS code: https://github.com/ylechelle/OpenUDID
|
||||
// Android code: https://github.com/vieux/OpenUDID
|
||||
//
|
||||
// Contributors:
|
||||
// https://github.com/ylechelle/OpenUDID/contributors
|
||||
//
|
||||
|
||||
/*
|
||||
http://en.wikipedia.org/wiki/Zlib_License
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#if __has_feature(objc_arc)
|
||||
#error This file uses the classic non-ARC retain/release model; hints below...
|
||||
// to selectively compile this file as non-ARC, do as follows:
|
||||
// https://img.skitch.com/20120717-g3ag5h9a6ehkgpmpjiuen3qpwp.png
|
||||
#endif
|
||||
|
||||
#import "OpenUDIDMac.h"
|
||||
#import <CommonCrypto/CommonDigest.h> // Need to import for CC_MD5 access
|
||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
#import <UIKit/UIPasteboard.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#import <AppKit/NSPasteboard.h>
|
||||
#endif
|
||||
|
||||
#define OpenUDIDLog(fmt, ...)
|
||||
//#define OpenUDIDLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
|
||||
//#define OpenUDIDLog(fmt, ...) NSLog((@"[Line %d] " fmt), __LINE__, ##__VA_ARGS__);
|
||||
|
||||
static NSString * kOpenUDIDSessionCache = nil;
|
||||
static NSString * const kOpenUDIDKey = @"OpenUDID";
|
||||
static NSString * const kOpenUDIDSlotKey = @"OpenUDID_slot";
|
||||
static NSString * const kOpenUDIDAppUIDKey = @"OpenUDID_appUID";
|
||||
static NSString * const kOpenUDIDTSKey = @"OpenUDID_createdTS";
|
||||
static NSString * const kOpenUDIDOOTSKey = @"OpenUDID_optOutTS";
|
||||
static NSString * const kOpenUDIDDomain = @"org.OpenUDID";
|
||||
static NSString * const kOpenUDIDSlotPBPrefix = @"org.OpenUDID.slot.";
|
||||
static int const kOpenUDIDRedundancySlots = 100;
|
||||
|
||||
@interface OpenUDIDMac (Private)
|
||||
+ (void) _setDict:(id)dict forPasteboard:(id)pboard;
|
||||
+ (NSMutableDictionary*) _getDictFromPasteboard:(id)pboard;
|
||||
+ (NSString*) _generateFreshOpenUDID;
|
||||
@end
|
||||
|
||||
@implementation OpenUDIDMac
|
||||
|
||||
// Archive a NSDictionary inside a pasteboard of a given type
|
||||
// Convenience method to support iOS & Mac OS X
|
||||
//
|
||||
+ (void) _setDict:(id)dict forPasteboard:(id)pboard {
|
||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
[pboard setData:[NSKeyedArchiver archivedDataWithRootObject:dict] forPasteboardType:kOpenUDIDDomain];
|
||||
#else
|
||||
[pboard setData:[NSKeyedArchiver archivedDataWithRootObject:dict] forType:kOpenUDIDDomain];
|
||||
#endif
|
||||
}
|
||||
|
||||
// Retrieve an NSDictionary from a pasteboard of a given type
|
||||
// Convenience method to support iOS & Mac OS X
|
||||
//
|
||||
+ (NSMutableDictionary*) _getDictFromPasteboard:(id)pboard {
|
||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
id item = [pboard dataForPasteboardType:kOpenUDIDDomain];
|
||||
#else
|
||||
id item = [pboard dataForType:kOpenUDIDDomain];
|
||||
#endif
|
||||
if (item) {
|
||||
@try{
|
||||
item = [NSKeyedUnarchiver unarchiveObjectWithData:item];
|
||||
} @catch(NSException* e) {
|
||||
OpenUDIDLog(@"Unable to unarchive item %@ on pasteboard!", [pboard name]);
|
||||
item = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// return an instance of a MutableDictionary
|
||||
return [NSMutableDictionary dictionaryWithDictionary:(item == nil || [item isKindOfClass:[NSDictionary class]]) ? item : nil];
|
||||
}
|
||||
|
||||
// Private method to create and return a new OpenUDID
|
||||
// Theoretically, this function is called once ever per application when calling [OpenUDID value] for the first time.
|
||||
// After that, the caching/pasteboard/redundancy mechanism inside [OpenUDID value] returns a persistent and cross application OpenUDID
|
||||
//
|
||||
+ (NSString*) _generateFreshOpenUDID {
|
||||
|
||||
NSString* _openUDID = nil;
|
||||
|
||||
// August 2011: One day, this may no longer be allowed in iOS. When that is, just comment this line out.
|
||||
// March 25th 2012: this day has come, let's remove this "outlawed" call...
|
||||
#if TARGET_OS_IPHONE
|
||||
// if([UIDevice instancesRespondToSelector:@selector(uniqueIdentifier)]){
|
||||
// _openUDID = [[UIDevice currentDevice] uniqueIdentifier];
|
||||
// }
|
||||
#endif
|
||||
// Next we generate a UUID.
|
||||
// UUIDs (Universally Unique Identifiers), also known as GUIDs (Globally Unique Identifiers) or IIDs
|
||||
// (Interface Identifiers), are 128-bit values guaranteed to be unique. A UUID is made unique over
|
||||
// both space and time by combining a value unique to the computer on which it was generated—usually the
|
||||
// Ethernet hardware address—and a value representing the number of 100-nanosecond intervals since
|
||||
// October 15, 1582 at 00:00:00.
|
||||
// We then hash this UUID with md5 to get 32 bytes, and then add 4 extra random bytes
|
||||
// Collision is possible of course, but unlikely and suitable for most industry needs (e.g. aggregate tracking)
|
||||
//
|
||||
if (_openUDID==nil) {
|
||||
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
|
||||
CFStringRef cfstring = CFUUIDCreateString(kCFAllocatorDefault, uuid);
|
||||
const char *cStr = CFStringGetCStringPtr(cfstring,CFStringGetFastestEncoding(cfstring));
|
||||
unsigned char result[16];
|
||||
CC_MD5( cStr, (unsigned int)strlen(cStr), result );
|
||||
CFRelease(uuid);
|
||||
|
||||
_openUDID = [NSString stringWithFormat:
|
||||
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%08x",
|
||||
result[0], result[1], result[2], result[3],
|
||||
result[4], result[5], result[6], result[7],
|
||||
result[8], result[9], result[10], result[11],
|
||||
result[12], result[13], result[14], result[15],
|
||||
(unsigned int)(arc4random() % NSUIntegerMax)];
|
||||
}
|
||||
|
||||
// Call to other developers in the Open Source community:
|
||||
//
|
||||
// feel free to suggest better or alternative "UDID" generation code above.
|
||||
// NOTE that the goal is NOT to find a better hash method, but rather, find a decentralized (i.e. not web-based)
|
||||
// 160 bits / 20 bytes random string generator with the fewest possible collisions.
|
||||
//
|
||||
|
||||
return _openUDID;
|
||||
}
|
||||
|
||||
|
||||
// Main public method that returns the OpenUDID
|
||||
// This method will generate and store the OpenUDID if it doesn't exist, typically the first time it is called
|
||||
// It will return the null udid (forty zeros) if the user has somehow opted this app out (this is subject to 3rd party implementation)
|
||||
// Otherwise, it will register the current app and return the OpenUDID
|
||||
//
|
||||
+ (NSString*) value {
|
||||
return [OpenUDIDMac valueWithError:nil];
|
||||
}
|
||||
|
||||
+ (NSString*) valueWithError:(NSError **)error {
|
||||
|
||||
if (kOpenUDIDSessionCache!=nil) {
|
||||
if (error!=nil)
|
||||
*error = [NSError errorWithDomain:kOpenUDIDDomain
|
||||
code:kOpenUDIDErrorNone
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID in cache from first call",@"description", nil]];
|
||||
return kOpenUDIDSessionCache;
|
||||
}
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
// The AppUID will uniquely identify this app within the pastebins
|
||||
//
|
||||
NSString * appUID = (NSString *) [defaults objectForKey:kOpenUDIDAppUIDKey];
|
||||
if(appUID == nil)
|
||||
{
|
||||
// generate a new uuid and store it in user defaults
|
||||
CFUUIDRef uuid = CFUUIDCreate(NULL);
|
||||
appUID = (NSString *) CFUUIDCreateString(NULL, uuid);
|
||||
CFRelease(uuid);
|
||||
}
|
||||
|
||||
NSString* openUDID = nil;
|
||||
NSString* myRedundancySlotPBid = nil;
|
||||
NSDate* optedOutDate = nil;
|
||||
BOOL optedOut = NO;
|
||||
BOOL saveLocalDictToDefaults = NO;
|
||||
BOOL isCompromised = NO;
|
||||
|
||||
// Do we have a local copy of the OpenUDID dictionary?
|
||||
// This local copy contains a copy of the openUDID, myRedundancySlotPBid (and unused in this block, the local bundleid, and the timestamp)
|
||||
//
|
||||
id localDict = [defaults objectForKey:kOpenUDIDKey];
|
||||
if ([localDict isKindOfClass:[NSDictionary class]]) {
|
||||
localDict = [NSMutableDictionary dictionaryWithDictionary:localDict]; // we might need to set/overwrite the redundancy slot
|
||||
openUDID = [localDict objectForKey:kOpenUDIDKey];
|
||||
myRedundancySlotPBid = [localDict objectForKey:kOpenUDIDSlotKey];
|
||||
optedOutDate = [localDict objectForKey:kOpenUDIDOOTSKey];
|
||||
optedOut = optedOutDate!=nil;
|
||||
OpenUDIDLog(@"localDict = %@",localDict);
|
||||
}
|
||||
|
||||
// Here we go through a sequence of slots, each of which being a UIPasteboard created by each participating app
|
||||
// The idea behind this is to both multiple and redundant representations of OpenUDIDs, as well as serve as placeholder for potential opt-out
|
||||
//
|
||||
NSString* availableSlotPBid = nil;
|
||||
NSMutableDictionary* frequencyDict = [NSMutableDictionary dictionaryWithCapacity:kOpenUDIDRedundancySlots];
|
||||
for (int n=0; n<kOpenUDIDRedundancySlots; n++) {
|
||||
NSString* slotPBid = [NSString stringWithFormat:@"%@%d",kOpenUDIDSlotPBPrefix,n];
|
||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:slotPBid create:NO];
|
||||
#else
|
||||
NSPasteboard* slotPB = [NSPasteboard pasteboardWithName:slotPBid];
|
||||
#endif
|
||||
OpenUDIDLog(@"SlotPB name = %@",slotPBid);
|
||||
if (slotPB==nil) {
|
||||
// assign availableSlotPBid to be the first one available
|
||||
if (availableSlotPBid==nil) availableSlotPBid = slotPBid;
|
||||
} else {
|
||||
NSDictionary* dict = [OpenUDIDMac _getDictFromPasteboard:slotPB];
|
||||
NSString* oudid = [dict objectForKey:kOpenUDIDKey];
|
||||
OpenUDIDLog(@"SlotPB dict = %@",dict);
|
||||
if (oudid==nil) {
|
||||
// availableSlotPBid could inside a non null slot where no oudid can be found
|
||||
if (availableSlotPBid==nil) availableSlotPBid = slotPBid;
|
||||
} else {
|
||||
// increment the frequency of this oudid key
|
||||
int count = [[frequencyDict valueForKey:oudid] intValue];
|
||||
[frequencyDict setObject:[NSNumber numberWithInt:++count] forKey:oudid];
|
||||
}
|
||||
// if we have a match with the app unique id,
|
||||
// then let's look if the external UIPasteboard representation marks this app as OptedOut
|
||||
NSString* gid = [dict objectForKey:kOpenUDIDAppUIDKey];
|
||||
if (gid!=nil && [gid isEqualToString:appUID]) {
|
||||
myRedundancySlotPBid = slotPBid;
|
||||
// the local dictionary is prime on the opt-out subject, so ignore if already opted-out locally
|
||||
if (optedOut) {
|
||||
optedOutDate = [dict objectForKey:kOpenUDIDOOTSKey];
|
||||
optedOut = optedOutDate!=nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort the Frequency dict with highest occurence count of the same OpenUDID (redundancy, failsafe)
|
||||
// highest is last in the list
|
||||
//
|
||||
NSArray* arrayOfUDIDs = [frequencyDict keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
NSString* mostReliableOpenUDID = (arrayOfUDIDs!=nil && [arrayOfUDIDs count]>0)? [arrayOfUDIDs lastObject] : nil;
|
||||
OpenUDIDLog(@"Freq Dict = %@\nMost reliable %@",frequencyDict,mostReliableOpenUDID);
|
||||
|
||||
// if openUDID was not retrieved from the local preferences, then let's try to get it from the frequency dictionary above
|
||||
//
|
||||
if (openUDID==nil) {
|
||||
if (mostReliableOpenUDID==nil) {
|
||||
// this is the case where this app instance is likely to be the first one to use OpenUDID on this device
|
||||
// we create the OpenUDID, legacy or semi-random (i.e. most certainly unique)
|
||||
//
|
||||
openUDID = [OpenUDIDMac _generateFreshOpenUDID];
|
||||
} else {
|
||||
// or we leverage the OpenUDID shared by other apps that have already gone through the process
|
||||
//
|
||||
openUDID = mostReliableOpenUDID;
|
||||
}
|
||||
// then we create a local representation
|
||||
//
|
||||
if (localDict==nil) {
|
||||
localDict = [NSMutableDictionary dictionaryWithCapacity:4];
|
||||
[localDict setObject:openUDID forKey:kOpenUDIDKey];
|
||||
[localDict setObject:appUID forKey:kOpenUDIDAppUIDKey];
|
||||
[localDict setObject:[NSDate date] forKey:kOpenUDIDTSKey];
|
||||
if (optedOut) [localDict setObject:optedOutDate forKey:kOpenUDIDTSKey];
|
||||
saveLocalDictToDefaults = YES;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Sanity/tampering check
|
||||
//
|
||||
if (mostReliableOpenUDID!=nil && ![mostReliableOpenUDID isEqualToString:openUDID])
|
||||
isCompromised = YES;
|
||||
}
|
||||
|
||||
// Here we store in the available PB slot, if applicable
|
||||
//
|
||||
OpenUDIDLog(@"Available Slot %@ Existing Slot %@",availableSlotPBid,myRedundancySlotPBid);
|
||||
if (availableSlotPBid!=nil && (myRedundancySlotPBid==nil || [availableSlotPBid isEqualToString:myRedundancySlotPBid])) {
|
||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:availableSlotPBid create:YES];
|
||||
[slotPB setPersistent:YES];
|
||||
#else
|
||||
NSPasteboard* slotPB = [NSPasteboard pasteboardWithName:availableSlotPBid];
|
||||
#endif
|
||||
|
||||
// save slotPBid to the defaults, and remember to save later
|
||||
//
|
||||
if (localDict) {
|
||||
[localDict setObject:availableSlotPBid forKey:kOpenUDIDSlotKey];
|
||||
saveLocalDictToDefaults = YES;
|
||||
}
|
||||
|
||||
// Save the local dictionary to the corresponding UIPasteboard slot
|
||||
//
|
||||
if (openUDID && localDict)
|
||||
[OpenUDIDMac _setDict:localDict forPasteboard:slotPB];
|
||||
}
|
||||
|
||||
// Save the dictionary locally if applicable
|
||||
//
|
||||
if (localDict && saveLocalDictToDefaults)
|
||||
[defaults setObject:localDict forKey:kOpenUDIDKey];
|
||||
|
||||
// If the UIPasteboard external representation marks this app as opted-out, then to respect privacy, we return the ZERO OpenUDID, a sequence of 40 zeros...
|
||||
// This is a *new* case that developers have to deal with. Unlikely, statistically low, but still.
|
||||
// To circumvent this and maintain good tracking (conversion ratios, etc.), developers are invited to calculate how many of their users have opted-out from the full set of users.
|
||||
// This ratio will let them extrapolate convertion ratios more accurately.
|
||||
//
|
||||
if (optedOut) {
|
||||
if (error!=nil) *error = [NSError errorWithDomain:kOpenUDIDDomain
|
||||
code:kOpenUDIDErrorOptedOut
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Application with unique id %@ is opted-out from OpenUDID as of %@",appUID,optedOutDate],@"description", nil]];
|
||||
|
||||
kOpenUDIDSessionCache = [[NSString stringWithFormat:@"%040x",0] retain];
|
||||
return kOpenUDIDSessionCache;
|
||||
}
|
||||
|
||||
// return the well earned openUDID!
|
||||
//
|
||||
if (error!=nil) {
|
||||
if (isCompromised)
|
||||
*error = [NSError errorWithDomain:kOpenUDIDDomain
|
||||
code:kOpenUDIDErrorCompromised
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Found a discrepancy between stored OpenUDID (reliable) and redundant copies; one of the apps on the device is most likely corrupting the OpenUDID protocol",@"description", nil]];
|
||||
else
|
||||
*error = [NSError errorWithDomain:kOpenUDIDDomain
|
||||
code:kOpenUDIDErrorNone
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID succesfully retrieved",@"description", nil]];
|
||||
}
|
||||
kOpenUDIDSessionCache = [openUDID retain];
|
||||
return kOpenUDIDSessionCache;
|
||||
}
|
||||
|
||||
+ (void) setOptOut:(BOOL)optOutValue {
|
||||
|
||||
// init call
|
||||
[OpenUDIDMac value];
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
// load the dictionary from local cache or create one
|
||||
id dict = [defaults objectForKey:kOpenUDIDKey];
|
||||
if ([dict isKindOfClass:[NSDictionary class]]) {
|
||||
dict = [NSMutableDictionary dictionaryWithDictionary:dict];
|
||||
} else {
|
||||
dict = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||
}
|
||||
|
||||
// set the opt-out date or remove key, according to parameter
|
||||
if (optOutValue)
|
||||
[dict setObject:[NSDate date] forKey:kOpenUDIDOOTSKey];
|
||||
else
|
||||
[dict removeObjectForKey:kOpenUDIDOOTSKey];
|
||||
|
||||
// store the dictionary locally
|
||||
[defaults setObject:dict forKey:kOpenUDIDKey];
|
||||
|
||||
OpenUDIDLog(@"Local dict after opt-out = %@",dict);
|
||||
|
||||
// reset memory cache
|
||||
kOpenUDIDSessionCache = nil;
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
162
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/DeviceEx-win32.cpp
Executable file
162
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/DeviceEx-win32.cpp
Executable file
@@ -0,0 +1,162 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "DeviceEx.h"
|
||||
|
||||
// for mac address
|
||||
#include <WinSock2.h>
|
||||
#include <Iphlpapi.h>
|
||||
#pragma comment(lib,"Iphlpapi.lib")
|
||||
|
||||
using namespace std;
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
DeviceEx *DeviceEx::getInstance()
|
||||
{
|
||||
static DeviceEx *instance = NULL;
|
||||
if (!instance)
|
||||
{
|
||||
instance = new DeviceEx();
|
||||
instance->init();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::string DeviceEx::getCurrentUILangName()
|
||||
{
|
||||
return _uiLangName;
|
||||
}
|
||||
|
||||
std::string DeviceEx::getUserGUID()
|
||||
{
|
||||
return _userGUID;
|
||||
}
|
||||
|
||||
|
||||
////////// private //////////
|
||||
|
||||
DeviceEx::DeviceEx()
|
||||
: _uiLangName("en")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeviceEx::init()
|
||||
{
|
||||
makeUILangName();
|
||||
makeUserGUID();
|
||||
}
|
||||
|
||||
void DeviceEx::makeUILangName()
|
||||
{
|
||||
//
|
||||
// get language
|
||||
// http://msdn.microsoft.com/en-us/library/windows/apps/jj244362(v=vs.105).aspx
|
||||
//
|
||||
ULONG numLanguages = 0;
|
||||
DWORD cchLanguagesBuffer = 0;
|
||||
BOOL hr = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numLanguages, NULL, &cchLanguagesBuffer);
|
||||
if (hr)
|
||||
{
|
||||
WCHAR* pwszLanguagesBuffer = new WCHAR[cchLanguagesBuffer];
|
||||
hr = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numLanguages, pwszLanguagesBuffer, &cchLanguagesBuffer);
|
||||
if (hr)
|
||||
{
|
||||
size_t size = wcslen(pwszLanguagesBuffer) * 3 + 1;
|
||||
char* dest = new char[size];
|
||||
memset(dest, 0, size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, pwszLanguagesBuffer, -1, dest, size, NULL, NULL);
|
||||
_uiLangName = dest;
|
||||
}
|
||||
delete [] pwszLanguagesBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
static bool getMacAddress(string& macstring)
|
||||
{
|
||||
bool ret = false;
|
||||
ULONG ipInfoLen = sizeof(IP_ADAPTER_INFO);
|
||||
PIP_ADAPTER_INFO adapterInfo = (IP_ADAPTER_INFO *)malloc(ipInfoLen);
|
||||
if (adapterInfo == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetAdaptersInfo(adapterInfo, &ipInfoLen) == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
free(adapterInfo);
|
||||
adapterInfo = (IP_ADAPTER_INFO *)malloc(ipInfoLen);
|
||||
if (adapterInfo == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetAdaptersInfo(adapterInfo, &ipInfoLen) == NO_ERROR)
|
||||
{
|
||||
for (PIP_ADAPTER_INFO pAdapter = adapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next)
|
||||
{
|
||||
if (pAdapter->Type != MIB_IF_TYPE_ETHERNET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pAdapter->AddressLength != 6)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
char buf32[32];
|
||||
sprintf(buf32, "%02X-%02X-%02X-%02X-%02X-%02X",
|
||||
int(pAdapter->Address[0]),
|
||||
int(pAdapter->Address[1]),
|
||||
int(pAdapter->Address[2]),
|
||||
int(pAdapter->Address[3]),
|
||||
int(pAdapter->Address[4]),
|
||||
int(pAdapter->Address[5]));
|
||||
macstring = buf32;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(adapterInfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string DeviceEx::makeUserGUID()
|
||||
{
|
||||
if (_userGUID.length() <= 0)
|
||||
{
|
||||
if (!getMacAddress(_userGUID))
|
||||
{
|
||||
_userGUID = "guid-fixed-1234567890";
|
||||
}
|
||||
}
|
||||
|
||||
return _userGUID;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,123 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 <string>
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerEditBoxServiceWin.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerEditBoxServiceWin::PlayerEditBoxServiceWin(HWND hwnd)
|
||||
: _hfont(NULL)
|
||||
{
|
||||
_hwnd = hwnd;
|
||||
HINSTANCE instance = (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE);
|
||||
DWORD style = WS_CHILD | ES_LEFT | ES_AUTOHSCROLL;
|
||||
_hwndSingle = CreateWindowEx(WS_EX_CLIENTEDGE, L"Edit", L"", style, 0, 0, 0, 0, _hwnd, NULL, instance, NULL);
|
||||
style = WS_CHILD | ES_MULTILINE | ES_LEFT | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL;
|
||||
_hwndMulti = CreateWindowEx(WS_EX_CLIENTEDGE, L"Edit", L"", style, 0, 0, 0, 0, _hwnd, NULL, instance, NULL);
|
||||
}
|
||||
|
||||
PlayerEditBoxServiceWin::~PlayerEditBoxServiceWin()
|
||||
{
|
||||
removeFont();
|
||||
DestroyWindow(_hwndSingle);
|
||||
DestroyWindow(_hwndMulti);
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::showSingleLineEditBox(const cocos2d::Rect &rect)
|
||||
{
|
||||
MoveWindow(_hwndSingle, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, TRUE);
|
||||
ShowWindow(_hwndSingle, SW_SHOW);
|
||||
SetFocus(_hwndSingle);
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::showMultiLineEditBox(const cocos2d::Rect &rect)
|
||||
{
|
||||
MoveWindow(_hwndMulti, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, TRUE);
|
||||
ShowWindow(_hwndMulti, SW_SHOW);
|
||||
SetFocus(_hwndMulti);
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::hide()
|
||||
{
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::setText(const std::string &text)
|
||||
{
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::setFont(const std::string &name, int size)
|
||||
{
|
||||
removeFont();
|
||||
|
||||
std::u16string u16name;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(name, u16name);
|
||||
|
||||
HDC hdc = GetDC(_hwnd);
|
||||
size = -MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
||||
ReleaseDC(_hwnd, hdc);
|
||||
|
||||
_hfont = CreateFont(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
||||
0, OUT_DEFAULT_PRECIS, FW_NORMAL, DEFAULT_QUALITY, DEFAULT_PITCH,
|
||||
(LPCTSTR)u16name.c_str());
|
||||
if (!_hfont)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("PlayerEditBoxServiceWin::setFont() - create HFONT for font \"%s\" failed, error code = 0x%08x",
|
||||
name.c_str(), err);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessage(_hwndSingle, WM_SETFONT, (WPARAM)_hfont, NULL);
|
||||
SendMessage(_hwndMulti, WM_SETFONT, (WPARAM)_hfont, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::setFontColor(const cocos2d::Color3B &color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::removeFont()
|
||||
{
|
||||
if (_hfont)
|
||||
{
|
||||
SendMessage(_hwndSingle, WM_SETFONT, NULL, NULL);
|
||||
SendMessage(_hwndMulti, WM_SETFONT, NULL, NULL);
|
||||
DeleteObject(_hfont);
|
||||
}
|
||||
_hfont = NULL;
|
||||
}
|
||||
|
||||
void PlayerEditBoxServiceWin::setFormator(int /*formator*/ )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_EDITBOX_SERVICE_WIN_H_
|
||||
#define __PLAYER_EDITBOX_SERVICE_WIN_H_
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "PlayerEditBoxServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerEditBoxServiceWin : public PlayerEditBoxServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerEditBoxServiceWin(HWND hwnd);
|
||||
virtual ~PlayerEditBoxServiceWin();
|
||||
|
||||
virtual void showSingleLineEditBox(const cocos2d::Rect &rect);
|
||||
virtual void showMultiLineEditBox(const cocos2d::Rect &rect);
|
||||
virtual void hide();
|
||||
|
||||
virtual void setText(const std::string &text);
|
||||
virtual void setFont(const std::string &name, int size);
|
||||
virtual void setFontColor(const cocos2d::Color3B &color);
|
||||
|
||||
virtual void setFormator(int formator);
|
||||
protected:
|
||||
HWND _hwnd;
|
||||
HWND _hwndSingle;
|
||||
HWND _hwndMulti;
|
||||
HFONT _hfont;
|
||||
|
||||
void removeFont();
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_EDITBOX_SERVICE_WIN_H_
|
||||
@@ -0,0 +1,301 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 <string.h>
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <Windowsx.h>
|
||||
#include <Shlobj.h>
|
||||
#include <Commdlg.h>
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerUtils.h"
|
||||
#include "PlayerFileDialogServiceWin.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerFileDialogServiceWin::PlayerFileDialogServiceWin(HWND hwnd)
|
||||
: _hwnd(hwnd)
|
||||
{
|
||||
}
|
||||
|
||||
std::string PlayerFileDialogServiceWin::openFile(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const
|
||||
{
|
||||
vector<std::string> result = openMultipleInternal(title, directory, extensions, false);
|
||||
if (result.size())
|
||||
{
|
||||
return result.at(0);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::vector<std::string> PlayerFileDialogServiceWin::openMultiple(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const
|
||||
{
|
||||
return openMultipleInternal(title, directory, extensions, true);
|
||||
}
|
||||
|
||||
std::string PlayerFileDialogServiceWin::saveFile(const std::string &title,
|
||||
const std::string &path) const
|
||||
{
|
||||
std::u16string u16title;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(title, u16title);
|
||||
|
||||
WCHAR buff[MAX_PATH + 1] = {0};
|
||||
if (path.length() > 0)
|
||||
{
|
||||
std::u16string u16filename;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(path, u16filename);
|
||||
wcscpy_s(buff, (WCHAR*)u16filename.c_str());
|
||||
}
|
||||
|
||||
OPENFILENAME ofn = {0};
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = _hwnd;
|
||||
ofn.lpstrFilter = L"All Files (*.*)\0*.*\0";
|
||||
ofn.lpstrTitle = (LPCTSTR)u16title.c_str();
|
||||
ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES;
|
||||
ofn.lpstrFile = buff;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
|
||||
std::string result;
|
||||
if (!GetSaveFileName(&ofn))
|
||||
{
|
||||
// user cancel dialog, GetSaveFileName() will return FALSE
|
||||
DWORD err = CommDlgExtendedError();
|
||||
if (err)
|
||||
{
|
||||
CCLOG("PlayerFileDialogServiceWin::saveFile() - failed, title (%s), error code = %u", title.c_str(), err);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
cocos2d::StringUtils::UTF16ToUTF8((char16_t*)buff, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// for openDirectory
|
||||
int CALLBACK BrowseFolderCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||||
{
|
||||
if (uMsg == BFFM_INITIALIZED && lpData)
|
||||
{
|
||||
LPCTSTR path = (LPCTSTR)lpData;
|
||||
SendMessage(hwnd, BFFM_SETSELECTION, true, (LPARAM)path);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string PlayerFileDialogServiceWin::openDirectory(const std::string &title,
|
||||
const std::string &directory) const
|
||||
{
|
||||
std::u16string u16title;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(title, u16title);
|
||||
|
||||
WCHAR basedir[MAX_PATH + 1];
|
||||
if (directory.length())
|
||||
{
|
||||
std::u16string u16directory;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(directory, u16directory);
|
||||
wcscpy_s(basedir, (WCHAR*)u16directory.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCurrentDirectory(MAX_PATH, basedir);
|
||||
}
|
||||
|
||||
WCHAR buff[MAX_PATH + 1] = {0};
|
||||
BROWSEINFO bi = {0};
|
||||
bi.hwndOwner = _hwnd;
|
||||
bi.pszDisplayName = buff;
|
||||
bi.lpszTitle = (LPCTSTR)u16title.c_str();
|
||||
bi.lParam = (LPARAM)basedir;
|
||||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NONEWFOLDERBUTTON | BIF_NEWDIALOGSTYLE;
|
||||
bi.lpfn = BrowseFolderCallback;
|
||||
|
||||
PIDLIST_ABSOLUTE pid = SHBrowseForFolder(&bi);
|
||||
if (pid)
|
||||
{
|
||||
SHGetPathFromIDList(pid, buff);
|
||||
std::string result;
|
||||
cocos2d::StringUtils::UTF16ToUTF8((char16_t*)buff, result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
}
|
||||
|
||||
LPTSTR PlayerFileDialogServiceWin::parseExtensions(const std::string &extensions) const
|
||||
{
|
||||
static WCHAR *defaultExtensions = L"All Files (*.*)\0*.*\0";
|
||||
if (extensions.length() == 0)
|
||||
{
|
||||
WCHAR *buff = new WCHAR[wcslen(defaultExtensions) + 1];
|
||||
wcscpy(buff, defaultExtensions);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// 1.
|
||||
// "Lua Script File|*.lua;JSON File|*.json"
|
||||
// to
|
||||
// "Lua Script File (*.lua)\0*.lua\0JSON File (*.json)\0*.json\0";
|
||||
//
|
||||
// 2.
|
||||
// "Lua Script File|*.lua;Cocos Studio File|*.csd,*.csb"
|
||||
// to
|
||||
// "Lua Script File (*.lua)\0*.lua\0Cocos Studio File (*.csd;*.csb")\0*.csd;*.csb"\0";
|
||||
std::u16string u16extensions;
|
||||
std::u16string split1((char16_t*)L";");
|
||||
std::u16string split2((char16_t*)L"|");
|
||||
std::u16string split3((char16_t*)L",");
|
||||
std::string extensionsArg(extensions);
|
||||
cocos2d::StringUtils::UTF8ToUTF16(extensions, u16extensions);
|
||||
vector<std::u16string> pairs = splitString(u16extensions, split1);
|
||||
|
||||
size_t buffsize = extensions.length() * 6;
|
||||
WCHAR *buff = new WCHAR[buffsize];
|
||||
memset(buff, 0, sizeof(WCHAR) * buffsize);
|
||||
size_t offset = 0;
|
||||
for (auto it = pairs.begin(); it != pairs.end(); ++it)
|
||||
{
|
||||
vector<std::u16string> p = splitString(*it, split2);
|
||||
std::u16string descr, ext;
|
||||
if (p.size() < 2)
|
||||
{
|
||||
descr = ext = *it;
|
||||
}
|
||||
else
|
||||
{
|
||||
descr = p.at(0);
|
||||
ext = p.at(1);
|
||||
}
|
||||
|
||||
// *.csd,*.csb -> *.csd;*.csb
|
||||
std::replace(ext.begin(), ext.end(), ',', ';');
|
||||
|
||||
wcscat(buff + offset, (WCHAR*)descr.c_str());
|
||||
wcscat(buff + offset, L" (");
|
||||
wcscat(buff + offset, (WCHAR*)ext.c_str());
|
||||
wcscat(buff + offset, L")");
|
||||
offset += descr.length() + ext.length() + 4;
|
||||
wcscat(buff + offset, (WCHAR*)ext.c_str());
|
||||
offset += ext.length() + 1;
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
std::vector<std::string> PlayerFileDialogServiceWin::openMultipleInternal(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions,
|
||||
bool isMulti) const
|
||||
{
|
||||
std::u16string u16title;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(title, u16title);
|
||||
|
||||
WCHAR basedir[MAX_PATH + 1];
|
||||
if (directory.length())
|
||||
{
|
||||
std::u16string u16directory;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(directory, u16directory);
|
||||
wcscpy_s(basedir, (WCHAR*)u16directory.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCurrentDirectory(MAX_PATH, basedir);
|
||||
}
|
||||
|
||||
size_t buffsize = MAX_PATH;
|
||||
if (isMulti) buffsize = MAX_PATH * 64;
|
||||
WCHAR *buff = new WCHAR[buffsize + 1];
|
||||
memset(buff, 0, sizeof(WCHAR) * (buffsize + 1));
|
||||
|
||||
OPENFILENAME ofn = {0};
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = _hwnd;
|
||||
ofn.lpstrFilter = parseExtensions(extensions);
|
||||
ofn.lpstrTitle = (LPCTSTR)u16title.c_str();
|
||||
ofn.lpstrInitialDir = basedir;
|
||||
ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES;
|
||||
if (isMulti) ofn.Flags |= OFN_ALLOWMULTISELECT | OFN_EXPLORER;
|
||||
ofn.lpstrFile = buff;
|
||||
ofn.nMaxFile = buffsize;
|
||||
|
||||
vector<std::string> result;
|
||||
BOOL ret = GetOpenFileName(&ofn);
|
||||
delete[] ofn.lpstrFilter;
|
||||
if (!ret)
|
||||
{
|
||||
// user cancel dialog, GetOpenFileName() will return FALSE
|
||||
DWORD err = CommDlgExtendedError();
|
||||
if (err)
|
||||
{
|
||||
CCLOG("PlayerFileDialogServiceWin::openMultipleInternal() - failed, title (%s), error code = %u", title.c_str(), err);
|
||||
}
|
||||
delete[] buff;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isMulti)
|
||||
{
|
||||
WORD offset = 0;
|
||||
std::string path;
|
||||
while (buff[offset] != '\0')
|
||||
{
|
||||
std::string filename;
|
||||
std::u16string u16filename((char16_t*)(buff + offset));
|
||||
cocos2d::StringUtils::UTF16ToUTF8(u16filename, filename);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
path = filename;
|
||||
if (path[path.length() - 1] != '\\')
|
||||
{
|
||||
path.append("\\");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(path + filename);
|
||||
}
|
||||
offset += u16filename.length() + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path;
|
||||
cocos2d::StringUtils::UTF16ToUTF8((char16_t*)buff, path);
|
||||
result.push_back(path);
|
||||
}
|
||||
delete[] buff;
|
||||
return result;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_FILE_DIALOG_SERVICE_WIN_H_
|
||||
#define __PLAYER_FILE_DIALOG_SERVICE_WIN_H_
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "PlayerFileDialogServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerFileDialogServiceWin : public PlayerFileDialogServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerFileDialogServiceWin(HWND hwnd);
|
||||
|
||||
virtual std::string openFile(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const;
|
||||
virtual std::vector<std::string> openMultiple(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions) const;
|
||||
virtual std::string saveFile(const std::string &title,
|
||||
const std::string &path) const;
|
||||
virtual std::string openDirectory(const std::string &title,
|
||||
const std::string &directory) const;
|
||||
|
||||
protected:
|
||||
HWND _hwnd;
|
||||
|
||||
LPTSTR parseExtensions(const std::string &extensions) const;
|
||||
vector<std::string> openMultipleInternal(const std::string &title,
|
||||
const std::string &directory,
|
||||
const std::string &extensions,
|
||||
bool isMulti) const;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_FILE_DIALOG_SERVICE_WIN_H_
|
||||
@@ -0,0 +1,376 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerMenuServiceWin.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerMenuItemWin *PlayerMenuItemWin::create(const std::string &menuId, const std::string &title)
|
||||
{
|
||||
PlayerMenuItemWin *item = new PlayerMenuItemWin();
|
||||
item->_menuId = menuId;
|
||||
item->_title = title;
|
||||
item->autorelease();
|
||||
return item;
|
||||
}
|
||||
|
||||
PlayerMenuItemWin::PlayerMenuItemWin()
|
||||
: _parent(nullptr)
|
||||
, _commandId(0)
|
||||
, _hmenu(NULL)
|
||||
, _menubarEnabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
PlayerMenuItemWin::~PlayerMenuItemWin()
|
||||
{
|
||||
CC_SAFE_RELEASE(_parent);
|
||||
if (_hmenu)
|
||||
{
|
||||
CCLOG("PlayerMenuItemWin::~PlayerMenuItemWin() - %s (HMENU)", _menuId.c_str());
|
||||
DestroyMenu(_hmenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOG("PlayerMenuItemWin::~PlayerMenuItemWin() - %s", _menuId.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMenuItemWin::setTitle(const std::string &title)
|
||||
{
|
||||
if (title.length() == 0)
|
||||
{
|
||||
CCLOG("MenuServiceWin::setTitle() - can not set menu title to empty, menu id (%s)", _menuId.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
MENUITEMINFO menuitem;
|
||||
menuitem.cbSize = sizeof(menuitem);
|
||||
menuitem.fMask = MIIM_FTYPE | MIIM_STRING;
|
||||
menuitem.fType = (title.compare("-") == 0) ? MFT_SEPARATOR : MFT_STRING;
|
||||
std::u16string u16title;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(title, u16title);
|
||||
menuitem.dwTypeData = (LPTSTR)u16title.c_str();
|
||||
if (SetMenuItemInfo(_parent->_hmenu, _commandId, MF_BYCOMMAND, &menuitem))
|
||||
{
|
||||
_title = title;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("MenuServiceWin::setTitle() - set menu title failed, menu id (%s). error code = %u", _menuId.c_str(), err);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMenuItemWin::setEnabled(bool enabled)
|
||||
{
|
||||
MENUITEMINFO menuitem = {0};
|
||||
menuitem.cbSize = sizeof(menuitem);
|
||||
menuitem.fMask = MIIM_STATE;
|
||||
menuitem.fState = (enabled && _menubarEnabled) ? MFS_ENABLED : MFS_DISABLED;
|
||||
if (SetMenuItemInfo(_parent->_hmenu, _commandId, MF_BYCOMMAND, &menuitem))
|
||||
{
|
||||
_isEnabled = enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("MenuServiceWin::setEnabled() - set menu enabled failed, menu id (%s). error code = %u", _menuId.c_str(), err);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMenuItemWin::setChecked(bool checked)
|
||||
{
|
||||
MENUITEMINFO menuitem;
|
||||
menuitem.cbSize = sizeof(menuitem);
|
||||
menuitem.fMask = MIIM_STATE;
|
||||
menuitem.fState = (checked) ? MFS_CHECKED : MFS_UNCHECKED;
|
||||
if (SetMenuItemInfo(_parent->_hmenu, _commandId, MF_BYCOMMAND, &menuitem))
|
||||
{
|
||||
_isChecked = checked;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("MenuServiceWin::setChecked() - set menu checked failed, menu id (%s). error code = %u", _menuId.c_str(), err);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMenuItemWin::setShortcut(const std::string &shortcut)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MenuServiceWin
|
||||
|
||||
WORD PlayerMenuServiceWin::_newCommandId = 0x1000;
|
||||
|
||||
PlayerMenuServiceWin::PlayerMenuServiceWin(HWND hwnd)
|
||||
: _hwnd(hwnd)
|
||||
, _menubarEnabled(true)
|
||||
{
|
||||
// create menu
|
||||
_root._menuId = "__ROOT__";
|
||||
_root._commandId = 0;
|
||||
|
||||
// hwnd has menu
|
||||
HMENU menu = GetSystemMenu(hwnd, FALSE);// GetMenu(hwnd);
|
||||
if (menu)
|
||||
{
|
||||
_root._hmenu = menu;
|
||||
}
|
||||
else
|
||||
{
|
||||
_root._hmenu = CreateMenu();
|
||||
SetMenu(hwnd, _root._hmenu);
|
||||
}
|
||||
}
|
||||
|
||||
PlayerMenuServiceWin::~PlayerMenuServiceWin()
|
||||
{
|
||||
}
|
||||
|
||||
PlayerMenuItem *PlayerMenuServiceWin::addItem(const std::string &menuId,
|
||||
const std::string &title,
|
||||
const std::string &parentId,
|
||||
int order /* = MAX_ORDER */)
|
||||
{
|
||||
if (menuId.length() == 0 || title.length() == 0)
|
||||
{
|
||||
CCLOG("MenuServiceWin::addItem() - menuId and title must is non-empty");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check menu id is exists
|
||||
if (_items.find(menuId) != _items.end())
|
||||
{
|
||||
CCLOG("MenuServiceWin::addItem() - menu id (%s) is exists", menuId.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// set parent
|
||||
PlayerMenuItemWin *parent = &_root;
|
||||
if (parentId.length())
|
||||
{
|
||||
// query parent menu
|
||||
auto it = _items.find(parentId);
|
||||
if (it != _items.end())
|
||||
{
|
||||
parent = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parent->_hmenu)
|
||||
{
|
||||
// create menu handle for parent (convert parent to submenu)
|
||||
parent->_hmenu = CreateMenu();
|
||||
parent->_isGroup = true;
|
||||
MENUITEMINFO menuitem;
|
||||
menuitem.cbSize = sizeof(menuitem);
|
||||
menuitem.fMask = MIIM_SUBMENU;
|
||||
menuitem.hSubMenu = parent->_hmenu;
|
||||
if (!SetMenuItemInfo(parent->_parent->_hmenu, parent->_commandId, MF_BYCOMMAND, &menuitem))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("MenuServiceWin::addItem() - set menu handle failed, menu id (%s). error code = %u", parent->_menuId.c_str(), err);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// create new menu item
|
||||
_newCommandId++;
|
||||
PlayerMenuItemWin *item = PlayerMenuItemWin::create(menuId, title);
|
||||
item->_commandId = _newCommandId;
|
||||
item->_parent = parent;
|
||||
item->_parent->retain();
|
||||
|
||||
// add menu item to menu bar
|
||||
MENUITEMINFO menuitem;
|
||||
menuitem.cbSize = sizeof(menuitem);
|
||||
menuitem.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING;
|
||||
menuitem.fType = (item->_title.compare("-") == 0) ? MFT_SEPARATOR : MFT_STRING;
|
||||
menuitem.fState = (item->_isEnabled) ? MFS_ENABLED : MFS_DISABLED;
|
||||
menuitem.fState |= (item->_isChecked) ? MFS_CHECKED : MFS_UNCHECKED;
|
||||
std::u16string u16title;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(item->_title, u16title);
|
||||
menuitem.dwTypeData = (LPTSTR)u16title.c_str();
|
||||
menuitem.wID = _newCommandId;
|
||||
|
||||
// check new menu item position
|
||||
if (order > parent->_children.size())
|
||||
{
|
||||
order = parent->_children.size();
|
||||
}
|
||||
else if (order < 0)
|
||||
{
|
||||
order = 0;
|
||||
}
|
||||
|
||||
// create new menu item
|
||||
if (!InsertMenuItem(parent->_hmenu, order, TRUE, &menuitem))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("MenuServiceWin::addItem() - insert new menu item failed, menu id (%s). error code = %u", item->_menuId.c_str(), err);
|
||||
item->release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// update menu state
|
||||
parent->_children.insert(order, item);
|
||||
_items[item->_menuId] = item;
|
||||
_commandId2menuId[item->_commandId] = item->_menuId;
|
||||
updateChildrenOrder(parent);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
PlayerMenuItem *PlayerMenuServiceWin::addItem(const std::string &menuId,
|
||||
const std::string &title)
|
||||
{
|
||||
return addItem(menuId, title, "");
|
||||
}
|
||||
|
||||
PlayerMenuItem *PlayerMenuServiceWin::getItem(const std::string &menuId)
|
||||
{
|
||||
auto it = _items.find(menuId);
|
||||
if (it == _items.end())
|
||||
{
|
||||
CCLOG("MenuServiceWin::getItem() - Invalid menu id (%s)", menuId.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool PlayerMenuServiceWin::removeItem(const std::string &menuId)
|
||||
{
|
||||
return removeItemInternal(menuId, true);
|
||||
}
|
||||
|
||||
void PlayerMenuServiceWin::setMenuBarEnabled(bool enabled)
|
||||
{
|
||||
_menubarEnabled = enabled;
|
||||
|
||||
UINT state = enabled ? MFS_ENABLED : MFS_DISABLED;
|
||||
for (auto it = _root._children.begin(); it != _root._children.end(); ++it)
|
||||
{
|
||||
PlayerMenuItemWin *item = *it;
|
||||
MENUITEMINFO menuitem = {0};
|
||||
menuitem.cbSize = sizeof(menuitem);
|
||||
menuitem.fMask = MIIM_STATE;
|
||||
menuitem.fState = state;
|
||||
SetMenuItemInfo(item->_parent->_hmenu, item->_commandId, MF_BYCOMMAND, &menuitem);
|
||||
item->_menubarEnabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerMenuItemWin *PlayerMenuServiceWin::getItemByCommandId(WORD commandId)
|
||||
{
|
||||
auto it = _commandId2menuId.find(commandId);
|
||||
if (it == _commandId2menuId.end()) return nullptr;
|
||||
return _items[it->second];
|
||||
}
|
||||
|
||||
bool PlayerMenuServiceWin::removeItemInternal(const std::string &menuId, bool isUpdateChildrenOrder)
|
||||
{
|
||||
auto it = _items.find(menuId);
|
||||
if (it == _items.end())
|
||||
{
|
||||
CCLOG("MenuServiceWin::removeItem() - Invalid menu id (%s)", menuId.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
PlayerMenuItemWin *item = it->second;
|
||||
if (item->_children.size() == 0)
|
||||
{
|
||||
if (!DeleteMenu(item->_parent->_hmenu, item->_commandId, MF_BYCOMMAND))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CCLOG("MenuServiceWin::removeItem() - remove menu item failed, menu id (%s). error code = %u", item->_menuId.c_str(), err);
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove item from parent
|
||||
bool removed = false;
|
||||
auto *children = &item->_parent->_children;
|
||||
for (auto it = children->begin(); it != children->end(); ++it)
|
||||
{
|
||||
if ((*it)->_commandId == item->_commandId)
|
||||
{
|
||||
CCLOG("MenuServiceWin::removeItem() - remove menu item (%s)", item->_menuId.c_str());
|
||||
children->erase(it);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!removed)
|
||||
{
|
||||
CCLOG("MenuServiceWin::removeItem() - remove menu item (%s) failed, not found command id from parent->children", item->_menuId.c_str());
|
||||
}
|
||||
|
||||
// remove menu id mapping
|
||||
_items.erase(menuId);
|
||||
_commandId2menuId.erase(item->_commandId);
|
||||
if (isUpdateChildrenOrder)
|
||||
{
|
||||
updateChildrenOrder(item->_parent);
|
||||
}
|
||||
DrawMenuBar(_hwnd);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove all children
|
||||
while (item->_children.size() != 0)
|
||||
{
|
||||
PlayerMenuItemWin *child = *item->_children.begin();
|
||||
if (!removeItemInternal(child->_menuId.c_str(), false))
|
||||
{
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return removeItemInternal(menuId, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PlayerMenuServiceWin::updateChildrenOrder(PlayerMenuItemWin *parent)
|
||||
{
|
||||
auto *children = &parent->_children;
|
||||
int order = 0;
|
||||
for (auto it = children->begin(); it != children->end(); ++it)
|
||||
{
|
||||
(*it)->_order = order;
|
||||
order++;
|
||||
}
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MENU_SERVICE_WIN_H_
|
||||
#define __PLAYER_MENU_SERVICE_WIN_H_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "cocos2d.h"
|
||||
#include "stdafx.h"
|
||||
#include "PlayerMenuServiceProtocol.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class CC_LIBSIM_DLL PlayerMenuItemWin : public PlayerMenuItem
|
||||
{
|
||||
public:
|
||||
static PlayerMenuItemWin *create(const std::string &menuId, const std::string &title);
|
||||
virtual ~PlayerMenuItemWin();
|
||||
|
||||
virtual void setTitle(const std::string &title);
|
||||
virtual void setEnabled(bool enabled);
|
||||
virtual void setChecked(bool checked);
|
||||
virtual void setShortcut(const std::string &shortcut);
|
||||
|
||||
protected:
|
||||
PlayerMenuItemWin();
|
||||
|
||||
PlayerMenuItemWin *_parent;
|
||||
UINT _commandId;
|
||||
HMENU _hmenu;
|
||||
bool _menubarEnabled;
|
||||
cocos2d::Vector<PlayerMenuItemWin*> _children;
|
||||
|
||||
friend class PlayerMenuServiceWin;
|
||||
};
|
||||
|
||||
class CC_LIBSIM_DLL PlayerMenuServiceWin : public PlayerMenuServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerMenuServiceWin(HWND hwnd);
|
||||
virtual ~PlayerMenuServiceWin();
|
||||
|
||||
virtual PlayerMenuItem *addItem(const std::string &menuId,
|
||||
const std::string &title,
|
||||
const std::string &parentId,
|
||||
int order = MAX_ORDER);
|
||||
virtual PlayerMenuItem *addItem(const std::string &menuId,
|
||||
const std::string &title);
|
||||
virtual PlayerMenuItem *getItem(const std::string &menuId);
|
||||
virtual bool removeItem(const std::string &menuId);
|
||||
virtual void setMenuBarEnabled(bool enabled);
|
||||
|
||||
PlayerMenuItemWin *getItemByCommandId(WORD commandId);
|
||||
|
||||
private:
|
||||
static WORD _newCommandId;
|
||||
|
||||
HWND _hwnd;
|
||||
bool _menubarEnabled;
|
||||
PlayerMenuItemWin _root;
|
||||
std::unordered_map<std::string, PlayerMenuItemWin*> _items;
|
||||
std::unordered_map<WORD, std::string> _commandId2menuId;
|
||||
|
||||
bool removeItemInternal(const std::string &menuId, bool isUpdateChildrenOrder);
|
||||
void updateChildrenOrder(PlayerMenuItemWin *parent);
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MENU_SERVICE_WIN_H_
|
||||
@@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerMessageBoxServiceWin.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerMessageBoxServiceWin::PlayerMessageBoxServiceWin(HWND hwnd)
|
||||
: _hwnd(hwnd)
|
||||
{
|
||||
}
|
||||
|
||||
int PlayerMessageBoxServiceWin::showMessageBox(const std::string &title,
|
||||
const std::string &message,
|
||||
int buttonsType /* = BUTTONS_OK */)
|
||||
{
|
||||
std::u16string u16title;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(title, u16title);
|
||||
std::u16string u16message;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(message, u16message);
|
||||
|
||||
CCLOG("PlayerMessageBoxServiceWin::showMessageBox() - title = %s, message = %s", title.c_str(), message.c_str());
|
||||
|
||||
UINT mbtype = MB_APPLMODAL;
|
||||
switch (buttonsType)
|
||||
{
|
||||
case BUTTONS_OK_CANCEL:
|
||||
mbtype |= MB_OKCANCEL | MB_ICONQUESTION;
|
||||
break;
|
||||
|
||||
case BUTTONS_YES_NO:
|
||||
mbtype |= MB_YESNO | MB_ICONQUESTION;
|
||||
break;
|
||||
|
||||
case BUTTONS_YES_NO_CANCEL:
|
||||
mbtype |= MB_YESNOCANCEL | MB_ICONQUESTION;
|
||||
break;
|
||||
|
||||
default:
|
||||
mbtype |= MB_OK | MB_ICONINFORMATION;
|
||||
}
|
||||
|
||||
// MessageBox() used by cocos2d
|
||||
int result = ::MessageBoxW(_hwnd, (LPCTSTR)u16message.c_str(), (LPCTSTR)u16title.c_str(), mbtype);
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case IDCANCEL:
|
||||
result = BUTTON_CANCEL;
|
||||
break;
|
||||
|
||||
case IDYES:
|
||||
result = BUTTON_YES;
|
||||
break;
|
||||
|
||||
case IDNO:
|
||||
result = BUTTON_NO;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = BUTTON_OK;
|
||||
}
|
||||
|
||||
CCLOG("PlayerMessageBoxServiceWin::showMessageBox() - result = %d", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_MESSAGEBOX_SERVICE_WIN_H_
|
||||
#define __PLAYER_MESSAGEBOX_SERVICE_WIN_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "cocos2d.h"
|
||||
#include "PlayerMessageBoxServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerMessageBoxServiceWin : public PlayerMessageBoxServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerMessageBoxServiceWin(HWND hwnd);
|
||||
|
||||
virtual int showMessageBox(const std::string &title,
|
||||
const std::string &message,
|
||||
int buttonsType = BUTTONS_OK);
|
||||
|
||||
protected:
|
||||
HWND _hwnd;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_MESSAGEBOX_SERVICE_WIN_H_
|
||||
@@ -0,0 +1,297 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 <sstream>
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "shellapi.h"
|
||||
#include "PlayerTaskServiceWin.h"
|
||||
|
||||
static const int MAX_LOG_LENGTH = 16 * 1024;// from 2dx
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerTaskWin *PlayerTaskWin::create(const std::string &name, const std::string &executePath, const std::string &commandLineArguments)
|
||||
{
|
||||
PlayerTaskWin *task = new PlayerTaskWin(name, executePath, commandLineArguments);
|
||||
task->autorelease();
|
||||
return task;
|
||||
}
|
||||
|
||||
PlayerTaskWin::PlayerTaskWin(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments)
|
||||
: PlayerTask(name, executePath, commandLineArguments)
|
||||
, _childStdInRead(NULL)
|
||||
, _childStdInWrite(NULL)
|
||||
, _childStdOutRead(NULL)
|
||||
, _childStdOutWrite(NULL)
|
||||
, _outputBuff(NULL)
|
||||
, _outputBuffWide(NULL)
|
||||
{
|
||||
ZeroMemory(&_pi, sizeof(_pi));
|
||||
}
|
||||
|
||||
PlayerTaskWin::~PlayerTaskWin()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
bool PlayerTaskWin::run()
|
||||
{
|
||||
if (!isIdle())
|
||||
{
|
||||
CCLOG("PlayerTaskWin::run() - task is not idle");
|
||||
return false;
|
||||
}
|
||||
|
||||
//BOOL WINAPI CreateProcess(
|
||||
// _In_opt_ LPCTSTR lpApplicationName,
|
||||
// _Inout_opt_ LPTSTR lpCommandLine,
|
||||
// _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
// _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
// _In_ BOOL bInheritHandles,
|
||||
// _In_ DWORD dwCreationFlags,
|
||||
// _In_opt_ LPVOID lpEnvironment,
|
||||
// _In_opt_ LPCTSTR lpCurrentDirectory,
|
||||
// _In_ LPSTARTUPINFO lpStartupInfo,
|
||||
// _Out_ LPPROCESS_INFORMATION lpProcessInformation
|
||||
//);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
|
||||
SECURITY_ATTRIBUTES sa = {0};
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.bInheritHandle = TRUE;
|
||||
|
||||
// Create a pipe for the child process's STDOUT.
|
||||
if (!CreatePipe(&_childStdOutRead, &_childStdOutWrite, &sa, 0) || !SetHandleInformation(_childStdOutRead, HANDLE_FLAG_INHERIT, 0))
|
||||
{
|
||||
CCLOG("PlayerTaskWin::run() - create stdout handle failed, for execute %s", _executePath.c_str());
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a pipe for the child process's STDIN.
|
||||
if (!CreatePipe(&_childStdInRead, &_childStdInWrite, &sa, 0) || !SetHandleInformation(_childStdInWrite, HANDLE_FLAG_INHERIT, 0))
|
||||
{
|
||||
CCLOG("PlayerTaskWin::run() - create stdout handle failed, for execute %s", _executePath.c_str());
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
ZeroMemory(&_pi, sizeof(_pi));
|
||||
STARTUPINFO si = {0};
|
||||
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.hStdError = _childStdOutWrite;
|
||||
si.hStdOutput = _childStdOutWrite;
|
||||
si.hStdInput = _childStdInRead;
|
||||
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
|
||||
#define MAX_COMMAND 4096 //MAX_PATH
|
||||
const std::u16string u16command = makeCommandLine();
|
||||
WCHAR command[MAX_COMMAND];
|
||||
wcscpy_s(command, MAX_COMMAND, (WCHAR*)u16command.c_str());
|
||||
|
||||
BOOL success = CreateProcess(NULL,
|
||||
command, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&si, // STARTUPINFO pointer
|
||||
&_pi); // receives PROCESS_INFORMATION
|
||||
|
||||
if (!success)
|
||||
{
|
||||
CCLOG("PlayerTaskWin::run() - create process failed, for execute %s", _executePath.c_str());
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
_outputBuff = new CHAR[BUFF_SIZE + 1];
|
||||
_outputBuffWide = new WCHAR[BUFF_SIZE];
|
||||
_state = STATE_RUNNING;
|
||||
|
||||
// cocos2d::Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerTaskWin::runInTerminal()
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf << "/K ";
|
||||
buf << _executePath;
|
||||
buf << " ";
|
||||
buf << _commandLineArguments;
|
||||
|
||||
std::u16string u16command;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(buf.str(), u16command);
|
||||
|
||||
ShellExecute(NULL, NULL, L"CMD.EXE", (WCHAR*)u16command.c_str(), NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
void PlayerTaskWin::stop()
|
||||
{
|
||||
if (_pi.hProcess)
|
||||
{
|
||||
TerminateProcess(_pi.hProcess, 0);
|
||||
_resultCode = -1;
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void PlayerTaskWin::update(float dt)
|
||||
{
|
||||
_lifetime += dt;
|
||||
|
||||
// read output
|
||||
for (;;)
|
||||
{
|
||||
DWORD readCount = 0;
|
||||
PeekNamedPipe(_childStdOutRead, NULL, NULL, NULL, &readCount, NULL);
|
||||
if (readCount == 0) break;
|
||||
if (_output.length() > MAX_LOG_LENGTH) break;
|
||||
|
||||
readCount = 0;
|
||||
ZeroMemory(_outputBuff, BUFF_SIZE + 1);
|
||||
BOOL success = ReadFile(_childStdOutRead, _outputBuff, BUFF_SIZE - 1, &readCount, NULL);
|
||||
if (!success || readCount == 0) break;
|
||||
|
||||
int chars = MultiByteToWideChar(CP_OEMCP, 0, _outputBuff, readCount, _outputBuffWide, BUFF_SIZE);
|
||||
if (chars)
|
||||
{
|
||||
ZeroMemory(_outputBuff, BUFF_SIZE + 1);
|
||||
WideCharToMultiByte(CP_UTF8, 0, _outputBuffWide, chars, _outputBuff, BUFF_SIZE + 1, 0, NULL);
|
||||
_output.append(_outputBuff);
|
||||
if (_output.length() > MAX_LOG_LENGTH) break;
|
||||
}
|
||||
}
|
||||
|
||||
// get child process exit code
|
||||
DWORD resultCode = 0;
|
||||
if (GetExitCodeProcess(_pi.hProcess, &resultCode))
|
||||
{
|
||||
if (resultCode == STILL_ACTIVE) return;
|
||||
_resultCode = (int)resultCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unexpected error
|
||||
_resultCode = (int)GetLastError();
|
||||
}
|
||||
|
||||
// cocos2d::Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void PlayerTaskWin::cleanup()
|
||||
{
|
||||
if (_pi.hProcess) CloseHandle(_pi.hProcess);
|
||||
if (_pi.hThread) CloseHandle(_pi.hThread);
|
||||
ZeroMemory(&_pi, sizeof(_pi));
|
||||
|
||||
if (_outputBuff) delete[] _outputBuff;
|
||||
_outputBuff = NULL;
|
||||
if (_outputBuffWide) delete[] _outputBuffWide;
|
||||
_outputBuffWide = NULL;
|
||||
|
||||
if (_childStdOutRead) CloseHandle(_childStdOutRead);
|
||||
if (_childStdOutWrite) CloseHandle(_childStdOutWrite);
|
||||
if (_childStdInRead) CloseHandle(_childStdInRead);
|
||||
if (_childStdInWrite) CloseHandle(_childStdInWrite);
|
||||
|
||||
_childStdOutRead = NULL;
|
||||
_childStdOutWrite = NULL;
|
||||
_childStdInRead = NULL;
|
||||
_childStdInWrite = NULL;
|
||||
|
||||
_state = STATE_COMPLETED;
|
||||
|
||||
CCLOG("CMD: %s", _output.c_str());
|
||||
|
||||
// cocos2d::Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(_name);
|
||||
}
|
||||
|
||||
std::u16string PlayerTaskWin::makeCommandLine() const
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf << "\"";
|
||||
buf << _executePath;
|
||||
buf << "\" ";
|
||||
buf << _commandLineArguments;
|
||||
|
||||
std::u16string u16command;
|
||||
cocos2d::StringUtils::UTF8ToUTF16(buf.str(), u16command);
|
||||
return u16command;
|
||||
}
|
||||
|
||||
PlayerTaskServiceWin::PlayerTaskServiceWin(HWND hwnd)
|
||||
: _hwnd(hwnd)
|
||||
{
|
||||
}
|
||||
|
||||
PlayerTaskServiceWin::~PlayerTaskServiceWin()
|
||||
{
|
||||
for (auto it = _tasks.begin(); it != _tasks.end(); ++it)
|
||||
{
|
||||
it->second->stop();
|
||||
}
|
||||
}
|
||||
|
||||
PlayerTask *PlayerTaskServiceWin::createTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments)
|
||||
{
|
||||
CCASSERT(_tasks.find(name) == _tasks.end(), "Task already exists.");
|
||||
PlayerTaskWin *task = PlayerTaskWin::create(name, executePath, commandLineArguments);
|
||||
_tasks.insert(name, task);
|
||||
return task;
|
||||
}
|
||||
|
||||
PlayerTask *PlayerTaskServiceWin::getTask(const std::string &name)
|
||||
{
|
||||
auto it = _tasks.find(name);
|
||||
return it != _tasks.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
void PlayerTaskServiceWin::removeTask(const std::string &name)
|
||||
{
|
||||
auto it = _tasks.find(name);
|
||||
if (it != _tasks.end())
|
||||
{
|
||||
if (!it->second->isCompleted())
|
||||
{
|
||||
it->second->stop();
|
||||
}
|
||||
_tasks.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PLAYER_TASK_SERVICE_WIN_H_
|
||||
#define __PLAYER_TASK_SERVICE_WIN_H_
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "PlayerTaskServiceProtocol.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class PlayerTaskWin : public PlayerTask
|
||||
{
|
||||
public:
|
||||
static PlayerTaskWin *create(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
|
||||
virtual ~PlayerTaskWin();
|
||||
|
||||
virtual bool run();
|
||||
virtual void stop();
|
||||
virtual void runInTerminal();
|
||||
|
||||
// check task status
|
||||
virtual void update(float dt);
|
||||
|
||||
protected:
|
||||
PlayerTaskWin(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
|
||||
void cleanup();
|
||||
std::u16string makeCommandLine() const;
|
||||
|
||||
HANDLE _childStdInRead;
|
||||
HANDLE _childStdInWrite;
|
||||
HANDLE _childStdOutRead;
|
||||
HANDLE _childStdOutWrite;
|
||||
PROCESS_INFORMATION _pi;
|
||||
|
||||
static const size_t BUFF_SIZE = 4096;
|
||||
CHAR *_outputBuff;
|
||||
WCHAR *_outputBuffWide;
|
||||
};
|
||||
|
||||
class PlayerTaskServiceWin : public PlayerTaskServiceProtocol
|
||||
{
|
||||
public:
|
||||
PlayerTaskServiceWin(HWND hwnd);
|
||||
virtual ~PlayerTaskServiceWin();
|
||||
|
||||
virtual PlayerTask *createTask(const std::string &name,
|
||||
const std::string &executePath,
|
||||
const std::string &commandLineArguments);
|
||||
virtual PlayerTask *getTask(const std::string &name);
|
||||
virtual void removeTask(const std::string &name);
|
||||
|
||||
protected:
|
||||
HWND _hwnd;
|
||||
cocos2d::Map<std::string, PlayerTaskWin*> _tasks;
|
||||
};
|
||||
|
||||
PLAYER_NS_END
|
||||
|
||||
#endif // __PLAYER_TASK_SERVICE_WIN_H_
|
||||
93
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/PlayerWin.cpp
Executable file
93
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/PlayerWin.cpp
Executable file
@@ -0,0 +1,93 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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 "PlayerWin.h"
|
||||
|
||||
USING_NS_CC;
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
PlayerWin::PlayerWin()
|
||||
: PlayerProtocol()
|
||||
, _messageBoxService(nullptr)
|
||||
, _menuService(nullptr)
|
||||
, _editboxService(nullptr)
|
||||
, _taskService(nullptr)
|
||||
, _hwnd(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PlayerWin::~PlayerWin()
|
||||
{
|
||||
CC_SAFE_DELETE(_menuService);
|
||||
CC_SAFE_DELETE(_messageBoxService);
|
||||
CC_SAFE_DELETE(_fileDialogService);
|
||||
}
|
||||
|
||||
PlayerWin *PlayerWin::createWithHwnd(HWND hWnd)
|
||||
{
|
||||
auto instance = new PlayerWin();
|
||||
instance->_hwnd = hWnd;
|
||||
instance->initServices();
|
||||
return instance;
|
||||
}
|
||||
|
||||
PlayerFileDialogServiceProtocol *PlayerWin::getFileDialogService()
|
||||
{
|
||||
return _fileDialogService;
|
||||
}
|
||||
|
||||
PlayerMessageBoxServiceProtocol *PlayerWin::getMessageBoxService()
|
||||
{
|
||||
return _messageBoxService;
|
||||
}
|
||||
|
||||
PlayerMenuServiceProtocol *PlayerWin::getMenuService()
|
||||
{
|
||||
return _menuService;
|
||||
}
|
||||
|
||||
PlayerEditBoxServiceProtocol *PlayerWin::getEditBoxService()
|
||||
{
|
||||
return _editboxService;
|
||||
}
|
||||
|
||||
PlayerTaskServiceProtocol *PlayerWin::getTaskService()
|
||||
{
|
||||
return _taskService;
|
||||
}
|
||||
|
||||
// services
|
||||
void PlayerWin::initServices()
|
||||
{
|
||||
CCASSERT(_menuService == nullptr, "CAN'T INITIALIZATION SERVICES MORE THAN ONCE");
|
||||
_menuService = new PlayerMenuServiceWin(_hwnd);
|
||||
_messageBoxService = new PlayerMessageBoxServiceWin(_hwnd);
|
||||
_fileDialogService = new PlayerFileDialogServiceWin(_hwnd);
|
||||
_editboxService = new PlayerEditBoxServiceWin(_hwnd);
|
||||
_taskService = new PlayerTaskServiceWin(_hwnd);
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
69
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/PlayerWin.h
Executable file
69
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/PlayerWin.h
Executable file
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cocos2d.h"
|
||||
|
||||
#include "PlayerMacros.h"
|
||||
#include "PlayerProtocol.h"
|
||||
#include "PlayerMenuServiceWin.h"
|
||||
#include "PlayerMessageBoxServiceWin.h"
|
||||
#include "PlayerFileDialogServiceWin.h"
|
||||
#include "PlayerEditBoxServiceWin.h"
|
||||
#include "PlayerTaskServiceWin.h"
|
||||
#include "SimulatorExport.h"
|
||||
|
||||
PLAYER_NS_BEGIN
|
||||
|
||||
class CC_LIBSIM_DLL PlayerWin : public PlayerProtocol, public cocos2d::Ref
|
||||
{
|
||||
public:
|
||||
static PlayerWin *createWithHwnd(HWND hWnd);
|
||||
virtual ~PlayerWin();
|
||||
|
||||
virtual PlayerFileDialogServiceProtocol *getFileDialogService();
|
||||
virtual PlayerMessageBoxServiceProtocol *getMessageBoxService();
|
||||
virtual PlayerMenuServiceProtocol *getMenuService();
|
||||
virtual PlayerEditBoxServiceProtocol *getEditBoxService();
|
||||
virtual PlayerTaskServiceProtocol *getTaskService();
|
||||
|
||||
protected:
|
||||
PlayerWin();
|
||||
|
||||
// services
|
||||
void initServices();
|
||||
|
||||
PlayerMenuServiceWin *_menuService;
|
||||
PlayerMessageBoxServiceWin *_messageBoxService;
|
||||
PlayerFileDialogServiceWin *_fileDialogService;
|
||||
PlayerEditBoxServiceWin *_editboxService;
|
||||
PlayerTaskServiceWin *_taskService;
|
||||
|
||||
HWND _hwnd;
|
||||
};
|
||||
|
||||
|
||||
PLAYER_NS_END
|
||||
834
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/SimulatorWin.cpp
Executable file
834
cocos2d-x/tools/simulator/libsimulator/lib/platform/win32/SimulatorWin.cpp
Executable file
@@ -0,0 +1,834 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <io.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <Commdlg.h>
|
||||
#include <Shlobj.h>
|
||||
#include <winnls.h>
|
||||
#include <shobjidl.h>
|
||||
#include <objbase.h>
|
||||
#include <objidl.h>
|
||||
#include <shlguid.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include "SimulatorWin.h"
|
||||
|
||||
#include "glfw3.h"
|
||||
#include "glfw3native.h"
|
||||
|
||||
#include "CCLuaEngine.h"
|
||||
#include "AppEvent.h"
|
||||
#include "AppLang.h"
|
||||
#include "ConfigParser.h"
|
||||
|
||||
USING_NS_CC;
|
||||
|
||||
static WNDPROC g_oldWindowProc = NULL;
|
||||
INT_PTR CALLBACK AboutDialogCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
return (INT_PTR)TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||||
{
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return (INT_PTR)TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (INT_PTR)FALSE;
|
||||
}
|
||||
void onHelpAbout()
|
||||
{
|
||||
DialogBox(GetModuleHandle(NULL),
|
||||
MAKEINTRESOURCE(IDD_DIALOG_ABOUT),
|
||||
Director::getInstance()->getOpenGLView()->getWin32Window(),
|
||||
AboutDialogCallback);
|
||||
}
|
||||
|
||||
void shutDownApp()
|
||||
{
|
||||
auto glview = dynamic_cast<GLViewImpl*> (Director::getInstance()->getOpenGLView());
|
||||
HWND hWnd = glview->getWin32Window();
|
||||
::SendMessage(hWnd, WM_CLOSE, NULL, NULL);
|
||||
}
|
||||
|
||||
std::string getCurAppPath(void)
|
||||
{
|
||||
TCHAR szAppDir[MAX_PATH] = { 0 };
|
||||
if (!GetModuleFileName(NULL, szAppDir, MAX_PATH))
|
||||
return "";
|
||||
int nEnd = 0;
|
||||
for (int i = 0; szAppDir[i]; i++)
|
||||
{
|
||||
if (szAppDir[i] == '\\')
|
||||
nEnd = i;
|
||||
}
|
||||
szAppDir[nEnd] = 0;
|
||||
int iLen = 2 * wcslen(szAppDir);
|
||||
char* chRtn = new char[iLen + 1];
|
||||
wcstombs(chRtn, szAppDir, iLen + 1);
|
||||
std::string strPath = chRtn;
|
||||
delete[] chRtn;
|
||||
chRtn = NULL;
|
||||
char fuldir[MAX_PATH] = { 0 };
|
||||
_fullpath(fuldir, strPath.c_str(), MAX_PATH);
|
||||
return fuldir;
|
||||
}
|
||||
|
||||
static void initGLContextAttrs()
|
||||
{
|
||||
//set OpenGL context attributions,now can only set six attributions:
|
||||
//red,green,blue,alpha,depth,stencil
|
||||
GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};
|
||||
|
||||
GLView::setGLContextAttrs(glContextAttrs);
|
||||
}
|
||||
|
||||
SimulatorWin *SimulatorWin::_instance = nullptr;
|
||||
|
||||
SimulatorWin *SimulatorWin::getInstance()
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
_instance = new SimulatorWin();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
SimulatorWin::SimulatorWin()
|
||||
: _app(nullptr)
|
||||
, _hwnd(NULL)
|
||||
, _hwndConsole(NULL)
|
||||
, _writeDebugLogFile(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
SimulatorWin::~SimulatorWin()
|
||||
{
|
||||
CC_SAFE_DELETE(_app);
|
||||
if (_writeDebugLogFile)
|
||||
{
|
||||
fclose(_writeDebugLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorWin::quit()
|
||||
{
|
||||
Director::getInstance()->end();
|
||||
}
|
||||
|
||||
void SimulatorWin::relaunch()
|
||||
{
|
||||
_project.setWindowOffset(Vec2(getPositionX(), getPositionY()));
|
||||
openNewPlayerWithProjectConfig(_project);
|
||||
|
||||
quit();
|
||||
}
|
||||
|
||||
void SimulatorWin::openNewPlayer()
|
||||
{
|
||||
openNewPlayerWithProjectConfig(_project);
|
||||
}
|
||||
|
||||
void SimulatorWin::openNewPlayerWithProjectConfig(const ProjectConfig &config)
|
||||
{
|
||||
static long taskid = 100;
|
||||
stringstream buf;
|
||||
buf << taskid++;
|
||||
|
||||
string commandLine;
|
||||
commandLine.append(getApplicationExePath());
|
||||
commandLine.append(" ");
|
||||
commandLine.append(config.makeCommandLine());
|
||||
|
||||
CCLOG("SimulatorWin::openNewPlayerWithProjectConfig(): %s", commandLine.c_str());
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
|
||||
SECURITY_ATTRIBUTES sa = {0};
|
||||
sa.nLength = sizeof(sa);
|
||||
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
STARTUPINFO si = {0};
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
|
||||
#define MAX_COMMAND 1024 // lenth of commandLine is always beyond MAX_PATH
|
||||
|
||||
WCHAR command[MAX_COMMAND];
|
||||
memset(command, 0, sizeof(command));
|
||||
MultiByteToWideChar(CP_UTF8, 0, commandLine.c_str(), -1, command, MAX_COMMAND);
|
||||
|
||||
BOOL success = CreateProcess(NULL,
|
||||
command, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
FALSE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&si, // STARTUPINFO pointer
|
||||
&pi); // receives PROCESS_INFORMATION
|
||||
|
||||
if (!success)
|
||||
{
|
||||
CCLOG("PlayerTaskWin::run() - create process failed, for execute %s", commandLine.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorWin::openProjectWithProjectConfig(const ProjectConfig &config)
|
||||
{
|
||||
openNewPlayerWithProjectConfig(config);
|
||||
quit();
|
||||
}
|
||||
|
||||
int SimulatorWin::getPositionX()
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(_hwnd, &rect);
|
||||
return rect.left;
|
||||
}
|
||||
|
||||
int SimulatorWin::getPositionY()
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(_hwnd, &rect);
|
||||
return rect.top;
|
||||
}
|
||||
|
||||
int SimulatorWin::run()
|
||||
{
|
||||
auto player = player::PlayerWin::create();
|
||||
|
||||
INITCOMMONCONTROLSEX InitCtrls;
|
||||
InitCtrls.dwSize = sizeof(InitCtrls);
|
||||
InitCtrls.dwICC = ICC_WIN95_CLASSES;
|
||||
InitCommonControlsEx(&InitCtrls);
|
||||
|
||||
parseCocosProjectConfig(_project);
|
||||
|
||||
// load project config from command line args
|
||||
vector<string> args;
|
||||
for (int i = 0; i < __argc; ++i)
|
||||
{
|
||||
wstring ws(__wargv[i]);
|
||||
string s;
|
||||
s.assign(ws.begin(), ws.end());
|
||||
args.push_back(s);
|
||||
}
|
||||
_project.parseCommandLine(args);
|
||||
|
||||
if (_project.getProjectDir().empty())
|
||||
{
|
||||
if (args.size() == 2)
|
||||
{
|
||||
// for Code IDE before RC2
|
||||
_project.setProjectDir(args.at(1));
|
||||
_project.setDebuggerType(kCCRuntimeDebuggerCodeIDE);
|
||||
}
|
||||
}
|
||||
|
||||
// create the application instance
|
||||
_app = new AppDelegate();
|
||||
_app->setProjectConfig(_project);
|
||||
|
||||
// create console window
|
||||
if (_project.isShowConsole())
|
||||
{
|
||||
AllocConsole();
|
||||
_hwndConsole = GetConsoleWindow();
|
||||
if (_hwndConsole != NULL)
|
||||
{
|
||||
ShowWindow(_hwndConsole, SW_SHOW);
|
||||
BringWindowToTop(_hwndConsole);
|
||||
freopen("CONOUT$", "wt", stdout);
|
||||
freopen("CONOUT$", "wt", stderr);
|
||||
|
||||
HMENU hmenu = GetSystemMenu(_hwndConsole, FALSE);
|
||||
if (hmenu != NULL)
|
||||
{
|
||||
DeleteMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log file
|
||||
if (_project.isWriteDebugLogToFile())
|
||||
{
|
||||
const string debugLogFilePath = _project.getDebugLogFilePath();
|
||||
_writeDebugLogFile = fopen(debugLogFilePath.c_str(), "w");
|
||||
if (!_writeDebugLogFile)
|
||||
{
|
||||
CCLOG("Cannot create debug log file %s", debugLogFilePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// set environments
|
||||
SetCurrentDirectoryA(_project.getProjectDir().c_str());
|
||||
FileUtils::getInstance()->setDefaultResourceRootPath(_project.getProjectDir());
|
||||
FileUtils::getInstance()->setWritablePath(_project.getWritableRealPath().c_str());
|
||||
|
||||
// check screen DPI
|
||||
HDC screen = GetDC(0);
|
||||
int dpi = GetDeviceCaps(screen, LOGPIXELSX);
|
||||
ReleaseDC(0, screen);
|
||||
|
||||
// set scale with DPI
|
||||
// 96 DPI = 100 % scaling
|
||||
// 120 DPI = 125 % scaling
|
||||
// 144 DPI = 150 % scaling
|
||||
// 192 DPI = 200 % scaling
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx#dpi_and_the_desktop_scaling_factor
|
||||
//
|
||||
// enable DPI-Aware with DeclareDPIAware.manifest
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx#declaring_dpi_awareness
|
||||
float screenScale = 1.0f;
|
||||
if (dpi >= 120 && dpi < 144)
|
||||
{
|
||||
screenScale = 1.25f;
|
||||
}
|
||||
else if (dpi >= 144 && dpi < 192)
|
||||
{
|
||||
screenScale = 1.5f;
|
||||
}
|
||||
else if (dpi >= 192)
|
||||
{
|
||||
screenScale = 2.0f;
|
||||
}
|
||||
CCLOG("SCREEN DPI = %d, SCREEN SCALE = %0.2f", dpi, screenScale);
|
||||
|
||||
// create opengl view
|
||||
Size frameSize = _project.getFrameSize();
|
||||
float frameScale = 1.0f;
|
||||
if (_project.isRetinaDisplay())
|
||||
{
|
||||
frameSize.width *= screenScale;
|
||||
frameSize.height *= screenScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
frameScale = screenScale;
|
||||
}
|
||||
|
||||
const Rect frameRect = Rect(0, 0, frameSize.width, frameSize.height);
|
||||
const bool isResize = _project.isResizeWindow();
|
||||
std::stringstream title;
|
||||
title << "Cocos Simulator - " << ConfigParser::getInstance()->getInitViewName();
|
||||
initGLContextAttrs();
|
||||
auto glview = GLViewImpl::createWithRect(title.str(), frameRect, frameScale, true);
|
||||
_hwnd = glview->getWin32Window();
|
||||
DragAcceptFiles(_hwnd, TRUE);
|
||||
//SendMessage(_hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
||||
//SendMessage(_hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
||||
//FreeResource(icon);
|
||||
|
||||
auto director = Director::getInstance();
|
||||
director->setOpenGLView(glview);
|
||||
|
||||
director->setAnimationInterval(1.0 / 60.0);
|
||||
|
||||
// set window position
|
||||
if (_project.getProjectDir().length())
|
||||
{
|
||||
setZoom(_project.getFrameScale());
|
||||
}
|
||||
Vec2 pos = _project.getWindowOffset();
|
||||
if (pos.x != 0 && pos.y != 0)
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(_hwnd, &rect);
|
||||
MoveWindow(_hwnd, pos.x, pos.y, rect.right - rect.left, rect.bottom - rect.top, FALSE);
|
||||
}
|
||||
|
||||
// path for looking Lang file, Studio Default images
|
||||
FileUtils::getInstance()->addSearchPath(getApplicationPath().c_str());
|
||||
|
||||
// init player services
|
||||
initServices();
|
||||
setupUI();
|
||||
DrawMenuBar(_hwnd);
|
||||
|
||||
// prepare
|
||||
FileUtils::getInstance()->setPopupNotify(false);
|
||||
_project.dump();
|
||||
auto app = Application::getInstance();
|
||||
|
||||
g_oldWindowProc = (WNDPROC)SetWindowLong(_hwnd, GWL_WNDPROC, (LONG)SimulatorWin::windowProc);
|
||||
|
||||
// update window size
|
||||
RECT rect;
|
||||
GetWindowRect(_hwnd, &rect);
|
||||
MoveWindow(_hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + GetSystemMetrics(SM_CYMENU), FALSE);
|
||||
|
||||
// startup message loop
|
||||
return app->run();
|
||||
}
|
||||
|
||||
// services
|
||||
|
||||
void SimulatorWin::setupUI()
|
||||
{
|
||||
auto menuBar = player::PlayerProtocol::getInstance()->getMenuService();
|
||||
|
||||
// FILE
|
||||
menuBar->addItem("FILE_MENU", tr("File"));
|
||||
menuBar->addItem("EXIT_MENU", tr("Exit"), "FILE_MENU");
|
||||
|
||||
// VIEW
|
||||
menuBar->addItem("VIEW_MENU", tr("View"));
|
||||
SimulatorConfig *config = SimulatorConfig::getInstance();
|
||||
int current = config->checkScreenSize(_project.getFrameSize());
|
||||
for (int i = 0; i < config->getScreenSizeCount(); i++)
|
||||
{
|
||||
SimulatorScreenSize size = config->getScreenSize(i);
|
||||
std::stringstream menuId;
|
||||
menuId << "VIEWSIZE_ITEM_MENU_" << i;
|
||||
auto menuItem = menuBar->addItem(menuId.str(), size.title.c_str(), "VIEW_MENU");
|
||||
|
||||
if (i == current)
|
||||
{
|
||||
menuItem->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
menuBar->addItem("DIRECTION_MENU_SEP", "-", "VIEW_MENU");
|
||||
menuBar->addItem("DIRECTION_PORTRAIT_MENU", tr("Portrait"), "VIEW_MENU")
|
||||
->setChecked(_project.isPortraitFrame());
|
||||
menuBar->addItem("DIRECTION_LANDSCAPE_MENU", tr("Landscape"), "VIEW_MENU")
|
||||
->setChecked(_project.isLandscapeFrame());
|
||||
|
||||
menuBar->addItem("VIEW_SCALE_MENU_SEP", "-", "VIEW_MENU");
|
||||
std::vector<player::PlayerMenuItem*> scaleMenuVector;
|
||||
auto scale100Menu = menuBar->addItem("VIEW_SCALE_MENU_100", tr("Zoom Out").append(" (100%)"), "VIEW_MENU");
|
||||
auto scale75Menu = menuBar->addItem("VIEW_SCALE_MENU_75", tr("Zoom Out").append(" (75%)"), "VIEW_MENU");
|
||||
auto scale50Menu = menuBar->addItem("VIEW_SCALE_MENU_50", tr("Zoom Out").append(" (50%)"), "VIEW_MENU");
|
||||
auto scale25Menu = menuBar->addItem("VIEW_SCALE_MENU_25", tr("Zoom Out").append(" (25%)"), "VIEW_MENU");
|
||||
int frameScale = int(_project.getFrameScale() * 100);
|
||||
if (frameScale == 100)
|
||||
{
|
||||
scale100Menu->setChecked(true);
|
||||
}
|
||||
else if (frameScale == 75)
|
||||
{
|
||||
scale75Menu->setChecked(true);
|
||||
}
|
||||
else if (frameScale == 50)
|
||||
{
|
||||
scale50Menu->setChecked(true);
|
||||
}
|
||||
else if (frameScale == 25)
|
||||
{
|
||||
scale25Menu->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
scale100Menu->setChecked(true);
|
||||
}
|
||||
|
||||
scaleMenuVector.push_back(scale100Menu);
|
||||
scaleMenuVector.push_back(scale75Menu);
|
||||
scaleMenuVector.push_back(scale50Menu);
|
||||
scaleMenuVector.push_back(scale25Menu);
|
||||
|
||||
menuBar->addItem("REFRESH_MENU_SEP", "-", "VIEW_MENU");
|
||||
menuBar->addItem("REFRESH_MENU", tr("Refresh"), "VIEW_MENU");
|
||||
|
||||
HWND &hwnd = _hwnd;
|
||||
ProjectConfig &project = _project;
|
||||
auto dispatcher = Director::getInstance()->getEventDispatcher();
|
||||
dispatcher->addEventListenerWithFixedPriority(EventListenerCustom::create("APP.EVENT", [&project, &hwnd, scaleMenuVector](EventCustom* event){
|
||||
auto menuEvent = dynamic_cast<AppEvent*>(event);
|
||||
if (menuEvent)
|
||||
{
|
||||
rapidjson::Document dArgParse;
|
||||
dArgParse.Parse<0>(menuEvent->getDataString().c_str());
|
||||
if (dArgParse.HasMember("name"))
|
||||
{
|
||||
string strcmd = dArgParse["name"].GetString();
|
||||
|
||||
if (strcmd == "menuClicked")
|
||||
{
|
||||
player::PlayerMenuItem *menuItem = static_cast<player::PlayerMenuItem*>(menuEvent->getUserData());
|
||||
if (menuItem)
|
||||
{
|
||||
if (menuItem->isChecked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string data = dArgParse["data"].GetString();
|
||||
auto player = player::PlayerProtocol::getInstance();
|
||||
|
||||
if ((data == "CLOSE_MENU") || (data == "EXIT_MENU"))
|
||||
{
|
||||
player->quit();
|
||||
}
|
||||
else if (data == "REFRESH_MENU")
|
||||
{
|
||||
player->relaunch();
|
||||
}
|
||||
else if (data.find("VIEW_SCALE_MENU_") == 0) // begin with VIEW_SCALE_MENU_
|
||||
{
|
||||
string tmp = data.erase(0, strlen("VIEW_SCALE_MENU_"));
|
||||
float scale = atof(tmp.c_str()) / 100.0f;
|
||||
project.setFrameScale(scale);
|
||||
|
||||
auto glview = static_cast<GLViewImpl*>(Director::getInstance()->getOpenGLView());
|
||||
glview->setFrameZoomFactor(scale);
|
||||
|
||||
// update scale menu state
|
||||
for (auto &it : scaleMenuVector)
|
||||
{
|
||||
it->setChecked(false);
|
||||
}
|
||||
menuItem->setChecked(true);
|
||||
|
||||
// update window size
|
||||
RECT rect;
|
||||
GetWindowRect(hwnd, &rect);
|
||||
MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + GetSystemMetrics(SM_CYMENU), FALSE);
|
||||
|
||||
// fix: can not update window on some windows system
|
||||
::SendMessage(hwnd, WM_MOVE, NULL, NULL);
|
||||
}
|
||||
else if (data.find("VIEWSIZE_ITEM_MENU_") == 0) // begin with VIEWSIZE_ITEM_MENU_
|
||||
{
|
||||
string tmp = data.erase(0, strlen("VIEWSIZE_ITEM_MENU_"));
|
||||
int index = atoi(tmp.c_str());
|
||||
SimulatorScreenSize size = SimulatorConfig::getInstance()->getScreenSize(index);
|
||||
|
||||
if (project.isLandscapeFrame())
|
||||
{
|
||||
std::swap(size.width, size.height);
|
||||
}
|
||||
|
||||
project.setFrameSize(cocos2d::Size(size.width, size.height));
|
||||
project.setWindowOffset(cocos2d::Vec2(player->getPositionX(), player->getPositionY()));
|
||||
player->openProjectWithProjectConfig(project);
|
||||
}
|
||||
else if (data == "DIRECTION_PORTRAIT_MENU")
|
||||
{
|
||||
project.changeFrameOrientationToPortait();
|
||||
player->openProjectWithProjectConfig(project);
|
||||
}
|
||||
else if (data == "DIRECTION_LANDSCAPE_MENU")
|
||||
{
|
||||
project.changeFrameOrientationToLandscape();
|
||||
player->openProjectWithProjectConfig(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}), 1);
|
||||
|
||||
AppDelegate *app = _app;
|
||||
auto listener = EventListenerCustom::create(kAppEventDropName, [&project, app](EventCustom* event)
|
||||
{
|
||||
AppEvent *dropEvent = dynamic_cast<AppEvent*>(event);
|
||||
if (dropEvent)
|
||||
{
|
||||
string dirPath = dropEvent->getDataString() + "/";
|
||||
string configFilePath = dirPath + CONFIG_FILE;
|
||||
|
||||
if (FileUtils::getInstance()->isDirectoryExist(dirPath) &&
|
||||
FileUtils::getInstance()->isFileExist(configFilePath))
|
||||
{
|
||||
// parse config.json
|
||||
ConfigParser::getInstance()->readConfig(configFilePath);
|
||||
|
||||
project.setProjectDir(dirPath);
|
||||
project.setScriptFile(ConfigParser::getInstance()->getEntryFile());
|
||||
project.setWritablePath(dirPath);
|
||||
|
||||
app->setProjectConfig(project);
|
||||
app->reopenProject();
|
||||
}
|
||||
}
|
||||
});
|
||||
dispatcher->addEventListenerWithFixedPriority(listener, 1);
|
||||
}
|
||||
|
||||
void SimulatorWin::setZoom(float frameScale)
|
||||
{
|
||||
_project.setFrameScale(frameScale);
|
||||
cocos2d::Director::getInstance()->getOpenGLView()->setFrameZoomFactor(frameScale);
|
||||
}
|
||||
|
||||
// debug log
|
||||
void SimulatorWin::writeDebugLog(const char *log)
|
||||
{
|
||||
if (!_writeDebugLogFile) return;
|
||||
|
||||
fputs(log, _writeDebugLogFile);
|
||||
fputc('\n', _writeDebugLogFile);
|
||||
fflush(_writeDebugLogFile);
|
||||
}
|
||||
|
||||
void SimulatorWin::parseCocosProjectConfig(ProjectConfig &config)
|
||||
{
|
||||
// get project directory
|
||||
ProjectConfig tmpConfig;
|
||||
// load project config from command line args
|
||||
vector<string> args;
|
||||
for (int i = 0; i < __argc; ++i)
|
||||
{
|
||||
wstring ws(__wargv[i]);
|
||||
string s;
|
||||
s.assign(ws.begin(), ws.end());
|
||||
args.push_back(s);
|
||||
}
|
||||
|
||||
if (args.size() >= 2)
|
||||
{
|
||||
if (args.size() && args.at(1).at(0) == '/')
|
||||
{
|
||||
// IDEA:
|
||||
// for Code IDE before RC2
|
||||
tmpConfig.setProjectDir(args.at(1));
|
||||
}
|
||||
|
||||
tmpConfig.parseCommandLine(args);
|
||||
}
|
||||
|
||||
// set project directory as search root path
|
||||
FileUtils::getInstance()->setDefaultResourceRootPath(tmpConfig.getProjectDir().c_str());
|
||||
|
||||
// parse config.json
|
||||
auto parser = ConfigParser::getInstance();
|
||||
auto configPath = tmpConfig.getProjectDir().append(CONFIG_FILE);
|
||||
parser->readConfig(configPath);
|
||||
|
||||
// set information
|
||||
config.setConsolePort(parser->getConsolePort());
|
||||
config.setFileUploadPort(parser->getUploadPort());
|
||||
config.setFrameSize(parser->getInitViewSize());
|
||||
if (parser->isLanscape())
|
||||
{
|
||||
config.changeFrameOrientationToLandscape();
|
||||
}
|
||||
else
|
||||
{
|
||||
config.changeFrameOrientationToPortait();
|
||||
}
|
||||
config.setScriptFile(parser->getEntryFile());
|
||||
}
|
||||
|
||||
//
|
||||
// D:\aaa\bbb\ccc\ddd\abc.txt --> D:/aaa/bbb/ccc/ddd/abc.txt
|
||||
//
|
||||
std::string SimulatorWin::convertPathFormatToUnixStyle(const std::string& path)
|
||||
{
|
||||
std::string ret = path;
|
||||
int len = ret.length();
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (ret[i] == '\\')
|
||||
{
|
||||
ret[i] = '/';
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// @return: C:/Users/win8/Documents/
|
||||
//
|
||||
std::string SimulatorWin::getUserDocumentPath()
|
||||
{
|
||||
TCHAR filePath[MAX_PATH];
|
||||
SHGetSpecialFolderPath(NULL, filePath, CSIDL_PERSONAL, FALSE);
|
||||
int length = 2 * wcslen(filePath);
|
||||
char* tempstring = new char[length + 1];
|
||||
wcstombs(tempstring, filePath, length + 1);
|
||||
string userDocumentPath(tempstring);
|
||||
delete [] tempstring;
|
||||
|
||||
userDocumentPath = convertPathFormatToUnixStyle(userDocumentPath);
|
||||
userDocumentPath.append("/");
|
||||
|
||||
return userDocumentPath;
|
||||
}
|
||||
|
||||
//
|
||||
// convert Unicode/LocalCode TCHAR to Utf8 char
|
||||
//
|
||||
char* SimulatorWin::convertTCharToUtf8(const TCHAR* src)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WCHAR* tmp = (WCHAR*)src;
|
||||
size_t size = wcslen(src) * 3 + 1;
|
||||
char* dest = new char[size];
|
||||
memset(dest, 0, size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, tmp, -1, dest, size, NULL, NULL);
|
||||
return dest;
|
||||
#else
|
||||
char* tmp = (char*)src;
|
||||
uint32 size = strlen(tmp) + 1;
|
||||
WCHAR* dest = new WCHAR[size];
|
||||
memset(dest, 0, sizeof(WCHAR)*size);
|
||||
MultiByteToWideChar(CP_ACP, 0, src, -1, dest, (int)size); // convert local code to unicode.
|
||||
|
||||
size = wcslen(dest) * 3 + 1;
|
||||
char* dest2 = new char[size];
|
||||
memset(dest2, 0, size);
|
||||
WideCharToMultiByte(CP_UTF8, 0, dest, -1, dest2, size, NULL, NULL); // convert unicode to utf8.
|
||||
delete[] dest;
|
||||
return dest2;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
std::string SimulatorWin::getApplicationExePath()
|
||||
{
|
||||
TCHAR szFileName[MAX_PATH];
|
||||
GetModuleFileName(NULL, szFileName, MAX_PATH);
|
||||
std::u16string u16ApplicationName;
|
||||
char *applicationExePath = convertTCharToUtf8(szFileName);
|
||||
std::string path(applicationExePath);
|
||||
CC_SAFE_FREE(applicationExePath);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string SimulatorWin::getApplicationPath()
|
||||
{
|
||||
std::string path = getApplicationExePath();
|
||||
size_t pos;
|
||||
while ((pos = path.find_first_of("\\")) != std::string::npos)
|
||||
{
|
||||
path.replace(pos, 1, "/");
|
||||
}
|
||||
size_t p = path.find_last_of("/");
|
||||
string workdir;
|
||||
if (p != path.npos)
|
||||
{
|
||||
workdir = path.substr(0, p);
|
||||
}
|
||||
|
||||
return workdir;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SimulatorWin::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (!_instance) return 0;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
{
|
||||
if (HIWORD(wParam) == 0)
|
||||
{
|
||||
// menu
|
||||
WORD menuId = LOWORD(wParam);
|
||||
PlayerMenuItemWin *menuItem = _instance->_menuService->getItemByCommandId(menuId);
|
||||
if (menuItem)
|
||||
{
|
||||
AppEvent event("APP.EVENT", APP_EVENT_MENU);
|
||||
|
||||
std::stringstream buf;
|
||||
buf << "{\"data\":\"" << menuItem->getMenuId().c_str() << "\"";
|
||||
buf << ",\"name\":" << "\"menuClicked\"" << "}";
|
||||
event.setDataString(buf.str());
|
||||
event.setUserData(menuItem);
|
||||
Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);
|
||||
}
|
||||
|
||||
if (menuId == ID_HELP_ABOUT)
|
||||
{
|
||||
onHelpAbout();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
if (wParam == VK_F5)
|
||||
{
|
||||
PlayerProtocol::getInstance()->relaunch();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_COPYDATA:
|
||||
{
|
||||
PCOPYDATASTRUCT pMyCDS = (PCOPYDATASTRUCT) lParam;
|
||||
if (pMyCDS->dwData == 1)
|
||||
{
|
||||
const char *szBuf = (const char*)(pMyCDS->lpData);
|
||||
SimulatorWin::getInstance()->writeDebugLog(szBuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
{
|
||||
DragAcceptFiles(hWnd, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DROPFILES:
|
||||
{
|
||||
HDROP hDrop = (HDROP)wParam;
|
||||
|
||||
const int count = DragQueryFileW(hDrop, 0xffffffff, NULL, 0);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
int fileIndex = 0;
|
||||
|
||||
const UINT length = DragQueryFileW(hDrop, fileIndex, NULL, 0);
|
||||
WCHAR* buffer = (WCHAR*)calloc(length + 1, sizeof(WCHAR));
|
||||
|
||||
DragQueryFileW(hDrop, fileIndex, buffer, length + 1);
|
||||
char *utf8 = SimulatorWin::convertTCharToUtf8(buffer);
|
||||
std::string firstFile(utf8);
|
||||
CC_SAFE_FREE(utf8);
|
||||
DragFinish(hDrop);
|
||||
|
||||
// broadcast drop event
|
||||
AppEvent forwardEvent("APP.EVENT.DROP", APP_EVENT_DROP);
|
||||
forwardEvent.setDataString(firstFile);
|
||||
|
||||
Director::getInstance()->getEventDispatcher()->dispatchEvent(&forwardEvent);
|
||||
}
|
||||
} // WM_DROPFILES
|
||||
|
||||
}
|
||||
return g_oldWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
PLAYER_NS_END
|
||||
210
cocos2d-x/tools/simulator/libsimulator/lib/protobuf-lite/config.h
Executable file
210
cocos2d-x/tools/simulator/libsimulator/lib/protobuf-lite/config.h
Executable file
@@ -0,0 +1,210 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.5.0"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* protobuf config.h for MSVC. On other platforms, this is generated
|
||||
* automatically by autoheader / autoconf / configure. */
|
||||
|
||||
/* the location of <hash_map> */
|
||||
#define HASH_MAP_H <hash_map>
|
||||
|
||||
/* the namespace of hash_map/hash_set */
|
||||
// Apparently Microsoft decided to move hash_map *back* to the std namespace
|
||||
// in MSVC 2010:
|
||||
// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
|
||||
// REFINE(kenton): Use unordered_map instead, which is available in MSVC 2010.
|
||||
#if _MSC_VER < 1310 || _MSC_VER >= 1600
|
||||
#define HASH_NAMESPACE std
|
||||
#else
|
||||
#define HASH_NAMESPACE stdext
|
||||
#endif
|
||||
|
||||
/* the location of <hash_set> */
|
||||
#define HASH_SET_H <hash_set>
|
||||
|
||||
/* define if the compiler has hash_map */
|
||||
#define HAVE_HASH_MAP 1
|
||||
|
||||
/* define if the compiler has hash_set */
|
||||
#define HAVE_HASH_SET 1
|
||||
|
||||
/* define if you want to use zlib. See readme.txt for additional
|
||||
* requirements. */
|
||||
// #define HAVE_ZLIB 1
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* the name of <hash_map> */
|
||||
#define HASH_MAP_CLASS unordered_map
|
||||
|
||||
/* the location of <unordered_map> or <hash_map> */
|
||||
#define HASH_MAP_H <unordered_map>
|
||||
|
||||
/* the namespace of hash_map/hash_set */
|
||||
#define HASH_NAMESPACE std
|
||||
|
||||
/* the name of <hash_set> */
|
||||
#define HASH_SET_CLASS unordered_set
|
||||
|
||||
/* the location of <unordered_set> or <hash_set> */
|
||||
#define HASH_SET_H <unordered_set>
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `ftruncate' function. */
|
||||
#define HAVE_FTRUNCATE 1
|
||||
|
||||
/* define if the compiler has hash_map */
|
||||
#define HAVE_HASH_MAP 1
|
||||
|
||||
/* define if the compiler has hash_set */
|
||||
#define HAVE_HASH_SET 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `mkdir' function. */
|
||||
#define HAVE_MKDIR 1
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#define HAVE_PTHREAD 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#define HAVE_STRCHR 1
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strtol' function. */
|
||||
#define HAVE_STRTOL 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Enable classes using zlib compression. */
|
||||
#define HAVE_ZLIB 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "protobuf"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "protobuf@googlegroups.com"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "Protocol Buffers"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "Protocol Buffers 2.5.0"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "protobuf"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "2.5.0"
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# define _ALL_SOURCE 1
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# define _TANDEM_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
/* #undef _MINIX */
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
/* #undef _POSIX_1_SOURCE */
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
/* #undef _POSIX_SOURCE */
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
double Infinity() {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
double NaN() {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
const ::std::string kEmptyString;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,77 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains miscellaneous helper code used by generated code --
|
||||
// including lite types -- but which should not be used directly by users.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Annotation for the compiler to emit a deprecation message if a field marked
|
||||
// with option 'deprecated=true' is used in the code, or for other things in
|
||||
// generated code which are deprecated.
|
||||
//
|
||||
// For internal use in the pb.cc files, deprecation warnings are suppressed
|
||||
// there.
|
||||
#undef DEPRECATED_PROTOBUF_FIELD
|
||||
#define PROTOBUF_DEPRECATED
|
||||
|
||||
|
||||
// Constants for special floating point values.
|
||||
LIBPROTOBUF_EXPORT double Infinity();
|
||||
LIBPROTOBUF_EXPORT double NaN();
|
||||
|
||||
// Constant used for empty default strings.
|
||||
LIBPROTOBUF_EXPORT extern const ::std::string kEmptyString;
|
||||
|
||||
// Defined in generated_message_reflection.cc -- not actually part of the lite
|
||||
// library.
|
||||
//
|
||||
// REFINE(jasonh): The various callers get this declaration from a variety of
|
||||
// places: probably in most cases repeated_field.h. Clean these up so they all
|
||||
// get the declaration from this file.
|
||||
LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
@@ -0,0 +1,857 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This implementation is heavily optimized to make reads and writes
|
||||
// of small values (especially varints) as fast as possible. In
|
||||
// particular, we optimize for the common case that a read or a write
|
||||
// will not cross the end of the buffer, since we can avoid a lot
|
||||
// of branching in this case.
|
||||
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
namespace {
|
||||
|
||||
static const int kMaxVarintBytes = 10;
|
||||
static const int kMaxVarint32Bytes = 5;
|
||||
|
||||
|
||||
inline bool NextNonEmpty(ZeroCopyInputStream* input,
|
||||
const void** data, int* size) {
|
||||
bool success;
|
||||
do {
|
||||
success = input->Next(data, size);
|
||||
} while (success && *size == 0);
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// CodedInputStream ==================================================
|
||||
|
||||
CodedInputStream::~CodedInputStream() {
|
||||
if (input_ != NULL) {
|
||||
BackUpInputToCurrentPosition();
|
||||
}
|
||||
|
||||
if (total_bytes_warning_threshold_ == -2) {
|
||||
GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_;
|
||||
}
|
||||
}
|
||||
|
||||
// Static.
|
||||
int CodedInputStream::default_recursion_limit_ = 100;
|
||||
|
||||
|
||||
void CodedInputStream::BackUpInputToCurrentPosition() {
|
||||
int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
|
||||
if (backup_bytes > 0) {
|
||||
input_->BackUp(backup_bytes);
|
||||
|
||||
// total_bytes_read_ doesn't include overflow_bytes_.
|
||||
total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
|
||||
buffer_end_ = buffer_;
|
||||
buffer_size_after_limit_ = 0;
|
||||
overflow_bytes_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CodedInputStream::RecomputeBufferLimits() {
|
||||
buffer_end_ += buffer_size_after_limit_;
|
||||
int closest_limit = min(current_limit_, total_bytes_limit_);
|
||||
if (closest_limit < total_bytes_read_) {
|
||||
// The limit position is in the current buffer. We must adjust
|
||||
// the buffer size accordingly.
|
||||
buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
|
||||
buffer_end_ -= buffer_size_after_limit_;
|
||||
} else {
|
||||
buffer_size_after_limit_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
|
||||
// Current position relative to the beginning of the stream.
|
||||
int current_position = CurrentPosition();
|
||||
|
||||
Limit old_limit = current_limit_;
|
||||
|
||||
// security: byte_limit is possibly evil, so check for negative values
|
||||
// and overflow.
|
||||
if (byte_limit >= 0 &&
|
||||
byte_limit <= INT_MAX - current_position) {
|
||||
current_limit_ = current_position + byte_limit;
|
||||
} else {
|
||||
// Negative or overflow.
|
||||
current_limit_ = INT_MAX;
|
||||
}
|
||||
|
||||
// We need to enforce all limits, not just the new one, so if the previous
|
||||
// limit was before the new requested limit, we continue to enforce the
|
||||
// previous limit.
|
||||
current_limit_ = min(current_limit_, old_limit);
|
||||
|
||||
RecomputeBufferLimits();
|
||||
return old_limit;
|
||||
}
|
||||
|
||||
void CodedInputStream::PopLimit(Limit limit) {
|
||||
// The limit passed in is actually the *old* limit, which we returned from
|
||||
// PushLimit().
|
||||
current_limit_ = limit;
|
||||
RecomputeBufferLimits();
|
||||
|
||||
// We may no longer be at a legitimate message end. ReadTag() needs to be
|
||||
// called again to find out.
|
||||
legitimate_message_end_ = false;
|
||||
}
|
||||
|
||||
int CodedInputStream::BytesUntilLimit() const {
|
||||
if (current_limit_ == INT_MAX) return -1;
|
||||
int current_position = CurrentPosition();
|
||||
|
||||
return current_limit_ - current_position;
|
||||
}
|
||||
|
||||
void CodedInputStream::SetTotalBytesLimit(
|
||||
int total_bytes_limit, int warning_threshold) {
|
||||
// Make sure the limit isn't already past, since this could confuse other
|
||||
// code.
|
||||
int current_position = CurrentPosition();
|
||||
total_bytes_limit_ = max(current_position, total_bytes_limit);
|
||||
if (warning_threshold >= 0) {
|
||||
total_bytes_warning_threshold_ = warning_threshold;
|
||||
} else {
|
||||
// warning_threshold is negative
|
||||
total_bytes_warning_threshold_ = -1;
|
||||
}
|
||||
RecomputeBufferLimits();
|
||||
}
|
||||
|
||||
void CodedInputStream::PrintTotalBytesLimitError() {
|
||||
GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
|
||||
"big (more than " << total_bytes_limit_
|
||||
<< " bytes). To increase the limit (or to disable these "
|
||||
"warnings), see CodedInputStream::SetTotalBytesLimit() "
|
||||
"in google/protobuf/io/coded_stream.h.";
|
||||
}
|
||||
|
||||
bool CodedInputStream::Skip(int count) {
|
||||
if (count < 0) return false; // security: count is often user-supplied
|
||||
|
||||
const int original_buffer_size = BufferSize();
|
||||
|
||||
if (count <= original_buffer_size) {
|
||||
// Just skipping within the current buffer. Easy.
|
||||
Advance(count);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (buffer_size_after_limit_ > 0) {
|
||||
// We hit a limit inside this buffer. Advance to the limit and fail.
|
||||
Advance(original_buffer_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
count -= original_buffer_size;
|
||||
buffer_ = NULL;
|
||||
buffer_end_ = buffer_;
|
||||
|
||||
// Make sure this skip doesn't try to skip past the current limit.
|
||||
int closest_limit = min(current_limit_, total_bytes_limit_);
|
||||
int bytes_until_limit = closest_limit - total_bytes_read_;
|
||||
if (bytes_until_limit < count) {
|
||||
// We hit the limit. Skip up to it then fail.
|
||||
if (bytes_until_limit > 0) {
|
||||
total_bytes_read_ = closest_limit;
|
||||
input_->Skip(bytes_until_limit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
total_bytes_read_ += count;
|
||||
return input_->Skip(count);
|
||||
}
|
||||
|
||||
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
|
||||
if (BufferSize() == 0 && !Refresh()) return false;
|
||||
|
||||
*data = buffer_;
|
||||
*size = BufferSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadRaw(void* buffer, int size) {
|
||||
int current_buffer_size;
|
||||
while ((current_buffer_size = BufferSize()) < size) {
|
||||
// Reading past end of buffer. Copy what we have, then refresh.
|
||||
memcpy(buffer, buffer_, current_buffer_size);
|
||||
buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
|
||||
size -= current_buffer_size;
|
||||
Advance(current_buffer_size);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
memcpy(buffer, buffer_, size);
|
||||
Advance(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadString(string* buffer, int size) {
|
||||
if (size < 0) return false; // security: size is often user-supplied
|
||||
return InternalReadStringInline(buffer, size);
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
|
||||
if (!buffer->empty()) {
|
||||
buffer->clear();
|
||||
}
|
||||
|
||||
int current_buffer_size;
|
||||
while ((current_buffer_size = BufferSize()) < size) {
|
||||
// Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
|
||||
if (current_buffer_size != 0) {
|
||||
// Note: string1.append(string2) is O(string2.size()) (as opposed to
|
||||
// O(string1.size() + string2.size()), which would be bad).
|
||||
buffer->append(reinterpret_cast<const char*>(buffer_),
|
||||
current_buffer_size);
|
||||
}
|
||||
size -= current_buffer_size;
|
||||
Advance(current_buffer_size);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
buffer->append(reinterpret_cast<const char*>(buffer_), size);
|
||||
Advance(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
|
||||
uint8 bytes[sizeof(*value)];
|
||||
|
||||
const uint8* ptr;
|
||||
if (BufferSize() >= sizeof(*value)) {
|
||||
// Fast path: Enough bytes in the buffer to read directly.
|
||||
ptr = buffer_;
|
||||
Advance(sizeof(*value));
|
||||
} else {
|
||||
// Slow path: Had to read past the end of the buffer.
|
||||
if (!ReadRaw(bytes, sizeof(*value))) return false;
|
||||
ptr = bytes;
|
||||
}
|
||||
ReadLittleEndian32FromArray(ptr, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
|
||||
uint8 bytes[sizeof(*value)];
|
||||
|
||||
const uint8* ptr;
|
||||
if (BufferSize() >= sizeof(*value)) {
|
||||
// Fast path: Enough bytes in the buffer to read directly.
|
||||
ptr = buffer_;
|
||||
Advance(sizeof(*value));
|
||||
} else {
|
||||
// Slow path: Had to read past the end of the buffer.
|
||||
if (!ReadRaw(bytes, sizeof(*value))) return false;
|
||||
ptr = bytes;
|
||||
}
|
||||
ReadLittleEndian64FromArray(ptr, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline const uint8* ReadVarint32FromArray(
|
||||
const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
|
||||
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||
// this read won't cross the end, so we can skip the checks.
|
||||
const uint8* ptr = buffer;
|
||||
uint32 b;
|
||||
uint32 result;
|
||||
|
||||
b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
|
||||
|
||||
// If the input is larger than 32 bits, we still need to read it all
|
||||
// and discard the high-order bits.
|
||||
for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
|
||||
b = *(ptr++); if (!(b & 0x80)) goto done;
|
||||
}
|
||||
|
||||
// We have overrun the maximum size of a varint (10 bytes). Assume
|
||||
// the data is corrupt.
|
||||
return NULL;
|
||||
|
||||
done:
|
||||
*value = result;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
|
||||
uint64 result;
|
||||
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
|
||||
// for one-byte varints.
|
||||
if (!ReadVarint64Fallback(&result)) return false;
|
||||
*value = (uint32)result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: If the varint ends at exactly the end of the buffer,
|
||||
// we can detect that and still use the fast path.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
const uint8* end = ReadVarint32FromArray(buffer_, value);
|
||||
if (end == NULL) return false;
|
||||
buffer_ = end;
|
||||
return true;
|
||||
} else {
|
||||
// Really slow case: we will incur the cost of an extra function call here,
|
||||
// but moving this out of line reduces the size of this function, which
|
||||
// improves the common case. In micro benchmarks, this is worth about 10-15%
|
||||
return ReadVarint32Slow(value);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 CodedInputStream::ReadTagSlow() {
|
||||
if (buffer_ == buffer_end_) {
|
||||
// Call refresh.
|
||||
if (!Refresh()) {
|
||||
// Refresh failed. Make sure that it failed due to EOF, not because
|
||||
// we hit total_bytes_limit_, which, unlike normal limits, is not a
|
||||
// valid place to end a message.
|
||||
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||
if (current_position >= total_bytes_limit_) {
|
||||
// Hit total_bytes_limit_. But if we also hit the normal limit,
|
||||
// we're still OK.
|
||||
legitimate_message_end_ = current_limit_ == total_bytes_limit_;
|
||||
} else {
|
||||
legitimate_message_end_ = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
|
||||
// again, since we have now refreshed the buffer.
|
||||
uint64 result = 0;
|
||||
if (!ReadVarint64(&result)) return 0;
|
||||
return static_cast<uint32>(result);
|
||||
}
|
||||
|
||||
uint32 CodedInputStream::ReadTagFallback() {
|
||||
const int buf_size = BufferSize();
|
||||
if (buf_size >= kMaxVarintBytes ||
|
||||
// Optimization: If the varint ends at exactly the end of the buffer,
|
||||
// we can detect that and still use the fast path.
|
||||
(buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
|
||||
uint32 tag;
|
||||
const uint8* end = ReadVarint32FromArray(buffer_, &tag);
|
||||
if (end == NULL) {
|
||||
return 0;
|
||||
}
|
||||
buffer_ = end;
|
||||
return tag;
|
||||
} else {
|
||||
// We are commonly at a limit when attempting to read tags. Try to quickly
|
||||
// detect this case without making another function call.
|
||||
if ((buf_size == 0) &&
|
||||
((buffer_size_after_limit_ > 0) ||
|
||||
(total_bytes_read_ == current_limit_)) &&
|
||||
// Make sure that the limit we hit is not total_bytes_limit_, since
|
||||
// in that case we still need to call Refresh() so that it prints an
|
||||
// error.
|
||||
total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
|
||||
// We hit a byte limit.
|
||||
legitimate_message_end_ = true;
|
||||
return 0;
|
||||
}
|
||||
return ReadTagSlow();
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadVarint64Slow(uint64* value) {
|
||||
// Slow path: This read might cross the end of the buffer, so we
|
||||
// need to check and refresh the buffer if and when it does.
|
||||
|
||||
uint64 result = 0;
|
||||
int count = 0;
|
||||
uint32 b;
|
||||
|
||||
do {
|
||||
if (count == kMaxVarintBytes) return false;
|
||||
while (buffer_ == buffer_end_) {
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
b = *buffer_;
|
||||
result |= static_cast<uint64>(b & 0x7F) << (7 * count);
|
||||
Advance(1);
|
||||
++count;
|
||||
} while (b & 0x80);
|
||||
|
||||
*value = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
|
||||
if (BufferSize() >= kMaxVarintBytes ||
|
||||
// Optimization: If the varint ends at exactly the end of the buffer,
|
||||
// we can detect that and still use the fast path.
|
||||
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
|
||||
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||
// this read won't cross the end, so we can skip the checks.
|
||||
|
||||
const uint8* ptr = buffer_;
|
||||
uint32 b;
|
||||
|
||||
// Splitting into 32-bit pieces gives better performance on 32-bit
|
||||
// processors.
|
||||
uint32 part0 = 0, part1 = 0, part2 = 0;
|
||||
|
||||
b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done;
|
||||
b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
|
||||
|
||||
// We have overrun the maximum size of a varint (10 bytes). The data
|
||||
// must be corrupt.
|
||||
return false;
|
||||
|
||||
done:
|
||||
Advance(ptr - buffer_);
|
||||
*value = (static_cast<uint64>(part0) ) |
|
||||
(static_cast<uint64>(part1) << 28) |
|
||||
(static_cast<uint64>(part2) << 56);
|
||||
return true;
|
||||
} else {
|
||||
return ReadVarint64Slow(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedInputStream::Refresh() {
|
||||
GOOGLE_DCHECK_EQ(0, BufferSize());
|
||||
|
||||
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
|
||||
total_bytes_read_ == current_limit_) {
|
||||
// We've hit a limit. Stop.
|
||||
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||
|
||||
if (current_position >= total_bytes_limit_ &&
|
||||
total_bytes_limit_ != current_limit_) {
|
||||
// Hit total_bytes_limit_.
|
||||
PrintTotalBytesLimitError();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (total_bytes_warning_threshold_ >= 0 &&
|
||||
total_bytes_read_ >= total_bytes_warning_threshold_) {
|
||||
GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message. If the "
|
||||
"message turns out to be larger than "
|
||||
<< total_bytes_limit_ << " bytes, parsing will be halted "
|
||||
"for security reasons. To increase the limit (or to "
|
||||
"disable these warnings), see "
|
||||
"CodedInputStream::SetTotalBytesLimit() in "
|
||||
"google/protobuf/io/coded_stream.h.";
|
||||
|
||||
// Don't warn again for this stream, and print total size at the end.
|
||||
total_bytes_warning_threshold_ = -2;
|
||||
}
|
||||
|
||||
const void* void_buffer;
|
||||
int buffer_size;
|
||||
if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
|
||||
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
|
||||
buffer_end_ = buffer_ + buffer_size;
|
||||
GOOGLE_CHECK_GE(buffer_size, 0);
|
||||
|
||||
if (total_bytes_read_ <= INT_MAX - buffer_size) {
|
||||
total_bytes_read_ += buffer_size;
|
||||
} else {
|
||||
// Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX.
|
||||
// We can't get that far anyway, because total_bytes_limit_ is guaranteed
|
||||
// to be less than it. We need to keep track of the number of bytes
|
||||
// we discarded, though, so that we can call input_->BackUp() to back
|
||||
// up over them on destruction.
|
||||
|
||||
// The following line is equivalent to:
|
||||
// overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
|
||||
// except that it avoids overflows. Signed integer overflow has
|
||||
// undefined results according to the C standard.
|
||||
overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
|
||||
buffer_end_ -= overflow_bytes_;
|
||||
total_bytes_read_ = INT_MAX;
|
||||
}
|
||||
|
||||
RecomputeBufferLimits();
|
||||
return true;
|
||||
} else {
|
||||
buffer_ = NULL;
|
||||
buffer_end_ = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// CodedOutputStream =================================================
|
||||
|
||||
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
|
||||
: output_(output),
|
||||
buffer_(NULL),
|
||||
buffer_size_(0),
|
||||
total_bytes_(0),
|
||||
had_error_(false) {
|
||||
// Eagerly Refresh() so buffer space is immediately available.
|
||||
Refresh();
|
||||
// The Refresh() may have failed. If the client doesn't write any data,
|
||||
// though, don't consider this an error. If the client does write data, then
|
||||
// another Refresh() will be attempted and it will set the error once again.
|
||||
had_error_ = false;
|
||||
}
|
||||
|
||||
CodedOutputStream::~CodedOutputStream() {
|
||||
if (buffer_size_ > 0) {
|
||||
output_->BackUp(buffer_size_);
|
||||
}
|
||||
}
|
||||
|
||||
bool CodedOutputStream::Skip(int count) {
|
||||
if (count < 0) return false;
|
||||
|
||||
while (count > buffer_size_) {
|
||||
count -= buffer_size_;
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
Advance(count);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
|
||||
if (buffer_size_ == 0 && !Refresh()) return false;
|
||||
|
||||
*data = buffer_;
|
||||
*size = buffer_size_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteRaw(const void* data, int size) {
|
||||
while (buffer_size_ < size) {
|
||||
memcpy(buffer_, data, buffer_size_);
|
||||
size -= buffer_size_;
|
||||
data = reinterpret_cast<const uint8*>(data) + buffer_size_;
|
||||
if (!Refresh()) return;
|
||||
}
|
||||
|
||||
memcpy(buffer_, data, size);
|
||||
Advance(size);
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteRawToArray(
|
||||
const void* data, int size, uint8* target) {
|
||||
memcpy(target, data, size);
|
||||
return target + size;
|
||||
}
|
||||
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian32(uint32 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
WriteLittleEndian32ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
} else {
|
||||
WriteRaw(bytes, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian64(uint64 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
WriteLittleEndian64ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
} else {
|
||||
WriteRaw(bytes, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
|
||||
uint32 value, uint8* target) {
|
||||
target[0] = static_cast<uint8>(value | 0x80);
|
||||
if (value >= (1 << 7)) {
|
||||
target[1] = static_cast<uint8>((value >> 7) | 0x80);
|
||||
if (value >= (1 << 14)) {
|
||||
target[2] = static_cast<uint8>((value >> 14) | 0x80);
|
||||
if (value >= (1 << 21)) {
|
||||
target[3] = static_cast<uint8>((value >> 21) | 0x80);
|
||||
if (value >= (1 << 28)) {
|
||||
target[4] = static_cast<uint8>(value >> 28);
|
||||
return target + 5;
|
||||
} else {
|
||||
target[3] &= 0x7F;
|
||||
return target + 4;
|
||||
}
|
||||
} else {
|
||||
target[2] &= 0x7F;
|
||||
return target + 3;
|
||||
}
|
||||
} else {
|
||||
target[1] &= 0x7F;
|
||||
return target + 2;
|
||||
}
|
||||
} else {
|
||||
target[0] &= 0x7F;
|
||||
return target + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteVarint32(uint32 value) {
|
||||
if (buffer_size_ >= kMaxVarint32Bytes) {
|
||||
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||
// this write won't cross the end, so we can skip the checks.
|
||||
uint8* target = buffer_;
|
||||
uint8* end = WriteVarint32FallbackToArrayInline(value, target);
|
||||
int size = end - target;
|
||||
Advance(size);
|
||||
} else {
|
||||
// Slow path: This write might cross the end of the buffer, so we
|
||||
// compose the bytes first then use WriteRaw().
|
||||
uint8 bytes[kMaxVarint32Bytes];
|
||||
int size = 0;
|
||||
while (value > 0x7F) {
|
||||
bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
|
||||
value >>= 7;
|
||||
}
|
||||
bytes[size++] = static_cast<uint8>(value) & 0x7F;
|
||||
WriteRaw(bytes, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteVarint32FallbackToArray(
|
||||
uint32 value, uint8* target) {
|
||||
return WriteVarint32FallbackToArrayInline(value, target);
|
||||
}
|
||||
|
||||
inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
|
||||
uint64 value, uint8* target) {
|
||||
// Splitting into 32-bit pieces gives better performance on 32-bit
|
||||
// processors.
|
||||
uint32 part0 = static_cast<uint32>(value );
|
||||
uint32 part1 = static_cast<uint32>(value >> 28);
|
||||
uint32 part2 = static_cast<uint32>(value >> 56);
|
||||
|
||||
int size;
|
||||
|
||||
// Here we can't really optimize for small numbers, since the value is
|
||||
// split into three parts. Cheking for numbers < 128, for instance,
|
||||
// would require three comparisons, since you'd have to make sure part1
|
||||
// and part2 are zero. However, if the caller is using 64-bit integers,
|
||||
// it is likely that they expect the numbers to often be very large, so
|
||||
// we probably don't want to optimize for small numbers anyway. Thus,
|
||||
// we end up with a hardcoded binary search tree...
|
||||
if (part2 == 0) {
|
||||
if (part1 == 0) {
|
||||
if (part0 < (1 << 14)) {
|
||||
if (part0 < (1 << 7)) {
|
||||
size = 1; goto size1;
|
||||
} else {
|
||||
size = 2; goto size2;
|
||||
}
|
||||
} else {
|
||||
if (part0 < (1 << 21)) {
|
||||
size = 3; goto size3;
|
||||
} else {
|
||||
size = 4; goto size4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (part1 < (1 << 14)) {
|
||||
if (part1 < (1 << 7)) {
|
||||
size = 5; goto size5;
|
||||
} else {
|
||||
size = 6; goto size6;
|
||||
}
|
||||
} else {
|
||||
if (part1 < (1 << 21)) {
|
||||
size = 7; goto size7;
|
||||
} else {
|
||||
size = 8; goto size8;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (part2 < (1 << 7)) {
|
||||
size = 9; goto size9;
|
||||
} else {
|
||||
size = 10; goto size10;
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
|
||||
size10: target[9] = static_cast<uint8>((part2 >> 7) | 0x80);
|
||||
size9 : target[8] = static_cast<uint8>((part2 ) | 0x80);
|
||||
size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
|
||||
size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
|
||||
size6 : target[5] = static_cast<uint8>((part1 >> 7) | 0x80);
|
||||
size5 : target[4] = static_cast<uint8>((part1 ) | 0x80);
|
||||
size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
|
||||
size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
|
||||
size2 : target[1] = static_cast<uint8>((part0 >> 7) | 0x80);
|
||||
size1 : target[0] = static_cast<uint8>((part0 ) | 0x80);
|
||||
|
||||
target[size-1] &= 0x7F;
|
||||
return target + size;
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteVarint64(uint64 value) {
|
||||
if (buffer_size_ >= kMaxVarintBytes) {
|
||||
// Fast path: We have enough bytes left in the buffer to guarantee that
|
||||
// this write won't cross the end, so we can skip the checks.
|
||||
uint8* target = buffer_;
|
||||
|
||||
uint8* end = WriteVarint64ToArrayInline(value, target);
|
||||
int size = end - target;
|
||||
Advance(size);
|
||||
} else {
|
||||
// Slow path: This write might cross the end of the buffer, so we
|
||||
// compose the bytes first then use WriteRaw().
|
||||
uint8 bytes[kMaxVarintBytes];
|
||||
int size = 0;
|
||||
while (value > 0x7F) {
|
||||
bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
|
||||
value >>= 7;
|
||||
}
|
||||
bytes[size++] = static_cast<uint8>(value) & 0x7F;
|
||||
WriteRaw(bytes, size);
|
||||
}
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteVarint64ToArray(
|
||||
uint64 value, uint8* target) {
|
||||
return WriteVarint64ToArrayInline(value, target);
|
||||
}
|
||||
|
||||
bool CodedOutputStream::Refresh() {
|
||||
void* void_buffer;
|
||||
if (output_->Next(&void_buffer, &buffer_size_)) {
|
||||
buffer_ = reinterpret_cast<uint8*>(void_buffer);
|
||||
total_bytes_ += buffer_size_;
|
||||
return true;
|
||||
} else {
|
||||
buffer_ = NULL;
|
||||
buffer_size_ = 0;
|
||||
had_error_ = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int CodedOutputStream::VarintSize32Fallback(uint32 value) {
|
||||
if (value < (1 << 7)) {
|
||||
return 1;
|
||||
} else if (value < (1 << 14)) {
|
||||
return 2;
|
||||
} else if (value < (1 << 21)) {
|
||||
return 3;
|
||||
} else if (value < (1 << 28)) {
|
||||
return 4;
|
||||
} else {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
int CodedOutputStream::VarintSize64(uint64 value) {
|
||||
if (value < (1ull << 35)) {
|
||||
if (value < (1ull << 7)) {
|
||||
return 1;
|
||||
} else if (value < (1ull << 14)) {
|
||||
return 2;
|
||||
} else if (value < (1ull << 21)) {
|
||||
return 3;
|
||||
} else if (value < (1ull << 28)) {
|
||||
return 4;
|
||||
} else {
|
||||
return 5;
|
||||
}
|
||||
} else {
|
||||
if (value < (1ull << 42)) {
|
||||
return 6;
|
||||
} else if (value < (1ull << 49)) {
|
||||
return 7;
|
||||
} else if (value < (1ull << 56)) {
|
||||
return 8;
|
||||
} else if (value < (1ull << 63)) {
|
||||
return 9;
|
||||
} else {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: jasonh@google.com (Jason Hsueh)
|
||||
//
|
||||
// Implements methods of coded_stream.h that need to be inlined for performance
|
||||
// reasons, but should not be defined in a public header.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
inline bool CodedInputStream::InternalReadStringInline(string* buffer,
|
||||
int size) {
|
||||
if (size < 0) return false; // security: size is often user-supplied
|
||||
|
||||
if (BufferSize() >= size) {
|
||||
STLStringResizeUninitialized(buffer, size);
|
||||
// When buffer is empty, string_as_array(buffer) will return NULL but memcpy
|
||||
// requires non-NULL pointers even when size is 0. Hench this check.
|
||||
if (size > 0) {
|
||||
memcpy(string_as_array(buffer), buffer_, size);
|
||||
Advance(size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return ReadStringFallback(buffer, size);
|
||||
}
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
|
||||
@@ -0,0 +1,48 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
ZeroCopyInputStream::~ZeroCopyInputStream() {}
|
||||
ZeroCopyOutputStream::~ZeroCopyOutputStream() {}
|
||||
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,238 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains the ZeroCopyInputStream and ZeroCopyOutputStream
|
||||
// interfaces, which represent abstract I/O streams to and from which
|
||||
// protocol buffers can be read and written. For a few simple
|
||||
// implementations of these interfaces, see zero_copy_stream_impl.h.
|
||||
//
|
||||
// These interfaces are different from classic I/O streams in that they
|
||||
// try to minimize the amount of data copying that needs to be done.
|
||||
// To accomplish this, responsibility for allocating buffers is moved to
|
||||
// the stream object, rather than being the responsibility of the caller.
|
||||
// So, the stream can return a buffer which actually points directly into
|
||||
// the final data structure where the bytes are to be stored, and the caller
|
||||
// can interact directly with that buffer, eliminating an intermediate copy
|
||||
// operation.
|
||||
//
|
||||
// As an example, consider the common case in which you are reading bytes
|
||||
// from an array that is already in memory (or perhaps an mmap()ed file).
|
||||
// With classic I/O streams, you would do something like:
|
||||
// char buffer[BUFFER_SIZE];
|
||||
// input->Read(buffer, BUFFER_SIZE);
|
||||
// DoSomething(buffer, BUFFER_SIZE);
|
||||
// Then, the stream basically just calls memcpy() to copy the data from
|
||||
// the array into your buffer. With a ZeroCopyInputStream, you would do
|
||||
// this instead:
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// input->Next(&buffer, &size);
|
||||
// DoSomething(buffer, size);
|
||||
// Here, no copy is performed. The input stream returns a pointer directly
|
||||
// into the backing array, and the caller ends up reading directly from it.
|
||||
//
|
||||
// If you want to be able to read the old-fashion way, you can create
|
||||
// a CodedInputStream or CodedOutputStream wrapping these objects and use
|
||||
// their ReadRaw()/WriteRaw() methods. These will, of course, add a copy
|
||||
// step, but Coded*Stream will handle buffering so at least it will be
|
||||
// reasonably efficient.
|
||||
//
|
||||
// ZeroCopyInputStream example:
|
||||
// // Read in a file and print its contents to stdout.
|
||||
// int fd = open("myfile", O_RDONLY);
|
||||
// ZeroCopyInputStream* input = new FileInputStream(fd);
|
||||
//
|
||||
// const void* buffer;
|
||||
// int size;
|
||||
// while (input->Next(&buffer, &size)) {
|
||||
// cout.write(buffer, size);
|
||||
// }
|
||||
//
|
||||
// delete input;
|
||||
// close(fd);
|
||||
//
|
||||
// ZeroCopyOutputStream example:
|
||||
// // Copy the contents of "infile" to "outfile", using plain read() for
|
||||
// // "infile" but a ZeroCopyOutputStream for "outfile".
|
||||
// int infd = open("infile", O_RDONLY);
|
||||
// int outfd = open("outfile", O_WRONLY);
|
||||
// ZeroCopyOutputStream* output = new FileOutputStream(outfd);
|
||||
//
|
||||
// void* buffer;
|
||||
// int size;
|
||||
// while (output->Next(&buffer, &size)) {
|
||||
// int bytes = read(infd, buffer, size);
|
||||
// if (bytes < size) {
|
||||
// // Reached EOF.
|
||||
// output->BackUp(size - bytes);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// delete output;
|
||||
// close(infd);
|
||||
// close(outfd);
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// Defined in this file.
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
|
||||
// Abstract interface similar to an input stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
|
||||
public:
|
||||
inline ZeroCopyInputStream() {}
|
||||
virtual ~ZeroCopyInputStream();
|
||||
|
||||
// Obtains a chunk of data from the stream.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, there is no more data to return or
|
||||
// an error occurred. All errors are permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes read and "data"
|
||||
// points to a pointer to a buffer containing these bytes.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(const void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the next call to Next() returns
|
||||
// data again that was already returned by the last call to Next(). This
|
||||
// is useful when writing procedures that are only supposed to read up
|
||||
// to a certain point in the input, then return. If Next() returns a
|
||||
// buffer that goes beyond what you wanted to read, you can use BackUp()
|
||||
// to return to the point where you intended to finish.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// pushed back into the stream. Subsequent calls to Next() will return
|
||||
// the same data again before producing new data.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Skips a number of bytes. Returns false if the end of the stream is
|
||||
// reached or some input error occurred. In the end-of-stream case, the
|
||||
// stream is advanced to the end of the stream (so ByteCount() will return
|
||||
// the total size of the stream).
|
||||
virtual bool Skip(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes read since this object was created.
|
||||
virtual int64 ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
|
||||
};
|
||||
|
||||
// Abstract interface similar to an output stream but designed to minimize
|
||||
// copying.
|
||||
class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
|
||||
public:
|
||||
inline ZeroCopyOutputStream() {}
|
||||
virtual ~ZeroCopyOutputStream();
|
||||
|
||||
// Obtains a buffer into which data can be written. Any data written
|
||||
// into this buffer will eventually (maybe instantly, maybe later on)
|
||||
// be written to the output.
|
||||
//
|
||||
// Preconditions:
|
||||
// * "size" and "data" are not NULL.
|
||||
//
|
||||
// Postconditions:
|
||||
// * If the returned value is false, an error occurred. All errors are
|
||||
// permanent.
|
||||
// * Otherwise, "size" points to the actual number of bytes in the buffer
|
||||
// and "data" points to the buffer.
|
||||
// * Ownership of this buffer remains with the stream, and the buffer
|
||||
// remains valid only until some other method of the stream is called
|
||||
// or the stream is destroyed.
|
||||
// * Any data which the caller stores in this buffer will eventually be
|
||||
// written to the output (unless BackUp() is called).
|
||||
// * It is legal for the returned buffer to have zero size, as long
|
||||
// as repeatedly calling Next() eventually yields a buffer with non-zero
|
||||
// size.
|
||||
virtual bool Next(void** data, int* size) = 0;
|
||||
|
||||
// Backs up a number of bytes, so that the end of the last buffer returned
|
||||
// by Next() is not actually written. This is needed when you finish
|
||||
// writing all the data you want to write, but the last buffer was bigger
|
||||
// than you needed. You don't want to write a bunch of garbage after the
|
||||
// end of your data, so you use BackUp() to back up.
|
||||
//
|
||||
// Preconditions:
|
||||
// * The last method called must have been Next().
|
||||
// * count must be less than or equal to the size of the last buffer
|
||||
// returned by Next().
|
||||
// * The caller must not have written anything to the last "count" bytes
|
||||
// of that buffer.
|
||||
//
|
||||
// Postconditions:
|
||||
// * The last "count" bytes of the last buffer returned by Next() will be
|
||||
// ignored.
|
||||
virtual void BackUp(int count) = 0;
|
||||
|
||||
// Returns the total number of bytes written since this object was created.
|
||||
virtual int64 ByteCount() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
|
||||
};
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
|
||||
@@ -0,0 +1,357 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are only included in the full (non-lite)
|
||||
// protobuf library. These implementations include Unix file descriptors
|
||||
// and C++ iostreams. See also: zero_copy_stream_impl_lite.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a file descriptor.
|
||||
//
|
||||
// FileInputStream is preferred over using an ifstream with IstreamInputStream.
|
||||
// The latter will introduce an extra layer of buffering, harming performance.
|
||||
// Also, it's conceivable that FileInputStream could someday be enhanced
|
||||
// to use zero-copy file descriptors on OSs which support them.
|
||||
class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit FileInputStream(int file_descriptor, int block_size = -1);
|
||||
~FileInputStream();
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() { return copying_input_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream {
|
||||
public:
|
||||
CopyingFileInputStream(int file_descriptor);
|
||||
~CopyingFileInputStream();
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() { return errno_; }
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size);
|
||||
int Skip(int count);
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
// Did we try to seek once and fail? If so, we assume this file descriptor
|
||||
// doesn't support seeking and won't try again.
|
||||
bool previous_seek_failed_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
|
||||
};
|
||||
|
||||
CopyingFileInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a file descriptor.
|
||||
//
|
||||
// FileOutputStream is preferred over using an ofstream with
|
||||
// OstreamOutputStream. The latter will introduce an extra layer of buffering,
|
||||
// harming performance. Also, it's conceivable that FileOutputStream could
|
||||
// someday be enhanced to use zero-copy file descriptors on OSs which
|
||||
// support them.
|
||||
class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit FileOutputStream(int file_descriptor, int block_size = -1);
|
||||
~FileOutputStream();
|
||||
|
||||
// Flushes any buffers and closes the underlying file. Returns false if
|
||||
// an error occurs during the process; use GetErrno() to examine the error.
|
||||
// Even if an error occurs, the file descriptor is closed when this returns.
|
||||
bool Close();
|
||||
|
||||
// Flushes FileOutputStream's buffers but does not close the
|
||||
// underlying file. No special measures are taken to ensure that
|
||||
// underlying operating system file object is synchronized to disk.
|
||||
bool Flush();
|
||||
|
||||
// By default, the file descriptor is not closed when the stream is
|
||||
// destroyed. Call SetCloseOnDelete(true) to change that. WARNING:
|
||||
// This leaves no way for the caller to detect if close() fails. If
|
||||
// detecting close() errors is important to you, you should arrange
|
||||
// to close the descriptor yourself.
|
||||
void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); }
|
||||
|
||||
// If an I/O error has occurred on this file descriptor, this is the
|
||||
// errno from that error. Otherwise, this is zero. Once an error
|
||||
// occurs, the stream is broken and all subsequent operations will
|
||||
// fail.
|
||||
int GetErrno() { return copying_output_.GetErrno(); }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream {
|
||||
public:
|
||||
CopyingFileOutputStream(int file_descriptor);
|
||||
~CopyingFileOutputStream();
|
||||
|
||||
bool Close();
|
||||
void SetCloseOnDelete(bool value) { close_on_delete_ = value; }
|
||||
int GetErrno() { return errno_; }
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size);
|
||||
|
||||
private:
|
||||
// The file descriptor.
|
||||
const int file_;
|
||||
bool close_on_delete_;
|
||||
bool is_closed_;
|
||||
|
||||
// The errno of the I/O error, if one has occurred. Otherwise, zero.
|
||||
int errno_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
|
||||
};
|
||||
|
||||
CopyingFileOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from a C++ istream.
|
||||
//
|
||||
// Note that for reading files (or anything represented by a file descriptor),
|
||||
// FileInputStream is more efficient.
|
||||
class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given C++ istream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used.
|
||||
explicit IstreamInputStream(istream* stream, int block_size = -1);
|
||||
~IstreamInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream {
|
||||
public:
|
||||
CopyingIstreamInputStream(istream* input);
|
||||
~CopyingIstreamInputStream();
|
||||
|
||||
// implements CopyingInputStream ---------------------------------
|
||||
int Read(void* buffer, int size);
|
||||
// (We use the default implementation of Skip().)
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
istream* input_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
|
||||
};
|
||||
|
||||
CopyingIstreamInputStream copying_input_;
|
||||
CopyingInputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a C++ ostream.
|
||||
//
|
||||
// Note that for writing files (or anything represented by a file descriptor),
|
||||
// FileOutputStream is more efficient.
|
||||
class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given C++ ostream.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit OstreamOutputStream(ostream* stream, int block_size = -1);
|
||||
~OstreamOutputStream();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream {
|
||||
public:
|
||||
CopyingOstreamOutputStream(ostream* output);
|
||||
~CopyingOstreamOutputStream();
|
||||
|
||||
// implements CopyingOutputStream --------------------------------
|
||||
bool Write(const void* buffer, int size);
|
||||
|
||||
private:
|
||||
// The stream.
|
||||
ostream* output_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
|
||||
};
|
||||
|
||||
CopyingOstreamOutputStream copying_output_;
|
||||
CopyingOutputStreamAdaptor impl_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which reads from several other streams in sequence.
|
||||
// ConcatenatingInputStream is unable to distinguish between end-of-stream
|
||||
// and read errors in the underlying streams, so it assumes any errors mean
|
||||
// end-of-stream. So, if the underlying streams fail for any other reason,
|
||||
// ConcatenatingInputStream may do odd things. It is suggested that you do
|
||||
// not use ConcatenatingInputStream on streams that might produce read errors
|
||||
// other than end-of-stream.
|
||||
class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// All streams passed in as well as the array itself must remain valid
|
||||
// until the ConcatenatingInputStream is destroyed.
|
||||
ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
|
||||
~ConcatenatingInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
// As streams are retired, streams_ is incremented and count_ is
|
||||
// decremented.
|
||||
ZeroCopyInputStream* const* streams_;
|
||||
int stream_count_;
|
||||
int64 bytes_retired_; // Bytes read from previous streams.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream which wraps some other stream and limits it to
|
||||
// a particular byte count.
|
||||
class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
LimitingInputStream(ZeroCopyInputStream* input, int64 limit);
|
||||
~LimitingInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
ZeroCopyInputStream* input_;
|
||||
int64 limit_; // Decreases as we go, becomes negative if we overshoot.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
|
||||
@@ -0,0 +1,393 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
namespace {
|
||||
|
||||
// Default block size for Copying{In,Out}putStreamAdaptor.
|
||||
static const int kDefaultBlockSize = 8192;
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
ArrayInputStream::ArrayInputStream(const void* data, int size,
|
||||
int block_size)
|
||||
: data_(reinterpret_cast<const uint8*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {
|
||||
}
|
||||
|
||||
ArrayInputStream::~ArrayInputStream() {
|
||||
}
|
||||
|
||||
bool ArrayInputStream::Next(const void** data, int* size) {
|
||||
if (position_ < size_) {
|
||||
last_returned_size_ = min(block_size_, size_ - position_);
|
||||
*data = data_ + position_;
|
||||
*size = last_returned_size_;
|
||||
position_ += last_returned_size_;
|
||||
return true;
|
||||
} else {
|
||||
// We're at the end of the array.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayInputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GT(last_returned_size_, 0)
|
||||
<< "BackUp() can only be called after a successful Next().";
|
||||
GOOGLE_CHECK_LE(count, last_returned_size_);
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
position_ -= count;
|
||||
last_returned_size_ = 0; // Don't let caller back up further.
|
||||
}
|
||||
|
||||
bool ArrayInputStream::Skip(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
if (count > size_ - position_) {
|
||||
position_ = size_;
|
||||
return false;
|
||||
} else {
|
||||
position_ += count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int64 ArrayInputStream::ByteCount() const {
|
||||
return position_;
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
|
||||
: data_(reinterpret_cast<uint8*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {
|
||||
}
|
||||
|
||||
ArrayOutputStream::~ArrayOutputStream() {
|
||||
}
|
||||
|
||||
bool ArrayOutputStream::Next(void** data, int* size) {
|
||||
if (position_ < size_) {
|
||||
last_returned_size_ = min(block_size_, size_ - position_);
|
||||
*data = data_ + position_;
|
||||
*size = last_returned_size_;
|
||||
position_ += last_returned_size_;
|
||||
return true;
|
||||
} else {
|
||||
// We're at the end of the array.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayOutputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GT(last_returned_size_, 0)
|
||||
<< "BackUp() can only be called after a successful Next().";
|
||||
GOOGLE_CHECK_LE(count, last_returned_size_);
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
position_ -= count;
|
||||
last_returned_size_ = 0; // Don't let caller back up further.
|
||||
}
|
||||
|
||||
int64 ArrayOutputStream::ByteCount() const {
|
||||
return position_;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
StringOutputStream::StringOutputStream(string* target)
|
||||
: target_(target) {
|
||||
}
|
||||
|
||||
StringOutputStream::~StringOutputStream() {
|
||||
}
|
||||
|
||||
bool StringOutputStream::Next(void** data, int* size) {
|
||||
int old_size = target_->size();
|
||||
|
||||
// Grow the string.
|
||||
if (old_size < target_->capacity()) {
|
||||
// Resize the string to match its capacity, since we can get away
|
||||
// without a memory allocation this way.
|
||||
STLStringResizeUninitialized(target_, target_->capacity());
|
||||
} else {
|
||||
// Size has reached capacity, so double the size. Also make sure
|
||||
// that the new size is at least kMinimumSize.
|
||||
STLStringResizeUninitialized(
|
||||
target_,
|
||||
max(old_size * 2,
|
||||
kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
|
||||
}
|
||||
|
||||
*data = string_as_array(target_) + old_size;
|
||||
*size = target_->size() - old_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StringOutputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
GOOGLE_CHECK_LE(count, target_->size());
|
||||
target_->resize(target_->size() - count);
|
||||
}
|
||||
|
||||
int64 StringOutputStream::ByteCount() const {
|
||||
return target_->size();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
CopyingInputStream::~CopyingInputStream() {}
|
||||
|
||||
int CopyingInputStream::Skip(int count) {
|
||||
char junk[4096];
|
||||
int skipped = 0;
|
||||
while (skipped < count) {
|
||||
int bytes = Read(junk, min(count - skipped,
|
||||
implicit_cast<int>(sizeof(junk))));
|
||||
if (bytes <= 0) {
|
||||
// EOF or read error.
|
||||
return skipped;
|
||||
}
|
||||
skipped += bytes;
|
||||
}
|
||||
return skipped;
|
||||
}
|
||||
|
||||
CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
|
||||
CopyingInputStream* copying_stream, int block_size)
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0),
|
||||
backup_bytes_(0) {
|
||||
}
|
||||
|
||||
CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
|
||||
if (owns_copying_stream_) {
|
||||
delete copying_stream_;
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
|
||||
if (failed_) {
|
||||
// Already failed on a previous read.
|
||||
return false;
|
||||
}
|
||||
|
||||
AllocateBufferIfNeeded();
|
||||
|
||||
if (backup_bytes_ > 0) {
|
||||
// We have data left over from a previous BackUp(), so just return that.
|
||||
*data = buffer_.get() + buffer_used_ - backup_bytes_;
|
||||
*size = backup_bytes_;
|
||||
backup_bytes_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read new data into the buffer.
|
||||
buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
|
||||
if (buffer_used_ <= 0) {
|
||||
// EOF or read error. We don't need the buffer anymore.
|
||||
if (buffer_used_ < 0) {
|
||||
// Read error (not EOF).
|
||||
failed_ = true;
|
||||
}
|
||||
FreeBuffer();
|
||||
return false;
|
||||
}
|
||||
position_ += buffer_used_;
|
||||
|
||||
*size = buffer_used_;
|
||||
*data = buffer_.get();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::BackUp(int count) {
|
||||
GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
|
||||
<< " BackUp() can only be called after Next().";
|
||||
GOOGLE_CHECK_LE(count, buffer_used_)
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
GOOGLE_CHECK_GE(count, 0)
|
||||
<< " Parameter to BackUp() can't be negative.";
|
||||
|
||||
backup_bytes_ = count;
|
||||
}
|
||||
|
||||
bool CopyingInputStreamAdaptor::Skip(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
|
||||
if (failed_) {
|
||||
// Already failed on a previous read.
|
||||
return false;
|
||||
}
|
||||
|
||||
// First skip any bytes left over from a previous BackUp().
|
||||
if (backup_bytes_ >= count) {
|
||||
// We have more data left over than we're trying to skip. Just chop it.
|
||||
backup_bytes_ -= count;
|
||||
return true;
|
||||
}
|
||||
|
||||
count -= backup_bytes_;
|
||||
backup_bytes_ = 0;
|
||||
|
||||
int skipped = copying_stream_->Skip(count);
|
||||
position_ += skipped;
|
||||
return skipped == count;
|
||||
}
|
||||
|
||||
int64 CopyingInputStreamAdaptor::ByteCount() const {
|
||||
return position_ - backup_bytes_;
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
|
||||
if (buffer_.get() == NULL) {
|
||||
buffer_.reset(new uint8[buffer_size_]);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::FreeBuffer() {
|
||||
GOOGLE_CHECK_EQ(backup_bytes_, 0);
|
||||
buffer_used_ = 0;
|
||||
buffer_.reset();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
CopyingOutputStream::~CopyingOutputStream() {}
|
||||
|
||||
CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
|
||||
CopyingOutputStream* copying_stream, int block_size)
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0) {
|
||||
}
|
||||
|
||||
CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
|
||||
WriteBuffer();
|
||||
if (owns_copying_stream_) {
|
||||
delete copying_stream_;
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::Flush() {
|
||||
return WriteBuffer();
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
|
||||
if (buffer_used_ == buffer_size_) {
|
||||
if (!WriteBuffer()) return false;
|
||||
}
|
||||
|
||||
AllocateBufferIfNeeded();
|
||||
|
||||
*data = buffer_.get() + buffer_used_;
|
||||
*size = buffer_size_ - buffer_used_;
|
||||
buffer_used_ = buffer_size_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyingOutputStreamAdaptor::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
|
||||
<< " BackUp() can only be called after Next().";
|
||||
GOOGLE_CHECK_LE(count, buffer_used_)
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
|
||||
buffer_used_ -= count;
|
||||
}
|
||||
|
||||
int64 CopyingOutputStreamAdaptor::ByteCount() const {
|
||||
return position_ + buffer_used_;
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::WriteBuffer() {
|
||||
if (failed_) {
|
||||
// Already failed on a previous write.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer_used_ == 0) return true;
|
||||
|
||||
if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
|
||||
position_ += buffer_used_;
|
||||
buffer_used_ = 0;
|
||||
return true;
|
||||
} else {
|
||||
failed_ = true;
|
||||
FreeBuffer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
|
||||
if (buffer_ == NULL) {
|
||||
buffer_.reset(new uint8[buffer_size_]);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyingOutputStreamAdaptor::FreeBuffer() {
|
||||
buffer_used_ = 0;
|
||||
buffer_.reset();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,340 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains common implementations of the interfaces defined in
|
||||
// zero_copy_stream.h which are included in the "lite" protobuf library.
|
||||
// These implementations cover I/O on raw arrays and strings, as well as
|
||||
// adaptors which make it easy to implement streams based on traditional
|
||||
// streams. Of course, many users will probably want to write their own
|
||||
// implementations of these interfaces specific to the particular I/O
|
||||
// abstractions they prefer to use, but these should cover the most common
|
||||
// cases.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace io {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyInputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Create an InputStream that returns the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayInputStream(const void* data, int size, int block_size = -1);
|
||||
~ArrayInputStream();
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
|
||||
private:
|
||||
const uint8* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream backed by an in-memory array of bytes.
|
||||
class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create an OutputStream that writes to the bytes pointed to by "data".
|
||||
// "data" remains the property of the caller but must remain valid until
|
||||
// the stream is destroyed. If a block_size is given, calls to Next()
|
||||
// will return data blocks no larger than the given size. Otherwise, the
|
||||
// first call to Next() returns the entire array. block_size is mainly
|
||||
// useful for testing; in production you would probably never want to set
|
||||
// it.
|
||||
ArrayOutputStream(void* data, int size, int block_size = -1);
|
||||
~ArrayOutputStream();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
uint8* const data_; // The byte array.
|
||||
const int size_; // Total size of the array.
|
||||
const int block_size_; // How many bytes to return at a time.
|
||||
|
||||
int position_;
|
||||
int last_returned_size_; // How many bytes we returned last time Next()
|
||||
// was called (used for error checking only).
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A ZeroCopyOutputStream which appends bytes to a string.
|
||||
class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Create a StringOutputStream which appends bytes to the given string.
|
||||
// The string remains property of the caller, but it MUST NOT be accessed
|
||||
// in any way until the stream is destroyed.
|
||||
//
|
||||
// Hint: If you call target->reserve(n) before creating the stream,
|
||||
// the first call to Next() will return at least n bytes of buffer
|
||||
// space.
|
||||
explicit StringOutputStream(string* target);
|
||||
~StringOutputStream();
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
static const int kMinimumSize = 16;
|
||||
|
||||
string* target_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
||||
};
|
||||
|
||||
// Note: There is no StringInputStream. Instead, just create an
|
||||
// ArrayInputStream as follows:
|
||||
// ArrayInputStream input(str.data(), str.size());
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional input stream interface.
|
||||
//
|
||||
// Lots of traditional input streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every read
|
||||
// involves copying bytes into a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyInputStream based on it, simply implement
|
||||
// CopyingInputStream and then use CopyingInputStreamAdaptor.
|
||||
//
|
||||
// CopyingInputStream implementations should avoid buffering if possible.
|
||||
// CopyingInputStreamAdaptor does its own buffering and will read data
|
||||
// in large blocks.
|
||||
class LIBPROTOBUF_EXPORT CopyingInputStream {
|
||||
public:
|
||||
virtual ~CopyingInputStream();
|
||||
|
||||
// Reads up to "size" bytes into the given buffer. Returns the number of
|
||||
// bytes read. Read() waits until at least one byte is available, or
|
||||
// returns zero if no bytes will ever become available (EOF), or -1 if a
|
||||
// permanent read error occurred.
|
||||
virtual int Read(void* buffer, int size) = 0;
|
||||
|
||||
// Skips the next "count" bytes of input. Returns the number of bytes
|
||||
// actually skipped. This will always be exactly equal to "count" unless
|
||||
// EOF was reached or a permanent read error occurred.
|
||||
//
|
||||
// The default implementation just repeatedly calls Read() into a scratch
|
||||
// buffer.
|
||||
virtual int Skip(int count);
|
||||
};
|
||||
|
||||
// A ZeroCopyInputStream which reads from a CopyingInputStream. This is
|
||||
// useful for implementing ZeroCopyInputStreams that read from traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to read from file descriptors or C++ istreams, this is
|
||||
// already implemented for you: use FileInputStream or IstreamInputStream
|
||||
// respectively.
|
||||
class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream {
|
||||
public:
|
||||
// Creates a stream that reads from the given CopyingInputStream.
|
||||
// If a block_size is given, it specifies the number of bytes that
|
||||
// should be read and returned with each call to Next(). Otherwise,
|
||||
// a reasonable default is used. The caller retains ownership of
|
||||
// copying_stream unless SetOwnsCopyingStream(true) is called.
|
||||
explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingInputStreamAdaptor();
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
|
||||
// delete the underlying CopyingInputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyInputStream ----------------------------------
|
||||
bool Next(const void** data, int* size);
|
||||
void BackUp(int count);
|
||||
bool Skip(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer and resets buffer_used_.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingInputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permenant error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started reading.
|
||||
int64 position_;
|
||||
|
||||
// Data is read into this buffer. It may be NULL if no buffer is currently
|
||||
// in use. Otherwise, it points to an array of size buffer_size_.
|
||||
scoped_array<uint8> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
// Number of bytes in the buffer which were backed up over by a call to
|
||||
// BackUp(). These need to be returned again.
|
||||
// 0 <= backup_bytes_ <= buffer_used_
|
||||
int backup_bytes_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// A generic traditional output stream interface.
|
||||
//
|
||||
// Lots of traditional output streams (e.g. file descriptors, C stdio
|
||||
// streams, and C++ iostreams) expose an interface where every write
|
||||
// involves copying bytes from a buffer. If you want to take such an
|
||||
// interface and make a ZeroCopyOutputStream based on it, simply implement
|
||||
// CopyingOutputStream and then use CopyingOutputStreamAdaptor.
|
||||
//
|
||||
// CopyingOutputStream implementations should avoid buffering if possible.
|
||||
// CopyingOutputStreamAdaptor does its own buffering and will write data
|
||||
// in large blocks.
|
||||
class LIBPROTOBUF_EXPORT CopyingOutputStream {
|
||||
public:
|
||||
virtual ~CopyingOutputStream();
|
||||
|
||||
// Writes "size" bytes from the given buffer to the output. Returns true
|
||||
// if successful, false on a write error.
|
||||
virtual bool Write(const void* buffer, int size) = 0;
|
||||
};
|
||||
|
||||
// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is
|
||||
// useful for implementing ZeroCopyOutputStreams that write to traditional
|
||||
// streams. Note that this class is not really zero-copy.
|
||||
//
|
||||
// If you want to write to file descriptors or C++ ostreams, this is
|
||||
// already implemented for you: use FileOutputStream or OstreamOutputStream
|
||||
// respectively.
|
||||
class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream {
|
||||
public:
|
||||
// Creates a stream that writes to the given Unix file descriptor.
|
||||
// If a block_size is given, it specifies the size of the buffers
|
||||
// that should be returned by Next(). Otherwise, a reasonable default
|
||||
// is used.
|
||||
explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream,
|
||||
int block_size = -1);
|
||||
~CopyingOutputStreamAdaptor();
|
||||
|
||||
// Writes all pending data to the underlying stream. Returns false if a
|
||||
// write error occurred on the underlying stream. (The underlying
|
||||
// stream itself is not necessarily flushed.)
|
||||
bool Flush();
|
||||
|
||||
// Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to
|
||||
// delete the underlying CopyingOutputStream when it is destroyed.
|
||||
void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
|
||||
|
||||
// implements ZeroCopyOutputStream ---------------------------------
|
||||
bool Next(void** data, int* size);
|
||||
void BackUp(int count);
|
||||
int64 ByteCount() const;
|
||||
|
||||
private:
|
||||
// Write the current buffer, if it is present.
|
||||
bool WriteBuffer();
|
||||
// Insures that buffer_ is not NULL.
|
||||
void AllocateBufferIfNeeded();
|
||||
// Frees the buffer.
|
||||
void FreeBuffer();
|
||||
|
||||
// The underlying copying stream.
|
||||
CopyingOutputStream* copying_stream_;
|
||||
bool owns_copying_stream_;
|
||||
|
||||
// True if we have seen a permenant error from the underlying stream.
|
||||
bool failed_;
|
||||
|
||||
// The current position of copying_stream_, relative to the point where
|
||||
// we started writing.
|
||||
int64 position_;
|
||||
|
||||
// Data is written from this buffer. It may be NULL if no buffer is
|
||||
// currently in use. Otherwise, it points to an array of size buffer_size_.
|
||||
scoped_array<uint8> buffer_;
|
||||
const int buffer_size_;
|
||||
|
||||
// Number of valid bytes currently in the buffer (i.e. the size last
|
||||
// returned by Next()). When BackUp() is called, we just reduce this.
|
||||
// 0 <= buffer_used_ <= buffer_size_.
|
||||
int buffer_used_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
|
||||
@@ -0,0 +1,334 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Authors: wink@google.com (Wink Saville),
|
||||
// kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
#include <google/protobuf/stubs/stl_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
MessageLite::~MessageLite() {}
|
||||
|
||||
string MessageLite::InitializationErrorString() const {
|
||||
return "(cannot determine missing fields for lite message)";
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// When serializing, we first compute the byte size, then serialize the message.
|
||||
// If serialization produces a different number of bytes than expected, we
|
||||
// call this function, which crashes. The problem could be due to a bug in the
|
||||
// protobuf implementation but is more likely caused by concurrent modification
|
||||
// of the message. This function attempts to distinguish between the two and
|
||||
// provide a useful error message.
|
||||
void ByteSizeConsistencyError(int byte_size_before_serialization,
|
||||
int byte_size_after_serialization,
|
||||
int bytes_produced_by_serialization) {
|
||||
GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
|
||||
<< "Protocol message was modified concurrently during serialization.";
|
||||
GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
|
||||
<< "Byte size calculation and serialization were inconsistent. This "
|
||||
"may indicate a bug in protocol buffers or it may be caused by "
|
||||
"concurrent modification of the message.";
|
||||
GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
|
||||
}
|
||||
|
||||
string InitializationErrorMessage(const char* action,
|
||||
const MessageLite& message) {
|
||||
// Note: We want to avoid depending on strutil in the lite library, otherwise
|
||||
// we'd use:
|
||||
//
|
||||
// return strings::Substitute(
|
||||
// "Can't $0 message of type \"$1\" because it is missing required "
|
||||
// "fields: $2",
|
||||
// action, message.GetTypeName(),
|
||||
// message.InitializationErrorString());
|
||||
|
||||
string result;
|
||||
result += "Can't ";
|
||||
result += action;
|
||||
result += " message of type \"";
|
||||
result += message.GetTypeName();
|
||||
result += "\" because it is missing required fields: ";
|
||||
result += message.InitializationErrorString();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Several of the Parse methods below just do one thing and then call another
|
||||
// method. In a naive implementation, we might have ParseFromString() call
|
||||
// ParseFromArray() which would call ParseFromZeroCopyStream() which would call
|
||||
// ParseFromCodedStream() which would call MergeFromCodedStream() which would
|
||||
// call MergePartialFromCodedStream(). However, when parsing very small
|
||||
// messages, every function call introduces significant overhead. To avoid
|
||||
// this without reproducing code, we use these forced-inline helpers.
|
||||
//
|
||||
// Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not
|
||||
// definitions.
|
||||
inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message)
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message)
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message)
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
inline bool InlineParseFromArray(const void* data, int size,
|
||||
MessageLite* message)
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
inline bool InlineParsePartialFromArray(const void* data, int size,
|
||||
MessageLite* message)
|
||||
GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
bool InlineMergeFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message) {
|
||||
if (!message->MergePartialFromCodedStream(input)) return false;
|
||||
if (!message->IsInitialized()) {
|
||||
GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InlineParseFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message) {
|
||||
message->Clear();
|
||||
return InlineMergeFromCodedStream(input, message);
|
||||
}
|
||||
|
||||
bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
|
||||
MessageLite* message) {
|
||||
message->Clear();
|
||||
return message->MergePartialFromCodedStream(input);
|
||||
}
|
||||
|
||||
bool InlineParseFromArray(const void* data, int size, MessageLite* message) {
|
||||
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
|
||||
return InlineParseFromCodedStream(&input, message) &&
|
||||
input.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
bool InlineParsePartialFromArray(const void* data, int size,
|
||||
MessageLite* message) {
|
||||
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
|
||||
return InlineParsePartialFromCodedStream(&input, message) &&
|
||||
input.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
|
||||
return InlineMergeFromCodedStream(input, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) {
|
||||
return InlineParseFromCodedStream(input, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) {
|
||||
return InlineParsePartialFromCodedStream(input, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) {
|
||||
io::CodedInputStream decoder(input);
|
||||
return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input) {
|
||||
io::CodedInputStream decoder(input);
|
||||
return ParsePartialFromCodedStream(&decoder) &&
|
||||
decoder.ConsumedEntireMessage();
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size) {
|
||||
io::CodedInputStream decoder(input);
|
||||
decoder.PushLimit(size);
|
||||
return ParseFromCodedStream(&decoder) &&
|
||||
decoder.ConsumedEntireMessage() &&
|
||||
decoder.BytesUntilLimit() == 0;
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromBoundedZeroCopyStream(
|
||||
io::ZeroCopyInputStream* input, int size) {
|
||||
io::CodedInputStream decoder(input);
|
||||
decoder.PushLimit(size);
|
||||
return ParsePartialFromCodedStream(&decoder) &&
|
||||
decoder.ConsumedEntireMessage() &&
|
||||
decoder.BytesUntilLimit() == 0;
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromString(const string& data) {
|
||||
return InlineParseFromArray(data.data(), data.size(), this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromString(const string& data) {
|
||||
return InlineParsePartialFromArray(data.data(), data.size(), this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParseFromArray(const void* data, int size) {
|
||||
return InlineParseFromArray(data, size, this);
|
||||
}
|
||||
|
||||
bool MessageLite::ParsePartialFromArray(const void* data, int size) {
|
||||
return InlineParsePartialFromArray(data, size, this);
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const {
|
||||
// We only optimize this when using optimize_for = SPEED. In other cases
|
||||
// we just use the CodedOutputStream path.
|
||||
int size = GetCachedSize();
|
||||
io::ArrayOutputStream out(target, size);
|
||||
io::CodedOutputStream coded_out(&out);
|
||||
SerializeWithCachedSizes(&coded_out);
|
||||
GOOGLE_CHECK(!coded_out.HadError());
|
||||
return target + size;
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
|
||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||
return SerializePartialToCodedStream(output);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToCodedStream(
|
||||
io::CodedOutputStream* output) const {
|
||||
const int size = ByteSize(); // Force size to be cached.
|
||||
uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
|
||||
if (buffer != NULL) {
|
||||
uint8* end = SerializeWithCachedSizesToArray(buffer);
|
||||
if (end - buffer != size) {
|
||||
ByteSizeConsistencyError(size, ByteSize(), end - buffer);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
int original_byte_count = output->ByteCount();
|
||||
SerializeWithCachedSizes(output);
|
||||
if (output->HadError()) {
|
||||
return false;
|
||||
}
|
||||
int final_byte_count = output->ByteCount();
|
||||
|
||||
if (final_byte_count - original_byte_count != size) {
|
||||
ByteSizeConsistencyError(size, ByteSize(),
|
||||
final_byte_count - original_byte_count);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToZeroCopyStream(
|
||||
io::ZeroCopyOutputStream* output) const {
|
||||
io::CodedOutputStream encoder(output);
|
||||
return SerializeToCodedStream(&encoder);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToZeroCopyStream(
|
||||
io::ZeroCopyOutputStream* output) const {
|
||||
io::CodedOutputStream encoder(output);
|
||||
return SerializePartialToCodedStream(&encoder);
|
||||
}
|
||||
|
||||
bool MessageLite::AppendToString(string* output) const {
|
||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||
return AppendPartialToString(output);
|
||||
}
|
||||
|
||||
bool MessageLite::AppendPartialToString(string* output) const {
|
||||
int old_size = output->size();
|
||||
int byte_size = ByteSize();
|
||||
STLStringResizeUninitialized(output, old_size + byte_size);
|
||||
uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size);
|
||||
uint8* end = SerializeWithCachedSizesToArray(start);
|
||||
if (end - start != byte_size) {
|
||||
ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToString(string* output) const {
|
||||
output->clear();
|
||||
return AppendToString(output);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToString(string* output) const {
|
||||
output->clear();
|
||||
return AppendPartialToString(output);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializeToArray(void* data, int size) const {
|
||||
GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
|
||||
return SerializePartialToArray(data, size);
|
||||
}
|
||||
|
||||
bool MessageLite::SerializePartialToArray(void* data, int size) const {
|
||||
int byte_size = ByteSize();
|
||||
if (size < byte_size) return false;
|
||||
uint8* start = reinterpret_cast<uint8*>(data);
|
||||
uint8* end = SerializeWithCachedSizesToArray(start);
|
||||
if (end - start != byte_size) {
|
||||
ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string MessageLite::SerializeAsString() const {
|
||||
// If the compiler implements the (Named) Return Value Optimization,
|
||||
// the local variable 'result' will not actually reside on the stack
|
||||
// of this function, but will be overlaid with the object that the
|
||||
// caller supplied for the return value to be constructed in.
|
||||
string output;
|
||||
if (!AppendToString(&output))
|
||||
output.clear();
|
||||
return output;
|
||||
}
|
||||
|
||||
string MessageLite::SerializePartialAsString() const {
|
||||
string output;
|
||||
if (!AppendPartialToString(&output))
|
||||
output.clear();
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,246 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Authors: wink@google.com (Wink Saville),
|
||||
// kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Defines MessageLite, the abstract interface implemented by all (lite
|
||||
// and non-lite) protocol message objects.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace io {
|
||||
class CodedInputStream;
|
||||
class CodedOutputStream;
|
||||
class ZeroCopyInputStream;
|
||||
class ZeroCopyOutputStream;
|
||||
}
|
||||
|
||||
// Interface to light weight protocol messages.
|
||||
//
|
||||
// This interface is implemented by all protocol message objects. Non-lite
|
||||
// messages additionally implement the Message interface, which is a
|
||||
// subclass of MessageLite. Use MessageLite instead when you only need
|
||||
// the subset of features which it supports -- namely, nothing that uses
|
||||
// descriptors or reflection. You can instruct the protocol compiler
|
||||
// to generate classes which implement only MessageLite, not the full
|
||||
// Message interface, by adding the following line to the .proto file:
|
||||
//
|
||||
// option optimize_for = LITE_RUNTIME;
|
||||
//
|
||||
// This is particularly useful on resource-constrained systems where
|
||||
// the full protocol buffers runtime library is too big.
|
||||
//
|
||||
// Note that on non-constrained systems (e.g. servers) when you need
|
||||
// to link in lots of protocol definitions, a better way to reduce
|
||||
// total code footprint is to use optimize_for = CODE_SIZE. This
|
||||
// will make the generated code smaller while still supporting all the
|
||||
// same features (at the expense of speed). optimize_for = LITE_RUNTIME
|
||||
// is best when you only have a small number of message types linked
|
||||
// into your binary, in which case the size of the protocol buffers
|
||||
// runtime itself is the biggest problem.
|
||||
class LIBPROTOBUF_EXPORT MessageLite {
|
||||
public:
|
||||
inline MessageLite() {}
|
||||
virtual ~MessageLite();
|
||||
|
||||
// Basic Operations ------------------------------------------------
|
||||
|
||||
// Get the name of this message type, e.g. "foo.bar.BazProto".
|
||||
virtual string GetTypeName() const = 0;
|
||||
|
||||
// Construct a new instance of the same type. Ownership is passed to the
|
||||
// caller.
|
||||
virtual MessageLite* New() const = 0;
|
||||
|
||||
// Clear all fields of the message and set them to their default values.
|
||||
// Clear() avoids freeing memory, assuming that any memory allocated
|
||||
// to hold parts of the message will be needed again to hold the next
|
||||
// message. If you actually want to free the memory used by a Message,
|
||||
// you must delete it.
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Quickly check if all required fields have values set.
|
||||
virtual bool IsInitialized() const = 0;
|
||||
|
||||
// This is not implemented for Lite messages -- it just returns "(cannot
|
||||
// determine missing fields for lite message)". However, it is implemented
|
||||
// for full messages. See message.h.
|
||||
virtual string InitializationErrorString() const;
|
||||
|
||||
// If |other| is the exact same class as this, calls MergeFrom(). Otherwise,
|
||||
// results are undefined (probably crash).
|
||||
virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
|
||||
|
||||
// Parsing ---------------------------------------------------------
|
||||
// Methods for parsing in protocol buffer format. Most of these are
|
||||
// just simple wrappers around MergeFromCodedStream().
|
||||
|
||||
// Fill the message with a protocol buffer parsed from the given input
|
||||
// stream. Returns false on a read error or if the input is in the
|
||||
// wrong format.
|
||||
bool ParseFromCodedStream(io::CodedInputStream* input);
|
||||
// Like ParseFromCodedStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromCodedStream(io::CodedInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream. If
|
||||
// successful, the entire input will be consumed.
|
||||
bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
// Like ParseFromZeroCopyStream(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input);
|
||||
// Read a protocol buffer from the given zero-copy input stream, expecting
|
||||
// the message to be exactly "size" bytes long. If successful, exactly
|
||||
// this many bytes will have been consumed from the input.
|
||||
bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size);
|
||||
// Like ParseFromBoundedZeroCopyStream(), but accepts messages that are
|
||||
// missing required fields.
|
||||
bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
|
||||
int size);
|
||||
// Parse a protocol buffer contained in a string.
|
||||
bool ParseFromString(const string& data);
|
||||
// Like ParseFromString(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromString(const string& data);
|
||||
// Parse a protocol buffer contained in an array of bytes.
|
||||
bool ParseFromArray(const void* data, int size);
|
||||
// Like ParseFromArray(), but accepts messages that are missing
|
||||
// required fields.
|
||||
bool ParsePartialFromArray(const void* data, int size);
|
||||
|
||||
|
||||
// Reads a protocol buffer from the stream and merges it into this
|
||||
// Message. Singular fields read from the input overwrite what is
|
||||
// already in the Message and repeated fields are appended to those
|
||||
// already present.
|
||||
//
|
||||
// It is the responsibility of the caller to call input->LastTagWas()
|
||||
// (for groups) or input->ConsumedEntireMessage() (for non-groups) after
|
||||
// this returns to verify that the message's end was delimited correctly.
|
||||
//
|
||||
// ParsefromCodedStream() is implemented as Clear() followed by
|
||||
// MergeFromCodedStream().
|
||||
bool MergeFromCodedStream(io::CodedInputStream* input);
|
||||
|
||||
// Like MergeFromCodedStream(), but succeeds even if required fields are
|
||||
// missing in the input.
|
||||
//
|
||||
// MergeFromCodedStream() is just implemented as MergePartialFromCodedStream()
|
||||
// followed by IsInitialized().
|
||||
virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
|
||||
|
||||
|
||||
// Serialization ---------------------------------------------------
|
||||
// Methods for serializing in protocol buffer format. Most of these
|
||||
// are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
|
||||
|
||||
// Write a protocol buffer of this message to the given output. Returns
|
||||
// false on a write error. If the message is missing required fields,
|
||||
// this may GOOGLE_CHECK-fail.
|
||||
bool SerializeToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Like SerializeToCodedStream(), but allows missing required fields.
|
||||
bool SerializePartialToCodedStream(io::CodedOutputStream* output) const;
|
||||
// Write the message to the given zero-copy output stream. All required
|
||||
// fields must be set.
|
||||
bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Like SerializeToZeroCopyStream(), but allows missing required fields.
|
||||
bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
|
||||
// Serialize the message and store it in the given string. All required
|
||||
// fields must be set.
|
||||
bool SerializeToString(string* output) const;
|
||||
// Like SerializeToString(), but allows missing required fields.
|
||||
bool SerializePartialToString(string* output) const;
|
||||
// Serialize the message and store it in the given byte array. All required
|
||||
// fields must be set.
|
||||
bool SerializeToArray(void* data, int size) const;
|
||||
// Like SerializeToArray(), but allows missing required fields.
|
||||
bool SerializePartialToArray(void* data, int size) const;
|
||||
|
||||
// Make a string encoding the message. Is equivalent to calling
|
||||
// SerializeToString() on a string and using that. Returns the empty
|
||||
// string if SerializeToString() would have returned an error.
|
||||
// Note: If you intend to generate many such strings, you may
|
||||
// reduce heap fragmentation by instead re-using the same string
|
||||
// object with calls to SerializeToString().
|
||||
string SerializeAsString() const;
|
||||
// Like SerializeAsString(), but allows missing required fields.
|
||||
string SerializePartialAsString() const;
|
||||
|
||||
// Like SerializeToString(), but appends to the data to the string's existing
|
||||
// contents. All required fields must be set.
|
||||
bool AppendToString(string* output) const;
|
||||
// Like AppendToString(), but allows missing required fields.
|
||||
bool AppendPartialToString(string* output) const;
|
||||
|
||||
// Computes the serialized size of the message. This recursively calls
|
||||
// ByteSize() on all embedded messages. If a subclass does not override
|
||||
// this, it MUST override SetCachedSize().
|
||||
virtual int ByteSize() const = 0;
|
||||
|
||||
// Serializes the message without recomputing the size. The message must
|
||||
// not have changed since the last call to ByteSize(); if it has, the results
|
||||
// are undefined.
|
||||
virtual void SerializeWithCachedSizes(
|
||||
io::CodedOutputStream* output) const = 0;
|
||||
|
||||
// Like SerializeWithCachedSizes, but writes directly to *target, returning
|
||||
// a pointer to the byte immediately after the last byte written. "target"
|
||||
// must point at a byte array of at least ByteSize() bytes.
|
||||
virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const;
|
||||
|
||||
// Returns the result of the last call to ByteSize(). An embedded message's
|
||||
// size is needed both to serialize it (because embedded messages are
|
||||
// length-delimited) and to compute the outer message's size. Caching
|
||||
// the size avoids computing it multiple times.
|
||||
//
|
||||
// ByteSize() does not automatically use the cached size when available
|
||||
// because this would require invalidating it every time the message was
|
||||
// modified, which would be too hard and expensive. (E.g. if a deeply-nested
|
||||
// sub-message is changed, all of its parents' cached sizes would need to be
|
||||
// invalidated, which is too much work for an otherwise inlined setter
|
||||
// method.)
|
||||
virtual int GetCachedSize() const = 0;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
|
||||
@@ -0,0 +1,87 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace internal {
|
||||
|
||||
void RepeatedPtrFieldBase::Reserve(int new_size) {
|
||||
if (total_size_ >= new_size) return;
|
||||
|
||||
void** old_elements = elements_;
|
||||
total_size_ = max(kMinRepeatedFieldAllocationSize,
|
||||
max(total_size_ * 2, new_size));
|
||||
elements_ = new void*[total_size_];
|
||||
if (old_elements != NULL) {
|
||||
memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
|
||||
delete [] old_elements;
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
|
||||
if (this == other) return;
|
||||
void** swap_elements = elements_;
|
||||
int swap_current_size = current_size_;
|
||||
int swap_allocated_size = allocated_size_;
|
||||
int swap_total_size = total_size_;
|
||||
|
||||
elements_ = other->elements_;
|
||||
current_size_ = other->current_size_;
|
||||
allocated_size_ = other->allocated_size_;
|
||||
total_size_ = other->total_size_;
|
||||
|
||||
other->elements_ = swap_elements;
|
||||
other->current_size_ = swap_current_size;
|
||||
other->allocated_size_ = swap_allocated_size;
|
||||
other->total_size_ = swap_total_size;
|
||||
}
|
||||
|
||||
string* StringTypeHandlerBase::New() {
|
||||
return new string;
|
||||
}
|
||||
void StringTypeHandlerBase::Delete(string* value) {
|
||||
delete value;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,206 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The routines exported by this module are subtle. If you use them, even if
|
||||
// you get the code right, it will depend on careful reasoning about atomicity
|
||||
// and memory ordering; it will be less readable, and harder to maintain. If
|
||||
// you plan to use these routines, you should have a good reason, such as solid
|
||||
// evidence that performance would otherwise suffer, or there being no
|
||||
// alternative. You should assume only properties explicitly guaranteed by the
|
||||
// specifications in this file. You are almost certainly _not_ writing code
|
||||
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
|
||||
// implementations on other archtectures will cause your code to break. If you
|
||||
// do not know what you are doing, avoid these routines, and use a Mutex.
|
||||
//
|
||||
// It is incorrect to make direct assignments to/from an atomic variable.
|
||||
// You should use one of the Load or Store routines. The NoBarrier
|
||||
// versions are provided when no barriers are needed:
|
||||
// NoBarrier_Store()
|
||||
// NoBarrier_Load()
|
||||
// Although there are currently no compiler enforcement, you are encouraged
|
||||
// to use these.
|
||||
|
||||
// This header and the implementations for each platform (located in
|
||||
// atomicops_internals_*) must be kept in sync with the upstream code (V8).
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_H_
|
||||
|
||||
// Don't include this file for people not concerned about thread safety.
|
||||
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#include <google/protobuf/stubs/platform_macros.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
typedef int32 Atomic32;
|
||||
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
|
||||
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
|
||||
// means Atomic64 and AtomicWord should be the same type on 64-bit.
|
||||
#if defined(GOOGLE_PROTOBUF_OS_NACL)
|
||||
// NaCl's intptr_t is not actually 64-bits on 64-bit!
|
||||
// http://code.google.com/p/nativeclient/issues/detail?id=1162
|
||||
typedef int64 Atomic64;
|
||||
#else
|
||||
typedef intptr_t Atomic64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
|
||||
// Atomic64 routines below, depending on your architecture.
|
||||
typedef intptr_t AtomicWord;
|
||||
|
||||
// Atomically execute:
|
||||
// result = *ptr;
|
||||
// if (*ptr == old_value)
|
||||
// *ptr = new_value;
|
||||
// return result;
|
||||
//
|
||||
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
|
||||
// Always return the old value of "*ptr"
|
||||
//
|
||||
// This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
// Atomically store new_value into *ptr, returning the previous value held in
|
||||
// *ptr. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
|
||||
|
||||
// Atomically increment *ptr by "increment". Returns the new value of
|
||||
// *ptr with the increment applied. This routine implies no memory barriers.
|
||||
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
|
||||
|
||||
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment);
|
||||
|
||||
// These following lower-level operations are typically useful only to people
|
||||
// implementing higher-level synchronization operations like spinlocks,
|
||||
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
|
||||
// a store with appropriate memory-ordering instructions. "Acquire" operations
|
||||
// ensure that no later memory access can be reordered ahead of the operation.
|
||||
// "Release" operations ensure that no previous memory access can be reordered
|
||||
// after the operation. "Barrier" operations have both "Acquire" and "Release"
|
||||
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
|
||||
// access.
|
||||
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value);
|
||||
|
||||
void MemoryBarrier();
|
||||
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
|
||||
|
||||
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
|
||||
Atomic32 Release_Load(volatile const Atomic32* ptr);
|
||||
|
||||
// 64-bit atomic operations (only available on 64-bit processors).
|
||||
#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
|
||||
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
|
||||
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
|
||||
|
||||
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value);
|
||||
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
|
||||
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
|
||||
Atomic64 Release_Load(volatile const Atomic64* ptr);
|
||||
#endif // GOOGLE_PROTOBUF_ARCH_64_BIT
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// Include our platform specific implementation.
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \
|
||||
#error "Atomic operations are not supported on your platform"
|
||||
|
||||
// MSVC.
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
|
||||
#include <google/protobuf/stubs/atomicops_internals_x86_msvc.h>
|
||||
#else
|
||||
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
#endif
|
||||
|
||||
// Apple.
|
||||
#elif defined(GOOGLE_PROTOBUF_OS_APPLE)
|
||||
#include <google/protobuf/stubs/atomicops_internals_macosx.h>
|
||||
|
||||
// GCC.
|
||||
#elif defined(__GNUC__)
|
||||
#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64)
|
||||
#include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_ARM)
|
||||
#include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
|
||||
#include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
|
||||
#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS)
|
||||
#include <google/protobuf/stubs/atomicops_internals_mips_gcc.h>
|
||||
#elif defined(__pnacl__)
|
||||
#include <google/protobuf/stubs/atomicops_internals_pnacl.h>
|
||||
#else
|
||||
#include <google/protobuf/stubs/atomicops_internals_generic_gcc.h>
|
||||
#endif
|
||||
|
||||
// Unknown.
|
||||
#else
|
||||
GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
#endif
|
||||
|
||||
// On some platforms we need additional declarations to make AtomicWord
|
||||
// compatible with our other Atomic* types.
|
||||
#if defined(GOOGLE_PROTOBUF_OS_APPLE)
|
||||
#include <google/protobuf/stubs/atomicops_internals_atomicword_compat.h>
|
||||
#endif
|
||||
|
||||
#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_H_
|
||||
@@ -0,0 +1,151 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
//
|
||||
// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// 0xffff0fc0 is the hard coded address of a function provided by
|
||||
// the kernel which implements an atomic compare-exchange. On older
|
||||
// ARM architecture revisions (pre-v6) this may be implemented using
|
||||
// a syscall. This address is stable, and in active use (hard coded)
|
||||
// by at least glibc-2.7 and the Android C library.
|
||||
typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value,
|
||||
Atomic32 new_value,
|
||||
volatile Atomic32* ptr);
|
||||
LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) =
|
||||
(LinuxKernelCmpxchgFunc) 0xffff0fc0;
|
||||
|
||||
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
|
||||
LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) =
|
||||
(LinuxKernelMemoryBarrierFunc) 0xffff0fa0;
|
||||
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev_value = *ptr;
|
||||
do {
|
||||
if (!pLinuxKernelCmpxchg(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 old_value;
|
||||
do {
|
||||
old_value = *ptr;
|
||||
} while (pLinuxKernelCmpxchg(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr)));
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
for (;;) {
|
||||
// Atomic exchange the old value with an incremented one.
|
||||
Atomic32 old_value = *ptr;
|
||||
Atomic32 new_value = old_value + increment;
|
||||
if (pLinuxKernelCmpxchg(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr)) == 0) {
|
||||
// The exchange took place as expected.
|
||||
return new_value;
|
||||
}
|
||||
// Otherwise, *ptr changed mid-loop and we need to retry.
|
||||
}
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
pLinuxKernelMemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
MemoryBarrier();
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr;
|
||||
MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_
|
||||
@@ -0,0 +1,122 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
|
||||
|
||||
// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32,
|
||||
// which in turn means int. On some LP32 platforms, intptr_t is an int, but
|
||||
// on others, it's a long. When AtomicWord and Atomic32 are based on different
|
||||
// fundamental types, their pointers are incompatible.
|
||||
//
|
||||
// This file defines function overloads to allow both AtomicWord and Atomic32
|
||||
// data to be used with this interface.
|
||||
//
|
||||
// On LP64 platforms, AtomicWord and Atomic64 are both always long,
|
||||
// so this problem doesn't occur.
|
||||
|
||||
#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
|
||||
AtomicWord old_value,
|
||||
AtomicWord new_value) {
|
||||
return NoBarrier_CompareAndSwap(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
|
||||
}
|
||||
|
||||
inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
|
||||
AtomicWord new_value) {
|
||||
return NoBarrier_AtomicExchange(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), new_value);
|
||||
}
|
||||
|
||||
inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
|
||||
AtomicWord increment) {
|
||||
return NoBarrier_AtomicIncrement(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), increment);
|
||||
}
|
||||
|
||||
inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
|
||||
AtomicWord increment) {
|
||||
return Barrier_AtomicIncrement(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), increment);
|
||||
}
|
||||
|
||||
inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
|
||||
AtomicWord old_value,
|
||||
AtomicWord new_value) {
|
||||
return Acquire_CompareAndSwap(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
|
||||
}
|
||||
|
||||
inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
|
||||
AtomicWord old_value,
|
||||
AtomicWord new_value) {
|
||||
return Release_CompareAndSwap(
|
||||
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
|
||||
NoBarrier_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
|
||||
return Acquire_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
|
||||
return Release_Store(reinterpret_cast<volatile Atomic32*>(ptr), value);
|
||||
}
|
||||
|
||||
inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
|
||||
return NoBarrier_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
|
||||
return Acquire_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
|
||||
return Release_Load(reinterpret_cast<volatile const Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
|
||||
@@ -0,0 +1,139 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2013 Red Hat Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Red Hat Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
__atomic_compare_exchange_n(ptr, &old_value, new_value, true,
|
||||
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return __atomic_add_fetch(ptr, increment, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
__atomic_compare_exchange(ptr, &old_value, &new_value, true,
|
||||
__ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
__atomic_compare_exchange_n(ptr, &old_value, new_value, true,
|
||||
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
__atomic_store_n(ptr, value, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
__sync_synchronize();
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
__atomic_store_n(ptr, value, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
__atomic_store_n(ptr, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return __atomic_load_n(ptr, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
return __atomic_load_n(ptr, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
#ifdef __LP64__
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
__atomic_store_n(ptr, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
__atomic_compare_exchange_n(ptr, &old_value, new_value, true,
|
||||
__ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
__atomic_compare_exchange_n(ptr, &old_value, new_value, true,
|
||||
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
|
||||
return old_value;
|
||||
}
|
||||
|
||||
#endif // defined(__LP64__)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_GENERIC_GCC_H_
|
||||
@@ -0,0 +1,225 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap32(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 old_value;
|
||||
do {
|
||||
old_value = *ptr;
|
||||
} while (!OSAtomicCompareAndSwap32(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr)));
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
|
||||
}
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
OSMemoryBarrier();
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
|
||||
const_cast<Atomic32*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return Acquire_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
MemoryBarrier();
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr;
|
||||
MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#ifdef __LP64__
|
||||
|
||||
// 64-bit implementation on 64-bit platform
|
||||
|
||||
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap64(old_value, new_value,
|
||||
reinterpret_cast<volatile int64_t*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 old_value;
|
||||
do {
|
||||
old_value = *ptr;
|
||||
} while (!OSAtomicCompareAndSwap64(old_value, new_value,
|
||||
reinterpret_cast<volatile int64_t*>(ptr)));
|
||||
return old_value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
|
||||
}
|
||||
|
||||
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return OSAtomicAdd64Barrier(increment,
|
||||
reinterpret_cast<volatile int64_t*>(ptr));
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 prev_value;
|
||||
do {
|
||||
if (OSAtomicCompareAndSwap64Barrier(
|
||||
old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
|
||||
return old_value;
|
||||
}
|
||||
prev_value = *ptr;
|
||||
} while (prev_value == old_value);
|
||||
return prev_value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
// The lib kern interface does not distinguish between
|
||||
// Acquire and Release memory barriers; they are equivalent.
|
||||
return Acquire_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
MemoryBarrier();
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr;
|
||||
MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#endif // defined(__LP64__)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_
|
||||
@@ -0,0 +1,137 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This module gets enough CPU information to optimize the
|
||||
// atomicops module on x86.
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
|
||||
// This file only makes sense with atomicops_internals_x86_gcc.h -- it
|
||||
// depends on structs that are defined in that file. If atomicops.h
|
||||
// doesn't sub-include that file, then we aren't needed, and shouldn't
|
||||
// try to do anything.
|
||||
#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
|
||||
|
||||
// Inline cpuid instruction. In PIC compilations, %ebx contains the address
|
||||
// of the global offset table. To avoid breaking such executables, this code
|
||||
// must preserve that register's value across cpuid instructions.
|
||||
#if defined(__i386__)
|
||||
#define cpuid(a, b, c, d, inp) \
|
||||
asm("mov %%ebx, %%edi\n" \
|
||||
"cpuid\n" \
|
||||
"xchg %%edi, %%ebx\n" \
|
||||
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
|
||||
#elif defined(__x86_64__)
|
||||
#define cpuid(a, b, c, d, inp) \
|
||||
asm("mov %%rbx, %%rdi\n" \
|
||||
"cpuid\n" \
|
||||
"xchg %%rdi, %%rbx\n" \
|
||||
: "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp))
|
||||
#endif
|
||||
|
||||
#if defined(cpuid) // initialize the struct only on x86
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Set the flags so that code will run correctly and conservatively, so even
|
||||
// if we haven't been initialized yet, we're probably single threaded, and our
|
||||
// default values should hopefully be pretty safe.
|
||||
struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = {
|
||||
false, // bug can't exist before process spawns multiple threads
|
||||
false, // no SSE2
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
// Initialize the AtomicOps_Internalx86CPUFeatures struct.
|
||||
void AtomicOps_Internalx86CPUFeaturesInit() {
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
|
||||
// Get vendor string (issue CPUID with eax = 0)
|
||||
cpuid(eax, ebx, ecx, edx, 0);
|
||||
char vendor[13];
|
||||
memcpy(vendor, &ebx, 4);
|
||||
memcpy(vendor + 4, &edx, 4);
|
||||
memcpy(vendor + 8, &ecx, 4);
|
||||
vendor[12] = 0;
|
||||
|
||||
// get feature flags in ecx/edx, and family/model in eax
|
||||
cpuid(eax, ebx, ecx, edx, 1);
|
||||
|
||||
int family = (eax >> 8) & 0xf; // family and model fields
|
||||
int model = (eax >> 4) & 0xf;
|
||||
if (family == 0xf) { // use extended family and model fields
|
||||
family += (eax >> 20) & 0xff;
|
||||
model += ((eax >> 16) & 0xf) << 4;
|
||||
}
|
||||
|
||||
// Opteron Rev E has a bug in which on very rare occasions a locked
|
||||
// instruction doesn't act as a read-acquire barrier if followed by a
|
||||
// non-locked read-modify-write instruction. Rev F has this bug in
|
||||
// pre-release versions, but not in versions released to customers,
|
||||
// so we test only for Rev E, which is family 15, model 32..63 inclusive.
|
||||
if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD
|
||||
family == 15 &&
|
||||
32 <= model && model <= 63) {
|
||||
AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true;
|
||||
} else {
|
||||
AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false;
|
||||
}
|
||||
|
||||
// edx bit 26 is SSE2 which we use to tell use whether we can use mfence
|
||||
AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1);
|
||||
}
|
||||
|
||||
class AtomicOpsx86Initializer {
|
||||
public:
|
||||
AtomicOpsx86Initializer() {
|
||||
AtomicOps_Internalx86CPUFeaturesInit();
|
||||
}
|
||||
};
|
||||
|
||||
// A global to get use initialized on startup via static initialization :/
|
||||
AtomicOpsx86Initializer g_initer;
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // __i386__
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
|
||||
@@ -0,0 +1,293 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// This struct is not part of the public API of this module; clients may not
|
||||
// use it.
|
||||
// Features of this x86. Values may not be correct before main() is run,
|
||||
// but are set conservatively.
|
||||
struct AtomicOps_x86CPUFeatureStruct {
|
||||
bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
|
||||
// after acquire compare-and-swap.
|
||||
bool has_sse2; // Processor has SSE2.
|
||||
};
|
||||
extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;
|
||||
|
||||
#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
|
||||
|
||||
// 32-bit low-level operations on any platform.
|
||||
|
||||
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 prev;
|
||||
__asm__ __volatile__("lock; cmpxchgl %1,%2"
|
||||
: "=a" (prev)
|
||||
: "q" (new_value), "m" (*ptr), "0" (old_value)
|
||||
: "memory");
|
||||
return prev;
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
__asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg.
|
||||
: "=r" (new_value)
|
||||
: "m" (*ptr), "0" (new_value)
|
||||
: "memory");
|
||||
return new_value; // Now it's the previous value.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
Atomic32 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddl %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now holds the old value of *ptr
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
Atomic32 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddl %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now holds the old value of *ptr
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
// 64-bit implementations of memory barrier can be simpler, because it
|
||||
// "mfence" is guaranteed to exist.
|
||||
inline void MemoryBarrier() {
|
||||
__asm__ __volatile__("mfence" : : : "memory");
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
|
||||
__asm__ __volatile__("mfence" : : : "memory");
|
||||
} else { // mfence is faster but not present on PIII
|
||||
Atomic32 x = 0;
|
||||
NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII
|
||||
}
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_sse2) {
|
||||
*ptr = value;
|
||||
__asm__ __volatile__("mfence" : : : "memory");
|
||||
} else {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier on PIII
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
*ptr = value; // An x86 store acts as a release barrier.
|
||||
// See comments in Atomic64 version of Release_Store(), below.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr; // An x86 load acts as a acquire barrier.
|
||||
// See comments in Atomic64 version of Release_Store(), below.
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
// 64-bit low-level operations on 64-bit platform.
|
||||
|
||||
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 prev;
|
||||
__asm__ __volatile__("lock; cmpxchgq %1,%2"
|
||||
: "=a" (prev)
|
||||
: "q" (new_value), "m" (*ptr), "0" (old_value)
|
||||
: "memory");
|
||||
return prev;
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
|
||||
Atomic64 new_value) {
|
||||
__asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg.
|
||||
: "=r" (new_value)
|
||||
: "m" (*ptr), "0" (new_value)
|
||||
: "memory");
|
||||
return new_value; // Now it's the previous value.
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
Atomic64 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddq %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now contains the previous value of *ptr
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
Atomic64 temp = increment;
|
||||
__asm__ __volatile__("lock; xaddq %0,%1"
|
||||
: "+r" (temp), "+m" (*ptr)
|
||||
: : "memory");
|
||||
// temp now contains the previous value of *ptr
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return temp + increment;
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
|
||||
*ptr = value; // An x86 store acts as a release barrier
|
||||
// for current AMD/Intel chips as of Jan 2008.
|
||||
// See also Acquire_Load(), below.
|
||||
|
||||
// When new chips come out, check:
|
||||
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
|
||||
// System Programming Guide, Chatper 7: Multiple-processor management,
|
||||
// Section 7.2, Memory Ordering.
|
||||
// Last seen at:
|
||||
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
|
||||
//
|
||||
// x86 stores/loads fail to act as barriers for a few instructions (clflush
|
||||
// maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are
|
||||
// not generated by the compiler, and are rare. Users of these instructions
|
||||
// need to know about cache behaviour in any case since all of these involve
|
||||
// either flushing cache lines or non-temporal cache hints.
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr; // An x86 load acts as a acquire barrier,
|
||||
// for current AMD/Intel chips as of Jan 2008.
|
||||
// See also Release_Store(), above.
|
||||
ATOMICOPS_COMPILER_BARRIER();
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) {
|
||||
__asm__ __volatile__("lfence" : : : "memory");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
#endif // defined(__x86_64__)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#undef ATOMICOPS_COMPILER_BARRIER
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_
|
||||
@@ -0,0 +1,112 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The compilation of extension_set.cc fails when windows.h is included.
|
||||
// Therefore we move the code depending on windows.h to this separate cc file.
|
||||
|
||||
// Don't compile this file for people not concerned about thread safety.
|
||||
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline void MemoryBarrier() {
|
||||
// We use MemoryBarrier from WinNT.h
|
||||
::MemoryBarrier();
|
||||
}
|
||||
|
||||
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
LONG result = InterlockedCompareExchange(
|
||||
reinterpret_cast<volatile LONG*>(ptr),
|
||||
static_cast<LONG>(new_value),
|
||||
static_cast<LONG>(old_value));
|
||||
return static_cast<Atomic32>(result);
|
||||
}
|
||||
|
||||
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
|
||||
Atomic32 new_value) {
|
||||
LONG result = InterlockedExchange(
|
||||
reinterpret_cast<volatile LONG*>(ptr),
|
||||
static_cast<LONG>(new_value));
|
||||
return static_cast<Atomic32>(result);
|
||||
}
|
||||
|
||||
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return InterlockedExchangeAdd(
|
||||
reinterpret_cast<volatile LONG*>(ptr),
|
||||
static_cast<LONG>(increment)) + increment;
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
// 64-bit low-level operations on 64-bit platform.
|
||||
|
||||
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
PVOID result = InterlockedCompareExchangePointer(
|
||||
reinterpret_cast<volatile PVOID*>(ptr),
|
||||
reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
|
||||
return reinterpret_cast<Atomic64>(result);
|
||||
}
|
||||
|
||||
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
|
||||
Atomic64 new_value) {
|
||||
PVOID result = InterlockedExchangePointer(
|
||||
reinterpret_cast<volatile PVOID*>(ptr),
|
||||
reinterpret_cast<PVOID>(new_value));
|
||||
return reinterpret_cast<Atomic64>(result);
|
||||
}
|
||||
|
||||
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return InterlockedExchangeAdd64(
|
||||
reinterpret_cast<volatile LONGLONG*>(ptr),
|
||||
static_cast<LONGLONG>(increment)) + increment;
|
||||
}
|
||||
|
||||
#endif // defined(_WIN64)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
@@ -0,0 +1,150 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file is an internal atomic implementation, use atomicops.h instead.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
|
||||
Atomic32 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
#if !(defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
#error "We require at least vs2005 for MemoryBarrier"
|
||||
#endif
|
||||
|
||||
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
|
||||
Atomic32 old_value,
|
||||
Atomic32 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier in this implementation
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
|
||||
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
|
||||
// See comments in Atomic64 version of Release_Store() below.
|
||||
}
|
||||
|
||||
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
|
||||
Atomic32 value = *ptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
// 64-bit low-level operations on 64-bit platform.
|
||||
|
||||
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
|
||||
Atomic64 increment) {
|
||||
return Barrier_AtomicIncrement(ptr, increment);
|
||||
}
|
||||
|
||||
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value;
|
||||
}
|
||||
|
||||
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
NoBarrier_AtomicExchange(ptr, value);
|
||||
// acts as a barrier in this implementation
|
||||
}
|
||||
|
||||
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
|
||||
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
|
||||
|
||||
// When new chips come out, check:
|
||||
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
|
||||
// System Programming Guide, Chatper 7: Multiple-processor management,
|
||||
// Section 7.2, Memory Ordering.
|
||||
// Last seen at:
|
||||
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
|
||||
}
|
||||
|
||||
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
|
||||
Atomic64 value = *ptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
|
||||
Atomic64 old_value,
|
||||
Atomic64 new_value) {
|
||||
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
|
||||
}
|
||||
|
||||
#endif // defined(_WIN64)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_
|
||||
@@ -0,0 +1,395 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN // We only need minimal includes
|
||||
#include <windows.h>
|
||||
#define snprintf _snprintf // see comment in strutil.cc
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#error "No suitable threading library available."
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace internal {
|
||||
|
||||
void VerifyVersion(int headerVersion,
|
||||
int minLibraryVersion,
|
||||
const char* filename) {
|
||||
if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) {
|
||||
// Library is too old for headers.
|
||||
GOOGLE_LOG(FATAL)
|
||||
<< "This program requires version " << VersionString(minLibraryVersion)
|
||||
<< " of the Protocol Buffer runtime library, but the installed version "
|
||||
"is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update "
|
||||
"your library. If you compiled the program yourself, make sure that "
|
||||
"your headers are from the same version of Protocol Buffers as your "
|
||||
"link-time library. (Version verification failed in \""
|
||||
<< filename << "\".)";
|
||||
}
|
||||
if (headerVersion < kMinHeaderVersionForLibrary) {
|
||||
// Headers are too old for library.
|
||||
GOOGLE_LOG(FATAL)
|
||||
<< "This program was compiled against version "
|
||||
<< VersionString(headerVersion) << " of the Protocol Buffer runtime "
|
||||
"library, which is not compatible with the installed version ("
|
||||
<< VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program "
|
||||
"author for an update. If you compiled the program yourself, make "
|
||||
"sure that your headers are from the same version of Protocol Buffers "
|
||||
"as your link-time library. (Version verification failed in \""
|
||||
<< filename << "\".)";
|
||||
}
|
||||
}
|
||||
|
||||
string VersionString(int version) {
|
||||
int major = version / 1000000;
|
||||
int minor = (version / 1000) % 1000;
|
||||
int micro = version % 1000;
|
||||
|
||||
// 128 bytes should always be enough, but we use snprintf() anyway to be
|
||||
// safe.
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro);
|
||||
|
||||
// Guard against broken MSVC snprintf().
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/logging.cc
|
||||
|
||||
namespace internal {
|
||||
|
||||
void DefaultLogHandler(LogLevel level, const char* filename, int line,
|
||||
const string& message) {
|
||||
static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" };
|
||||
|
||||
// We use fprintf() instead of cerr because we want this to work at static
|
||||
// initialization time.
|
||||
fprintf(stderr, "[libprotobuf %s %s:%d] %s\n",
|
||||
level_names[level], filename, line, message.c_str());
|
||||
fflush(stderr); // Needed on MSVC.
|
||||
}
|
||||
|
||||
void NullLogHandler(LogLevel level, const char* filename, int line,
|
||||
const string& message) {
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
static LogHandler* log_handler_ = &DefaultLogHandler;
|
||||
static int log_silencer_count_ = 0;
|
||||
|
||||
static Mutex* log_silencer_count_mutex_ = NULL;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_);
|
||||
|
||||
void DeleteLogSilencerCount() {
|
||||
delete log_silencer_count_mutex_;
|
||||
log_silencer_count_mutex_ = NULL;
|
||||
}
|
||||
void InitLogSilencerCount() {
|
||||
log_silencer_count_mutex_ = new Mutex;
|
||||
OnShutdown(&DeleteLogSilencerCount);
|
||||
}
|
||||
void InitLogSilencerCountOnce() {
|
||||
GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount);
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(const string& value) {
|
||||
message_ += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogMessage& LogMessage::operator<<(const char* value) {
|
||||
message_ += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Since this is just for logging, we don't care if the current locale changes
|
||||
// the results -- in fact, we probably prefer that. So we use snprintf()
|
||||
// instead of Simple*toa().
|
||||
#undef DECLARE_STREAM_OPERATOR
|
||||
#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \
|
||||
LogMessage& LogMessage::operator<<(TYPE value) { \
|
||||
/* 128 bytes should be big enough for any of the primitive */ \
|
||||
/* values which we print with this, but well use snprintf() */ \
|
||||
/* anyway to be extra safe. */ \
|
||||
char buffer[128]; \
|
||||
snprintf(buffer, sizeof(buffer), FORMAT, value); \
|
||||
/* Guard against broken MSVC snprintf(). */ \
|
||||
buffer[sizeof(buffer)-1] = '\0'; \
|
||||
message_ += buffer; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
DECLARE_STREAM_OPERATOR(char , "%c" )
|
||||
DECLARE_STREAM_OPERATOR(int , "%d" )
|
||||
DECLARE_STREAM_OPERATOR(uint , "%u" )
|
||||
DECLARE_STREAM_OPERATOR(long , "%ld")
|
||||
DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
|
||||
DECLARE_STREAM_OPERATOR(double , "%g" )
|
||||
#undef DECLARE_STREAM_OPERATOR
|
||||
|
||||
LogMessage::LogMessage(LogLevel level, const char* filename, int line)
|
||||
: level_(level), filename_(filename), line_(line) {}
|
||||
LogMessage::~LogMessage() {}
|
||||
|
||||
void LogMessage::Finish() {
|
||||
bool suppress = false;
|
||||
|
||||
if (level_ != LOGLEVEL_FATAL) {
|
||||
InitLogSilencerCountOnce();
|
||||
MutexLock lock(log_silencer_count_mutex_);
|
||||
suppress = log_silencer_count_ > 0;
|
||||
}
|
||||
|
||||
if (!suppress) {
|
||||
log_handler_(level_, filename_, line_, message_);
|
||||
}
|
||||
|
||||
if (level_ == LOGLEVEL_FATAL) {
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
throw FatalException(filename_, line_, message_);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void LogFinisher::operator=(LogMessage& other) {
|
||||
other.Finish();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
LogHandler* SetLogHandler(LogHandler* new_func) {
|
||||
LogHandler* old = internal::log_handler_;
|
||||
if (old == &internal::NullLogHandler) {
|
||||
old = NULL;
|
||||
}
|
||||
if (new_func == NULL) {
|
||||
internal::log_handler_ = &internal::NullLogHandler;
|
||||
} else {
|
||||
internal::log_handler_ = new_func;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
LogSilencer::LogSilencer() {
|
||||
internal::InitLogSilencerCountOnce();
|
||||
MutexLock lock(internal::log_silencer_count_mutex_);
|
||||
++internal::log_silencer_count_;
|
||||
};
|
||||
|
||||
LogSilencer::~LogSilencer() {
|
||||
internal::InitLogSilencerCountOnce();
|
||||
MutexLock lock(internal::log_silencer_count_mutex_);
|
||||
--internal::log_silencer_count_;
|
||||
};
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/callback.cc
|
||||
|
||||
Closure::~Closure() {}
|
||||
|
||||
namespace internal { FunctionClosure0::~FunctionClosure0() {} }
|
||||
|
||||
void DoNothing() {}
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/base/mutex.cc
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
struct Mutex::Internal {
|
||||
CRITICAL_SECTION mutex;
|
||||
#ifndef NDEBUG
|
||||
// Used only to implement AssertHeld().
|
||||
DWORD thread_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
Mutex::Mutex()
|
||||
: mInternal(new Internal) {
|
||||
InitializeCriticalSection(&mInternal->mutex);
|
||||
}
|
||||
|
||||
Mutex::~Mutex() {
|
||||
DeleteCriticalSection(&mInternal->mutex);
|
||||
delete mInternal;
|
||||
}
|
||||
|
||||
void Mutex::Lock() {
|
||||
EnterCriticalSection(&mInternal->mutex);
|
||||
#ifndef NDEBUG
|
||||
mInternal->thread_id = GetCurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mutex::Unlock() {
|
||||
#ifndef NDEBUG
|
||||
mInternal->thread_id = 0;
|
||||
#endif
|
||||
LeaveCriticalSection(&mInternal->mutex);
|
||||
}
|
||||
|
||||
void Mutex::AssertHeld() {
|
||||
#ifndef NDEBUG
|
||||
GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId());
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
|
||||
struct Mutex::Internal {
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
Mutex::Mutex()
|
||||
: mInternal(new Internal) {
|
||||
pthread_mutex_init(&mInternal->mutex, NULL);
|
||||
}
|
||||
|
||||
Mutex::~Mutex() {
|
||||
pthread_mutex_destroy(&mInternal->mutex);
|
||||
delete mInternal;
|
||||
}
|
||||
|
||||
void Mutex::Lock() {
|
||||
int result = pthread_mutex_lock(&mInternal->mutex);
|
||||
if (result != 0) {
|
||||
GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutex::Unlock() {
|
||||
int result = pthread_mutex_unlock(&mInternal->mutex);
|
||||
if (result != 0) {
|
||||
GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result);
|
||||
}
|
||||
}
|
||||
|
||||
void Mutex::AssertHeld() {
|
||||
// pthreads dosn't provide a way to check which thread holds the mutex.
|
||||
// REFINE(kenton): Maybe keep track of locking thread ID like with WIN32?
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ===================================================================
|
||||
// emulates google3/util/endian/endian.h
|
||||
//
|
||||
// REFINE(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in
|
||||
// google/protobuf/io/coded_stream.h and therefore can not be used here.
|
||||
// Maybe move that macro definition here in the furture.
|
||||
uint32 ghtonl(uint32 x) {
|
||||
union {
|
||||
uint32 result;
|
||||
uint8 result_array[4];
|
||||
};
|
||||
result_array[0] = static_cast<uint8>(x >> 24);
|
||||
result_array[1] = static_cast<uint8>((x >> 16) & 0xFF);
|
||||
result_array[2] = static_cast<uint8>((x >> 8) & 0xFF);
|
||||
result_array[3] = static_cast<uint8>(x & 0xFF);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
// Shutdown support.
|
||||
|
||||
namespace internal {
|
||||
|
||||
typedef void OnShutdownFunc();
|
||||
vector<void (*)()>* shutdown_functions = NULL;
|
||||
Mutex* shutdown_functions_mutex = NULL;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init);
|
||||
|
||||
void InitShutdownFunctions() {
|
||||
shutdown_functions = new vector<void (*)()>;
|
||||
shutdown_functions_mutex = new Mutex;
|
||||
}
|
||||
|
||||
inline void InitShutdownFunctionsOnce() {
|
||||
GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions);
|
||||
}
|
||||
|
||||
void OnShutdown(void (*func)()) {
|
||||
InitShutdownFunctionsOnce();
|
||||
MutexLock lock(shutdown_functions_mutex);
|
||||
shutdown_functions->push_back(func);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
void ShutdownProtobufLibrary() {
|
||||
internal::InitShutdownFunctionsOnce();
|
||||
|
||||
// We don't need to lock shutdown_functions_mutex because it's up to the
|
||||
// caller to make sure that no one is using the library before this is
|
||||
// called.
|
||||
|
||||
// Make it safe to call this multiple times.
|
||||
if (internal::shutdown_functions == NULL) return;
|
||||
|
||||
for (int i = 0; i < internal::shutdown_functions->size(); i++) {
|
||||
internal::shutdown_functions->at(i)();
|
||||
}
|
||||
delete internal::shutdown_functions;
|
||||
internal::shutdown_functions = NULL;
|
||||
delete internal::shutdown_functions_mutex;
|
||||
internal::shutdown_functions_mutex = NULL;
|
||||
}
|
||||
|
||||
#if PROTOBUF_USE_EXCEPTIONS
|
||||
FatalException::~FatalException() throw() {}
|
||||
|
||||
const char* FatalException::what() const throw() {
|
||||
return message_.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,232 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// Deals with the fact that hash_map is not defined everywhere.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include "config.h"
|
||||
|
||||
#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
|
||||
#include HASH_MAP_H
|
||||
#include HASH_SET_H
|
||||
#else
|
||||
#define MISSING_HASH
|
||||
#include <map>
|
||||
#include <set>
|
||||
#endif
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef MISSING_HASH
|
||||
|
||||
// This system doesn't have hash_map or hash_set. Emulate them using map and
|
||||
// set.
|
||||
|
||||
// Make hash<T> be the same as less<T>. Note that everywhere where custom
|
||||
// hash functions are defined in the protobuf code, they are also defined such
|
||||
// that they can be used as "less" functions, which is required by MSVC anyway.
|
||||
template <typename Key>
|
||||
struct hash {
|
||||
// Dummy, just to make derivative hash functions compile.
|
||||
int operator()(const Key& key) {
|
||||
GOOGLE_LOG(FATAL) << "Should never be called.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator()(const Key& a, const Key& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure char* is compared by value.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
// Dummy, just to make derivative hash functions compile.
|
||||
int operator()(const char* key) {
|
||||
GOOGLE_LOG(FATAL) << "Should never be called.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_map : public std::map<Key, Data, HashFcn> {
|
||||
public:
|
||||
hash_map(int = 0) {}
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_set : public std::set<Key, HashFcn> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
};
|
||||
|
||||
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public HASH_NAMESPACE::hash_compare<Key> {
|
||||
};
|
||||
|
||||
// MSVC's hash_compare<const char*> hashes based on the string contents but
|
||||
// compares based on the string pointer. WTF?
|
||||
class CstringLess {
|
||||
public:
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<const char*>
|
||||
: public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_map : public HASH_NAMESPACE::hash_map<
|
||||
Key, Data, HashFcn> {
|
||||
public:
|
||||
hash_map(int = 0) {}
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = int >
|
||||
class hash_set : public HASH_NAMESPACE::hash_set<
|
||||
Key, HashFcn> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename Key>
|
||||
struct hash : public HASH_NAMESPACE::hash<Key> {
|
||||
};
|
||||
|
||||
template <typename Key>
|
||||
struct hash<const Key*> {
|
||||
inline size_t operator()(const Key* key) const {
|
||||
return reinterpret_cast<size_t>(key);
|
||||
}
|
||||
};
|
||||
|
||||
// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
|
||||
// we go ahead and provide our own implementation.
|
||||
template <>
|
||||
struct hash<const char*> {
|
||||
inline size_t operator()(const char* str) const {
|
||||
size_t result = 0;
|
||||
for (; *str != '\0'; str++) {
|
||||
result = 5 * result + *str;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key, typename Data,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key> >
|
||||
class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
|
||||
Key, Data, HashFcn, EqualKey> {
|
||||
public:
|
||||
hash_map(int = 0) {}
|
||||
};
|
||||
|
||||
template <typename Key,
|
||||
typename HashFcn = hash<Key>,
|
||||
typename EqualKey = std::equal_to<Key> >
|
||||
class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
|
||||
Key, HashFcn, EqualKey> {
|
||||
public:
|
||||
hash_set(int = 0) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct hash<string> {
|
||||
inline size_t operator()(const string& key) const {
|
||||
return hash<const char*>()(key.c_str());
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline size_t operator()(const string& a, const string& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename First, typename Second>
|
||||
struct hash<pair<First, Second> > {
|
||||
inline size_t operator()(const pair<First, Second>& key) const {
|
||||
size_t first_hash = hash<First>()(key.first);
|
||||
size_t second_hash = hash<Second>()(key.second);
|
||||
|
||||
// IDEA(kenton): What is the best way to compute this hash? I have
|
||||
// no idea! This seems a bit better than an XOR.
|
||||
return first_hash * ((1 << 16) - 1) + second_hash;
|
||||
}
|
||||
|
||||
static const size_t bucket_size = 4;
|
||||
static const size_t min_buckets = 8;
|
||||
inline size_t operator()(const pair<First, Second>& a,
|
||||
const pair<First, Second>& b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
// Used by GCC/SGI STL only. (Why isn't this provided by the standard
|
||||
// library? :( )
|
||||
struct streq {
|
||||
inline bool operator()(const char* a, const char* b) const {
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__
|
||||
@@ -0,0 +1,143 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/util/gtl/map-util.h
|
||||
// Author: Anton Carver
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Perform a lookup in a map or hash_map.
|
||||
// If the key is present in the map then the value associated with that
|
||||
// key is returned, otherwise the value passed as a default is returned.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindWithDefault(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key,
|
||||
const typename Collection::value_type::second_type& value) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return value;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Perform a lookup in a map or hash_map.
|
||||
// If the key is present a const pointer to the associated value is returned,
|
||||
// otherwise a NULL pointer is returned.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type*
|
||||
FindOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
// Perform a lookup in a map or hash_map, assuming that the key exists.
|
||||
// Crash if it does not.
|
||||
//
|
||||
// This is intended as a replacement for operator[] as an rvalue (for reading)
|
||||
// when the key is guaranteed to exist.
|
||||
//
|
||||
// operator[] is discouraged for several reasons:
|
||||
// * It has a side-effect of inserting missing keys
|
||||
// * It is not thread-safe (even when it is not inserting, it can still
|
||||
// choose to resize the underlying storage)
|
||||
// * It invalidates iterators (when it chooses to resize)
|
||||
// * It default constructs a value object even if it doesn't need to
|
||||
//
|
||||
// This version assumes the key is printable, and includes it in the fatal log
|
||||
// message.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type&
|
||||
FindOrDie(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Perform a lookup in a map or hash_map whose values are pointers.
|
||||
// If the key is present a const pointer to the associated value is returned,
|
||||
// otherwise a NULL pointer is returned.
|
||||
// This function does not distinguish between a missing key and a key mapped
|
||||
// to a NULL value.
|
||||
template <class Collection>
|
||||
const typename Collection::value_type::second_type
|
||||
FindPtrOrNull(const Collection& collection,
|
||||
const typename Collection::value_type::first_type& key) {
|
||||
typename Collection::const_iterator it = collection.find(key);
|
||||
if (it == collection.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Change the value associated with a particular key in a map or hash_map.
|
||||
// If the key is not present in the map the key and value are inserted,
|
||||
// otherwise the value is updated to be a copy of the value provided.
|
||||
// True indicates that an insert took place, false indicates an update.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool InsertOrUpdate(Collection * const collection,
|
||||
const Key& key, const Value& value) {
|
||||
pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
if (!ret.second) {
|
||||
// update
|
||||
ret.first->second = value;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Insert a new key and value into a map or hash_map.
|
||||
// If the key is not present in the map the key and value are
|
||||
// inserted, otherwise nothing happens. True indicates that an insert
|
||||
// took place, false indicates the key was already present.
|
||||
template <class Collection, class Key, class Value>
|
||||
bool InsertIfNotPresent(Collection * const collection,
|
||||
const Key& key, const Value& value) {
|
||||
pair<typename Collection::iterator, bool> ret =
|
||||
collection->insert(typename Collection::value_type(key, value));
|
||||
return ret.second;
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
|
||||
@@ -0,0 +1,99 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// emulates google3/base/once.h
|
||||
//
|
||||
// This header is intended to be included only by internal .cc files and
|
||||
// generated .pb.cc files. Users should not use this directly.
|
||||
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
namespace {
|
||||
|
||||
void SchedYield() {
|
||||
#ifdef _WIN32
|
||||
Sleep(0);
|
||||
#else // POSIX
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) {
|
||||
internal::AtomicWord state = internal::Acquire_Load(once);
|
||||
// Fast path. The provided closure was already executed.
|
||||
if (state == ONCE_STATE_DONE) {
|
||||
return;
|
||||
}
|
||||
// The closure execution did not complete yet. The once object can be in one
|
||||
// of the two following states:
|
||||
// - UNINITIALIZED: We are the first thread calling this function.
|
||||
// - EXECUTING_CLOSURE: Another thread is already executing the closure.
|
||||
//
|
||||
// First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE
|
||||
// atomically.
|
||||
state = internal::Acquire_CompareAndSwap(
|
||||
once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE);
|
||||
if (state == ONCE_STATE_UNINITIALIZED) {
|
||||
// We are the first thread to call this function, so we have to call the
|
||||
// closure.
|
||||
closure->Run();
|
||||
internal::Release_Store(once, ONCE_STATE_DONE);
|
||||
} else {
|
||||
// Another thread has already started executing the closure. We need to
|
||||
// wait until it completes the initialization.
|
||||
while (state == ONCE_STATE_EXECUTING_CLOSURE) {
|
||||
// Note that futex() could be used here on Linux as an improvement.
|
||||
SchedYield();
|
||||
state = internal::Acquire_Load(once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
@@ -0,0 +1,148 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// emulates google3/base/once.h
|
||||
//
|
||||
// This header is intended to be included only by internal .cc files and
|
||||
// generated .pb.cc files. Users should not use this directly.
|
||||
//
|
||||
// This is basically a portable version of pthread_once().
|
||||
//
|
||||
// This header declares:
|
||||
// * A type called ProtobufOnceType.
|
||||
// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
|
||||
// ProtobufOnceType. This is the only legal way to declare such a variable.
|
||||
// The macro may only be used at the global scope (you cannot create local or
|
||||
// class member variables of this type).
|
||||
// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()).
|
||||
// This function, when invoked multiple times given the same ProtobufOnceType
|
||||
// object, will invoke init_func on the first call only, and will make sure
|
||||
// none of the calls return before that first call to init_func has finished.
|
||||
// * The user can provide a parameter which GoogleOnceInit() forwards to the
|
||||
// user-provided function when it is called. Usage example:
|
||||
// int a = 10;
|
||||
// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a);
|
||||
// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no
|
||||
// static initializer generated).
|
||||
//
|
||||
// This implements a way to perform lazy initialization. It's more efficient
|
||||
// than using mutexes as no lock is needed if initialization has already
|
||||
// happened.
|
||||
//
|
||||
// Example usage:
|
||||
// void Init();
|
||||
// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);
|
||||
//
|
||||
// // Calls Init() exactly once.
|
||||
// void InitOnce() {
|
||||
// GoogleOnceInit(&once_init, &Init);
|
||||
// }
|
||||
//
|
||||
// Note that if GoogleOnceInit() is called before main() has begun, it must
|
||||
// only be called by the thread that will eventually call main() -- that is,
|
||||
// the thread that performs dynamic initialization. In general this is a safe
|
||||
// assumption since people don't usually construct threads before main() starts,
|
||||
// but it is technically not guaranteed. Unfortunately, Win32 provides no way
|
||||
// whatsoever to statically-initialize its synchronization primitives, so our
|
||||
// only choice is to assume that dynamic initialization is single-threaded.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
|
||||
#include <google/protobuf/stubs/atomicops.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
typedef bool ProtobufOnceType;
|
||||
|
||||
#define GOOGLE_PROTOBUF_ONCE_INIT false
|
||||
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
|
||||
if (!*once) {
|
||||
*once = true;
|
||||
init_func();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg),
|
||||
Arg arg) {
|
||||
if (!*once) {
|
||||
*once = true;
|
||||
init_func(arg);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
enum {
|
||||
ONCE_STATE_UNINITIALIZED = 0,
|
||||
ONCE_STATE_EXECUTING_CLOSURE = 1,
|
||||
ONCE_STATE_DONE = 2
|
||||
};
|
||||
|
||||
typedef internal::AtomicWord ProtobufOnceType;
|
||||
|
||||
#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED
|
||||
|
||||
LIBPROTOBUF_EXPORT
|
||||
void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure);
|
||||
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) {
|
||||
if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
|
||||
internal::FunctionClosure0 func(init_func, false);
|
||||
GoogleOnceInitImpl(once, &func);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*),
|
||||
Arg* arg) {
|
||||
if (internal::Acquire_Load(once) != ONCE_STATE_DONE) {
|
||||
internal::FunctionClosure1<Arg*> func(init_func, false, arg);
|
||||
GoogleOnceInitImpl(once, &func);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY
|
||||
|
||||
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
|
||||
::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__
|
||||
@@ -0,0 +1,82 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
// Processor architecture detection. For more info on what's defined, see:
|
||||
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// http://www.agner.org/optimize/calling_conventions.pdf
|
||||
// or with gcc, run: "echo | gcc -E -dM -"
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_X64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_IA32 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__aarch64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_AARCH64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__QNX__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__ARMEL__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_ARM 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__MIPSEL__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_MIPS 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__pnacl__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__ppc64__) || defined(__PPC64__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_PPC64 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#elif defined(__ppc__) || defined(__PPC__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_PPC 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#elif defined(__s390x__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_64_BIT 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_S390X 1
|
||||
#elif defined(__s390__)
|
||||
#define GOOGLE_PROTOBUF_ARCH_32_BIT 1
|
||||
#define GOOGLE_PROTOBUF_ARCH_S390 1
|
||||
#else
|
||||
#error Host architecture was not detected as supported by protobuf
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define GOOGLE_PROTOBUF_OS_APPLE
|
||||
#elif defined(__native_client__)
|
||||
#define GOOGLE_PROTOBUF_OS_NACL
|
||||
#endif
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_
|
||||
@@ -0,0 +1,121 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/util/gtl/stl_util.h
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// STLDeleteContainerPointers()
|
||||
// For a range within a container of pointers, calls delete
|
||||
// (non-array version) on these pointers.
|
||||
// NOTE: for these three functions, we could just implement a DeleteObject
|
||||
// functor and then call for_each() on the range and functor, but this
|
||||
// requires us to pull in all of algorithm.h, which seems expensive.
|
||||
// For hash_[multi]set, it is important that this deletes behind the iterator
|
||||
// because the hash_set may call the hash function on the iterator when it is
|
||||
// advanced, which could result in the hash function trying to deference a
|
||||
// stale pointer.
|
||||
template <class ForwardIterator>
|
||||
void STLDeleteContainerPointers(ForwardIterator begin,
|
||||
ForwardIterator end) {
|
||||
while (begin != end) {
|
||||
ForwardIterator temp = begin;
|
||||
++begin;
|
||||
delete *temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Inside Google, this function implements a horrible, disgusting hack in which
|
||||
// we reach into the string's private implementation and resize it without
|
||||
// initializing the new bytes. In some cases doing this can significantly
|
||||
// improve performance. However, since it's totally non-portable it has no
|
||||
// place in open source code. Feel free to fill this function in with your
|
||||
// own disgusting hack if you want the perf boost.
|
||||
inline void STLStringResizeUninitialized(string* s, size_t new_size) {
|
||||
s->resize(new_size);
|
||||
}
|
||||
|
||||
// Return a mutable char* pointing to a string's internal buffer,
|
||||
// which may not be null-terminated. Writing through this pointer will
|
||||
// modify the string.
|
||||
//
|
||||
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
|
||||
// next call to a string method that invalidates iterators.
|
||||
//
|
||||
// As of 2006-04, there is no standard-blessed way of getting a
|
||||
// mutable reference to a string's internal buffer. However, issue 530
|
||||
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
|
||||
// proposes this as the method. According to Matt Austern, this should
|
||||
// already work on all current implementations.
|
||||
inline char* string_as_array(string* str) {
|
||||
// DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
|
||||
return str->empty() ? NULL : &*str->begin();
|
||||
}
|
||||
|
||||
// STLDeleteElements() deletes all the elements in an STL container and clears
|
||||
// the container. This function is suitable for use with a vector, set,
|
||||
// hash_set, or any other STL container which defines sensible begin(), end(),
|
||||
// and clear() methods.
|
||||
//
|
||||
// If container is NULL, this function is a no-op.
|
||||
//
|
||||
// As an alternative to calling STLDeleteElements() directly, consider
|
||||
// ElementDeleter (defined below), which ensures that your container's elements
|
||||
// are deleted when the ElementDeleter goes out of scope.
|
||||
template <class T>
|
||||
void STLDeleteElements(T *container) {
|
||||
if (!container) return;
|
||||
STLDeleteContainerPointers(container->begin(), container->end());
|
||||
container->clear();
|
||||
}
|
||||
|
||||
// Given an STL container consisting of (key, value) pairs, STLDeleteValues
|
||||
// deletes all the "value" components and clears the container. Does nothing
|
||||
// in the case it's given a NULL pointer.
|
||||
|
||||
template <class T>
|
||||
void STLDeleteValues(T *v) {
|
||||
if (!v) return;
|
||||
for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
|
||||
delete i->second;
|
||||
}
|
||||
v->clear();
|
||||
}
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
|
||||
@@ -0,0 +1,175 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/base/stringprintf.cc
|
||||
|
||||
#include <google/protobuf/stubs/stringprintf.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h> // For va_list and related operations
|
||||
#include <stdio.h> // MSVC requires this for _vsnprintf
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
//#include <google/protobuf/testing/googletest.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
enum { IS_COMPILER_MSVC = 1 };
|
||||
#ifndef va_copy
|
||||
// Define va_copy for MSVC. This is a hack, assuming va_list is simply a
|
||||
// pointer into the stack and is safe to copy.
|
||||
#define va_copy(dest, src) ((dest) = (src))
|
||||
#endif
|
||||
#else
|
||||
enum { IS_COMPILER_MSVC = 0 };
|
||||
#endif
|
||||
|
||||
void StringAppendV(string* dst, const char* format, va_list ap) {
|
||||
// First try with a small fixed size buffer
|
||||
static const int kSpaceLength = 1024;
|
||||
char space[kSpaceLength];
|
||||
|
||||
// It's possible for methods that use a va_list to invalidate
|
||||
// the data in it upon use. The fix is to make a copy
|
||||
// of the structure before using it and use that copy instead.
|
||||
va_list backup_ap;
|
||||
va_copy(backup_ap, ap);
|
||||
int result = vsnprintf(space, kSpaceLength, format, backup_ap);
|
||||
va_end(backup_ap);
|
||||
|
||||
if (result < kSpaceLength) {
|
||||
if (result >= 0) {
|
||||
// Normal case -- everything fit.
|
||||
dst->append(space, result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_COMPILER_MSVC) {
|
||||
// Error or MSVC running out of space. MSVC 8.0 and higher
|
||||
// can be asked about space needed with the special idiom below:
|
||||
va_copy(backup_ap, ap);
|
||||
result = vsnprintf(NULL, 0, format, backup_ap);
|
||||
va_end(backup_ap);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
// Just an error.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Increase the buffer size to the size requested by vsnprintf,
|
||||
// plus one for the closing \0.
|
||||
int length = result+1;
|
||||
char* buf = new char[length];
|
||||
|
||||
// Restore the va_list before we use it again
|
||||
va_copy(backup_ap, ap);
|
||||
result = vsnprintf(buf, length, format, backup_ap);
|
||||
va_end(backup_ap);
|
||||
|
||||
if (result >= 0 && result < length) {
|
||||
// It fit
|
||||
dst->append(buf, result);
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
|
||||
string StringPrintf(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
string result;
|
||||
StringAppendV(&result, format, ap);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
||||
const string& SStringPrintf(string* dst, const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
dst->clear();
|
||||
StringAppendV(dst, format, ap);
|
||||
va_end(ap);
|
||||
return *dst;
|
||||
}
|
||||
|
||||
void StringAppendF(string* dst, const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
StringAppendV(dst, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Max arguments supported by StringPrintVector
|
||||
const int kStringPrintfVectorMaxArgs = 32;
|
||||
|
||||
// An empty block of zero for filler arguments. This is const so that if
|
||||
// printf tries to write to it (via %n) then the program gets a SIGSEGV
|
||||
// and we can fix the problem or protect against an attack.
|
||||
static const char string_printf_empty_block[256] = { '\0' };
|
||||
|
||||
string StringPrintfVector(const char* format, const vector<string>& v) {
|
||||
GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs)
|
||||
<< "StringPrintfVector currently only supports up to "
|
||||
<< kStringPrintfVectorMaxArgs << " arguments. "
|
||||
<< "Feel free to add support for more if you need it.";
|
||||
|
||||
// Add filler arguments so that bogus format+args have a harder time
|
||||
// crashing the program, corrupting the program (%n),
|
||||
// or displaying random chunks of memory to users.
|
||||
|
||||
const char* cstr[kStringPrintfVectorMaxArgs];
|
||||
for (int i = 0; i < v.size(); ++i) {
|
||||
cstr[i] = v[i].c_str();
|
||||
}
|
||||
for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
|
||||
cstr[i] = &string_printf_empty_block[0];
|
||||
}
|
||||
|
||||
// I do not know any way to pass kStringPrintfVectorMaxArgs arguments,
|
||||
// or any way to build a va_list by hand, or any API for printf
|
||||
// that accepts an array of arguments. The best I can do is stick
|
||||
// this COMPILE_ASSERT right next to the actual statement.
|
||||
|
||||
GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
|
||||
return StringPrintf(format,
|
||||
cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
|
||||
cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],
|
||||
cstr[10], cstr[11], cstr[12], cstr[13], cstr[14],
|
||||
cstr[15], cstr[16], cstr[17], cstr[18], cstr[19],
|
||||
cstr[20], cstr[21], cstr[22], cstr[23], cstr[24],
|
||||
cstr[25], cstr[26], cstr[27], cstr[28], cstr[29],
|
||||
cstr[30], cstr[31]);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,76 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2012 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// from google3/base/stringprintf.h
|
||||
//
|
||||
// Printf variants that place their output in a C++ string.
|
||||
//
|
||||
// Usage:
|
||||
// string result = StringPrintf("%d %s\n", 10, "hello");
|
||||
// SStringPrintf(&result, "%d %s\n", 10, "hello");
|
||||
// StringAppendF(&result, "%d %s\n", 20, "there");
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// Return a C++ string
|
||||
LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...);
|
||||
|
||||
// Store result into a supplied string and return it
|
||||
LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...);
|
||||
|
||||
// Append result to a supplied string
|
||||
LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...);
|
||||
|
||||
// Lower-level routine that takes a va_list and appends to a specified
|
||||
// string. All other routines are just convenience wrappers around it.
|
||||
LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap);
|
||||
|
||||
// The max arguments supported by StringPrintfVector
|
||||
LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs;
|
||||
|
||||
// You can use this version when all your arguments are strings, but
|
||||
// you don't know how many arguments you'll have at compile time.
|
||||
// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
|
||||
LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const vector<string>& v);
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2005 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// ----
|
||||
// Author: lar@google.com (Laramie Leavitt)
|
||||
//
|
||||
// Template metaprogramming utility functions.
|
||||
//
|
||||
// This code is compiled directly on many platforms, including client
|
||||
// platforms like Windows, Mac, and embedded systems. Before making
|
||||
// any changes here, make sure that you're not breaking any platforms.
|
||||
//
|
||||
//
|
||||
// The names choosen here reflect those used in tr1 and the boost::mpl
|
||||
// library, there are similar operations used in the Loki library as
|
||||
// well. I prefer the boost names for 2 reasons:
|
||||
// 1. I think that portions of the Boost libraries are more likely to
|
||||
// be included in the c++ standard.
|
||||
// 2. It is not impossible that some of the boost libraries will be
|
||||
// included in our own build in the future.
|
||||
// Both of these outcomes means that we may be able to directly replace
|
||||
// some of these with boost equivalents.
|
||||
//
|
||||
#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Types small_ and big_ are guaranteed such that sizeof(small_) <
|
||||
// sizeof(big_)
|
||||
typedef char small_;
|
||||
|
||||
struct big_ {
|
||||
char dummy[2];
|
||||
};
|
||||
|
||||
// Identity metafunction.
|
||||
template <class T>
|
||||
struct identity_ {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// integral_constant, defined in tr1, is a wrapper for an integer
|
||||
// value. We don't really need this generality; we could get away
|
||||
// with hardcoding the integer type to bool. We use the fully
|
||||
// general integer_constant for compatibility with tr1.
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
template <class T, T v> const T integral_constant<T, v>::value;
|
||||
|
||||
|
||||
// Abbreviations: true_type and false_type are structs that represent boolean
|
||||
// true and false values. Also define the boost::mpl versions of those names,
|
||||
// true_ and false_.
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
typedef true_type true_;
|
||||
typedef false_type false_;
|
||||
|
||||
// if_ is a templatized conditional statement.
|
||||
// if_<cond, A, B> is a compile time evaluation of cond.
|
||||
// if_<>::type contains A if cond is true, B otherwise.
|
||||
template<bool cond, typename A, typename B>
|
||||
struct if_{
|
||||
typedef A type;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
struct if_<false, A, B> {
|
||||
typedef B type;
|
||||
};
|
||||
|
||||
|
||||
// type_equals_ is a template type comparator, similar to Loki IsSameType.
|
||||
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
|
||||
//
|
||||
// New code should prefer base::is_same, defined in base/type_traits.h.
|
||||
// It is functionally identical, but is_same is the standard spelling.
|
||||
template<typename A, typename B>
|
||||
struct type_equals_ : public false_ {
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct type_equals_<A, A> : public true_ {
|
||||
};
|
||||
|
||||
// and_ is a template && operator.
|
||||
// and_<A, B>::value evaluates "A::value && B::value".
|
||||
template<typename A, typename B>
|
||||
struct and_ : public integral_constant<bool, (A::value && B::value)> {
|
||||
};
|
||||
|
||||
// or_ is a template || operator.
|
||||
// or_<A, B>::value evaluates "A::value || B::value".
|
||||
template<typename A, typename B>
|
||||
struct or_ : public integral_constant<bool, (A::value || B::value)> {
|
||||
};
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
|
||||
@@ -0,0 +1,336 @@
|
||||
// Copyright (c) 2006, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// ----
|
||||
// Author: Matt Austern
|
||||
//
|
||||
// This code is compiled directly on many platforms, including client
|
||||
// platforms like Windows, Mac, and embedded systems. Before making
|
||||
// any changes here, make sure that you're not breaking any platforms.
|
||||
//
|
||||
// Define a small subset of tr1 type traits. The traits we define are:
|
||||
// is_integral
|
||||
// is_floating_point
|
||||
// is_pointer
|
||||
// is_enum
|
||||
// is_reference
|
||||
// is_pod
|
||||
// has_trivial_constructor
|
||||
// has_trivial_copy
|
||||
// has_trivial_assign
|
||||
// has_trivial_destructor
|
||||
// remove_const
|
||||
// remove_volatile
|
||||
// remove_cv
|
||||
// remove_reference
|
||||
// add_reference
|
||||
// remove_pointer
|
||||
// is_same
|
||||
// is_convertible
|
||||
// We can add more type traits as required.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
|
||||
#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
|
||||
|
||||
#include <utility> // For pair
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h> // For true_type and false_type
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <class T> struct is_integral;
|
||||
template <class T> struct is_floating_point;
|
||||
template <class T> struct is_pointer;
|
||||
// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
// is_enum uses is_convertible, which is not available on MSVC.
|
||||
template <class T> struct is_enum;
|
||||
#endif
|
||||
template <class T> struct is_reference;
|
||||
template <class T> struct is_pod;
|
||||
template <class T> struct has_trivial_constructor;
|
||||
template <class T> struct has_trivial_copy;
|
||||
template <class T> struct has_trivial_assign;
|
||||
template <class T> struct has_trivial_destructor;
|
||||
template <class T> struct remove_const;
|
||||
template <class T> struct remove_volatile;
|
||||
template <class T> struct remove_cv;
|
||||
template <class T> struct remove_reference;
|
||||
template <class T> struct add_reference;
|
||||
template <class T> struct remove_pointer;
|
||||
template <class T, class U> struct is_same;
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
template <class From, class To> struct is_convertible;
|
||||
#endif
|
||||
|
||||
// is_integral is false except for the built-in integer types. A
|
||||
// cv-qualified type is integral if and only if the underlying type is.
|
||||
template <class T> struct is_integral : false_type { };
|
||||
template<> struct is_integral<bool> : true_type { };
|
||||
template<> struct is_integral<char> : true_type { };
|
||||
template<> struct is_integral<unsigned char> : true_type { };
|
||||
template<> struct is_integral<signed char> : true_type { };
|
||||
#if defined(_MSC_VER)
|
||||
// wchar_t is not by default a distinct type from unsigned short in
|
||||
// Microsoft C.
|
||||
// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
|
||||
template<> struct is_integral<__wchar_t> : true_type { };
|
||||
#else
|
||||
template<> struct is_integral<wchar_t> : true_type { };
|
||||
#endif
|
||||
template<> struct is_integral<short> : true_type { };
|
||||
template<> struct is_integral<unsigned short> : true_type { };
|
||||
template<> struct is_integral<int> : true_type { };
|
||||
template<> struct is_integral<unsigned int> : true_type { };
|
||||
template<> struct is_integral<long> : true_type { };
|
||||
template<> struct is_integral<unsigned long> : true_type { };
|
||||
#ifdef HAVE_LONG_LONG
|
||||
template<> struct is_integral<long long> : true_type { };
|
||||
template<> struct is_integral<unsigned long long> : true_type { };
|
||||
#endif
|
||||
template <class T> struct is_integral<const T> : is_integral<T> { };
|
||||
template <class T> struct is_integral<volatile T> : is_integral<T> { };
|
||||
template <class T> struct is_integral<const volatile T> : is_integral<T> { };
|
||||
|
||||
// is_floating_point is false except for the built-in floating-point types.
|
||||
// A cv-qualified type is integral if and only if the underlying type is.
|
||||
template <class T> struct is_floating_point : false_type { };
|
||||
template<> struct is_floating_point<float> : true_type { };
|
||||
template<> struct is_floating_point<double> : true_type { };
|
||||
template<> struct is_floating_point<long double> : true_type { };
|
||||
template <class T> struct is_floating_point<const T>
|
||||
: is_floating_point<T> { };
|
||||
template <class T> struct is_floating_point<volatile T>
|
||||
: is_floating_point<T> { };
|
||||
template <class T> struct is_floating_point<const volatile T>
|
||||
: is_floating_point<T> { };
|
||||
|
||||
// is_pointer is false except for pointer types. A cv-qualified type (e.g.
|
||||
// "int* const", as opposed to "int const*") is cv-qualified if and only if
|
||||
// the underlying type is.
|
||||
template <class T> struct is_pointer : false_type { };
|
||||
template <class T> struct is_pointer<T*> : true_type { };
|
||||
template <class T> struct is_pointer<const T> : is_pointer<T> { };
|
||||
template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
|
||||
template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
|
||||
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class T> struct is_class_or_union {
|
||||
template <class U> static small_ tester(void (U::*)());
|
||||
template <class U> static big_ tester(...);
|
||||
static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
|
||||
};
|
||||
|
||||
// is_convertible chokes if the first argument is an array. That's why
|
||||
// we use add_reference here.
|
||||
template <bool NotUnum, class T> struct is_enum_impl
|
||||
: is_convertible<typename add_reference<T>::type, int> { };
|
||||
|
||||
template <class T> struct is_enum_impl<true, T> : false_type { };
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Specified by TR1 [4.5.1] primary type categories.
|
||||
|
||||
// Implementation note:
|
||||
//
|
||||
// Each type is either void, integral, floating point, array, pointer,
|
||||
// reference, member object pointer, member function pointer, enum,
|
||||
// union or class. Out of these, only integral, floating point, reference,
|
||||
// class and enum types are potentially convertible to int. Therefore,
|
||||
// if a type is not a reference, integral, floating point or class and
|
||||
// is convertible to int, it's a enum. Adding cv-qualification to a type
|
||||
// does not change whether it's an enum.
|
||||
//
|
||||
// Is-convertible-to-int check is done only if all other checks pass,
|
||||
// because it can't be used with some types (e.g. void or classes with
|
||||
// inaccessible conversion operators).
|
||||
template <class T> struct is_enum
|
||||
: internal::is_enum_impl<
|
||||
is_same<T, void>::value ||
|
||||
is_integral<T>::value ||
|
||||
is_floating_point<T>::value ||
|
||||
is_reference<T>::value ||
|
||||
internal::is_class_or_union<T>::value,
|
||||
T> { };
|
||||
|
||||
template <class T> struct is_enum<const T> : is_enum<T> { };
|
||||
template <class T> struct is_enum<volatile T> : is_enum<T> { };
|
||||
template <class T> struct is_enum<const volatile T> : is_enum<T> { };
|
||||
|
||||
#endif
|
||||
|
||||
// is_reference is false except for reference types.
|
||||
template<typename T> struct is_reference : false_type {};
|
||||
template<typename T> struct is_reference<T&> : true_type {};
|
||||
|
||||
|
||||
// We can't get is_pod right without compiler help, so fail conservatively.
|
||||
// We will assume it's false except for arithmetic types, enumerations,
|
||||
// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
|
||||
// is not a POD even if T and U are PODs.
|
||||
template <class T> struct is_pod
|
||||
: integral_constant<bool, (is_integral<T>::value ||
|
||||
is_floating_point<T>::value ||
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
// is_enum is not available on MSVC.
|
||||
is_enum<T>::value ||
|
||||
#endif
|
||||
is_pointer<T>::value)> { };
|
||||
template <class T> struct is_pod<const T> : is_pod<T> { };
|
||||
template <class T> struct is_pod<volatile T> : is_pod<T> { };
|
||||
template <class T> struct is_pod<const volatile T> : is_pod<T> { };
|
||||
|
||||
|
||||
// We can't get has_trivial_constructor right without compiler help, so
|
||||
// fail conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial
|
||||
// constructors. (3) array of a type with a trivial constructor.
|
||||
// (4) const versions thereof.
|
||||
template <class T> struct has_trivial_constructor : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_constructor<T>::value &&
|
||||
has_trivial_constructor<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_constructor<A[N]>
|
||||
: has_trivial_constructor<A> { };
|
||||
template <class T> struct has_trivial_constructor<const T>
|
||||
: has_trivial_constructor<T> { };
|
||||
|
||||
// We can't get has_trivial_copy right without compiler help, so fail
|
||||
// conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial copy
|
||||
// constructors. (3) array of a type with a trivial copy constructor.
|
||||
// (4) const versions thereof.
|
||||
template <class T> struct has_trivial_copy : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_copy<T>::value &&
|
||||
has_trivial_copy<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_copy<A[N]>
|
||||
: has_trivial_copy<A> { };
|
||||
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
|
||||
|
||||
// We can't get has_trivial_assign right without compiler help, so fail
|
||||
// conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial copy
|
||||
// constructors. (3) array of a type with a trivial assign constructor.
|
||||
template <class T> struct has_trivial_assign : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_assign<T>::value &&
|
||||
has_trivial_assign<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_assign<A[N]>
|
||||
: has_trivial_assign<A> { };
|
||||
|
||||
// We can't get has_trivial_destructor right without compiler help, so
|
||||
// fail conservatively. We will assume it's false except for: (1) types
|
||||
// for which is_pod is true. (2) std::pair of types with trivial
|
||||
// destructors. (3) array of a type with a trivial destructor.
|
||||
// (4) const versions thereof.
|
||||
template <class T> struct has_trivial_destructor : is_pod<T> { };
|
||||
template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
|
||||
: integral_constant<bool,
|
||||
(has_trivial_destructor<T>::value &&
|
||||
has_trivial_destructor<U>::value)> { };
|
||||
template <class A, int N> struct has_trivial_destructor<A[N]>
|
||||
: has_trivial_destructor<A> { };
|
||||
template <class T> struct has_trivial_destructor<const T>
|
||||
: has_trivial_destructor<T> { };
|
||||
|
||||
// Specified by TR1 [4.7.1]
|
||||
template<typename T> struct remove_const { typedef T type; };
|
||||
template<typename T> struct remove_const<T const> { typedef T type; };
|
||||
template<typename T> struct remove_volatile { typedef T type; };
|
||||
template<typename T> struct remove_volatile<T volatile> { typedef T type; };
|
||||
template<typename T> struct remove_cv {
|
||||
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
|
||||
};
|
||||
|
||||
|
||||
// Specified by TR1 [4.7.2] Reference modifications.
|
||||
template<typename T> struct remove_reference { typedef T type; };
|
||||
template<typename T> struct remove_reference<T&> { typedef T type; };
|
||||
|
||||
template <typename T> struct add_reference { typedef T& type; };
|
||||
template <typename T> struct add_reference<T&> { typedef T& type; };
|
||||
|
||||
// Specified by TR1 [4.7.4] Pointer modifications.
|
||||
template<typename T> struct remove_pointer { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T*> { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T* const> { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
|
||||
template<typename T> struct remove_pointer<T* const volatile> {
|
||||
typedef T type; };
|
||||
|
||||
// Specified by TR1 [4.6] Relationships between types
|
||||
template<typename T, typename U> struct is_same : public false_type { };
|
||||
template<typename T> struct is_same<T, T> : public true_type { };
|
||||
|
||||
// Specified by TR1 [4.6] Relationships between types
|
||||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
|
||||
namespace internal {
|
||||
|
||||
// This class is an implementation detail for is_convertible, and you
|
||||
// don't need to know how it works to use is_convertible. For those
|
||||
// who care: we declare two different functions, one whose argument is
|
||||
// of type To and one with a variadic argument list. We give them
|
||||
// return types of different size, so we can use sizeof to trick the
|
||||
// compiler into telling us which function it would have chosen if we
|
||||
// had called it with an argument of type From. See Alexandrescu's
|
||||
// _Modern C++ Design_ for more details on this sort of trick.
|
||||
|
||||
template <typename From, typename To>
|
||||
struct ConvertHelper {
|
||||
static small_ Test(To);
|
||||
static big_ Test(...);
|
||||
static From Create();
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
||||
template <typename From, typename To>
|
||||
struct is_convertible
|
||||
: integral_constant<bool,
|
||||
sizeof(internal::ConvertHelper<From, To>::Test(
|
||||
internal::ConvertHelper<From, To>::Create()))
|
||||
== sizeof(small_)> {
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_TYPE_TRAITS_H_
|
||||
@@ -0,0 +1,361 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/wire_format_lite_inl.h>
|
||||
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/io/coded_stream_inl.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
#ifndef _MSC_VER // MSVC doesn't like definitions of inline constants, GCC
|
||||
// requires them.
|
||||
const int WireFormatLite::kMessageSetItemStartTag;
|
||||
const int WireFormatLite::kMessageSetItemEndTag;
|
||||
const int WireFormatLite::kMessageSetTypeIdTag;
|
||||
const int WireFormatLite::kMessageSetMessageTag;
|
||||
|
||||
#endif
|
||||
|
||||
const int WireFormatLite::kMessageSetItemTagsSize =
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetItemStartTag>::value +
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetItemEndTag>::value +
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetTypeIdTag>::value +
|
||||
io::CodedOutputStream::StaticVarintSize32<kMessageSetMessageTag>::value;
|
||||
|
||||
const WireFormatLite::CppType
|
||||
WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = {
|
||||
static_cast<CppType>(0), // 0 is reserved for errors
|
||||
|
||||
CPPTYPE_DOUBLE, // TYPE_DOUBLE
|
||||
CPPTYPE_FLOAT, // TYPE_FLOAT
|
||||
CPPTYPE_INT64, // TYPE_INT64
|
||||
CPPTYPE_UINT64, // TYPE_UINT64
|
||||
CPPTYPE_INT32, // TYPE_INT32
|
||||
CPPTYPE_UINT64, // TYPE_FIXED64
|
||||
CPPTYPE_UINT32, // TYPE_FIXED32
|
||||
CPPTYPE_BOOL, // TYPE_BOOL
|
||||
CPPTYPE_STRING, // TYPE_STRING
|
||||
CPPTYPE_MESSAGE, // TYPE_GROUP
|
||||
CPPTYPE_MESSAGE, // TYPE_MESSAGE
|
||||
CPPTYPE_STRING, // TYPE_BYTES
|
||||
CPPTYPE_UINT32, // TYPE_UINT32
|
||||
CPPTYPE_ENUM, // TYPE_ENUM
|
||||
CPPTYPE_INT32, // TYPE_SFIXED32
|
||||
CPPTYPE_INT64, // TYPE_SFIXED64
|
||||
CPPTYPE_INT32, // TYPE_SINT32
|
||||
CPPTYPE_INT64, // TYPE_SINT64
|
||||
};
|
||||
|
||||
const WireFormatLite::WireType
|
||||
WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
|
||||
static_cast<WireFormatLite::WireType>(-1), // invalid
|
||||
WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE
|
||||
WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32
|
||||
WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64
|
||||
WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING
|
||||
WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM
|
||||
WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32
|
||||
WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32
|
||||
WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64
|
||||
};
|
||||
|
||||
bool WireFormatLite::SkipField(
|
||||
io::CodedInputStream* input, uint32 tag) {
|
||||
switch (WireFormatLite::GetTagWireType(tag)) {
|
||||
case WireFormatLite::WIRETYPE_VARINT: {
|
||||
uint64 value;
|
||||
if (!input->ReadVarint64(&value)) return false;
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_FIXED64: {
|
||||
uint64 value;
|
||||
if (!input->ReadLittleEndian64(&value)) return false;
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->Skip(length)) return false;
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_START_GROUP: {
|
||||
if (!input->IncrementRecursionDepth()) return false;
|
||||
if (!SkipMessage(input)) return false;
|
||||
input->DecrementRecursionDepth();
|
||||
// Check that the ending tag matched the starting tag.
|
||||
if (!input->LastTagWas(WireFormatLite::MakeTag(
|
||||
WireFormatLite::GetTagFieldNumber(tag),
|
||||
WireFormatLite::WIRETYPE_END_GROUP))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_END_GROUP: {
|
||||
return false;
|
||||
}
|
||||
case WireFormatLite::WIRETYPE_FIXED32: {
|
||||
uint32 value;
|
||||
if (!input->ReadLittleEndian32(&value)) return false;
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WireFormatLite::SkipMessage(io::CodedInputStream* input) {
|
||||
while(true) {
|
||||
uint32 tag = input->ReadTag();
|
||||
if (tag == 0) {
|
||||
// End of input. This is a valid place to end, so return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
|
||||
|
||||
if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
|
||||
// Must be the end of the message.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SkipField(input, tag)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FieldSkipper::SkipField(
|
||||
io::CodedInputStream* input, uint32 tag) {
|
||||
return WireFormatLite::SkipField(input, tag);
|
||||
}
|
||||
|
||||
bool FieldSkipper::SkipMessage(io::CodedInputStream* input) {
|
||||
return WireFormatLite::SkipMessage(input);
|
||||
}
|
||||
|
||||
void FieldSkipper::SkipUnknownEnum(
|
||||
int field_number, int value) {
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
|
||||
bool (*is_valid)(int),
|
||||
RepeatedField<int>* values) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
io::CodedInputStream::Limit limit = input->PushLimit(length);
|
||||
while (input->BytesUntilLimit() > 0) {
|
||||
int value;
|
||||
if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
|
||||
int, WireFormatLite::TYPE_ENUM>(input, &value)) {
|
||||
return false;
|
||||
}
|
||||
if (is_valid(value)) {
|
||||
values->Add(value);
|
||||
}
|
||||
}
|
||||
input->PopLimit(limit);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteInt32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteInt32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteInt64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteInt64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteUInt32(int field_number, uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteUInt32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteUInt64(int field_number, uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteUInt64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSInt32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteSInt32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSInt64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteSInt64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteFixed32(int field_number, uint32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED32, output);
|
||||
WriteFixed32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteFixed64(int field_number, uint64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED64, output);
|
||||
WriteFixed64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSFixed32(int field_number, int32 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED32, output);
|
||||
WriteSFixed32NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteSFixed64(int field_number, int64 value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED64, output);
|
||||
WriteSFixed64NoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteFloat(int field_number, float value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED32, output);
|
||||
WriteFloatNoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteDouble(int field_number, double value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_FIXED64, output);
|
||||
WriteDoubleNoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteBool(int field_number, bool value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteBoolNoTag(value, output);
|
||||
}
|
||||
void WireFormatLite::WriteEnum(int field_number, int value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_VARINT, output);
|
||||
WriteEnumNoTag(value, output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteString(int field_number, const string& value,
|
||||
io::CodedOutputStream* output) {
|
||||
// String is for UTF-8 text only
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
GOOGLE_CHECK(value.size() <= kint32max);
|
||||
output->WriteVarint32(value.size());
|
||||
output->WriteString(value);
|
||||
}
|
||||
void WireFormatLite::WriteBytes(int field_number, const string& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
GOOGLE_CHECK(value.size() <= kint32max);
|
||||
output->WriteVarint32(value.size());
|
||||
output->WriteString(value);
|
||||
}
|
||||
|
||||
|
||||
void WireFormatLite::WriteGroup(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_START_GROUP, output);
|
||||
value.SerializeWithCachedSizes(output);
|
||||
WriteTag(field_number, WIRETYPE_END_GROUP, output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteMessage(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
const int size = value.GetCachedSize();
|
||||
output->WriteVarint32(size);
|
||||
value.SerializeWithCachedSizes(output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteGroupMaybeToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_START_GROUP, output);
|
||||
const int size = value.GetCachedSize();
|
||||
uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
|
||||
if (target != NULL) {
|
||||
uint8* end = value.SerializeWithCachedSizesToArray(target);
|
||||
GOOGLE_DCHECK_EQ(end - target, size);
|
||||
} else {
|
||||
value.SerializeWithCachedSizes(output);
|
||||
}
|
||||
WriteTag(field_number, WIRETYPE_END_GROUP, output);
|
||||
}
|
||||
|
||||
void WireFormatLite::WriteMessageMaybeToArray(int field_number,
|
||||
const MessageLite& value,
|
||||
io::CodedOutputStream* output) {
|
||||
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
|
||||
const int size = value.GetCachedSize();
|
||||
output->WriteVarint32(size);
|
||||
uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
|
||||
if (target != NULL) {
|
||||
uint8* end = value.SerializeWithCachedSizesToArray(target);
|
||||
GOOGLE_DCHECK_EQ(end - target, size);
|
||||
} else {
|
||||
value.SerializeWithCachedSizes(output);
|
||||
}
|
||||
}
|
||||
|
||||
bool WireFormatLite::ReadString(io::CodedInputStream* input,
|
||||
string* value) {
|
||||
// String is for UTF-8 text only
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
if (!input->InternalReadStringInline(value, length)) return false;
|
||||
return true;
|
||||
}
|
||||
bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
|
||||
string* value) {
|
||||
uint32 length;
|
||||
if (!input->ReadVarint32(&length)) return false;
|
||||
return input->InternalReadStringInline(value, length);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,622 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// atenasio@google.com (Chris Atenasio) (ZigZag transform)
|
||||
// wink@google.com (Wink Saville) (refactored from wire_format.h)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This header is logically internal, but is made public because it is used
|
||||
// from protocol-compiler-generated code, which may reside in other components.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message_lite.h>
|
||||
#include <google/protobuf/io/coded_stream.h> // for CodedOutputStream::Varint32Size
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
template <typename T> class RepeatedField; // repeated_field.h
|
||||
}
|
||||
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
class StringPieceField;
|
||||
|
||||
// This class is for internal use by the protocol buffer library and by
|
||||
// protocol-complier-generated message classes. It must not be called
|
||||
// directly by clients.
|
||||
//
|
||||
// This class contains helpers for implementing the binary protocol buffer
|
||||
// wire format without the need for reflection. Use WireFormat when using
|
||||
// reflection.
|
||||
//
|
||||
// This class is really a namespace that contains only static methods.
|
||||
class LIBPROTOBUF_EXPORT WireFormatLite {
|
||||
public:
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Helper constants and functions related to the format. These are
|
||||
// mostly meant for internal and generated code to use.
|
||||
|
||||
// The wire format is composed of a sequence of tag/value pairs, each
|
||||
// of which contains the value of one field (or one element of a repeated
|
||||
// field). Each tag is encoded as a varint. The lower bits of the tag
|
||||
// identify its wire type, which specifies the format of the data to follow.
|
||||
// The rest of the bits contain the field number. Each type of field (as
|
||||
// declared by FieldDescriptor::Type, in descriptor.h) maps to one of
|
||||
// these wire types. Immediately following each tag is the field's value,
|
||||
// encoded in the format specified by the wire type. Because the tag
|
||||
// identifies the encoding of this data, it is possible to skip
|
||||
// unrecognized fields for forwards compatibility.
|
||||
|
||||
enum WireType {
|
||||
WIRETYPE_VARINT = 0,
|
||||
WIRETYPE_FIXED64 = 1,
|
||||
WIRETYPE_LENGTH_DELIMITED = 2,
|
||||
WIRETYPE_START_GROUP = 3,
|
||||
WIRETYPE_END_GROUP = 4,
|
||||
WIRETYPE_FIXED32 = 5,
|
||||
};
|
||||
|
||||
// Lite alternative to FieldDescriptor::Type. Must be kept in sync.
|
||||
enum FieldType {
|
||||
TYPE_DOUBLE = 1,
|
||||
TYPE_FLOAT = 2,
|
||||
TYPE_INT64 = 3,
|
||||
TYPE_UINT64 = 4,
|
||||
TYPE_INT32 = 5,
|
||||
TYPE_FIXED64 = 6,
|
||||
TYPE_FIXED32 = 7,
|
||||
TYPE_BOOL = 8,
|
||||
TYPE_STRING = 9,
|
||||
TYPE_GROUP = 10,
|
||||
TYPE_MESSAGE = 11,
|
||||
TYPE_BYTES = 12,
|
||||
TYPE_UINT32 = 13,
|
||||
TYPE_ENUM = 14,
|
||||
TYPE_SFIXED32 = 15,
|
||||
TYPE_SFIXED64 = 16,
|
||||
TYPE_SINT32 = 17,
|
||||
TYPE_SINT64 = 18,
|
||||
MAX_FIELD_TYPE = 18,
|
||||
};
|
||||
|
||||
// Lite alternative to FieldDescriptor::CppType. Must be kept in sync.
|
||||
enum CppType {
|
||||
CPPTYPE_INT32 = 1,
|
||||
CPPTYPE_INT64 = 2,
|
||||
CPPTYPE_UINT32 = 3,
|
||||
CPPTYPE_UINT64 = 4,
|
||||
CPPTYPE_DOUBLE = 5,
|
||||
CPPTYPE_FLOAT = 6,
|
||||
CPPTYPE_BOOL = 7,
|
||||
CPPTYPE_ENUM = 8,
|
||||
CPPTYPE_STRING = 9,
|
||||
CPPTYPE_MESSAGE = 10,
|
||||
MAX_CPPTYPE = 10,
|
||||
};
|
||||
|
||||
// Helper method to get the CppType for a particular Type.
|
||||
static CppType FieldTypeToCppType(FieldType type);
|
||||
|
||||
// Given a FieldSescriptor::Type return its WireType
|
||||
static inline WireFormatLite::WireType WireTypeForFieldType(
|
||||
WireFormatLite::FieldType type) {
|
||||
return kWireTypeForFieldType[type];
|
||||
}
|
||||
|
||||
// Number of bits in a tag which identify the wire type.
|
||||
static const int kTagTypeBits = 3;
|
||||
// Mask for those bits.
|
||||
static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1;
|
||||
|
||||
// Helper functions for encoding and decoding tags. (Inlined below and in
|
||||
// _inl.h)
|
||||
//
|
||||
// This is different from MakeTag(field->number(), field->type()) in the case
|
||||
// of packed repeated fields.
|
||||
static uint32 MakeTag(int field_number, WireType type);
|
||||
static WireType GetTagWireType(uint32 tag);
|
||||
static int GetTagFieldNumber(uint32 tag);
|
||||
|
||||
// Compute the byte size of a tag. For groups, this includes both the start
|
||||
// and end tags.
|
||||
static inline int TagSize(int field_number, WireFormatLite::FieldType type);
|
||||
|
||||
// Skips a field value with the given tag. The input should start
|
||||
// positioned immediately after the tag. Skipped values are simply discarded,
|
||||
// not recorded anywhere. See WireFormat::SkipField() for a version that
|
||||
// records to an UnknownFieldSet.
|
||||
static bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
|
||||
// Reads and ignores a message from the input. Skipped values are simply
|
||||
// discarded, not recorded anywhere. See WireFormat::SkipMessage() for a
|
||||
// version that records to an UnknownFieldSet.
|
||||
static bool SkipMessage(io::CodedInputStream* input);
|
||||
|
||||
// This macro does the same thing as WireFormatLite::MakeTag(), but the
|
||||
// result is usable as a compile-time constant, which makes it usable
|
||||
// as a switch case or a template input. WireFormatLite::MakeTag() is more
|
||||
// type-safe, though, so prefer it if possible.
|
||||
#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \
|
||||
static_cast<uint32>( \
|
||||
((FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \
|
||||
| (TYPE))
|
||||
|
||||
// These are the tags for the old MessageSet format, which was defined as:
|
||||
// message MessageSet {
|
||||
// repeated group Item = 1 {
|
||||
// required int32 type_id = 2;
|
||||
// required string message = 3;
|
||||
// }
|
||||
// }
|
||||
static const int kMessageSetItemNumber = 1;
|
||||
static const int kMessageSetTypeIdNumber = 2;
|
||||
static const int kMessageSetMessageNumber = 3;
|
||||
static const int kMessageSetItemStartTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
|
||||
WireFormatLite::WIRETYPE_START_GROUP);
|
||||
static const int kMessageSetItemEndTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
|
||||
WireFormatLite::WIRETYPE_END_GROUP);
|
||||
static const int kMessageSetTypeIdTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber,
|
||||
WireFormatLite::WIRETYPE_VARINT);
|
||||
static const int kMessageSetMessageTag =
|
||||
GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber,
|
||||
WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
|
||||
|
||||
// Byte size of all tags of a MessageSet::Item combined.
|
||||
static const int kMessageSetItemTagsSize;
|
||||
|
||||
// Helper functions for converting between floats/doubles and IEEE-754
|
||||
// uint32s/uint64s so that they can be written. (Assumes your platform
|
||||
// uses IEEE-754 floats.)
|
||||
static uint32 EncodeFloat(float value);
|
||||
static float DecodeFloat(uint32 value);
|
||||
static uint64 EncodeDouble(double value);
|
||||
static double DecodeDouble(uint64 value);
|
||||
|
||||
// Helper functions for mapping signed integers to unsigned integers in
|
||||
// such a way that numbers with small magnitudes will encode to smaller
|
||||
// varints. If you simply static_cast a negative number to an unsigned
|
||||
// number and varint-encode it, it will always take 10 bytes, defeating
|
||||
// the purpose of varint. So, for the "sint32" and "sint64" field types,
|
||||
// we ZigZag-encode the values.
|
||||
static uint32 ZigZagEncode32(int32 n);
|
||||
static int32 ZigZagDecode32(uint32 n);
|
||||
static uint64 ZigZagEncode64(int64 n);
|
||||
static int64 ZigZagDecode64(uint64 n);
|
||||
|
||||
// =================================================================
|
||||
// Methods for reading/writing individual field. The implementations
|
||||
// of these methods are defined in wire_format_lite_inl.h; you must #include
|
||||
// that file to use these.
|
||||
|
||||
// Avoid ugly line wrapping
|
||||
#define input io::CodedInputStream* input
|
||||
#define output io::CodedOutputStream* output
|
||||
#define field_number int field_number
|
||||
#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE
|
||||
|
||||
// Read fields, not including tags. The assumption is that you already
|
||||
// read the tag to determine what field to read.
|
||||
|
||||
// For primitive fields, we just use a templatized routine parameterized by
|
||||
// the represented type and the FieldType. These are specialized with the
|
||||
// appropriate definition for each declared type.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadPrimitive(input, CType* value) INL;
|
||||
|
||||
// Reads repeated primitive values, with optimizations for repeats.
|
||||
// tag_size and tag should both be compile-time constants provided by the
|
||||
// protocol compiler.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadRepeatedPrimitive(int tag_size,
|
||||
uint32 tag,
|
||||
input,
|
||||
RepeatedField<CType>* value) INL;
|
||||
|
||||
// Identical to ReadRepeatedPrimitive, except will not inline the
|
||||
// implementation.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static bool ReadRepeatedPrimitiveNoInline(int tag_size,
|
||||
uint32 tag,
|
||||
input,
|
||||
RepeatedField<CType>* value);
|
||||
|
||||
// Reads a primitive value directly from the provided buffer. It returns a
|
||||
// pointer past the segment of data that was read.
|
||||
//
|
||||
// This is only implemented for the types with fixed wire size, e.g.
|
||||
// float, double, and the (s)fixed* types.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer,
|
||||
CType* value) INL;
|
||||
|
||||
// Reads a primitive packed field.
|
||||
//
|
||||
// This is only implemented for packable types.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadPackedPrimitive(input,
|
||||
RepeatedField<CType>* value) INL;
|
||||
|
||||
// Identical to ReadPackedPrimitive, except will not inline the
|
||||
// implementation.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
|
||||
|
||||
// Read a packed enum field. Values for which is_valid() returns false are
|
||||
// dropped.
|
||||
static bool ReadPackedEnumNoInline(input,
|
||||
bool (*is_valid)(int),
|
||||
RepeatedField<int>* value);
|
||||
|
||||
static bool ReadString(input, string* value);
|
||||
static bool ReadBytes (input, string* value);
|
||||
|
||||
static inline bool ReadGroup (field_number, input, MessageLite* value);
|
||||
static inline bool ReadMessage(input, MessageLite* value);
|
||||
|
||||
// Like above, but de-virtualize the call to MergePartialFromCodedStream().
|
||||
// The pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override MergePartialFromCodedStream()).
|
||||
template<typename MessageType>
|
||||
static inline bool ReadGroupNoVirtual(field_number, input,
|
||||
MessageType* value);
|
||||
template<typename MessageType>
|
||||
static inline bool ReadMessageNoVirtual(input, MessageType* value);
|
||||
|
||||
// Write a tag. The Write*() functions typically include the tag, so
|
||||
// normally there's no need to call this unless using the Write*NoTag()
|
||||
// variants.
|
||||
static inline void WriteTag(field_number, WireType type, output) INL;
|
||||
|
||||
// Write fields, without tags.
|
||||
static inline void WriteInt32NoTag (int32 value, output) INL;
|
||||
static inline void WriteInt64NoTag (int64 value, output) INL;
|
||||
static inline void WriteUInt32NoTag (uint32 value, output) INL;
|
||||
static inline void WriteUInt64NoTag (uint64 value, output) INL;
|
||||
static inline void WriteSInt32NoTag (int32 value, output) INL;
|
||||
static inline void WriteSInt64NoTag (int64 value, output) INL;
|
||||
static inline void WriteFixed32NoTag (uint32 value, output) INL;
|
||||
static inline void WriteFixed64NoTag (uint64 value, output) INL;
|
||||
static inline void WriteSFixed32NoTag(int32 value, output) INL;
|
||||
static inline void WriteSFixed64NoTag(int64 value, output) INL;
|
||||
static inline void WriteFloatNoTag (float value, output) INL;
|
||||
static inline void WriteDoubleNoTag (double value, output) INL;
|
||||
static inline void WriteBoolNoTag (bool value, output) INL;
|
||||
static inline void WriteEnumNoTag (int value, output) INL;
|
||||
|
||||
// Write fields, including tags.
|
||||
static void WriteInt32 (field_number, int32 value, output);
|
||||
static void WriteInt64 (field_number, int64 value, output);
|
||||
static void WriteUInt32 (field_number, uint32 value, output);
|
||||
static void WriteUInt64 (field_number, uint64 value, output);
|
||||
static void WriteSInt32 (field_number, int32 value, output);
|
||||
static void WriteSInt64 (field_number, int64 value, output);
|
||||
static void WriteFixed32 (field_number, uint32 value, output);
|
||||
static void WriteFixed64 (field_number, uint64 value, output);
|
||||
static void WriteSFixed32(field_number, int32 value, output);
|
||||
static void WriteSFixed64(field_number, int64 value, output);
|
||||
static void WriteFloat (field_number, float value, output);
|
||||
static void WriteDouble (field_number, double value, output);
|
||||
static void WriteBool (field_number, bool value, output);
|
||||
static void WriteEnum (field_number, int value, output);
|
||||
|
||||
static void WriteString(field_number, const string& value, output);
|
||||
static void WriteBytes (field_number, const string& value, output);
|
||||
|
||||
static void WriteGroup(
|
||||
field_number, const MessageLite& value, output);
|
||||
static void WriteMessage(
|
||||
field_number, const MessageLite& value, output);
|
||||
// Like above, but these will check if the output stream has enough
|
||||
// space to write directly to a flat array.
|
||||
static void WriteGroupMaybeToArray(
|
||||
field_number, const MessageLite& value, output);
|
||||
static void WriteMessageMaybeToArray(
|
||||
field_number, const MessageLite& value, output);
|
||||
|
||||
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override SerializeWithCachedSizes()).
|
||||
template<typename MessageType>
|
||||
static inline void WriteGroupNoVirtual(
|
||||
field_number, const MessageType& value, output);
|
||||
template<typename MessageType>
|
||||
static inline void WriteMessageNoVirtual(
|
||||
field_number, const MessageType& value, output);
|
||||
|
||||
#undef output
|
||||
#define output uint8* target
|
||||
|
||||
// Like above, but use only *ToArray methods of CodedOutputStream.
|
||||
static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
|
||||
|
||||
// Write fields, without tags.
|
||||
static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL;
|
||||
static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL;
|
||||
static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL;
|
||||
static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL;
|
||||
static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL;
|
||||
static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL;
|
||||
static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
|
||||
static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
|
||||
static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
|
||||
static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
|
||||
static inline uint8* WriteFloatNoTagToArray (float value, output) INL;
|
||||
static inline uint8* WriteDoubleNoTagToArray (double value, output) INL;
|
||||
static inline uint8* WriteBoolNoTagToArray (bool value, output) INL;
|
||||
static inline uint8* WriteEnumNoTagToArray (int value, output) INL;
|
||||
|
||||
// Write fields, including tags.
|
||||
static inline uint8* WriteInt32ToArray(
|
||||
field_number, int32 value, output) INL;
|
||||
static inline uint8* WriteInt64ToArray(
|
||||
field_number, int64 value, output) INL;
|
||||
static inline uint8* WriteUInt32ToArray(
|
||||
field_number, uint32 value, output) INL;
|
||||
static inline uint8* WriteUInt64ToArray(
|
||||
field_number, uint64 value, output) INL;
|
||||
static inline uint8* WriteSInt32ToArray(
|
||||
field_number, int32 value, output) INL;
|
||||
static inline uint8* WriteSInt64ToArray(
|
||||
field_number, int64 value, output) INL;
|
||||
static inline uint8* WriteFixed32ToArray(
|
||||
field_number, uint32 value, output) INL;
|
||||
static inline uint8* WriteFixed64ToArray(
|
||||
field_number, uint64 value, output) INL;
|
||||
static inline uint8* WriteSFixed32ToArray(
|
||||
field_number, int32 value, output) INL;
|
||||
static inline uint8* WriteSFixed64ToArray(
|
||||
field_number, int64 value, output) INL;
|
||||
static inline uint8* WriteFloatToArray(
|
||||
field_number, float value, output) INL;
|
||||
static inline uint8* WriteDoubleToArray(
|
||||
field_number, double value, output) INL;
|
||||
static inline uint8* WriteBoolToArray(
|
||||
field_number, bool value, output) INL;
|
||||
static inline uint8* WriteEnumToArray(
|
||||
field_number, int value, output) INL;
|
||||
|
||||
static inline uint8* WriteStringToArray(
|
||||
field_number, const string& value, output) INL;
|
||||
static inline uint8* WriteBytesToArray(
|
||||
field_number, const string& value, output) INL;
|
||||
|
||||
static inline uint8* WriteGroupToArray(
|
||||
field_number, const MessageLite& value, output) INL;
|
||||
static inline uint8* WriteMessageToArray(
|
||||
field_number, const MessageLite& value, output) INL;
|
||||
|
||||
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override SerializeWithCachedSizes()).
|
||||
template<typename MessageType>
|
||||
static inline uint8* WriteGroupNoVirtualToArray(
|
||||
field_number, const MessageType& value, output) INL;
|
||||
template<typename MessageType>
|
||||
static inline uint8* WriteMessageNoVirtualToArray(
|
||||
field_number, const MessageType& value, output) INL;
|
||||
|
||||
#undef output
|
||||
#undef input
|
||||
#undef INL
|
||||
|
||||
#undef field_number
|
||||
|
||||
// Compute the byte size of a field. The XxSize() functions do NOT include
|
||||
// the tag, so you must also call TagSize(). (This is because, for repeated
|
||||
// fields, you should only call TagSize() once and multiply it by the element
|
||||
// count, but you may have to call XxSize() for each individual element.)
|
||||
static inline int Int32Size ( int32 value);
|
||||
static inline int Int64Size ( int64 value);
|
||||
static inline int UInt32Size (uint32 value);
|
||||
static inline int UInt64Size (uint64 value);
|
||||
static inline int SInt32Size ( int32 value);
|
||||
static inline int SInt64Size ( int64 value);
|
||||
static inline int EnumSize ( int value);
|
||||
|
||||
// These types always have the same size.
|
||||
static const int kFixed32Size = 4;
|
||||
static const int kFixed64Size = 8;
|
||||
static const int kSFixed32Size = 4;
|
||||
static const int kSFixed64Size = 8;
|
||||
static const int kFloatSize = 4;
|
||||
static const int kDoubleSize = 8;
|
||||
static const int kBoolSize = 1;
|
||||
|
||||
static inline int StringSize(const string& value);
|
||||
static inline int BytesSize (const string& value);
|
||||
|
||||
static inline int GroupSize (const MessageLite& value);
|
||||
static inline int MessageSize(const MessageLite& value);
|
||||
|
||||
// Like above, but de-virtualize the call to ByteSize(). The
|
||||
// pointer must point at an instance of MessageType, *not* a subclass (or
|
||||
// the subclass must not override ByteSize()).
|
||||
template<typename MessageType>
|
||||
static inline int GroupSizeNoVirtual (const MessageType& value);
|
||||
template<typename MessageType>
|
||||
static inline int MessageSizeNoVirtual(const MessageType& value);
|
||||
|
||||
// Given the length of data, calculate the byte size of the data on the
|
||||
// wire if we encode the data as a length delimited field.
|
||||
static inline int LengthDelimitedSize(int length);
|
||||
|
||||
private:
|
||||
// A helper method for the repeated primitive reader. This method has
|
||||
// optimizations for primitive types that have fixed size on the wire, and
|
||||
// can be read using potentially faster paths.
|
||||
template <typename CType, enum FieldType DeclaredType>
|
||||
static inline bool ReadRepeatedFixedSizePrimitive(
|
||||
int tag_size,
|
||||
uint32 tag,
|
||||
google::protobuf::io::CodedInputStream* input,
|
||||
RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
|
||||
|
||||
static const CppType kFieldTypeToCppTypeMap[];
|
||||
static const WireFormatLite::WireType kWireTypeForFieldType[];
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
|
||||
};
|
||||
|
||||
// A class which deals with unknown values. The default implementation just
|
||||
// discards them. WireFormat defines a subclass which writes to an
|
||||
// UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since
|
||||
// ExtensionSet is part of the lite library but UnknownFieldSet is not.
|
||||
class LIBPROTOBUF_EXPORT FieldSkipper {
|
||||
public:
|
||||
FieldSkipper() {}
|
||||
virtual ~FieldSkipper() {}
|
||||
|
||||
// Skip a field whose tag has already been consumed.
|
||||
virtual bool SkipField(io::CodedInputStream* input, uint32 tag);
|
||||
|
||||
// Skip an entire message or group, up to an end-group tag (which is consumed)
|
||||
// or end-of-stream.
|
||||
virtual bool SkipMessage(io::CodedInputStream* input);
|
||||
|
||||
// Deal with an already-parsed unrecognized enum value. The default
|
||||
// implementation does nothing, but the UnknownFieldSet-based implementation
|
||||
// saves it as an unknown varint.
|
||||
virtual void SkipUnknownEnum(int field_number, int value);
|
||||
};
|
||||
|
||||
// inline methods ====================================================
|
||||
|
||||
inline WireFormatLite::CppType
|
||||
WireFormatLite::FieldTypeToCppType(FieldType type) {
|
||||
return kFieldTypeToCppTypeMap[type];
|
||||
}
|
||||
|
||||
inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) {
|
||||
return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type);
|
||||
}
|
||||
|
||||
inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) {
|
||||
return static_cast<WireType>(tag & kTagTypeMask);
|
||||
}
|
||||
|
||||
inline int WireFormatLite::GetTagFieldNumber(uint32 tag) {
|
||||
return static_cast<int>(tag >> kTagTypeBits);
|
||||
}
|
||||
|
||||
inline int WireFormatLite::TagSize(int field_number,
|
||||
WireFormatLite::FieldType type) {
|
||||
int result = io::CodedOutputStream::VarintSize32(
|
||||
field_number << kTagTypeBits);
|
||||
if (type == TYPE_GROUP) {
|
||||
// Groups have both a start and an end tag.
|
||||
return result * 2;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32 WireFormatLite::EncodeFloat(float value) {
|
||||
union {float f; uint32 i;};
|
||||
f = value;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline float WireFormatLite::DecodeFloat(uint32 value) {
|
||||
union {float f; uint32 i;};
|
||||
i = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
inline uint64 WireFormatLite::EncodeDouble(double value) {
|
||||
union {double f; uint64 i;};
|
||||
f = value;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline double WireFormatLite::DecodeDouble(uint64 value) {
|
||||
union {double f; uint64 i;};
|
||||
i = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
// ZigZag Transform: Encodes signed integers so that they can be
|
||||
// effectively used with varint encoding.
|
||||
//
|
||||
// varint operates on unsigned integers, encoding smaller numbers into
|
||||
// fewer bytes. If you try to use it on a signed integer, it will treat
|
||||
// this number as a very large unsigned integer, which means that even
|
||||
// small signed numbers like -1 will take the maximum number of bytes
|
||||
// (10) to encode. ZigZagEncode() maps signed integers to unsigned
|
||||
// in such a way that those with a small absolute value will have smaller
|
||||
// encoded values, making them appropriate for encoding using varint.
|
||||
//
|
||||
// int32 -> uint32
|
||||
// -------------------------
|
||||
// 0 -> 0
|
||||
// -1 -> 1
|
||||
// 1 -> 2
|
||||
// -2 -> 3
|
||||
// ... -> ...
|
||||
// 2147483647 -> 4294967294
|
||||
// -2147483648 -> 4294967295
|
||||
//
|
||||
// >> encode >>
|
||||
// << decode <<
|
||||
|
||||
inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (n << 1) ^ (n >> 31);
|
||||
}
|
||||
|
||||
inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
|
||||
return (n >> 1) ^ -static_cast<int32>(n & 1);
|
||||
}
|
||||
|
||||
inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (n << 1) ^ (n >> 63);
|
||||
}
|
||||
|
||||
inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
|
||||
return (n >> 1) ^ -static_cast<int64>(n & 1);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user