Merge pull request #13276 from JoshuaVandaele/sfml-3.0.0
Migrate to SFML 3.0.0
This commit is contained in:
commit
9f43f59c9b
|
@ -84,3 +84,6 @@
|
|||
[submodule "Externals/Vulkan-Headers"]
|
||||
path = Externals/Vulkan-Headers
|
||||
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||
[submodule "Externals/SFML/SFML"]
|
||||
path = Externals/SFML/SFML
|
||||
url = https://github.com/SFML/SFML.git
|
||||
|
|
|
@ -87,9 +87,10 @@ if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
|
|||
set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp")
|
||||
endif()
|
||||
FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS)
|
||||
STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}")
|
||||
STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}")
|
||||
STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}")
|
||||
STRING(REGEX MATCH "#define SFML_VERSION_MAJOR[ \t]+([0-9]+)" SFML_VERSION_MAJOR_MATCH "${SFML_CONFIG_HPP_CONTENTS}")
|
||||
STRING(REGEX MATCH "#define SFML_VERSION_MINOR[ \t]+([0-9]+)" SFML_VERSION_MINOR_MATCH "${SFML_CONFIG_HPP_CONTENTS}")
|
||||
STRING(REGEX REPLACE "#define SFML_VERSION_MAJOR[ \t]+([0-9]+)" "\\1" SFML_VERSION_MAJOR "${SFML_VERSION_MAJOR_MATCH}")
|
||||
STRING(REGEX REPLACE "#define SFML_VERSION_MINOR[ \t]+([0-9]+)" "\\1" SFML_VERSION_MINOR "${SFML_VERSION_MINOR_MATCH}")
|
||||
math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10 + ${SFML_FIND_VERSION_MINOR}")
|
||||
|
||||
# if we could extract them, compare with the requested version number
|
||||
|
@ -102,10 +103,14 @@ if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
|
|||
set(SFML_VERSION_OK FALSE)
|
||||
endif()
|
||||
else()
|
||||
# SFML version is < 2.0
|
||||
if (SFML_REQUESTED_VERSION GREATER 19)
|
||||
# SFML version is < 3.0
|
||||
if (SFML_REQUESTED_VERSION GREATER 29)
|
||||
set(SFML_VERSION_OK FALSE)
|
||||
set(SFML_VERSION_MAJOR 1)
|
||||
if (SFML_REQUESTED_VERSION GREATER 19)
|
||||
set(SFML_VERSION_MAJOR 1)
|
||||
else()
|
||||
set(SFML_VERSION_MAJOR 2)
|
||||
endif()
|
||||
set(SFML_VERSION_MINOR x)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -713,7 +713,7 @@ if(NOT ANDROID)
|
|||
add_definitions(-D__LIBUSB__)
|
||||
endif()
|
||||
|
||||
dolphin_find_optional_system_library(SFML Externals/SFML 2.1 COMPONENTS network system)
|
||||
dolphin_find_optional_system_library(SFML Externals/SFML 3.0 COMPONENTS Network System)
|
||||
|
||||
if(USE_UPNP)
|
||||
dolphin_find_optional_system_library(MINIUPNPC Externals/miniupnpc 1.6)
|
||||
|
|
|
@ -1,31 +1,34 @@
|
|||
set(SRC_NETWORK
|
||||
src/SFML/Network/Http.cpp
|
||||
src/SFML/Network/IPAddress.cpp
|
||||
src/SFML/Network/Packet.cpp
|
||||
src/SFML/Network/Socket.cpp
|
||||
src/SFML/Network/SocketSelector.cpp
|
||||
src/SFML/Network/TcpListener.cpp
|
||||
src/SFML/Network/TcpSocket.cpp
|
||||
src/SFML/Network/UdpSocket.cpp
|
||||
SFML/src/SFML/Network/Http.cpp
|
||||
SFML/src/SFML/Network/IpAddress.cpp
|
||||
SFML/src/SFML/Network/Packet.cpp
|
||||
SFML/src/SFML/Network/Socket.cpp
|
||||
SFML/src/SFML/Network/SocketSelector.cpp
|
||||
SFML/src/SFML/Network/TcpListener.cpp
|
||||
SFML/src/SFML/Network/TcpSocket.cpp
|
||||
SFML/src/SFML/Network/UdpSocket.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND SRC_NETWORK src/SFML/Network/Win32/SocketImpl.cpp)
|
||||
list(APPEND SRC_NETWORK SFML/src/SFML/Network/Win32/SocketImpl.cpp)
|
||||
else()
|
||||
list(APPEND SRC_NETWORK src/SFML/Network/Unix/SocketImpl.cpp)
|
||||
list(APPEND SRC_NETWORK SFML/src/SFML/Network/Unix/SocketImpl.cpp)
|
||||
endif()
|
||||
|
||||
set(SRC_SYSTEM
|
||||
src/SFML/System/Err.cpp
|
||||
src/SFML/System/String.cpp
|
||||
src/SFML/System/Time.cpp
|
||||
SFML/src/SFML/System/Err.cpp
|
||||
SFML/include/SFML/System/String.hpp
|
||||
SFML/src/SFML/System/String.cpp
|
||||
SFML/src/SFML/System/Utils.cpp
|
||||
)
|
||||
|
||||
add_library(sfml-network STATIC ${SRC_NETWORK})
|
||||
add_library(sfml-system STATIC ${SRC_SYSTEM})
|
||||
target_compile_features(sfml-network PUBLIC cxx_std_17)
|
||||
target_compile_features(sfml-system PUBLIC cxx_std_17)
|
||||
target_compile_definitions(sfml-system PUBLIC SFML_STATIC)
|
||||
target_include_directories(sfml-system PUBLIC include PRIVATE src)
|
||||
target_include_directories(sfml-network PUBLIC include PRIVATE src)
|
||||
target_include_directories(sfml-system PUBLIC SFML/include PRIVATE SFML/src)
|
||||
target_include_directories(sfml-network PUBLIC SFML/include PRIVATE SFML/src)
|
||||
target_link_libraries(sfml-network PUBLIC sfml-system)
|
||||
dolphin_disable_warnings(sfml-network)
|
||||
dolphin_disable_warnings(sfml-system)
|
||||
dolphin_disable_warnings(sfml-system)
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7f1162dfea4969bc17417563ac55d93b72e84c1e
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Import Project="..\..\Source\VSProps\Base.Macros.props" />
|
||||
<Import Project="$(VSPropsDir)Base.Targets.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{93D73454-2512-424E-9CDA-4BB357FE13DD}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
|
||||
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
|
||||
Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VSPropsDir)Base.props" />
|
||||
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>SFML\include;SFML\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SFML\src\SFML\Network\Http.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\IpAddress.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\Packet.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\Socket.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\SocketSelector.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\TcpListener.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\TcpSocket.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\UdpSocket.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\Network\Win32\SocketImpl.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\System\Err.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\System\String.cpp" />
|
||||
<ClCompile Include="SFML\src\SFML\System\Utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SFML\include\SFML\Config.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\Export.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\Http.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\IPAddress.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\Packet.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\Socket.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\SocketHandle.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\SocketSelector.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\TcpListener.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\TcpSocket.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\Network\UdpSocket.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System\Err.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System\Export.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System\NonCopyable.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System\String.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System\String.inl" />
|
||||
<ClInclude Include="SFML\include\SFML\System\Utf.hpp" />
|
||||
<ClInclude Include="SFML\include\SFML\System\Utf.inl" />
|
||||
<ClInclude Include="SFML\src\SFML\Network\SocketImpl.hpp" />
|
||||
<ClInclude Include="SFML\src\SFML\Network\Win32\SocketImpl.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,66 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<Import Project="..\..\..\..\Source\VSProps\Base.Macros.props" />
|
||||
<Import Project="$(VSPropsDir)Base.Targets.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{93D73454-2512-424E-9CDA-4BB357FE13DD}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VSPropsDir)Base.props" />
|
||||
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\SFML\Network\Http.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\IPAddress.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\Packet.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\Socket.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\SocketSelector.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\TcpListener.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\TcpSocket.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\UdpSocket.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\Win32\SocketImpl.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\System\Err.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\System\String.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\System\Time.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\SFML\Config.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Export.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Http.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\IPAddress.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Packet.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Socket.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\SocketHandle.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\SocketSelector.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\TcpListener.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\TcpSocket.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\UdpSocket.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Err.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Export.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\NonCopyable.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\String.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\String.inl" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Time.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Utf.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Utf.inl" />
|
||||
<ClInclude Include="..\..\src\SFML\Network\SocketImpl.hpp" />
|
||||
<ClInclude Include="..\..\src\SFML\Network\Win32\SocketImpl.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,51 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\SFML\Network\Http.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\IPAddress.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\Packet.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\Socket.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\SocketSelector.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\TcpListener.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\TcpSocket.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\UdpSocket.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\Network\Win32\SocketImpl.cpp">
|
||||
<Filter>Win32</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\SFML\System\Err.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\System\String.cpp" />
|
||||
<ClCompile Include="..\..\src\SFML\System\Time.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\SFML\Config.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Export.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Http.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\IPAddress.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Packet.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\Socket.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\SocketHandle.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\SocketSelector.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\TcpListener.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\TcpSocket.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\Network\UdpSocket.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Err.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Export.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\NonCopyable.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\String.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\String.inl" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Time.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Utf.hpp" />
|
||||
<ClInclude Include="..\..\include\SFML\System\Utf.inl" />
|
||||
<ClInclude Include="..\..\src\SFML\Network\SocketImpl.hpp" />
|
||||
<ClInclude Include="..\..\src\SFML\Network\Win32\SocketImpl.hpp">
|
||||
<Filter>Win32</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Win32">
|
||||
<UniqueIdentifier>{8280ecca-24fc-48a2-b7f5-6aca41826b66}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -2,13 +2,13 @@
|
|||
<Project>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ExternalsDir)SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ExternalsDir)SFML\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(ExternalsDir)SFML\build\vc2010\SFML_Network.vcxproj">
|
||||
<ProjectReference Include="$(ExternalsDir)SFML\SFML.vcxproj">
|
||||
<Project>{93d73454-2512-424e-9cda-4bb357fe13dd}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -1,236 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_CONFIG_HPP
|
||||
#define SFML_CONFIG_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define the SFML version
|
||||
////////////////////////////////////////////////////////////
|
||||
#define SFML_VERSION_MAJOR 2
|
||||
#define SFML_VERSION_MINOR 5
|
||||
#define SFML_VERSION_PATCH 0
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Identify the operating system
|
||||
// see http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
|
||||
////////////////////////////////////////////////////////////
|
||||
#if defined(_WIN32)
|
||||
|
||||
// Windows
|
||||
#define SFML_SYSTEM_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
// Apple platform, see which one it is
|
||||
#include "TargetConditionals.h"
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
|
||||
|
||||
// iOS
|
||||
#define SFML_SYSTEM_IOS
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
|
||||
// MacOS
|
||||
#define SFML_SYSTEM_MACOS
|
||||
|
||||
#else
|
||||
|
||||
// Unsupported Apple system
|
||||
#error This Apple operating system is not supported by SFML library
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(__unix__)
|
||||
|
||||
// UNIX system, see which one it is
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Android
|
||||
#define SFML_SYSTEM_ANDROID
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
// Linux
|
||||
#define SFML_SYSTEM_LINUX
|
||||
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
|
||||
// FreeBSD
|
||||
#define SFML_SYSTEM_FREEBSD
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
// OpenBSD
|
||||
#define SFML_SYSTEM_OPENBSD
|
||||
|
||||
#else
|
||||
|
||||
// Unsupported UNIX system
|
||||
#error This UNIX operating system is not supported by SFML library
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// Unsupported system
|
||||
#error This operating system is not supported by SFML library
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define a portable debug macro
|
||||
////////////////////////////////////////////////////////////
|
||||
#if !defined(NDEBUG)
|
||||
|
||||
#define SFML_DEBUG
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define helpers to create portable import / export macros for each module
|
||||
////////////////////////////////////////////////////////////
|
||||
#if !defined(SFML_STATIC)
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
// Windows compilers need specific (and different) keywords for export and import
|
||||
#define SFML_API_EXPORT __declspec(dllexport)
|
||||
#define SFML_API_IMPORT __declspec(dllimport)
|
||||
|
||||
// For Visual C++ compilers, we also need to turn off this annoying C4251 warning
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning(disable: 4251)
|
||||
|
||||
#endif
|
||||
|
||||
#else // Linux, FreeBSD, Mac OS X
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
|
||||
// GCC 4 has special keywords for showing/hidding symbols,
|
||||
// the same keyword is used for both importing and exporting
|
||||
#define SFML_API_EXPORT __attribute__ ((__visibility__ ("default")))
|
||||
#define SFML_API_IMPORT __attribute__ ((__visibility__ ("default")))
|
||||
|
||||
#else
|
||||
|
||||
// GCC < 4 has no mechanism to explicitely hide symbols, everything's exported
|
||||
#define SFML_API_EXPORT
|
||||
#define SFML_API_IMPORT
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// Static build doesn't need import/export macros
|
||||
#define SFML_API_EXPORT
|
||||
#define SFML_API_IMPORT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Cross-platform warning for deprecated functions and classes
|
||||
//
|
||||
// Usage:
|
||||
// class SFML_DEPRECATED MyClass
|
||||
// {
|
||||
// SFML_DEPRECATED void memberFunc();
|
||||
// };
|
||||
//
|
||||
// SFML_DEPRECATED void globalFunc();
|
||||
////////////////////////////////////////////////////////////
|
||||
#if defined(SFML_NO_DEPRECATED_WARNINGS)
|
||||
|
||||
// User explicitly requests to disable deprecation warnings
|
||||
#define SFML_DEPRECATED
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
// Microsoft C++ compiler
|
||||
// Note: On newer MSVC versions, using deprecated functions causes a compiler error. In order to
|
||||
// trigger a warning instead of an error, the compiler flag /sdl- (instead of /sdl) must be specified.
|
||||
#define SFML_DEPRECATED __declspec(deprecated)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
// g++ and Clang
|
||||
#define SFML_DEPRECATED __attribute__ ((deprecated))
|
||||
|
||||
#else
|
||||
|
||||
// Other compilers are not supported, leave class or function as-is.
|
||||
// With a bit of luck, the #pragma directive works, otherwise users get a warning (no error!) for unrecognized #pragma.
|
||||
#pragma message("SFML_DEPRECATED is not supported for your compiler, please contact the SFML team")
|
||||
#define SFML_DEPRECATED
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define portable fixed-size types
|
||||
////////////////////////////////////////////////////////////
|
||||
namespace sf
|
||||
{
|
||||
// All "common" platforms use the same size for char, short and int
|
||||
// (basically there are 3 types for 3 sizes, so no other match is possible),
|
||||
// we can use them without doing any kind of check
|
||||
|
||||
// 8 bits integer types
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char Uint8;
|
||||
|
||||
// 16 bits integer types
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short Uint16;
|
||||
|
||||
// 32 bits integer types
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int Uint32;
|
||||
|
||||
// 64 bits integer types
|
||||
#if defined(_MSC_VER)
|
||||
typedef signed __int64 Int64;
|
||||
typedef unsigned __int64 Uint64;
|
||||
#else
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long Uint64;
|
||||
#endif
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_CONFIG_HPP
|
|
@ -1,55 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_NETWORK_HPP
|
||||
#define SFML_NETWORK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#include <SFML/System.hpp>
|
||||
//#include <SFML/Network/Ftp.hpp>
|
||||
#include <SFML/Network/Http.hpp>
|
||||
|
||||
// This file is "IpAddress.hpp" upstream
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketHandle.hpp>
|
||||
#include <SFML/Network/SocketSelector.hpp>
|
||||
#include <SFML/Network/TcpListener.hpp>
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/UdpSocket.hpp>
|
||||
|
||||
|
||||
#endif // SFML_NETWORK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \defgroup network Network module
|
||||
///
|
||||
/// Socket-based communication, utilities and higher-level
|
||||
/// network protocols (HTTP, FTP).
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,48 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_NETWORK_EXPORT_HPP
|
||||
#define SFML_NETWORK_EXPORT_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define portable import / export macros
|
||||
////////////////////////////////////////////////////////////
|
||||
#if defined(SFML_NETWORK_EXPORTS)
|
||||
|
||||
#define SFML_NETWORK_API SFML_API_EXPORT
|
||||
|
||||
#else
|
||||
|
||||
#define SFML_NETWORK_API SFML_API_IMPORT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SFML_NETWORK_EXPORT_HPP
|
|
@ -1,482 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_HTTP_HPP
|
||||
#define SFML_HTTP_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief A HTTP client
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Http : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Define a HTTP request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Request
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Enumerate the available HTTP methods for a request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum Method
|
||||
{
|
||||
Get, ///< Request in get mode, standard method to retrieve a page
|
||||
Post, ///< Request in post mode, usually to send data to a page
|
||||
Head, ///< Request a page's header only
|
||||
Put, ///< Request in put mode, useful for a REST API
|
||||
Delete ///< Request in delete mode, useful for a REST API
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor creates a GET request, with the root
|
||||
/// URI ("/") and an empty body.
|
||||
///
|
||||
/// \param uri Target URI
|
||||
/// \param method Method to use for the request
|
||||
/// \param body Content of the request's body
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "");
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the value of a field
|
||||
///
|
||||
/// The field is created if it doesn't exist. The name of
|
||||
/// the field is case-insensitive.
|
||||
/// By default, a request doesn't contain any field (but the
|
||||
/// mandatory fields are added later by the HTTP client when
|
||||
/// sending the request).
|
||||
///
|
||||
/// \param field Name of the field to set
|
||||
/// \param value Value of the field
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setField(const std::string& field, const std::string& value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the request method
|
||||
///
|
||||
/// See the Method enumeration for a complete list of all
|
||||
/// the availale methods.
|
||||
/// The method is Http::Request::Get by default.
|
||||
///
|
||||
/// \param method Method to use for the request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setMethod(Method method);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the requested URI
|
||||
///
|
||||
/// The URI is the resource (usually a web page or a file)
|
||||
/// that you want to get or post.
|
||||
/// The URI is "/" (the root page) by default.
|
||||
///
|
||||
/// \param uri URI to request, relative to the host
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setUri(const std::string& uri);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the HTTP version for the request
|
||||
///
|
||||
/// The HTTP version is 1.0 by default.
|
||||
///
|
||||
/// \param major Major HTTP version number
|
||||
/// \param minor Minor HTTP version number
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setHttpVersion(unsigned int major, unsigned int minor);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the body of the request
|
||||
///
|
||||
/// The body of a request is optional and only makes sense
|
||||
/// for POST requests. It is ignored for all other methods.
|
||||
/// The body is empty by default.
|
||||
///
|
||||
/// \param body Content of the body
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setBody(const std::string& body);
|
||||
|
||||
private:
|
||||
|
||||
friend class Http;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Prepare the final request to send to the server
|
||||
///
|
||||
/// This is used internally by Http before sending the
|
||||
/// request to the web server.
|
||||
///
|
||||
/// \return String containing the request, ready to be sent
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string prepare() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if the request defines a field
|
||||
///
|
||||
/// This function uses case-insensitive comparisons.
|
||||
///
|
||||
/// \param field Name of the field to test
|
||||
///
|
||||
/// \return True if the field exists, false otherwise
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool hasField(const std::string& field) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef std::map<std::string, std::string> FieldTable;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
FieldTable m_fields; ///< Fields of the header associated to their value
|
||||
Method m_method; ///< Method to use for the request
|
||||
std::string m_uri; ///< Target URI of the request
|
||||
unsigned int m_majorVersion; ///< Major HTTP version
|
||||
unsigned int m_minorVersion; ///< Minor HTTP version
|
||||
std::string m_body; ///< Body of the request
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Define a HTTP response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Response
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Enumerate all the valid status codes for a response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum Status
|
||||
{
|
||||
// 2xx: success
|
||||
Ok = 200, ///< Most common code returned when operation was successful
|
||||
Created = 201, ///< The resource has successfully been created
|
||||
Accepted = 202, ///< The request has been accepted, but will be processed later by the server
|
||||
NoContent = 204, ///< The server didn't send any data in return
|
||||
ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent
|
||||
PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request
|
||||
|
||||
// 3xx: redirection
|
||||
MultipleChoices = 300, ///< The requested page can be accessed from several locations
|
||||
MovedPermanently = 301, ///< The requested page has permanently moved to a new location
|
||||
MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location
|
||||
NotModified = 304, ///< For conditional requests, means the requested page hasn't changed and doesn't need to be refreshed
|
||||
|
||||
// 4xx: client error
|
||||
BadRequest = 400, ///< The server couldn't understand the request (syntax error)
|
||||
Unauthorized = 401, ///< The requested page needs an authentication to be accessed
|
||||
Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentication
|
||||
NotFound = 404, ///< The requested page doesn't exist
|
||||
RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field)
|
||||
|
||||
// 5xx: server error
|
||||
InternalServerError = 500, ///< The server encountered an unexpected error
|
||||
NotImplemented = 501, ///< The server doesn't implement a requested feature
|
||||
BadGateway = 502, ///< The gateway server has received an error from the source server
|
||||
ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...)
|
||||
GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server
|
||||
VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version
|
||||
|
||||
// 10xx: SFML custom codes
|
||||
InvalidResponse = 1000, ///< Response is not a valid HTTP one
|
||||
ConnectionFailed = 1001 ///< Connection with server failed
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// Constructs an empty response.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the value of a field
|
||||
///
|
||||
/// If the field \a field is not found in the response header,
|
||||
/// the empty string is returned. This function uses
|
||||
/// case-insensitive comparisons.
|
||||
///
|
||||
/// \param field Name of the field to get
|
||||
///
|
||||
/// \return Value of the field, or empty string if not found
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& getField(const std::string& field) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the response status code
|
||||
///
|
||||
/// The status code should be the first thing to be checked
|
||||
/// after receiving a response, it defines whether it is a
|
||||
/// success, a failure or anything else (see the Status
|
||||
/// enumeration).
|
||||
///
|
||||
/// \return Status code of the response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status getStatus() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the major HTTP version number of the response
|
||||
///
|
||||
/// \return Major HTTP version number
|
||||
///
|
||||
/// \see getMinorHttpVersion
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getMajorHttpVersion() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the minor HTTP version number of the response
|
||||
///
|
||||
/// \return Minor HTTP version number
|
||||
///
|
||||
/// \see getMajorHttpVersion
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getMinorHttpVersion() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the body of the response
|
||||
///
|
||||
/// The body of a response may contain:
|
||||
/// \li the requested page (for GET requests)
|
||||
/// \li a response from the server (for POST requests)
|
||||
/// \li nothing (for HEAD requests)
|
||||
/// \li an error message (in case of an error)
|
||||
///
|
||||
/// \return The response body
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& getBody() const;
|
||||
|
||||
private:
|
||||
|
||||
friend class Http;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the header from a response string
|
||||
///
|
||||
/// This function is used by Http to build the response
|
||||
/// of a request.
|
||||
///
|
||||
/// \param data Content of the response to parse
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void parse(const std::string& data);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read values passed in the answer header
|
||||
///
|
||||
/// This function is used by Http to extract values passed
|
||||
/// in the response.
|
||||
///
|
||||
/// \param in String stream containing the header values
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void parseFields(std::istream &in);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef std::map<std::string, std::string> FieldTable;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
FieldTable m_fields; ///< Fields of the header
|
||||
Status m_status; ///< Status code
|
||||
unsigned int m_majorVersion; ///< Major HTTP version
|
||||
unsigned int m_minorVersion; ///< Minor HTTP version
|
||||
std::string m_body; ///< Body of the response
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Http();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the HTTP client with the target host
|
||||
///
|
||||
/// This is equivalent to calling setHost(host, port).
|
||||
/// The port has a default value of 0, which means that the
|
||||
/// HTTP client will use the right port according to the
|
||||
/// protocol used (80 for HTTP). You should leave it like
|
||||
/// this unless you really need a port other than the
|
||||
/// standard one, or use an unknown protocol.
|
||||
///
|
||||
/// \param host Web server to connect to
|
||||
/// \param port Port to use for connection
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Http(const std::string& host, unsigned short port = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the target host
|
||||
///
|
||||
/// This function just stores the host address and port, it
|
||||
/// doesn't actually connect to it until you send a request.
|
||||
/// The port has a default value of 0, which means that the
|
||||
/// HTTP client will use the right port according to the
|
||||
/// protocol used (80 for HTTP). You should leave it like
|
||||
/// this unless you really need a port other than the
|
||||
/// standard one, or use an unknown protocol.
|
||||
///
|
||||
/// \param host Web server to connect to
|
||||
/// \param port Port to use for connection
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setHost(const std::string& host, unsigned short port = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send a HTTP request and return the server's response.
|
||||
///
|
||||
/// You must have a valid host before sending a request (see setHost).
|
||||
/// Any missing mandatory header field in the request will be added
|
||||
/// with an appropriate value.
|
||||
/// Warning: this function waits for the server's response and may
|
||||
/// not return instantly; use a thread if you don't want to block your
|
||||
/// application, or use a timeout to limit the time to wait. A value
|
||||
/// of Time::Zero means that the client will use the system default timeout
|
||||
/// (which is usually pretty long).
|
||||
///
|
||||
/// \param request Request to send
|
||||
/// \param timeout Maximum time to wait
|
||||
///
|
||||
/// \return Server's response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response sendRequest(const Request& request, Time timeout = Time::Zero);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket m_connection; ///< Connection to the host
|
||||
IpAddress m_host; ///< Web host address
|
||||
std::string m_hostName; ///< Web host name
|
||||
unsigned short m_port; ///< Port used for connection with host
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_HTTP_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Http
|
||||
/// \ingroup network
|
||||
///
|
||||
/// sf::Http is a very simple HTTP client that allows you
|
||||
/// to communicate with a web server. You can retrieve
|
||||
/// web pages, send data to an interactive resource,
|
||||
/// download a remote file, etc. The HTTPS protocol is
|
||||
/// not supported.
|
||||
///
|
||||
/// The HTTP client is split into 3 classes:
|
||||
/// \li sf::Http::Request
|
||||
/// \li sf::Http::Response
|
||||
/// \li sf::Http
|
||||
///
|
||||
/// sf::Http::Request builds the request that will be
|
||||
/// sent to the server. A request is made of:
|
||||
/// \li a method (what you want to do)
|
||||
/// \li a target URI (usually the name of the web page or file)
|
||||
/// \li one or more header fields (options that you can pass to the server)
|
||||
/// \li an optional body (for POST requests)
|
||||
///
|
||||
/// sf::Http::Response parse the response from the web server
|
||||
/// and provides getters to read them. The response contains:
|
||||
/// \li a status code
|
||||
/// \li header fields (that may be answers to the ones that you requested)
|
||||
/// \li a body, which contains the contents of the requested resource
|
||||
///
|
||||
/// sf::Http provides a simple function, SendRequest, to send a
|
||||
/// sf::Http::Request and return the corresponding sf::Http::Response
|
||||
/// from the server.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // Create a new HTTP client
|
||||
/// sf::Http http;
|
||||
///
|
||||
/// // We'll work on http://www.sfml-dev.org
|
||||
/// http.setHost("http://www.sfml-dev.org");
|
||||
///
|
||||
/// // Prepare a request to get the 'features.php' page
|
||||
/// sf::Http::Request request("features.php");
|
||||
///
|
||||
/// // Send the request
|
||||
/// sf::Http::Response response = http.sendRequest(request);
|
||||
///
|
||||
/// // Check the status code and display the result
|
||||
/// sf::Http::Response::Status status = response.getStatus();
|
||||
/// if (status == sf::Http::Response::Ok)
|
||||
/// {
|
||||
/// std::cout << response.getBody() << std::endl;
|
||||
/// }
|
||||
/// else
|
||||
/// {
|
||||
/// std::cout << "Error " << status << std::endl;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,328 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_IPADDRESS_HPP
|
||||
#define SFML_IPADDRESS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Encapsulate an IPv4 network address
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API IpAddress
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor creates an empty (invalid) address
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from a string
|
||||
///
|
||||
/// Here \a address can be either a decimal address
|
||||
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
|
||||
///
|
||||
/// \param address IP address or network name
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress(const std::string& address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from a string
|
||||
///
|
||||
/// Here \a address can be either a decimal address
|
||||
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
|
||||
/// This is equivalent to the constructor taking a std::string
|
||||
/// parameter, it is defined for convenience so that the
|
||||
/// implicit conversions from literal strings to IpAddress work.
|
||||
///
|
||||
/// \param address IP address or network name
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress(const char* address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from 4 bytes
|
||||
///
|
||||
/// Calling IpAddress(a, b, c, d) is equivalent to calling
|
||||
/// IpAddress("a.b.c.d"), but safer as it doesn't have to
|
||||
/// parse a string to get the address components.
|
||||
///
|
||||
/// \param byte0 First byte of the address
|
||||
/// \param byte1 Second byte of the address
|
||||
/// \param byte2 Third byte of the address
|
||||
/// \param byte3 Fourth byte of the address
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the address from a 32-bits integer
|
||||
///
|
||||
/// This constructor uses the internal representation of
|
||||
/// the address directly. It should be used for optimization
|
||||
/// purposes, and only if you got that representation from
|
||||
/// IpAddress::toInteger().
|
||||
///
|
||||
/// \param address 4 bytes of the address packed into a 32-bits integer
|
||||
///
|
||||
/// \see toInteger
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit IpAddress(Uint32 address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get a string representation of the address
|
||||
///
|
||||
/// The returned string is the decimal representation of the
|
||||
/// IP address (like "192.168.1.56"), even if it was constructed
|
||||
/// from a host name.
|
||||
///
|
||||
/// \return String representation of the address
|
||||
///
|
||||
/// \see toInteger
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string toString() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get an integer representation of the address
|
||||
///
|
||||
/// The returned number is the internal representation of the
|
||||
/// address, and should be used for optimization purposes only
|
||||
/// (like sending the address through a socket).
|
||||
/// The integer produced by this function can then be converted
|
||||
/// back to a sf::IpAddress with the proper constructor.
|
||||
///
|
||||
/// \return 32-bits unsigned integer representation of the address
|
||||
///
|
||||
/// \see toString
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 toInteger() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the computer's local address
|
||||
///
|
||||
/// The local address is the address of the computer from the
|
||||
/// LAN point of view, i.e. something like 192.168.1.56. It is
|
||||
/// meaningful only for communications over the local network.
|
||||
/// Unlike getPublicAddress, this function is fast and may be
|
||||
/// used safely anywhere.
|
||||
///
|
||||
/// \return Local IP address of the computer
|
||||
///
|
||||
/// \see getPublicAddress
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static IpAddress getLocalAddress();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the computer's public address
|
||||
///
|
||||
/// The public address is the address of the computer from the
|
||||
/// internet point of view, i.e. something like 89.54.1.169.
|
||||
/// It is necessary for communications over the world wide web.
|
||||
/// The only way to get a public address is to ask it to a
|
||||
/// distant website; as a consequence, this function depends on
|
||||
/// both your network connection and the server, and may be
|
||||
/// very slow. You should use it as few as possible. Because
|
||||
/// this function depends on the network connection and on a distant
|
||||
/// server, you may use a time limit if you don't want your program
|
||||
/// to be possibly stuck waiting in case there is a problem; this
|
||||
/// limit is deactivated by default.
|
||||
///
|
||||
/// \param timeout Maximum time to wait
|
||||
///
|
||||
/// \return Public IP address of the computer
|
||||
///
|
||||
/// \see getLocalAddress
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static IpAddress getPublicAddress(Time timeout = Time::Zero);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
static const IpAddress None; ///< Value representing an empty/invalid address
|
||||
static const IpAddress Any; ///< Value representing any address (0.0.0.0)
|
||||
static const IpAddress LocalHost; ///< The "localhost" address (for connecting a computer to itself locally)
|
||||
static const IpAddress Broadcast; ///< The "broadcast" address (for sending UDP messages to everyone on a local network)
|
||||
|
||||
private:
|
||||
|
||||
friend SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Resolve the given address string
|
||||
///
|
||||
/// \param address Address string
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void resolve(const std::string& address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 m_address; ///< Address stored as an unsigned 32 bits integer
|
||||
bool m_valid; ///< Is the address valid?
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of == operator to compare two IP addresses
|
||||
///
|
||||
/// \param left Left operand (a IP address)
|
||||
/// \param right Right operand (a IP address)
|
||||
///
|
||||
/// \return True if both addresses are equal
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API bool operator ==(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of != operator to compare two IP addresses
|
||||
///
|
||||
/// \param left Left operand (a IP address)
|
||||
/// \param right Right operand (a IP address)
|
||||
///
|
||||
/// \return True if both addresses are different
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API bool operator !=(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of < operator to compare two IP addresses
|
||||
///
|
||||
/// \param left Left operand (a IP address)
|
||||
/// \param right Right operand (a IP address)
|
||||
///
|
||||
/// \return True if \a left is lesser than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of > operator to compare two IP addresses
|
||||
///
|
||||
/// \param left Left operand (a IP address)
|
||||
/// \param right Right operand (a IP address)
|
||||
///
|
||||
/// \return True if \a left is greater than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API bool operator >(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of <= operator to compare two IP addresses
|
||||
///
|
||||
/// \param left Left operand (a IP address)
|
||||
/// \param right Right operand (a IP address)
|
||||
///
|
||||
/// \return True if \a left is lesser or equal than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API bool operator <=(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of >= operator to compare two IP addresses
|
||||
///
|
||||
/// \param left Left operand (a IP address)
|
||||
/// \param right Right operand (a IP address)
|
||||
///
|
||||
/// \return True if \a left is greater or equal than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API bool operator >=(const IpAddress& left, const IpAddress& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of >> operator to extract an IP address from an input stream
|
||||
///
|
||||
/// \param stream Input stream
|
||||
/// \param address IP address to extract
|
||||
///
|
||||
/// \return Reference to the input stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of << operator to print an IP address to an output stream
|
||||
///
|
||||
/// \param stream Output stream
|
||||
/// \param address IP address to print
|
||||
///
|
||||
/// \return Reference to the output stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_NETWORK_API std::ostream& operator <<(std::ostream& stream, const IpAddress& address);
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_IPADDRESS_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::IpAddress
|
||||
/// \ingroup network
|
||||
///
|
||||
/// sf::IpAddress is a utility class for manipulating network
|
||||
/// addresses. It provides a set a implicit constructors and
|
||||
/// conversion functions to easily build or transform an IP
|
||||
/// address from/to various representations.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::IpAddress a0; // an invalid address
|
||||
/// sf::IpAddress a1 = sf::IpAddress::None; // an invalid address (same as a0)
|
||||
/// sf::IpAddress a2("127.0.0.1"); // the local host address
|
||||
/// sf::IpAddress a3 = sf::IpAddress::Broadcast; // the broadcast address
|
||||
/// sf::IpAddress a4(192, 168, 1, 56); // a local address
|
||||
/// sf::IpAddress a5("my_computer"); // a local address created from a network name
|
||||
/// sf::IpAddress a6("89.54.1.169"); // a distant address
|
||||
/// sf::IpAddress a7("www.google.com"); // a distant address created from a network name
|
||||
/// sf::IpAddress a8 = sf::IpAddress::getLocalAddress(); // my address on the local network
|
||||
/// sf::IpAddress a9 = sf::IpAddress::getPublicAddress(); // my address on the internet
|
||||
/// \endcode
|
||||
///
|
||||
/// Note that sf::IpAddress currently doesn't support IPv6
|
||||
/// nor other types of network addresses.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,532 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_PACKET_HPP
|
||||
#define SFML_PACKET_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class String;
|
||||
class TcpSocket;
|
||||
class UdpSocket;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility class to build blocks of data to transfer
|
||||
/// over the network
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Packet
|
||||
{
|
||||
// A bool-like type that cannot be converted to integer or pointer types
|
||||
typedef bool (Packet::*BoolType)(std::size_t);
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// Creates an empty packet.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Virtual destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~Packet();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Append data to the end of the packet
|
||||
///
|
||||
/// \param data Pointer to the sequence of bytes to append
|
||||
/// \param sizeInBytes Number of bytes to append
|
||||
///
|
||||
/// \see clear
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void append(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Clear the packet
|
||||
///
|
||||
/// After calling Clear, the packet is empty.
|
||||
///
|
||||
/// \see append
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void clear();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get a pointer to the data contained in the packet
|
||||
///
|
||||
/// Warning: the returned pointer may become invalid after
|
||||
/// you append data to the packet, therefore it should never
|
||||
/// be stored.
|
||||
/// The return pointer is NULL if the packet is empty.
|
||||
///
|
||||
/// \return Pointer to the data
|
||||
///
|
||||
/// \see getDataSize
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const void* getData() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the size of the data contained in the packet
|
||||
///
|
||||
/// This function returns the number of bytes pointed to by
|
||||
/// what getData returns.
|
||||
///
|
||||
/// \return Data size, in bytes
|
||||
///
|
||||
/// \see getData
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t getDataSize() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Tell if the reading position has reached the
|
||||
/// end of the packet
|
||||
///
|
||||
/// This function is useful to know if there is some data
|
||||
/// left to be read, without actually reading it.
|
||||
///
|
||||
/// \return True if all data was read, false otherwise
|
||||
///
|
||||
/// \see operator bool
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool endOfPacket() const;
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Test the validity of the packet, for reading
|
||||
///
|
||||
/// This operator allows to test the packet as a boolean
|
||||
/// variable, to check if a reading operation was successful.
|
||||
///
|
||||
/// A packet will be in an invalid state if it has no more
|
||||
/// data to read.
|
||||
///
|
||||
/// This behavior is the same as standard C++ streams.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// float x;
|
||||
/// packet >> x;
|
||||
/// if (packet)
|
||||
/// {
|
||||
/// // ok, x was extracted successfully
|
||||
/// }
|
||||
///
|
||||
/// // -- or --
|
||||
///
|
||||
/// float x;
|
||||
/// if (packet >> x)
|
||||
/// {
|
||||
/// // ok, x was extracted successfully
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Don't focus on the return type, it's equivalent to bool but
|
||||
/// it disallows unwanted implicit conversions to integer or
|
||||
/// pointer types.
|
||||
///
|
||||
/// \return True if last data extraction from packet was successful
|
||||
///
|
||||
/// \see endOfPacket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
operator BoolType() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Overload of operator >> to read data from the packet
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(bool& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Int8& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Uint8& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Int16& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Uint16& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Int32& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Uint32& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Int64& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(Uint64& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(float& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(double& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(char* data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(std::string& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(wchar_t* data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(std::wstring& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator >>(String& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Overload of operator << to write data into the packet
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(bool data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Int8 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Uint8 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Int16 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Uint16 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Int32 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Uint32 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Int64 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(Uint64 data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(float data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(double data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(const char* data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(const std::string& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(const wchar_t* data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(const std::wstring& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \overload
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& operator <<(const String& data);
|
||||
|
||||
protected:
|
||||
|
||||
friend class TcpSocket;
|
||||
friend class UdpSocket;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Called before the packet is sent over the network
|
||||
///
|
||||
/// This function can be defined by derived classes to
|
||||
/// transform the data before it is sent; this can be
|
||||
/// used for compression, encryption, etc.
|
||||
/// The function must return a pointer to the modified data,
|
||||
/// as well as the number of bytes pointed.
|
||||
/// The default implementation provides the packet's data
|
||||
/// without transforming it.
|
||||
///
|
||||
/// \param size Variable to fill with the size of data to send
|
||||
///
|
||||
/// \return Pointer to the array of bytes to send
|
||||
///
|
||||
/// \see onReceive
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual const void* onSend(std::size_t& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Called after the packet is received over the network
|
||||
///
|
||||
/// This function can be defined by derived classes to
|
||||
/// transform the data after it is received; this can be
|
||||
/// used for decompression, decryption, etc.
|
||||
/// The function receives a pointer to the received data,
|
||||
/// and must fill the packet with the transformed bytes.
|
||||
/// The default implementation fills the packet directly
|
||||
/// without transforming the data.
|
||||
///
|
||||
/// \param data Pointer to the received bytes
|
||||
/// \param size Number of bytes
|
||||
///
|
||||
/// \see onSend
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void onReceive(const void* data, std::size_t size);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Disallow comparisons between packets
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const Packet& right) const;
|
||||
bool operator !=(const Packet& right) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if the packet can extract a given number of bytes
|
||||
///
|
||||
/// This function updates accordingly the state of the packet.
|
||||
///
|
||||
/// \param size Size to check
|
||||
///
|
||||
/// \return True if \a size bytes can be read from the packet
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool checkSize(std::size_t size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::vector<char> m_data; ///< Data stored in the packet
|
||||
std::size_t m_readPos; ///< Current reading position in the packet
|
||||
std::size_t m_sendPos; ///< Current send position in the packet (for handling partial sends)
|
||||
bool m_isValid; ///< Reading state of the packet
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_PACKET_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Packet
|
||||
/// \ingroup network
|
||||
///
|
||||
/// Packets provide a safe and easy way to serialize data,
|
||||
/// in order to send it over the network using sockets
|
||||
/// (sf::TcpSocket, sf::UdpSocket).
|
||||
///
|
||||
/// Packets solve 2 fundamental problems that arise when
|
||||
/// transferring data over the network:
|
||||
/// \li data is interpreted correctly according to the endianness
|
||||
/// \li the bounds of the packet are preserved (one send == one receive)
|
||||
///
|
||||
/// The sf::Packet class provides both input and output modes.
|
||||
/// It is designed to follow the behavior of standard C++ streams,
|
||||
/// using operators >> and << to extract and insert data.
|
||||
///
|
||||
/// It is recommended to use only fixed-size types (like sf::Int32, etc.),
|
||||
/// to avoid possible differences between the sender and the receiver.
|
||||
/// Indeed, the native C++ types may have different sizes on two platforms
|
||||
/// and your data may be corrupted if that happens.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::Uint32 x = 24;
|
||||
/// std::string s = "hello";
|
||||
/// double d = 5.89;
|
||||
///
|
||||
/// // Group the variables to send into a packet
|
||||
/// sf::Packet packet;
|
||||
/// packet << x << s << d;
|
||||
///
|
||||
/// // Send it over the network (socket is a valid sf::TcpSocket)
|
||||
/// socket.send(packet);
|
||||
///
|
||||
/// -----------------------------------------------------------------
|
||||
///
|
||||
/// // Receive the packet at the other end
|
||||
/// sf::Packet packet;
|
||||
/// socket.receive(packet);
|
||||
///
|
||||
/// // Extract the variables contained in the packet
|
||||
/// sf::Uint32 x;
|
||||
/// std::string s;
|
||||
/// double d;
|
||||
/// if (packet >> x >> s >> d)
|
||||
/// {
|
||||
/// // Data extracted successfully...
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Packets have built-in operator >> and << overloads for
|
||||
/// standard types:
|
||||
/// \li bool
|
||||
/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32)
|
||||
/// \li floating point numbers (float, double)
|
||||
/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String)
|
||||
///
|
||||
/// Like standard streams, it is also possible to define your own
|
||||
/// overloads of operators >> and << in order to handle your
|
||||
/// custom types.
|
||||
///
|
||||
/// \code
|
||||
/// struct MyStruct
|
||||
/// {
|
||||
/// float number;
|
||||
/// sf::Int8 integer;
|
||||
/// std::string str;
|
||||
/// };
|
||||
///
|
||||
/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m)
|
||||
/// {
|
||||
/// return packet << m.number << m.integer << m.str;
|
||||
/// }
|
||||
///
|
||||
/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m)
|
||||
/// {
|
||||
/// return packet >> m.number >> m.integer >> m.str;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Packets also provide an extra feature that allows to apply
|
||||
/// custom transformations to the data before it is sent,
|
||||
/// and after it is received. This is typically used to
|
||||
/// handle automatic compression or encryption of the data.
|
||||
/// This is achieved by inheriting from sf::Packet, and overriding
|
||||
/// the onSend and onReceive functions.
|
||||
///
|
||||
/// Here is an example:
|
||||
/// \code
|
||||
/// class ZipPacket : public sf::Packet
|
||||
/// {
|
||||
/// virtual const void* onSend(std::size_t& size)
|
||||
/// {
|
||||
/// const void* srcData = getData();
|
||||
/// std::size_t srcSize = getDataSize();
|
||||
///
|
||||
/// return MySuperZipFunction(srcData, srcSize, &size);
|
||||
/// }
|
||||
///
|
||||
/// virtual void onReceive(const void* data, std::size_t size)
|
||||
/// {
|
||||
/// std::size_t dstSize;
|
||||
/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize);
|
||||
///
|
||||
/// append(dstData, dstSize);
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// // Use like regular packets:
|
||||
/// ZipPacket packet;
|
||||
/// packet << x << s << d;
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// \see sf::TcpSocket, sf::UdpSocket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,219 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKET_HPP
|
||||
#define SFML_SOCKET_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/SocketHandle.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class SocketSelector;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Base class for all the socket types
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Socket : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Status codes that may be returned by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum Status
|
||||
{
|
||||
Done, ///< The socket has sent / received the data
|
||||
NotReady, ///< The socket is not ready to send / receive data yet
|
||||
Partial, ///< The socket sent a part of the data
|
||||
Disconnected, ///< The TCP socket has been disconnected
|
||||
Error ///< An unexpected error happened
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Some special values used by sockets
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
AnyPort = 0 ///< Special value that tells the system to pick any available port
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~Socket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the blocking state of the socket
|
||||
///
|
||||
/// In blocking mode, calls will not return until they have
|
||||
/// completed their task. For example, a call to Receive in
|
||||
/// blocking mode won't return until some data was actually
|
||||
/// received.
|
||||
/// In non-blocking mode, calls will always return immediately,
|
||||
/// using the return code to signal whether there was data
|
||||
/// available or not.
|
||||
/// By default, all sockets are blocking.
|
||||
///
|
||||
/// \param blocking True to set the socket as blocking, false for non-blocking
|
||||
///
|
||||
/// \see isBlocking
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setBlocking(bool blocking);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Tell whether the socket is in blocking or non-blocking mode
|
||||
///
|
||||
/// \return True if the socket is blocking, false otherwise
|
||||
///
|
||||
/// \see setBlocking
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool isBlocking() const;
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Types of protocols that the socket can use
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum Type
|
||||
{
|
||||
Tcp, ///< TCP protocol
|
||||
Udp ///< UDP protocol
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor can only be accessed by derived classes.
|
||||
///
|
||||
/// \param type Type of the socket (TCP or UDP)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket(Type type);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the internal handle of the socket
|
||||
///
|
||||
/// The returned handle may be invalid if the socket
|
||||
/// was not created yet (or already destroyed).
|
||||
/// This function can only be accessed by derived classes.
|
||||
///
|
||||
/// \return The internal (OS-specific) handle of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle getHandle() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the internal representation of the socket
|
||||
///
|
||||
/// This function can only be accessed by derived classes.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void create();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the internal representation of the socket
|
||||
/// from a socket handle
|
||||
///
|
||||
/// This function can only be accessed by derived classes.
|
||||
///
|
||||
/// \param handle OS-specific handle of the socket to wrap
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void create(SocketHandle handle);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close the socket gracefully
|
||||
///
|
||||
/// This function can only be accessed by derived classes.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
||||
friend class SocketSelector;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Type m_type; ///< Type of the socket (TCP or UDP)
|
||||
SocketHandle m_socket; ///< Socket descriptor
|
||||
bool m_isBlocking; ///< Current blocking mode of the socket
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKET_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Socket
|
||||
/// \ingroup network
|
||||
///
|
||||
/// This class mainly defines internal stuff to be used by
|
||||
/// derived classes.
|
||||
///
|
||||
/// The only public features that it defines, and which
|
||||
/// is therefore common to all the socket classes, is the
|
||||
/// blocking state. All sockets can be set as blocking or
|
||||
/// non-blocking.
|
||||
///
|
||||
/// In blocking mode, socket functions will hang until
|
||||
/// the operation completes, which means that the entire
|
||||
/// program (well, in fact the current thread if you use
|
||||
/// multiple ones) will be stuck waiting for your socket
|
||||
/// operation to complete.
|
||||
///
|
||||
/// In non-blocking mode, all the socket functions will
|
||||
/// return immediately. If the socket is not ready to complete
|
||||
/// the requested operation, the function simply returns
|
||||
/// the proper status code (Socket::NotReady).
|
||||
///
|
||||
/// The default mode, which is blocking, is the one that is
|
||||
/// generally used, in combination with threads or selectors.
|
||||
/// The non-blocking mode is rather used in real-time
|
||||
/// applications that run an endless loop that can poll
|
||||
/// the socket often enough, and cannot afford blocking
|
||||
/// this loop.
|
||||
///
|
||||
/// \see sf::TcpListener, sf::TcpSocket, sf::UdpSocket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,57 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETHANDLE_HPP
|
||||
#define SFML_SOCKETHANDLE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <basetsd.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define the low-level socket handle type, specific to
|
||||
// each platform
|
||||
////////////////////////////////////////////////////////////
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
typedef UINT_PTR SocketHandle;
|
||||
|
||||
#else
|
||||
|
||||
typedef int SocketHandle;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETHANDLE_HPP
|
|
@ -1,263 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETSELECTOR_HPP
|
||||
#define SFML_SOCKETSELECTOR_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Socket;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Multiplexer that allows to read from multiple sockets
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API SocketSelector
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Copy constructor
|
||||
///
|
||||
/// \param copy Instance to copy
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector(const SocketSelector& copy);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SocketSelector();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Add a new socket to the selector
|
||||
///
|
||||
/// This function keeps a weak reference to the socket,
|
||||
/// so you have to make sure that the socket is not destroyed
|
||||
/// while it is stored in the selector.
|
||||
/// This function does nothing if the socket is not valid.
|
||||
///
|
||||
/// \param socket Reference to the socket to add
|
||||
///
|
||||
/// \see remove, clear
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void add(Socket& socket);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Remove a socket from the selector
|
||||
///
|
||||
/// This function doesn't destroy the socket, it simply
|
||||
/// removes the reference that the selector has to it.
|
||||
///
|
||||
/// \param socket Reference to the socket to remove
|
||||
///
|
||||
/// \see add, clear
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void remove(Socket& socket);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Remove all the sockets stored in the selector
|
||||
///
|
||||
/// This function doesn't destroy any instance, it simply
|
||||
/// removes all the references that the selector has to
|
||||
/// external sockets.
|
||||
///
|
||||
/// \see add, remove
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void clear();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until one or more sockets are ready to receive
|
||||
///
|
||||
/// This function returns as soon as at least one socket has
|
||||
/// some data available to be received. To know which sockets are
|
||||
/// ready, use the isReady function.
|
||||
/// If you use a timeout and no socket is ready before the timeout
|
||||
/// is over, the function returns false.
|
||||
///
|
||||
/// \param timeout Maximum time to wait, (use Time::Zero for infinity)
|
||||
///
|
||||
/// \return True if there are sockets ready, false otherwise
|
||||
///
|
||||
/// \see isReady
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool wait(Time timeout = Time::Zero);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Test a socket to know if it is ready to receive data
|
||||
///
|
||||
/// This function must be used after a call to Wait, to know
|
||||
/// which sockets are ready to receive data. If a socket is
|
||||
/// ready, a call to receive will never block because we know
|
||||
/// that there is data available to read.
|
||||
/// Note that if this function returns true for a TcpListener,
|
||||
/// this means that it is ready to accept a new connection.
|
||||
///
|
||||
/// \param socket Socket to test
|
||||
///
|
||||
/// \return True if the socket is ready to read, false otherwise
|
||||
///
|
||||
/// \see isReady
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool isReady(Socket& socket) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of assignment operator
|
||||
///
|
||||
/// \param right Instance to assign
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector& operator =(const SocketSelector& right);
|
||||
|
||||
private:
|
||||
|
||||
struct SocketSelectorImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelectorImpl* m_impl; ///< Opaque pointer to the implementation (which requires OS-specific types)
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETSELECTOR_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::SocketSelector
|
||||
/// \ingroup network
|
||||
///
|
||||
/// Socket selectors provide a way to wait until some data is
|
||||
/// available on a set of sockets, instead of just one. This
|
||||
/// is convenient when you have multiple sockets that may
|
||||
/// possibly receive data, but you don't know which one will
|
||||
/// be ready first. In particular, it avoids to use a thread
|
||||
/// for each socket; with selectors, a single thread can handle
|
||||
/// all the sockets.
|
||||
///
|
||||
/// All types of sockets can be used in a selector:
|
||||
/// \li sf::TcpListener
|
||||
/// \li sf::TcpSocket
|
||||
/// \li sf::UdpSocket
|
||||
///
|
||||
/// A selector doesn't store its own copies of the sockets
|
||||
/// (socket classes are not copyable anyway), it simply keeps
|
||||
/// a reference to the original sockets that you pass to the
|
||||
/// "add" function. Therefore, you can't use the selector as a
|
||||
/// socket container, you must store them outside and make sure
|
||||
/// that they are alive as long as they are used in the selector.
|
||||
///
|
||||
/// Using a selector is simple:
|
||||
/// \li populate the selector with all the sockets that you want to observe
|
||||
/// \li make it wait until there is data available on any of the sockets
|
||||
/// \li test each socket to find out which ones are ready
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // Create a socket to listen to new connections
|
||||
/// sf::TcpListener listener;
|
||||
/// listener.listen(55001);
|
||||
///
|
||||
/// // Create a list to store the future clients
|
||||
/// std::list<sf::TcpSocket*> clients;
|
||||
///
|
||||
/// // Create a selector
|
||||
/// sf::SocketSelector selector;
|
||||
///
|
||||
/// // Add the listener to the selector
|
||||
/// selector.add(listener);
|
||||
///
|
||||
/// // Endless loop that waits for new connections
|
||||
/// while (running)
|
||||
/// {
|
||||
/// // Make the selector wait for data on any socket
|
||||
/// if (selector.wait())
|
||||
/// {
|
||||
/// // Test the listener
|
||||
/// if (selector.isReady(listener))
|
||||
/// {
|
||||
/// // The listener is ready: there is a pending connection
|
||||
/// sf::TcpSocket* client = new sf::TcpSocket;
|
||||
/// if (listener.accept(*client) == sf::Socket::Done)
|
||||
/// {
|
||||
/// // Add the new client to the clients list
|
||||
/// clients.push_back(client);
|
||||
///
|
||||
/// // Add the new client to the selector so that we will
|
||||
/// // be notified when he sends something
|
||||
/// selector.add(*client);
|
||||
/// }
|
||||
/// else
|
||||
/// {
|
||||
/// // Error, we won't get a new connection, delete the socket
|
||||
/// delete client;
|
||||
/// }
|
||||
/// }
|
||||
/// else
|
||||
/// {
|
||||
/// // The listener socket is not ready, test all other sockets (the clients)
|
||||
/// for (std::list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
/// {
|
||||
/// sf::TcpSocket& client = **it;
|
||||
/// if (selector.isReady(client))
|
||||
/// {
|
||||
/// // The client has sent some data, we can receive it
|
||||
/// sf::Packet packet;
|
||||
/// if (client.receive(packet) == sf::Socket::Done)
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \see sf::Socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,166 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_TCPLISTENER_HPP
|
||||
#define SFML_TCPLISTENER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class TcpSocket;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Socket that listens to new TCP connections
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API TcpListener : public Socket
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpListener();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the port to which the socket is bound locally
|
||||
///
|
||||
/// If the socket is not listening to a port, this function
|
||||
/// returns 0.
|
||||
///
|
||||
/// \return Port to which the socket is bound
|
||||
///
|
||||
/// \see listen
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short getLocalPort() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Start listening for incoming connection attempts
|
||||
///
|
||||
/// This function makes the socket start listening on the
|
||||
/// specified port, waiting for incoming connection attempts.
|
||||
///
|
||||
/// If the socket is already listening on a port when this
|
||||
/// function is called, it will stop listening on the old
|
||||
/// port before starting to listen on the new port.
|
||||
///
|
||||
/// \param port Port to listen on for incoming connection attempts
|
||||
/// \param address Address of the interface to listen on
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see accept, close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status listen(unsigned short port, const IpAddress& address = IpAddress::Any);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Stop listening and close the socket
|
||||
///
|
||||
/// This function gracefully stops the listener. If the
|
||||
/// socket is not listening, this function has no effect.
|
||||
///
|
||||
/// \see listen
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void close();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Accept a new connection
|
||||
///
|
||||
/// If the socket is in blocking mode, this function will
|
||||
/// not return until a connection is actually received.
|
||||
///
|
||||
/// \param socket Socket that will hold the new connection
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see listen
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status accept(TcpSocket& socket);
|
||||
};
|
||||
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_TCPLISTENER_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::TcpListener
|
||||
/// \ingroup network
|
||||
///
|
||||
/// A listener socket is a special type of socket that listens to
|
||||
/// a given port and waits for connections on that port.
|
||||
/// This is all it can do.
|
||||
///
|
||||
/// When a new connection is received, you must call accept and
|
||||
/// the listener returns a new instance of sf::TcpSocket that
|
||||
/// is properly initialized and can be used to communicate with
|
||||
/// the new client.
|
||||
///
|
||||
/// Listener sockets are specific to the TCP protocol,
|
||||
/// UDP sockets are connectionless and can therefore communicate
|
||||
/// directly. As a consequence, a listener socket will always
|
||||
/// return the new connections as sf::TcpSocket instances.
|
||||
///
|
||||
/// A listener is automatically closed on destruction, like all
|
||||
/// other types of socket. However if you want to stop listening
|
||||
/// before the socket is destroyed, you can call its close()
|
||||
/// function.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // Create a listener socket and make it wait for new
|
||||
/// // connections on port 55001
|
||||
/// sf::TcpListener listener;
|
||||
/// listener.listen(55001);
|
||||
///
|
||||
/// // Endless loop that waits for new connections
|
||||
/// while (running)
|
||||
/// {
|
||||
/// sf::TcpSocket client;
|
||||
/// if (listener.accept(client) == sf::Socket::Done)
|
||||
/// {
|
||||
/// // A new client just connected!
|
||||
/// std::cout << "New connection received from " << client.getRemoteAddress() << std::endl;
|
||||
/// doSomethingWith(client);
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \see sf::TcpSocket, sf::Socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,316 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_TCPSOCKET_HPP
|
||||
#define SFML_TCPSOCKET_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class TcpListener;
|
||||
class IpAddress;
|
||||
class Packet;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialized socket using the TCP protocol
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API TcpSocket : public Socket
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the port to which the socket is bound locally
|
||||
///
|
||||
/// If the socket is not connected, this function returns 0.
|
||||
///
|
||||
/// \return Port to which the socket is bound
|
||||
///
|
||||
/// \see connect, getRemotePort
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short getLocalPort() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the address of the connected peer
|
||||
///
|
||||
/// It the socket is not connected, this function returns
|
||||
/// sf::IpAddress::None.
|
||||
///
|
||||
/// \return Address of the remote peer
|
||||
///
|
||||
/// \see getRemotePort
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress getRemoteAddress() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the port of the connected peer to which
|
||||
/// the socket is connected
|
||||
///
|
||||
/// If the socket is not connected, this function returns 0.
|
||||
///
|
||||
/// \return Remote port to which the socket is connected
|
||||
///
|
||||
/// \see getRemoteAddress
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short getRemotePort() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Connect the socket to a remote peer
|
||||
///
|
||||
/// In blocking mode, this function may take a while, especially
|
||||
/// if the remote peer is not reachable. The last parameter allows
|
||||
/// you to stop trying to connect after a given timeout.
|
||||
/// If the socket is already connected, the connection is
|
||||
/// forcibly disconnected before attempting to connect again.
|
||||
///
|
||||
/// \param remoteAddress Address of the remote peer
|
||||
/// \param remotePort Port of the remote peer
|
||||
/// \param timeout Optional maximum time to wait
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see disconnect
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Disconnect the socket from its remote peer
|
||||
///
|
||||
/// This function gracefully closes the connection. If the
|
||||
/// socket is not connected, this function has no effect.
|
||||
///
|
||||
/// \see connect
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void disconnect();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send raw data to the remote peer
|
||||
///
|
||||
/// To be able to handle partial sends over non-blocking
|
||||
/// sockets, use the send(const void*, std::size_t, std::size_t&)
|
||||
/// overload instead.
|
||||
/// This function will fail if the socket is not connected.
|
||||
///
|
||||
/// \param data Pointer to the sequence of bytes to send
|
||||
/// \param size Number of bytes to send
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see receive
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status send(const void* data, std::size_t size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send raw data to the remote peer
|
||||
///
|
||||
/// This function will fail if the socket is not connected.
|
||||
///
|
||||
/// \param data Pointer to the sequence of bytes to send
|
||||
/// \param size Number of bytes to send
|
||||
/// \param sent The number of bytes sent will be written here
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see receive
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status send(const void* data, std::size_t size, std::size_t& sent);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Receive raw data from the remote peer
|
||||
///
|
||||
/// In blocking mode, this function will wait until some
|
||||
/// bytes are actually received.
|
||||
/// This function will fail if the socket is not connected.
|
||||
///
|
||||
/// \param data Pointer to the array to fill with the received bytes
|
||||
/// \param size Maximum number of bytes that can be received
|
||||
/// \param received This variable is filled with the actual number of bytes received
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see send
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status receive(void* data, std::size_t size, std::size_t& received);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send a formatted packet of data to the remote peer
|
||||
///
|
||||
/// In non-blocking mode, if this function returns sf::Socket::Partial,
|
||||
/// you \em must retry sending the same unmodified packet before sending
|
||||
/// anything else in order to guarantee the packet arrives at the remote
|
||||
/// peer uncorrupted.
|
||||
/// This function will fail if the socket is not connected.
|
||||
///
|
||||
/// \param packet Packet to send
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see receive
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status send(Packet& packet);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Receive a formatted packet of data from the remote peer
|
||||
///
|
||||
/// In blocking mode, this function will wait until the whole packet
|
||||
/// has been received.
|
||||
/// This function will fail if the socket is not connected.
|
||||
///
|
||||
/// \param packet Packet to fill with the received data
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see send
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status receive(Packet& packet);
|
||||
|
||||
private:
|
||||
|
||||
friend class TcpListener;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Structure holding the data of a pending packet
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct PendingPacket
|
||||
{
|
||||
PendingPacket();
|
||||
|
||||
Uint32 Size; ///< Data of packet size
|
||||
std::size_t SizeReceived; ///< Number of size bytes received so far
|
||||
std::vector<char> Data; ///< Data of the packet
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
PendingPacket m_pendingPacket; ///< Temporary data of the packet currently being received
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_TCPSOCKET_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::TcpSocket
|
||||
/// \ingroup network
|
||||
///
|
||||
/// TCP is a connected protocol, which means that a TCP
|
||||
/// socket can only communicate with the host it is connected
|
||||
/// to. It can't send or receive anything if it is not connected.
|
||||
///
|
||||
/// The TCP protocol is reliable but adds a slight overhead.
|
||||
/// It ensures that your data will always be received in order
|
||||
/// and without errors (no data corrupted, lost or duplicated).
|
||||
///
|
||||
/// When a socket is connected to a remote host, you can
|
||||
/// retrieve informations about this host with the
|
||||
/// getRemoteAddress and getRemotePort functions. You can
|
||||
/// also get the local port to which the socket is bound
|
||||
/// (which is automatically chosen when the socket is connected),
|
||||
/// with the getLocalPort function.
|
||||
///
|
||||
/// Sending and receiving data can use either the low-level
|
||||
/// or the high-level functions. The low-level functions
|
||||
/// process a raw sequence of bytes, and cannot ensure that
|
||||
/// one call to Send will exactly match one call to Receive
|
||||
/// at the other end of the socket.
|
||||
///
|
||||
/// The high-level interface uses packets (see sf::Packet),
|
||||
/// which are easier to use and provide more safety regarding
|
||||
/// the data that is exchanged. You can look at the sf::Packet
|
||||
/// class to get more details about how they work.
|
||||
///
|
||||
/// The socket is automatically disconnected when it is destroyed,
|
||||
/// but if you want to explicitly close the connection while
|
||||
/// the socket instance is still alive, you can call disconnect.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // ----- The client -----
|
||||
///
|
||||
/// // Create a socket and connect it to 192.168.1.50 on port 55001
|
||||
/// sf::TcpSocket socket;
|
||||
/// socket.connect("192.168.1.50", 55001);
|
||||
///
|
||||
/// // Send a message to the connected host
|
||||
/// std::string message = "Hi, I am a client";
|
||||
/// socket.send(message.c_str(), message.size() + 1);
|
||||
///
|
||||
/// // Receive an answer from the server
|
||||
/// char buffer[1024];
|
||||
/// std::size_t received = 0;
|
||||
/// socket.receive(buffer, sizeof(buffer), received);
|
||||
/// std::cout << "The server said: " << buffer << std::endl;
|
||||
///
|
||||
/// // ----- The server -----
|
||||
///
|
||||
/// // Create a listener to wait for incoming connections on port 55001
|
||||
/// sf::TcpListener listener;
|
||||
/// listener.listen(55001);
|
||||
///
|
||||
/// // Wait for a connection
|
||||
/// sf::TcpSocket socket;
|
||||
/// listener.accept(socket);
|
||||
/// std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
|
||||
///
|
||||
/// // Receive a message from the client
|
||||
/// char buffer[1024];
|
||||
/// std::size_t received = 0;
|
||||
/// socket.receive(buffer, sizeof(buffer), received);
|
||||
/// std::cout << "The client said: " << buffer << std::endl;
|
||||
///
|
||||
/// // Send an answer
|
||||
/// std::string message = "Welcome, client";
|
||||
/// socket.send(message.c_str(), message.size() + 1);
|
||||
/// \endcode
|
||||
///
|
||||
/// \see sf::Socket, sf::UdpSocket, sf::Packet
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,291 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_UDPSOCKET_HPP
|
||||
#define SFML_UDPSOCKET_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Packet;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialized socket using the UDP protocol
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API UdpSocket : public Socket
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
UdpSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the port to which the socket is bound locally
|
||||
///
|
||||
/// If the socket is not bound to a port, this function
|
||||
/// returns 0.
|
||||
///
|
||||
/// \return Port to which the socket is bound
|
||||
///
|
||||
/// \see bind
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short getLocalPort() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Bind the socket to a specific port
|
||||
///
|
||||
/// Binding the socket to a port is necessary for being
|
||||
/// able to receive data on that port.
|
||||
/// You can use the special value Socket::AnyPort to tell the
|
||||
/// system to automatically pick an available port, and then
|
||||
/// call getLocalPort to retrieve the chosen port.
|
||||
///
|
||||
/// Since the socket can only be bound to a single port at
|
||||
/// any given moment, if it is already bound when this
|
||||
/// function is called, it will be unbound from the previous
|
||||
/// port before being bound to the new one.
|
||||
///
|
||||
/// \param port Port to bind the socket to
|
||||
/// \param address Address of the interface to bind to
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see unbind, getLocalPort
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status bind(unsigned short port, const IpAddress& address = IpAddress::Any);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unbind the socket from the local port to which it is bound
|
||||
///
|
||||
/// The port that the socket was previously bound to is immediately
|
||||
/// made available to the operating system after this function is called.
|
||||
/// This means that a subsequent call to bind() will be able to re-bind
|
||||
/// the port if no other process has done so in the mean time.
|
||||
/// If the socket is not bound to a port, this function has no effect.
|
||||
///
|
||||
/// \see bind
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unbind();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send raw data to a remote peer
|
||||
///
|
||||
/// Make sure that \a size is not greater than
|
||||
/// UdpSocket::MaxDatagramSize, otherwise this function will
|
||||
/// fail and no data will be sent.
|
||||
///
|
||||
/// \param data Pointer to the sequence of bytes to send
|
||||
/// \param size Number of bytes to send
|
||||
/// \param remoteAddress Address of the receiver
|
||||
/// \param remotePort Port of the receiver to send the data to
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see receive
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Receive raw data from a remote peer
|
||||
///
|
||||
/// In blocking mode, this function will wait until some
|
||||
/// bytes are actually received.
|
||||
/// Be careful to use a buffer which is large enough for
|
||||
/// the data that you intend to receive, if it is too small
|
||||
/// then an error will be returned and *all* the data will
|
||||
/// be lost.
|
||||
///
|
||||
/// \param data Pointer to the array to fill with the received bytes
|
||||
/// \param size Maximum number of bytes that can be received
|
||||
/// \param received This variable is filled with the actual number of bytes received
|
||||
/// \param remoteAddress Address of the peer that sent the data
|
||||
/// \param remotePort Port of the peer that sent the data
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see send
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send a formatted packet of data to a remote peer
|
||||
///
|
||||
/// Make sure that the packet size is not greater than
|
||||
/// UdpSocket::MaxDatagramSize, otherwise this function will
|
||||
/// fail and no data will be sent.
|
||||
///
|
||||
/// \param packet Packet to send
|
||||
/// \param remoteAddress Address of the receiver
|
||||
/// \param remotePort Port of the receiver to send the data to
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see receive
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Receive a formatted packet of data from a remote peer
|
||||
///
|
||||
/// In blocking mode, this function will wait until the whole packet
|
||||
/// has been received.
|
||||
///
|
||||
/// \param packet Packet to fill with the received data
|
||||
/// \param remoteAddress Address of the peer that sent the data
|
||||
/// \param remotePort Port of the peer that sent the data
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
/// \see send
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::vector<char> m_buffer; ///< Temporary buffer holding the received data in Receive(Packet)
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_UDPSOCKET_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::UdpSocket
|
||||
/// \ingroup network
|
||||
///
|
||||
/// A UDP socket is a connectionless socket. Instead of
|
||||
/// connecting once to a remote host, like TCP sockets,
|
||||
/// it can send to and receive from any host at any time.
|
||||
///
|
||||
/// It is a datagram protocol: bounded blocks of data (datagrams)
|
||||
/// are transfered over the network rather than a continuous
|
||||
/// stream of data (TCP). Therefore, one call to send will always
|
||||
/// match one call to receive (if the datagram is not lost),
|
||||
/// with the same data that was sent.
|
||||
///
|
||||
/// The UDP protocol is lightweight but unreliable. Unreliable
|
||||
/// means that datagrams may be duplicated, be lost or
|
||||
/// arrive reordered. However, if a datagram arrives, its
|
||||
/// data is guaranteed to be valid.
|
||||
///
|
||||
/// UDP is generally used for real-time communication
|
||||
/// (audio or video streaming, real-time games, etc.) where
|
||||
/// speed is crucial and lost data doesn't matter much.
|
||||
///
|
||||
/// Sending and receiving data can use either the low-level
|
||||
/// or the high-level functions. The low-level functions
|
||||
/// process a raw sequence of bytes, whereas the high-level
|
||||
/// interface uses packets (see sf::Packet), which are easier
|
||||
/// to use and provide more safety regarding the data that is
|
||||
/// exchanged. You can look at the sf::Packet class to get
|
||||
/// more details about how they work.
|
||||
///
|
||||
/// It is important to note that UdpSocket is unable to send
|
||||
/// datagrams bigger than MaxDatagramSize. In this case, it
|
||||
/// returns an error and doesn't send anything. This applies
|
||||
/// to both raw data and packets. Indeed, even packets are
|
||||
/// unable to split and recompose data, due to the unreliability
|
||||
/// of the protocol (dropped, mixed or duplicated datagrams may
|
||||
/// lead to a big mess when trying to recompose a packet).
|
||||
///
|
||||
/// If the socket is bound to a port, it is automatically
|
||||
/// unbound from it when the socket is destroyed. However,
|
||||
/// you can unbind the socket explicitly with the Unbind
|
||||
/// function if necessary, to stop receiving messages or
|
||||
/// make the port available for other sockets.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // ----- The client -----
|
||||
///
|
||||
/// // Create a socket and bind it to the port 55001
|
||||
/// sf::UdpSocket socket;
|
||||
/// socket.bind(55001);
|
||||
///
|
||||
/// // Send a message to 192.168.1.50 on port 55002
|
||||
/// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString();
|
||||
/// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002);
|
||||
///
|
||||
/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else)
|
||||
/// char buffer[1024];
|
||||
/// std::size_t received = 0;
|
||||
/// sf::IpAddress sender;
|
||||
/// unsigned short port;
|
||||
/// socket.receive(buffer, sizeof(buffer), received, sender, port);
|
||||
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
|
||||
///
|
||||
/// // ----- The server -----
|
||||
///
|
||||
/// // Create a socket and bind it to the port 55002
|
||||
/// sf::UdpSocket socket;
|
||||
/// socket.bind(55002);
|
||||
///
|
||||
/// // Receive a message from anyone
|
||||
/// char buffer[1024];
|
||||
/// std::size_t received = 0;
|
||||
/// sf::IpAddress sender;
|
||||
/// unsigned short port;
|
||||
/// socket.receive(buffer, sizeof(buffer), received, sender, port);
|
||||
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
|
||||
///
|
||||
/// // Send an answer
|
||||
/// std::string message = "Welcome " + sender.toString();
|
||||
/// socket.send(message.c_str(), message.size() + 1, sender, port);
|
||||
/// \endcode
|
||||
///
|
||||
/// \see sf::Socket, sf::TcpSocket, sf::Packet
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,58 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SYSTEM_HPP
|
||||
#define SFML_SYSTEM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#include <SFML/Config.hpp>
|
||||
//#include <SFML/System/Clock.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
//#include <SFML/System/InputStream.hpp>
|
||||
//#include <SFML/System/Lock.hpp>
|
||||
//#include <SFML/System/Mutex.hpp>
|
||||
//#include <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/String.hpp>
|
||||
//#include <SFML/System/Thread.hpp>
|
||||
//#include <SFML/System/ThreadLocal.hpp>
|
||||
//#include <SFML/System/ThreadLocalPtr.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
//#include <SFML/System/Vector2.hpp>
|
||||
//#include <SFML/System/Vector3.hpp>
|
||||
|
||||
#endif // SFML_SYSTEM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \defgroup system System module
|
||||
///
|
||||
/// Base module of SFML, defining various utilities. It provides
|
||||
/// vector classes, Unicode strings and conversion functions,
|
||||
/// threads and mutexes, timing classes.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,80 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_ERR_HPP
|
||||
#define SFML_ERR_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <ostream>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Standard stream used by SFML to output warnings and errors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API std::ostream& err();
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_ERR_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \fn sf::err
|
||||
/// \ingroup system
|
||||
///
|
||||
/// By default, sf::err() outputs to the same location as std::cerr,
|
||||
/// (-> the stderr descriptor) which is the console if there's
|
||||
/// one available.
|
||||
///
|
||||
/// It is a standard std::ostream instance, so it supports all the
|
||||
/// insertion operations defined by the STL
|
||||
/// (operator <<, manipulators, etc.).
|
||||
///
|
||||
/// sf::err() can be redirected to write to another output, independently
|
||||
/// of std::cerr, by using the rdbuf() function provided by the
|
||||
/// std::ostream class.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// // Redirect to a file
|
||||
/// std::ofstream file("sfml-log.txt");
|
||||
/// std::streambuf* previous = sf::err().rdbuf(file.rdbuf());
|
||||
///
|
||||
/// // Redirect to nothing
|
||||
/// sf::err().rdbuf(NULL);
|
||||
///
|
||||
/// // Restore the original output
|
||||
/// sf::err().rdbuf(previous);
|
||||
/// \endcode
|
||||
///
|
||||
/// \return Reference to std::ostream representing the SFML error stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,48 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SYSTEM_EXPORT_HPP
|
||||
#define SFML_SYSTEM_EXPORT_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Define portable import / export macros
|
||||
////////////////////////////////////////////////////////////
|
||||
#if defined(SFML_SYSTEM_EXPORTS)
|
||||
|
||||
#define SFML_SYSTEM_API SFML_API_EXPORT
|
||||
|
||||
#else
|
||||
|
||||
#define SFML_SYSTEM_API SFML_API_IMPORT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SFML_SYSTEM_EXPORT_HPP
|
|
@ -1,129 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_NONCOPYABLE_HPP
|
||||
#define SFML_NONCOPYABLE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility class that makes any derived
|
||||
/// class non-copyable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API NonCopyable
|
||||
{
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// Because this class has a copy constructor, the compiler
|
||||
/// will not automatically generate the default constructor.
|
||||
/// That's why we must define it explicitly.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
NonCopyable() {}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default destructor
|
||||
///
|
||||
/// By declaring a protected destructor it's impossible to
|
||||
/// call delete on a pointer of sf::NonCopyable, thus
|
||||
/// preventing possible resource leaks.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~NonCopyable() {}
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Disabled copy constructor
|
||||
///
|
||||
/// By making the copy constructor private, the compiler will
|
||||
/// trigger an error if anyone outside tries to use it.
|
||||
/// To prevent NonCopyable or friend classes from using it,
|
||||
/// we also give no definition, so that the linker will
|
||||
/// produce an error if the first protection was inefficient.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
NonCopyable(const NonCopyable&);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Disabled assignment operator
|
||||
///
|
||||
/// By making the assignment operator private, the compiler will
|
||||
/// trigger an error if anyone outside tries to use it.
|
||||
/// To prevent NonCopyable or friend classes from using it,
|
||||
/// we also give no definition, so that the linker will
|
||||
/// produce an error if the first protection was inefficient.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
NonCopyable& operator =(const NonCopyable&);
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_NONCOPYABLE_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::NonCopyable
|
||||
/// \ingroup system
|
||||
///
|
||||
/// This class makes its instances non-copyable, by explicitly
|
||||
/// disabling its copy constructor and its assignment operator.
|
||||
///
|
||||
/// To create a non-copyable class, simply inherit from
|
||||
/// sf::NonCopyable.
|
||||
///
|
||||
/// The type of inheritance (public or private) doesn't matter,
|
||||
/// the copy constructor and assignment operator are declared private
|
||||
/// in sf::NonCopyable so they will end up being inaccessible in both
|
||||
/// cases. Thus you can use a shorter syntax for inheriting from it
|
||||
/// (see below).
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// class MyNonCopyableClass : sf::NonCopyable
|
||||
/// {
|
||||
/// ...
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// Deciding whether the instances of a class can be copied
|
||||
/// or not is a very important design choice. You are strongly
|
||||
/// encouraged to think about it before writing a class,
|
||||
/// and to use sf::NonCopyable when necessary to prevent
|
||||
/// many potential future errors when using it. This is also
|
||||
/// a very important indication to users of your class.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,669 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_STRING_HPP
|
||||
#define SFML_STRING_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
#include <iterator>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility string class that automatically handles
|
||||
/// conversions between types and encodings
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API String
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef std::basic_string<Uint32>::iterator Iterator; ///< Iterator type
|
||||
typedef std::basic_string<Uint32>::const_iterator ConstIterator; ///< Read-only iterator type
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
static const std::size_t InvalidPos; ///< Represents an invalid position in the string
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor creates an empty string.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from a single ANSI character and a locale
|
||||
///
|
||||
/// The source character is converted to UTF-32 according
|
||||
/// to the given locale.
|
||||
///
|
||||
/// \param ansiChar ANSI character to convert
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(char ansiChar, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from single wide character
|
||||
///
|
||||
/// \param wideChar Wide character to convert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(wchar_t wideChar);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from single UTF-32 character
|
||||
///
|
||||
/// \param utf32Char UTF-32 character to convert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(Uint32 utf32Char);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from a null-terminated C-style ANSI string and a locale
|
||||
///
|
||||
/// The source string is converted to UTF-32 according
|
||||
/// to the given locale.
|
||||
///
|
||||
/// \param ansiString ANSI string to convert
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const char* ansiString, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from an ANSI string and a locale
|
||||
///
|
||||
/// The source string is converted to UTF-32 according
|
||||
/// to the given locale.
|
||||
///
|
||||
/// \param ansiString ANSI string to convert
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const std::string& ansiString, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from null-terminated C-style wide string
|
||||
///
|
||||
/// \param wideString Wide string to convert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const wchar_t* wideString);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from a wide string
|
||||
///
|
||||
/// \param wideString Wide string to convert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const std::wstring& wideString);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from a null-terminated C-style UTF-32 string
|
||||
///
|
||||
/// \param utf32String UTF-32 string to assign
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const Uint32* utf32String);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from an UTF-32 string
|
||||
///
|
||||
/// \param utf32String UTF-32 string to assign
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const std::basic_string<Uint32>& utf32String);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Copy constructor
|
||||
///
|
||||
/// \param copy Instance to copy
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String(const String& copy);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new sf::String from a UTF-8 encoded string
|
||||
///
|
||||
/// \param begin Forward iterator to the beginning of the UTF-8 sequence
|
||||
/// \param end Forward iterator to the end of the UTF-8 sequence
|
||||
///
|
||||
/// \return A sf::String containing the source string
|
||||
///
|
||||
/// \see fromUtf16, fromUtf32
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
static String fromUtf8(T begin, T end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new sf::String from a UTF-16 encoded string
|
||||
///
|
||||
/// \param begin Forward iterator to the beginning of the UTF-16 sequence
|
||||
/// \param end Forward iterator to the end of the UTF-16 sequence
|
||||
///
|
||||
/// \return A sf::String containing the source string
|
||||
///
|
||||
/// \see fromUtf8, fromUtf32
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
static String fromUtf16(T begin, T end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new sf::String from a UTF-32 encoded string
|
||||
///
|
||||
/// This function is provided for consistency, it is equivalent to
|
||||
/// using the constructors that takes a const sf::Uint32* or
|
||||
/// a std::basic_string<sf::Uint32>.
|
||||
///
|
||||
/// \param begin Forward iterator to the beginning of the UTF-32 sequence
|
||||
/// \param end Forward iterator to the end of the UTF-32 sequence
|
||||
///
|
||||
/// \return A sf::String containing the source string
|
||||
///
|
||||
/// \see fromUtf8, fromUtf16
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
static String fromUtf32(T begin, T end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implicit conversion operator to std::string (ANSI string)
|
||||
///
|
||||
/// The current global locale is used for conversion. If you
|
||||
/// want to explicitly specify a locale, see toAnsiString.
|
||||
/// Characters that do not fit in the target encoding are
|
||||
/// discarded from the returned string.
|
||||
/// This operator is defined for convenience, and is equivalent
|
||||
/// to calling toAnsiString().
|
||||
///
|
||||
/// \return Converted ANSI string
|
||||
///
|
||||
/// \see toAnsiString, operator std::wstring
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
operator std::string() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implicit conversion operator to std::wstring (wide string)
|
||||
///
|
||||
/// Characters that do not fit in the target encoding are
|
||||
/// discarded from the returned string.
|
||||
/// This operator is defined for convenience, and is equivalent
|
||||
/// to calling toWideString().
|
||||
///
|
||||
/// \return Converted wide string
|
||||
///
|
||||
/// \see toWideString, operator std::string
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
operator std::wstring() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert the Unicode string to an ANSI string
|
||||
///
|
||||
/// The UTF-32 string is converted to an ANSI string in
|
||||
/// the encoding defined by \a locale.
|
||||
/// Characters that do not fit in the target encoding are
|
||||
/// discarded from the returned string.
|
||||
///
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Converted ANSI string
|
||||
///
|
||||
/// \see toWideString, operator std::string
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string toAnsiString(const std::locale& locale = std::locale()) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert the Unicode string to a wide string
|
||||
///
|
||||
/// Characters that do not fit in the target encoding are
|
||||
/// discarded from the returned string.
|
||||
///
|
||||
/// \return Converted wide string
|
||||
///
|
||||
/// \see toAnsiString, operator std::wstring
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::wstring toWideString() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert the Unicode string to a UTF-8 string
|
||||
///
|
||||
/// \return Converted UTF-8 string
|
||||
///
|
||||
/// \see toUtf16, toUtf32
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint8> toUtf8() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert the Unicode string to a UTF-16 string
|
||||
///
|
||||
/// \return Converted UTF-16 string
|
||||
///
|
||||
/// \see toUtf8, toUtf32
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint16> toUtf16() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert the Unicode string to a UTF-32 string
|
||||
///
|
||||
/// This function doesn't perform any conversion, since the
|
||||
/// string is already stored as UTF-32 internally.
|
||||
///
|
||||
/// \return Converted UTF-32 string
|
||||
///
|
||||
/// \see toUtf8, toUtf16
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint32> toUtf32() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of assignment operator
|
||||
///
|
||||
/// \param right Instance to assign
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String& operator =(const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of += operator to append an UTF-32 string
|
||||
///
|
||||
/// \param right String to append
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String& operator +=(const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of [] operator to access a character by its position
|
||||
///
|
||||
/// This function provides read-only access to characters.
|
||||
/// Note: the behavior is undefined if \a index is out of range.
|
||||
///
|
||||
/// \param index Index of the character to get
|
||||
///
|
||||
/// \return Character at position \a index
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 operator [](std::size_t index) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of [] operator to access a character by its position
|
||||
///
|
||||
/// This function provides read and write access to characters.
|
||||
/// Note: the behavior is undefined if \a index is out of range.
|
||||
///
|
||||
/// \param index Index of the character to get
|
||||
///
|
||||
/// \return Reference to the character at position \a index
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32& operator [](std::size_t index);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Clear the string
|
||||
///
|
||||
/// This function removes all the characters from the string.
|
||||
///
|
||||
/// \see isEmpty, erase
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void clear();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the size of the string
|
||||
///
|
||||
/// \return Number of characters in the string
|
||||
///
|
||||
/// \see isEmpty
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t getSize() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check whether the string is empty or not
|
||||
///
|
||||
/// \return True if the string is empty (i.e. contains no character)
|
||||
///
|
||||
/// \see clear, getSize
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool isEmpty() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Erase one or more characters from the string
|
||||
///
|
||||
/// This function removes a sequence of \a count characters
|
||||
/// starting from \a position.
|
||||
///
|
||||
/// \param position Position of the first character to erase
|
||||
/// \param count Number of characters to erase
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void erase(std::size_t position, std::size_t count = 1);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Insert one or more characters into the string
|
||||
///
|
||||
/// This function inserts the characters of \a str
|
||||
/// into the string, starting from \a position.
|
||||
///
|
||||
/// \param position Position of insertion
|
||||
/// \param str Characters to insert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void insert(std::size_t position, const String& str);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Find a sequence of one or more characters in the string
|
||||
///
|
||||
/// This function searches for the characters of \a str
|
||||
/// in the string, starting from \a start.
|
||||
///
|
||||
/// \param str Characters to find
|
||||
/// \param start Where to begin searching
|
||||
///
|
||||
/// \return Position of \a str in the string, or String::InvalidPos if not found
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t find(const String& str, std::size_t start = 0) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Replace a substring with another string
|
||||
///
|
||||
/// This function replaces the substring that starts at index \a position
|
||||
/// and spans \a length characters with the string \a replaceWith.
|
||||
///
|
||||
/// \param position Index of the first character to be replaced
|
||||
/// \param length Number of characters to replace. You can pass InvalidPos to
|
||||
/// replace all characters until the end of the string.
|
||||
/// \param replaceWith String that replaces the given substring.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void replace(std::size_t position, std::size_t length, const String& replaceWith);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Replace all occurrences of a substring with a replacement string
|
||||
///
|
||||
/// This function replaces all occurrences of \a searchFor in this string
|
||||
/// with the string \a replaceWith.
|
||||
///
|
||||
/// \param searchFor The value being searched for
|
||||
/// \param replaceWith The value that replaces found \a searchFor values
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void replace(const String& searchFor, const String& replaceWith);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return a part of the string
|
||||
///
|
||||
/// This function returns the substring that starts at index \a position
|
||||
/// and spans \a length characters.
|
||||
///
|
||||
/// \param position Index of the first character
|
||||
/// \param length Number of characters to include in the substring (if
|
||||
/// the string is shorter, as many characters as possible
|
||||
/// are included). \ref InvalidPos can be used to include all
|
||||
/// characters until the end of the string.
|
||||
///
|
||||
/// \return String object containing a substring of this object
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
String substring(std::size_t position, std::size_t length = InvalidPos) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get a pointer to the C-style array of characters
|
||||
///
|
||||
/// This functions provides a read-only access to a
|
||||
/// null-terminated C-style representation of the string.
|
||||
/// The returned pointer is temporary and is meant only for
|
||||
/// immediate use, thus it is not recommended to store it.
|
||||
///
|
||||
/// \return Read-only pointer to the array of characters
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint32* getData() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return an iterator to the beginning of the string
|
||||
///
|
||||
/// \return Read-write iterator to the beginning of the string characters
|
||||
///
|
||||
/// \see end
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Iterator begin();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return an iterator to the beginning of the string
|
||||
///
|
||||
/// \return Read-only iterator to the beginning of the string characters
|
||||
///
|
||||
/// \see end
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ConstIterator begin() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return an iterator to the end of the string
|
||||
///
|
||||
/// The end iterator refers to 1 position past the last character;
|
||||
/// thus it represents an invalid character and should never be
|
||||
/// accessed.
|
||||
///
|
||||
/// \return Read-write iterator to the end of the string characters
|
||||
///
|
||||
/// \see begin
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Iterator end();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return an iterator to the end of the string
|
||||
///
|
||||
/// The end iterator refers to 1 position past the last character;
|
||||
/// thus it represents an invalid character and should never be
|
||||
/// accessed.
|
||||
///
|
||||
/// \return Read-only iterator to the end of the string characters
|
||||
///
|
||||
/// \see begin
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ConstIterator end() const;
|
||||
|
||||
private:
|
||||
|
||||
friend SFML_SYSTEM_API bool operator ==(const String& left, const String& right);
|
||||
friend SFML_SYSTEM_API bool operator <(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint32> m_string; ///< Internal string of UTF-32 characters
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of == operator to compare two UTF-32 strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return True if both strings are equal
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator ==(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of != operator to compare two UTF-32 strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return True if both strings are different
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator !=(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of < operator to compare two UTF-32 strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return True if \a left is lexicographically before \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator <(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of > operator to compare two UTF-32 strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return True if \a left is lexicographically after \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator >(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of <= operator to compare two UTF-32 strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return True if \a left is lexicographically before or equivalent to \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator <=(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of >= operator to compare two UTF-32 strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return True if \a left is lexicographically after or equivalent to \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator >=(const String& left, const String& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates String
|
||||
/// \brief Overload of binary + operator to concatenate two strings
|
||||
///
|
||||
/// \param left Left operand (a string)
|
||||
/// \param right Right operand (a string)
|
||||
///
|
||||
/// \return Concatenated string
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API String operator +(const String& left, const String& right);
|
||||
|
||||
#include <SFML/System/String.inl>
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_STRING_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::String
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::String is a utility string class defined mainly for
|
||||
/// convenience. It is a Unicode string (implemented using
|
||||
/// UTF-32), thus it can store any character in the world
|
||||
/// (European, Chinese, Arabic, Hebrew, etc.).
|
||||
///
|
||||
/// It automatically handles conversions from/to ANSI and
|
||||
/// wide strings, so that you can work with standard string
|
||||
/// classes and still be compatible with functions taking a
|
||||
/// sf::String.
|
||||
///
|
||||
/// \code
|
||||
/// sf::String s;
|
||||
///
|
||||
/// std::string s1 = s; // automatically converted to ANSI string
|
||||
/// std::wstring s2 = s; // automatically converted to wide string
|
||||
/// s = "hello"; // automatically converted from ANSI string
|
||||
/// s = L"hello"; // automatically converted from wide string
|
||||
/// s += 'a'; // automatically converted from ANSI string
|
||||
/// s += L'a'; // automatically converted from wide string
|
||||
/// \endcode
|
||||
///
|
||||
/// Conversions involving ANSI strings use the default user locale. However
|
||||
/// it is possible to use a custom locale if necessary:
|
||||
/// \code
|
||||
/// std::locale locale;
|
||||
/// sf::String s;
|
||||
/// ...
|
||||
/// std::string s1 = s.toAnsiString(locale);
|
||||
/// s = sf::String("hello", locale);
|
||||
/// \endcode
|
||||
///
|
||||
/// sf::String defines the most important functions of the
|
||||
/// standard std::string class: removing, random access, iterating,
|
||||
/// appending, comparing, etc. However it is a simple class
|
||||
/// provided for convenience, and you may have to consider using
|
||||
/// a more optimized class if your program requires complex string
|
||||
/// handling. The automatic conversion functions will then take
|
||||
/// care of converting your string to sf::String whenever SFML
|
||||
/// requires it.
|
||||
///
|
||||
/// Please note that SFML also defines a low-level, generic
|
||||
/// interface for Unicode handling, see the sf::Utf classes.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,53 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
String String::fromUtf8(T begin, T end)
|
||||
{
|
||||
String string;
|
||||
Utf8::toUtf32(begin, end, std::back_inserter(string.m_string));
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
String String::fromUtf16(T begin, T end)
|
||||
{
|
||||
String string;
|
||||
Utf16::toUtf32(begin, end, std::back_inserter(string.m_string));
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
String String::fromUtf32(T begin, T end)
|
||||
{
|
||||
String string;
|
||||
string.m_string.assign(begin, end);
|
||||
return string;
|
||||
}
|
|
@ -1,488 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_TIME_HPP
|
||||
#define SFML_TIME_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Represents a time value
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API Time
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// Sets the time value to zero.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Time();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the time value as a number of seconds
|
||||
///
|
||||
/// \return Time in seconds
|
||||
///
|
||||
/// \see asMilliseconds, asMicroseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
float asSeconds() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the time value as a number of milliseconds
|
||||
///
|
||||
/// \return Time in milliseconds
|
||||
///
|
||||
/// \see asSeconds, asMicroseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Int32 asMilliseconds() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the time value as a number of microseconds
|
||||
///
|
||||
/// \return Time in microseconds
|
||||
///
|
||||
/// \see asSeconds, asMilliseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 asMicroseconds() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
static const Time Zero; ///< Predefined "zero" time value
|
||||
|
||||
private:
|
||||
|
||||
friend SFML_SYSTEM_API Time seconds(float);
|
||||
friend SFML_SYSTEM_API Time milliseconds(Int32);
|
||||
friend SFML_SYSTEM_API Time microseconds(Int64);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from a number of microseconds
|
||||
///
|
||||
/// This function is internal. To construct time values,
|
||||
/// use sf::seconds, sf::milliseconds or sf::microseconds instead.
|
||||
///
|
||||
/// \param microseconds Number of microseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit Time(Int64 microseconds);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 m_microseconds; ///< Time value stored as microseconds
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Construct a time value from a number of seconds
|
||||
///
|
||||
/// \param amount Number of seconds
|
||||
///
|
||||
/// \return Time value constructed from the amount of seconds
|
||||
///
|
||||
/// \see milliseconds, microseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time seconds(float amount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Construct a time value from a number of milliseconds
|
||||
///
|
||||
/// \param amount Number of milliseconds
|
||||
///
|
||||
/// \return Time value constructed from the amount of milliseconds
|
||||
///
|
||||
/// \see seconds, microseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time milliseconds(Int32 amount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Construct a time value from a number of microseconds
|
||||
///
|
||||
/// \param amount Number of microseconds
|
||||
///
|
||||
/// \return Time value constructed from the amount of microseconds
|
||||
///
|
||||
/// \see seconds, milliseconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time microseconds(Int64 amount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of == operator to compare two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return True if both time values are equal
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator ==(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of != operator to compare two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return True if both time values are different
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator !=(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of < operator to compare two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return True if \a left is lesser than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator <(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of > operator to compare two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return True if \a left is greater than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator >(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of <= operator to compare two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return True if \a left is lesser or equal than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator <=(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of >= operator to compare two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return True if \a left is greater or equal than \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API bool operator >=(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of unary - operator to negate a time value
|
||||
///
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return Opposite of the time value
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator -(Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary + operator to add two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return Sum of the two times values
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator +(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary += operator to add/assign two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return Sum of the two times values
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator +=(Time& left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary - operator to subtract two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return Difference of the two times values
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator -(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary -= operator to subtract/assign two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return Difference of the two times values
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator -=(Time& left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary * operator to scale a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left multiplied by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator *(Time left, float right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary * operator to scale a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left multiplied by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator *(Time left, Int64 right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary * operator to scale a time value
|
||||
///
|
||||
/// \param left Left operand (a number)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return \a left multiplied by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator *(float left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary * operator to scale a time value
|
||||
///
|
||||
/// \param left Left operand (a number)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return \a left multiplied by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator *(Int64 left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary *= operator to scale/assign a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left multiplied by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator *=(Time& left, float right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary *= operator to scale/assign a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left multiplied by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator *=(Time& left, Int64 right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary / operator to scale a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left divided by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator /(Time left, float right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary / operator to scale a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left divided by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator /(Time left, Int64 right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary /= operator to scale/assign a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left divided by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator /=(Time& left, float right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary /= operator to scale/assign a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a number)
|
||||
///
|
||||
/// \return \a left divided by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator /=(Time& left, Int64 right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary / operator to compute the ratio of two time values
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return \a left divided by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API float operator /(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary % operator to compute remainder of a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return \a left modulo \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time operator %(Time left, Time right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Time
|
||||
/// \brief Overload of binary %= operator to compute/assign remainder of a time value
|
||||
///
|
||||
/// \param left Left operand (a time)
|
||||
/// \param right Right operand (a time)
|
||||
///
|
||||
/// \return \a left modulo \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API Time& operator %=(Time& left, Time right);
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_TIME_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Time
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::Time encapsulates a time value in a flexible way.
|
||||
/// It allows to define a time value either as a number of
|
||||
/// seconds, milliseconds or microseconds. It also works the
|
||||
/// other way round: you can read a time value as either
|
||||
/// a number of seconds, milliseconds or microseconds.
|
||||
///
|
||||
/// By using such a flexible interface, the API doesn't
|
||||
/// impose any fixed type or resolution for time values,
|
||||
/// and let the user choose its own favorite representation.
|
||||
///
|
||||
/// Time values support the usual mathematical operations:
|
||||
/// you can add or subtract two times, multiply or divide
|
||||
/// a time by a number, compare two times, etc.
|
||||
///
|
||||
/// Since they represent a time span and not an absolute time
|
||||
/// value, times can also be negative.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::Time t1 = sf::seconds(0.1f);
|
||||
/// Int32 milli = t1.asMilliseconds(); // 100
|
||||
///
|
||||
/// sf::Time t2 = sf::milliseconds(30);
|
||||
/// Int64 micro = t2.asMicroseconds(); // 30000
|
||||
///
|
||||
/// sf::Time t3 = sf::microseconds(-800000);
|
||||
/// float sec = t3.asSeconds(); // -0.8
|
||||
/// \endcode
|
||||
///
|
||||
/// \code
|
||||
/// void update(sf::Time elapsed)
|
||||
/// {
|
||||
/// position += speed * elapsed.asSeconds();
|
||||
/// }
|
||||
///
|
||||
/// update(sf::milliseconds(100));
|
||||
/// \endcode
|
||||
///
|
||||
/// \see sf::Clock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,763 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_UTF_HPP
|
||||
#define SFML_UTF_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
template <unsigned int N>
|
||||
class Utf;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of the Utf template for UTF-8
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
class Utf<8>
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Decode a single UTF-8 character
|
||||
///
|
||||
/// Decoding a character means finding its unique 32-bits
|
||||
/// code (called the codepoint) in the Unicode standard.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Codepoint of the decoded UTF-8 character
|
||||
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Encode a single UTF-8 character
|
||||
///
|
||||
/// Encoding a character means converting a unique 32-bits
|
||||
/// code (called the codepoint) in the target encoding, UTF-8.
|
||||
///
|
||||
/// \param input Codepoint to encode as UTF-8
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
static Out encode(Uint32 input, Out output, Uint8 replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Advance to the next UTF-8 character
|
||||
///
|
||||
/// This function is necessary for multi-elements encodings, as
|
||||
/// a single character may use more than 1 storage element.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static In next(In begin, In end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Count the number of characters of a UTF-8 sequence
|
||||
///
|
||||
/// This function is necessary for multi-elements encodings, as
|
||||
/// a single character may use more than 1 storage element, thus the
|
||||
/// total size can be different from (begin - end).
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static std::size_t count(In begin, In end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an ANSI characters range to UTF-8
|
||||
///
|
||||
/// The current global locale will be used by default, unless you
|
||||
/// pass a custom one in the \a locale parameter.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a wide characters range to UTF-8
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromWide(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromLatin1(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-8 characters range to ANSI characters
|
||||
///
|
||||
/// The current global locale will be used by default, unless you
|
||||
/// pass a custom one in the \a locale parameter.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-8 characters range to wide characters
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-8 characters range to UTF-8
|
||||
///
|
||||
/// This functions does nothing more than a direct copy;
|
||||
/// it is defined only to provide the same interface as other
|
||||
/// specializations of the sf::Utf<> template, and allow
|
||||
/// generic code to be written on top of it.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf8(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-8 characters range to UTF-16
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf16(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-8 characters range to UTF-32
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf32(In begin, In end, Out output);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of the Utf template for UTF-16
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
class Utf<16>
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Decode a single UTF-16 character
|
||||
///
|
||||
/// Decoding a character means finding its unique 32-bits
|
||||
/// code (called the codepoint) in the Unicode standard.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Codepoint of the decoded UTF-16 character
|
||||
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Encode a single UTF-16 character
|
||||
///
|
||||
/// Encoding a character means converting a unique 32-bits
|
||||
/// code (called the codepoint) in the target encoding, UTF-16.
|
||||
///
|
||||
/// \param input Codepoint to encode as UTF-16
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
static Out encode(Uint32 input, Out output, Uint16 replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Advance to the next UTF-16 character
|
||||
///
|
||||
/// This function is necessary for multi-elements encodings, as
|
||||
/// a single character may use more than 1 storage element.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static In next(In begin, In end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Count the number of characters of a UTF-16 sequence
|
||||
///
|
||||
/// This function is necessary for multi-elements encodings, as
|
||||
/// a single character may use more than 1 storage element, thus the
|
||||
/// total size can be different from (begin - end).
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static std::size_t count(In begin, In end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an ANSI characters range to UTF-16
|
||||
///
|
||||
/// The current global locale will be used by default, unless you
|
||||
/// pass a custom one in the \a locale parameter.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a wide characters range to UTF-16
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromWide(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromLatin1(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-16 characters range to ANSI characters
|
||||
///
|
||||
/// The current global locale will be used by default, unless you
|
||||
/// pass a custom one in the \a locale parameter.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-16 characters range to wide characters
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-16 characters range to UTF-8
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf8(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-16 characters range to UTF-16
|
||||
///
|
||||
/// This functions does nothing more than a direct copy;
|
||||
/// it is defined only to provide the same interface as other
|
||||
/// specializations of the sf::Utf<> template, and allow
|
||||
/// generic code to be written on top of it.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf16(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-16 characters range to UTF-32
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf32(In begin, In end, Out output);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of the Utf template for UTF-32
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
class Utf<32>
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Decode a single UTF-32 character
|
||||
///
|
||||
/// Decoding a character means finding its unique 32-bits
|
||||
/// code (called the codepoint) in the Unicode standard.
|
||||
/// For UTF-32, the character value is the same as the codepoint.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Codepoint of the decoded UTF-32 character
|
||||
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Encode a single UTF-32 character
|
||||
///
|
||||
/// Encoding a character means converting a unique 32-bits
|
||||
/// code (called the codepoint) in the target encoding, UTF-32.
|
||||
/// For UTF-32, the codepoint is the same as the character value.
|
||||
///
|
||||
/// \param input Codepoint to encode as UTF-32
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
static Out encode(Uint32 input, Out output, Uint32 replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Advance to the next UTF-32 character
|
||||
///
|
||||
/// This function is trivial for UTF-32, which can store
|
||||
/// every character in a single storage element.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static In next(In begin, In end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Count the number of characters of a UTF-32 sequence
|
||||
///
|
||||
/// This function is trivial for UTF-32, which can store
|
||||
/// every character in a single storage element.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
///
|
||||
/// \return Iterator pointing to one past the last read element of the input sequence
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static std::size_t count(In begin, In end);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an ANSI characters range to UTF-32
|
||||
///
|
||||
/// The current global locale will be used by default, unless you
|
||||
/// pass a custom one in the \a locale parameter.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a wide characters range to UTF-32
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromWide(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out fromLatin1(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-32 characters range to ANSI characters
|
||||
///
|
||||
/// The current global locale will be used by default, unless you
|
||||
/// pass a custom one in the \a locale parameter.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-32 characters range to wide characters
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-32 characters range to UTF-8
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf8(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-32 characters range to UTF-16
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf16(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a UTF-32 characters range to UTF-32
|
||||
///
|
||||
/// This functions does nothing more than a direct copy;
|
||||
/// it is defined only to provide the same interface as other
|
||||
/// specializations of the sf::Utf<> template, and allow
|
||||
/// generic code to be written on top of it.
|
||||
///
|
||||
/// \param begin Iterator pointing to the beginning of the input sequence
|
||||
/// \param end Iterator pointing to the end of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
static Out toUtf32(In begin, In end, Out output);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Decode a single ANSI character to UTF-32
|
||||
///
|
||||
/// This function does not exist in other specializations
|
||||
/// of sf::Utf<>, it is defined for convenience (it is used by
|
||||
/// several other conversion functions).
|
||||
///
|
||||
/// \param input Input ANSI character
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Converted character
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static Uint32 decodeAnsi(In input, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Decode a single wide character to UTF-32
|
||||
///
|
||||
/// This function does not exist in other specializations
|
||||
/// of sf::Utf<>, it is defined for convenience (it is used by
|
||||
/// several other conversion functions).
|
||||
///
|
||||
/// \param input Input wide character
|
||||
///
|
||||
/// \return Converted character
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
static Uint32 decodeWide(In input);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Encode a single UTF-32 character to ANSI
|
||||
///
|
||||
/// This function does not exist in other specializations
|
||||
/// of sf::Utf<>, it is defined for convenience (it is used by
|
||||
/// several other conversion functions).
|
||||
///
|
||||
/// \param codepoint Iterator pointing to the beginning of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it)
|
||||
/// \param locale Locale to use for conversion
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
static Out encodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Encode a single UTF-32 character to wide
|
||||
///
|
||||
/// This function does not exist in other specializations
|
||||
/// of sf::Utf<>, it is defined for convenience (it is used by
|
||||
/// several other conversion functions).
|
||||
///
|
||||
/// \param codepoint Iterator pointing to the beginning of the input sequence
|
||||
/// \param output Iterator pointing to the beginning of the output sequence
|
||||
/// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it)
|
||||
///
|
||||
/// \return Iterator to the end of the output sequence which has been written
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
static Out encodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0);
|
||||
};
|
||||
|
||||
#include <SFML/System/Utf.inl>
|
||||
|
||||
// Make typedefs to get rid of the template syntax
|
||||
typedef Utf<8> Utf8;
|
||||
typedef Utf<16> Utf16;
|
||||
typedef Utf<32> Utf32;
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_UTF_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Utf
|
||||
/// \ingroup system
|
||||
///
|
||||
/// Utility class providing generic functions for UTF conversions.
|
||||
///
|
||||
/// sf::Utf is a low-level, generic interface for counting, iterating,
|
||||
/// encoding and decoding Unicode characters and strings. It is able
|
||||
/// to handle ANSI, wide, latin-1, UTF-8, UTF-16 and UTF-32 encodings.
|
||||
///
|
||||
/// sf::Utf<X> functions are all static, these classes are not meant to
|
||||
/// be instantiated. All the functions are template, so that you
|
||||
/// can use any character / string type for a given encoding.
|
||||
///
|
||||
/// It has 3 specializations:
|
||||
/// \li sf::Utf<8> (typedef'd to sf::Utf8)
|
||||
/// \li sf::Utf<16> (typedef'd to sf::Utf16)
|
||||
/// \li sf::Utf<32> (typedef'd to sf::Utf32)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -1,752 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// References:
|
||||
//
|
||||
// https://www.unicode.org/
|
||||
// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
|
||||
// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
|
||||
// https://people.w3.org/rishida/scripts/uniview/conversion
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
In Utf<8>::decode(In begin, In end, Uint32& output, Uint32 replacement)
|
||||
{
|
||||
// Some useful precomputed data
|
||||
static const int trailing[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
|
||||
};
|
||||
static const Uint32 offsets[6] =
|
||||
{
|
||||
0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
|
||||
};
|
||||
|
||||
// decode the character
|
||||
int trailingBytes = trailing[static_cast<Uint8>(*begin)];
|
||||
if (begin + trailingBytes < end)
|
||||
{
|
||||
output = 0;
|
||||
switch (trailingBytes)
|
||||
{
|
||||
case 5: output += static_cast<Uint8>(*begin++); output <<= 6;
|
||||
case 4: output += static_cast<Uint8>(*begin++); output <<= 6;
|
||||
case 3: output += static_cast<Uint8>(*begin++); output <<= 6;
|
||||
case 2: output += static_cast<Uint8>(*begin++); output <<= 6;
|
||||
case 1: output += static_cast<Uint8>(*begin++); output <<= 6;
|
||||
case 0: output += static_cast<Uint8>(*begin++);
|
||||
}
|
||||
output -= offsets[trailingBytes];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Incomplete character
|
||||
begin = end;
|
||||
output = replacement;
|
||||
}
|
||||
|
||||
return begin;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
Out Utf<8>::encode(Uint32 input, Out output, Uint8 replacement)
|
||||
{
|
||||
// Some useful precomputed data
|
||||
static const Uint8 firstBytes[7] =
|
||||
{
|
||||
0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
|
||||
};
|
||||
|
||||
// encode the character
|
||||
if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
|
||||
{
|
||||
// Invalid character
|
||||
if (replacement)
|
||||
*output++ = replacement;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Valid character
|
||||
|
||||
// Get the number of bytes to write
|
||||
std::size_t bytestoWrite = 1;
|
||||
if (input < 0x80) bytestoWrite = 1;
|
||||
else if (input < 0x800) bytestoWrite = 2;
|
||||
else if (input < 0x10000) bytestoWrite = 3;
|
||||
else if (input <= 0x0010FFFF) bytestoWrite = 4;
|
||||
|
||||
// Extract the bytes to write
|
||||
Uint8 bytes[4];
|
||||
switch (bytestoWrite)
|
||||
{
|
||||
case 4: bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
|
||||
case 3: bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
|
||||
case 2: bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
|
||||
case 1: bytes[0] = static_cast<Uint8> (input | firstBytes[bytestoWrite]);
|
||||
}
|
||||
|
||||
// Add them to the output
|
||||
output = std::copy(bytes, bytes + bytestoWrite, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
In Utf<8>::next(In begin, In end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
return decode(begin, end, codepoint);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
std::size_t Utf<8>::count(In begin, In end)
|
||||
{
|
||||
std::size_t length = 0;
|
||||
while (begin < end)
|
||||
{
|
||||
begin = next(begin, end);
|
||||
++length;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale);
|
||||
output = encode(codepoint, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::fromWide(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint = Utf<32>::decodeWide(*begin++);
|
||||
output = encode(codepoint, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::fromLatin1(In begin, In end, Out output)
|
||||
{
|
||||
// Latin-1 is directly compatible with Unicode encodings,
|
||||
// and can thus be treated as (a sub-range of) UTF-32
|
||||
while (begin < end)
|
||||
output = encode(*begin++, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::toWide(In begin, In end, Out output, wchar_t replacement)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
output = Utf<32>::encodeWide(codepoint, output, replacement);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::toLatin1(In begin, In end, Out output, char replacement)
|
||||
{
|
||||
// Latin-1 is directly compatible with Unicode encodings,
|
||||
// and can thus be treated as (a sub-range of) UTF-32
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
*output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::toUtf8(In begin, In end, Out output)
|
||||
{
|
||||
return std::copy(begin, end, output);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::toUtf16(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
output = Utf<16>::encode(codepoint, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<8>::toUtf32(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
*output++ = codepoint;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
In Utf<16>::decode(In begin, In end, Uint32& output, Uint32 replacement)
|
||||
{
|
||||
Uint16 first = *begin++;
|
||||
|
||||
// If it's a surrogate pair, first convert to a single UTF-32 character
|
||||
if ((first >= 0xD800) && (first <= 0xDBFF))
|
||||
{
|
||||
if (begin < end)
|
||||
{
|
||||
Uint32 second = *begin++;
|
||||
if ((second >= 0xDC00) && (second <= 0xDFFF))
|
||||
{
|
||||
// The second element is valid: convert the two elements to a UTF-32 character
|
||||
output = static_cast<Uint32>(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid character
|
||||
output = replacement;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid character
|
||||
begin = end;
|
||||
output = replacement;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can make a direct copy
|
||||
output = first;
|
||||
}
|
||||
|
||||
return begin;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
Out Utf<16>::encode(Uint32 input, Out output, Uint16 replacement)
|
||||
{
|
||||
if (input <= 0xFFFF)
|
||||
{
|
||||
// The character can be copied directly, we just need to check if it's in the valid range
|
||||
if ((input >= 0xD800) && (input <= 0xDFFF))
|
||||
{
|
||||
// Invalid character (this range is reserved)
|
||||
if (replacement)
|
||||
*output++ = replacement;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Valid character directly convertible to a single UTF-16 character
|
||||
*output++ = static_cast<Uint16>(input);
|
||||
}
|
||||
}
|
||||
else if (input > 0x0010FFFF)
|
||||
{
|
||||
// Invalid character (greater than the maximum Unicode value)
|
||||
if (replacement)
|
||||
*output++ = replacement;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The input character will be converted to two UTF-16 elements
|
||||
input -= 0x0010000;
|
||||
*output++ = static_cast<Uint16>((input >> 10) + 0xD800);
|
||||
*output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
In Utf<16>::next(In begin, In end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
return decode(begin, end, codepoint);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
std::size_t Utf<16>::count(In begin, In end)
|
||||
{
|
||||
std::size_t length = 0;
|
||||
while (begin < end)
|
||||
{
|
||||
begin = next(begin, end);
|
||||
++length;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale);
|
||||
output = encode(codepoint, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::fromWide(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint = Utf<32>::decodeWide(*begin++);
|
||||
output = encode(codepoint, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::fromLatin1(In begin, In end, Out output)
|
||||
{
|
||||
// Latin-1 is directly compatible with Unicode encodings,
|
||||
// and can thus be treated as (a sub-range of) UTF-32
|
||||
return std::copy(begin, end, output);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::toWide(In begin, In end, Out output, wchar_t replacement)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
output = Utf<32>::encodeWide(codepoint, output, replacement);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::toLatin1(In begin, In end, Out output, char replacement)
|
||||
{
|
||||
// Latin-1 is directly compatible with Unicode encodings,
|
||||
// and can thus be treated as (a sub-range of) UTF-32
|
||||
while (begin < end)
|
||||
{
|
||||
*output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
|
||||
begin++;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::toUtf8(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
output = Utf<8>::encode(codepoint, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::toUtf16(In begin, In end, Out output)
|
||||
{
|
||||
return std::copy(begin, end, output);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<16>::toUtf32(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
{
|
||||
Uint32 codepoint;
|
||||
begin = decode(begin, end, codepoint);
|
||||
*output++ = codepoint;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
In Utf<32>::decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/)
|
||||
{
|
||||
output = *begin++;
|
||||
return begin;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
Out Utf<32>::encode(Uint32 input, Out output, Uint32 /*replacement*/)
|
||||
{
|
||||
*output++ = input;
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
In Utf<32>::next(In begin, In /*end*/)
|
||||
{
|
||||
return ++begin;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
std::size_t Utf<32>::count(In begin, In end)
|
||||
{
|
||||
return begin - end;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
|
||||
{
|
||||
while (begin < end)
|
||||
*output++ = decodeAnsi(*begin++, locale);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::fromWide(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
*output++ = decodeWide(*begin++);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::fromLatin1(In begin, In end, Out output)
|
||||
{
|
||||
// Latin-1 is directly compatible with Unicode encodings,
|
||||
// and can thus be treated as (a sub-range of) UTF-32
|
||||
return std::copy(begin, end, output);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
|
||||
{
|
||||
while (begin < end)
|
||||
output = encodeAnsi(*begin++, output, replacement, locale);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement)
|
||||
{
|
||||
while (begin < end)
|
||||
output = encodeWide(*begin++, output, replacement);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::toLatin1(In begin, In end, Out output, char replacement)
|
||||
{
|
||||
// Latin-1 is directly compatible with Unicode encodings,
|
||||
// and can thus be treated as (a sub-range of) UTF-32
|
||||
while (begin < end)
|
||||
{
|
||||
*output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
|
||||
begin++;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::toUtf8(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
output = Utf<8>::encode(*begin++, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::toUtf16(In begin, In end, Out output)
|
||||
{
|
||||
while (begin < end)
|
||||
output = Utf<16>::encode(*begin++, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In, typename Out>
|
||||
Out Utf<32>::toUtf32(In begin, In end, Out output)
|
||||
{
|
||||
return std::copy(begin, end, output);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
Uint32 Utf<32>::decodeAnsi(In input, const std::locale& locale)
|
||||
{
|
||||
// On Windows, GCC's standard library (glibc++) has almost
|
||||
// no support for Unicode stuff. As a consequence, in this
|
||||
// context we can only use the default locale and ignore
|
||||
// the one passed as parameter.
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
|
||||
(defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
|
||||
!(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
|
||||
|
||||
(void)locale; // to avoid warnings
|
||||
|
||||
wchar_t character = 0;
|
||||
mbtowc(&character, &input, 1);
|
||||
return static_cast<Uint32>(character);
|
||||
|
||||
#else
|
||||
|
||||
// Get the facet of the locale which deals with character conversion
|
||||
const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
|
||||
|
||||
// Use the facet to convert each character of the input string
|
||||
return static_cast<Uint32>(facet.widen(input));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename In>
|
||||
Uint32 Utf<32>::decodeWide(In input)
|
||||
{
|
||||
// The encoding of wide characters is not well defined and is left to the system;
|
||||
// however we can safely assume that it is UCS-2 on Windows and
|
||||
// UCS-4 on Unix systems.
|
||||
// In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4,
|
||||
// and UCS-4 *is* UTF-32).
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
Out Utf<32>::encodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale)
|
||||
{
|
||||
// On Windows, gcc's standard library (glibc++) has almost
|
||||
// no support for Unicode stuff. As a consequence, in this
|
||||
// context we can only use the default locale and ignore
|
||||
// the one passed as parameter.
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
|
||||
(defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
|
||||
!(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
|
||||
|
||||
(void)locale; // to avoid warnings
|
||||
|
||||
char character = 0;
|
||||
if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0)
|
||||
*output++ = character;
|
||||
else if (replacement)
|
||||
*output++ = replacement;
|
||||
|
||||
return output;
|
||||
|
||||
#else
|
||||
|
||||
// Get the facet of the locale which deals with character conversion
|
||||
const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
|
||||
|
||||
// Use the facet to convert each character of the input string
|
||||
*output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement);
|
||||
|
||||
return output;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename Out>
|
||||
Out Utf<32>::encodeWide(Uint32 codepoint, Out output, wchar_t replacement)
|
||||
{
|
||||
// The encoding of wide characters is not well defined and is left to the system;
|
||||
// however we can safely assume that it is UCS-2 on Windows and
|
||||
// UCS-4 on Unix systems.
|
||||
// For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4).
|
||||
// For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32).
|
||||
|
||||
switch (sizeof(wchar_t))
|
||||
{
|
||||
case 4:
|
||||
{
|
||||
*output++ = static_cast<wchar_t>(codepoint);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF)))
|
||||
{
|
||||
*output++ = static_cast<wchar_t>(codepoint);
|
||||
}
|
||||
else if (replacement)
|
||||
{
|
||||
*output++ = replacement;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
|
@ -1,415 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
|
||||
{
|
||||
setMethod(method);
|
||||
setUri(uri);
|
||||
setHttpVersion(1, 0);
|
||||
setBody(body);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setField(const std::string& field, const std::string& value)
|
||||
{
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setMethod(Http::Request::Method method)
|
||||
{
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setUri(const std::string& uri)
|
||||
{
|
||||
m_uri = uri;
|
||||
|
||||
// Make sure it starts with a '/'
|
||||
if (m_uri.empty() || (m_uri[0] != '/'))
|
||||
m_uri.insert(0, "/");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
|
||||
{
|
||||
m_majorVersion = major;
|
||||
m_minorVersion = minor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setBody(const std::string& body)
|
||||
{
|
||||
m_body = body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string Http::Request::prepare() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
// Convert the method to its string representation
|
||||
std::string method;
|
||||
switch (m_method)
|
||||
{
|
||||
case Get: method = "GET"; break;
|
||||
case Post: method = "POST"; break;
|
||||
case Head: method = "HEAD"; break;
|
||||
case Put: method = "PUT"; break;
|
||||
case Delete: method = "DELETE"; break;
|
||||
}
|
||||
|
||||
// Write the first line containing the request type
|
||||
out << method << " " << m_uri << " ";
|
||||
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
|
||||
|
||||
// Write fields
|
||||
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
|
||||
{
|
||||
out << i->first << ": " << i->second << "\r\n";
|
||||
}
|
||||
|
||||
// Use an extra \r\n to separate the header from the body
|
||||
out << "\r\n";
|
||||
|
||||
// Add the body
|
||||
out << m_body;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Http::Request::hasField(const std::string& field) const
|
||||
{
|
||||
return m_fields.find(toLower(field)) != m_fields.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Response() :
|
||||
m_status (ConnectionFailed),
|
||||
m_majorVersion(0),
|
||||
m_minorVersion(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Http::Response::getField(const std::string& field) const
|
||||
{
|
||||
FieldTable::const_iterator it = m_fields.find(toLower(field));
|
||||
if (it != m_fields.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const std::string empty = "";
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Status Http::Response::getStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::getMajorHttpVersion() const
|
||||
{
|
||||
return m_majorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::getMinorHttpVersion() const
|
||||
{
|
||||
return m_minorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Http::Response::getBody() const
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::parse(const std::string& data)
|
||||
{
|
||||
std::istringstream in(data);
|
||||
|
||||
// Extract the HTTP version from the first line
|
||||
std::string version;
|
||||
if (in >> version)
|
||||
{
|
||||
if ((version.size() >= 8) && (version[6] == '.') &&
|
||||
(toLower(version.substr(0, 5)) == "http/") &&
|
||||
isdigit(version[5]) && isdigit(version[7]))
|
||||
{
|
||||
m_majorVersion = version[5] - '0';
|
||||
m_minorVersion = version[7] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid HTTP version
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the status code from the first line
|
||||
int status;
|
||||
if (in >> status)
|
||||
{
|
||||
m_status = static_cast<Status>(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid status code
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore the end of the first line
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Parse the other lines, which contain fields, one by one
|
||||
parseFields(in);
|
||||
|
||||
m_body.clear();
|
||||
|
||||
// Determine whether the transfer is chunked
|
||||
if (toLower(getField("transfer-encoding")) != "chunked")
|
||||
{
|
||||
// Not chunked - just read everything at once
|
||||
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chunked - have to read chunk by chunk
|
||||
std::size_t length;
|
||||
|
||||
// Read all chunks, identified by a chunk-size not being 0
|
||||
while (in >> std::hex >> length)
|
||||
{
|
||||
// Drop the rest of the line (chunk-extension)
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Copy the actual content data
|
||||
std::istreambuf_iterator<char> it(in);
|
||||
std::istreambuf_iterator<char> itEnd;
|
||||
for (std::size_t i = 0; ((i < length) && (it != itEnd)); i++)
|
||||
m_body.push_back(*it++);
|
||||
}
|
||||
|
||||
// Drop the rest of the line (chunk-extension)
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Read all trailers (if present)
|
||||
parseFields(in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::parseFields(std::istream &in)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(in, line) && (line.size() > 2))
|
||||
{
|
||||
std::string::size_type pos = line.find(": ");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
// Extract the field name and its value
|
||||
std::string field = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 2);
|
||||
|
||||
// Remove any trailing \r
|
||||
if (!value.empty() && (*value.rbegin() == '\r'))
|
||||
value.erase(value.size() - 1);
|
||||
|
||||
// Add the field
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http() :
|
||||
m_host(),
|
||||
m_port(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http(const std::string& host, unsigned short port)
|
||||
{
|
||||
setHost(host, port);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::setHost(const std::string& host, unsigned short port)
|
||||
{
|
||||
// Check the protocol
|
||||
if (toLower(host.substr(0, 7)) == "http://")
|
||||
{
|
||||
// HTTP protocol
|
||||
m_hostName = host.substr(7);
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
else if (toLower(host.substr(0, 8)) == "https://")
|
||||
{
|
||||
// HTTPS protocol -- unsupported (requires encryption and certificates and stuff...)
|
||||
err() << "HTTPS protocol is not supported by sf::Http" << std::endl;
|
||||
m_hostName = "";
|
||||
m_port = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undefined protocol - use HTTP
|
||||
m_hostName = host;
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
|
||||
// Remove any trailing '/' from the host name
|
||||
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
|
||||
m_hostName.erase(m_hostName.size() - 1);
|
||||
|
||||
m_host = IpAddress(m_hostName);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
|
||||
{
|
||||
// First make sure that the request is valid -- add missing mandatory fields
|
||||
Request toSend(request);
|
||||
if (!toSend.hasField("From"))
|
||||
{
|
||||
toSend.setField("From", "user@sfml-dev.org");
|
||||
}
|
||||
if (!toSend.hasField("User-Agent"))
|
||||
{
|
||||
toSend.setField("User-Agent", "libsfml-network/2.x");
|
||||
}
|
||||
if (!toSend.hasField("Host"))
|
||||
{
|
||||
toSend.setField("Host", m_hostName);
|
||||
}
|
||||
if (!toSend.hasField("Content-Length"))
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << toSend.m_body.size();
|
||||
toSend.setField("Content-Length", out.str());
|
||||
}
|
||||
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
|
||||
{
|
||||
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
|
||||
{
|
||||
toSend.setField("Connection", "close");
|
||||
}
|
||||
|
||||
// Prepare the response
|
||||
Response received;
|
||||
|
||||
// Connect the socket to the host
|
||||
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
|
||||
{
|
||||
// Convert the request to string and send it through the connected socket
|
||||
std::string requestStr = toSend.prepare();
|
||||
|
||||
if (!requestStr.empty())
|
||||
{
|
||||
// Send it through the socket
|
||||
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
|
||||
{
|
||||
// Wait for the server's response
|
||||
std::string receivedStr;
|
||||
std::size_t size = 0;
|
||||
char buffer[1024];
|
||||
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
|
||||
{
|
||||
receivedStr.append(buffer, buffer + size);
|
||||
}
|
||||
|
||||
// Build the Response object from the received data
|
||||
received.parse(receivedStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
m_connection.disconnect();
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,271 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const IpAddress IpAddress::None;
|
||||
const IpAddress IpAddress::Any(0, 0, 0, 0);
|
||||
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
||||
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress() :
|
||||
m_address(0),
|
||||
m_valid (false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const std::string& address) :
|
||||
m_address(0),
|
||||
m_valid (false)
|
||||
{
|
||||
resolve(address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const char* address) :
|
||||
m_address(0),
|
||||
m_valid (false)
|
||||
{
|
||||
resolve(address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
||||
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)),
|
||||
m_valid (true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint32 address) :
|
||||
m_address(htonl(address)),
|
||||
m_valid (true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string IpAddress::toString() const
|
||||
{
|
||||
in_addr address;
|
||||
address.s_addr = m_address;
|
||||
|
||||
return inet_ntoa(address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 IpAddress::toInteger() const
|
||||
{
|
||||
return ntohl(m_address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getLocalAddress()
|
||||
{
|
||||
// The method here is to connect a UDP socket to anyone (here to localhost),
|
||||
// and get the local socket address with the getsockname function.
|
||||
// UDP connection will not send anything to the network, so this function won't cause any overhead.
|
||||
|
||||
IpAddress localAddress;
|
||||
|
||||
// Create the socket
|
||||
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == priv::SocketImpl::invalidSocket())
|
||||
return localAddress;
|
||||
|
||||
// Connect the socket to localhost on any port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
|
||||
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Get the local address of the socket connection
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Close the socket
|
||||
priv::SocketImpl::close(sock);
|
||||
|
||||
// Finally build the IP address
|
||||
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getPublicAddress(Time timeout)
|
||||
{
|
||||
// The trick here is more complicated, because the only way
|
||||
// to get our public IP address is to get it from a distant computer.
|
||||
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
|
||||
// and parse the result to extract our IP address
|
||||
// (not very hard: the web page contains only our IP address).
|
||||
|
||||
Http server("www.sfml-dev.org");
|
||||
Http::Request request("/ip-provider.php", Http::Request::Get);
|
||||
Http::Response page = server.sendRequest(request, timeout);
|
||||
if (page.getStatus() == Http::Response::Ok)
|
||||
return IpAddress(page.getBody());
|
||||
|
||||
// Something failed: return an invalid address
|
||||
return IpAddress();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void IpAddress::resolve(const std::string& address)
|
||||
{
|
||||
m_address = 0;
|
||||
m_valid = false;
|
||||
|
||||
if (address == "255.255.255.255")
|
||||
{
|
||||
// The broadcast address needs to be handled explicitly,
|
||||
// because it is also the value returned by inet_addr on error
|
||||
m_address = INADDR_BROADCAST;
|
||||
m_valid = true;
|
||||
}
|
||||
else if (address == "0.0.0.0")
|
||||
{
|
||||
m_address = INADDR_ANY;
|
||||
m_valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
Uint32 ip = inet_addr(address.c_str());
|
||||
if (ip != INADDR_NONE)
|
||||
{
|
||||
m_address = ip;
|
||||
m_valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a valid address, try to convert it as a host name
|
||||
addrinfo hints;
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
addrinfo* result = NULL;
|
||||
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo(result);
|
||||
m_address = ip;
|
||||
m_valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left < right) && !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return std::make_pair(left.m_valid, left.m_address) < std::make_pair(right.m_valid, right.m_address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::istream& operator >>(std::istream& stream, IpAddress& address)
|
||||
{
|
||||
std::string str;
|
||||
stream >> str;
|
||||
address = IpAddress(str);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
|
||||
{
|
||||
return stream << address.toString();
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,596 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet::Packet() :
|
||||
m_readPos(0),
|
||||
m_sendPos(0),
|
||||
m_isValid(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet::~Packet()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Packet::append(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
if (data && (sizeInBytes > 0))
|
||||
{
|
||||
std::size_t start = m_data.size();
|
||||
m_data.resize(start + sizeInBytes);
|
||||
std::memcpy(&m_data[start], data, sizeInBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Packet::clear()
|
||||
{
|
||||
m_data.clear();
|
||||
m_readPos = 0;
|
||||
m_isValid = true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const void* Packet::getData() const
|
||||
{
|
||||
return !m_data.empty() ? &m_data[0] : NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t Packet::getDataSize() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Packet::endOfPacket() const
|
||||
{
|
||||
return m_readPos >= m_data.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet::operator BoolType() const
|
||||
{
|
||||
return m_isValid ? &Packet::checkSize : NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(bool& data)
|
||||
{
|
||||
Uint8 value;
|
||||
if (*this >> value)
|
||||
data = (value != 0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int8& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = *reinterpret_cast<const Int8*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint8& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = *reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int16& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = ntohs(*reinterpret_cast<const Int16*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint16& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = ntohs(*reinterpret_cast<const Uint16*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int32& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = ntohl(*reinterpret_cast<const Int32*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint32& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = ntohl(*reinterpret_cast<const Uint32*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int64& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
// Since ntohll is not available everywhere, we have to convert
|
||||
// to network byte order (big endian) manually
|
||||
const Uint8* bytes = reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
|
||||
data = (static_cast<Int64>(bytes[0]) << 56) |
|
||||
(static_cast<Int64>(bytes[1]) << 48) |
|
||||
(static_cast<Int64>(bytes[2]) << 40) |
|
||||
(static_cast<Int64>(bytes[3]) << 32) |
|
||||
(static_cast<Int64>(bytes[4]) << 24) |
|
||||
(static_cast<Int64>(bytes[5]) << 16) |
|
||||
(static_cast<Int64>(bytes[6]) << 8) |
|
||||
(static_cast<Int64>(bytes[7]) );
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint64& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
// Since ntohll is not available everywhere, we have to convert
|
||||
// to network byte order (big endian) manually
|
||||
const Uint8* bytes = reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
|
||||
data = (static_cast<Uint64>(bytes[0]) << 56) |
|
||||
(static_cast<Uint64>(bytes[1]) << 48) |
|
||||
(static_cast<Uint64>(bytes[2]) << 40) |
|
||||
(static_cast<Uint64>(bytes[3]) << 32) |
|
||||
(static_cast<Uint64>(bytes[4]) << 24) |
|
||||
(static_cast<Uint64>(bytes[5]) << 16) |
|
||||
(static_cast<Uint64>(bytes[6]) << 8) |
|
||||
(static_cast<Uint64>(bytes[7]) );
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(float& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = *reinterpret_cast<const float*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(double& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
data = *reinterpret_cast<const double*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(char* data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
if ((length > 0) && checkSize(length))
|
||||
{
|
||||
// Then extract characters
|
||||
std::memcpy(data, &m_data[m_readPos], length);
|
||||
data[length] = '\0';
|
||||
|
||||
// Update reading position
|
||||
m_readPos += length;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(std::string& data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
data.clear();
|
||||
if ((length > 0) && checkSize(length))
|
||||
{
|
||||
// Then extract characters
|
||||
data.assign(&m_data[m_readPos], length);
|
||||
|
||||
// Update reading position
|
||||
m_readPos += length;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(wchar_t* data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
if ((length > 0) && checkSize(length * sizeof(Uint32)))
|
||||
{
|
||||
// Then extract characters
|
||||
for (Uint32 i = 0; i < length; ++i)
|
||||
{
|
||||
Uint32 character = 0;
|
||||
*this >> character;
|
||||
data[i] = static_cast<wchar_t>(character);
|
||||
}
|
||||
data[length] = L'\0';
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(std::wstring& data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
data.clear();
|
||||
if ((length > 0) && checkSize(length * sizeof(Uint32)))
|
||||
{
|
||||
// Then extract characters
|
||||
for (Uint32 i = 0; i < length; ++i)
|
||||
{
|
||||
Uint32 character = 0;
|
||||
*this >> character;
|
||||
data += static_cast<wchar_t>(character);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(String& data)
|
||||
{
|
||||
// First extract the string length
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
data.clear();
|
||||
if ((length > 0) && checkSize(length * sizeof(Uint32)))
|
||||
{
|
||||
// Then extract characters
|
||||
for (Uint32 i = 0; i < length; ++i)
|
||||
{
|
||||
Uint32 character = 0;
|
||||
*this >> character;
|
||||
data += character;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(bool data)
|
||||
{
|
||||
*this << static_cast<Uint8>(data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Int8 data)
|
||||
{
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Uint8 data)
|
||||
{
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Int16 data)
|
||||
{
|
||||
Int16 toWrite = htons(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Uint16 data)
|
||||
{
|
||||
Uint16 toWrite = htons(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Int32 data)
|
||||
{
|
||||
Int32 toWrite = htonl(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Uint32 data)
|
||||
{
|
||||
Uint32 toWrite = htonl(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Int64 data)
|
||||
{
|
||||
// Since htonll is not available everywhere, we have to convert
|
||||
// to network byte order (big endian) manually
|
||||
Uint8 toWrite[] =
|
||||
{
|
||||
static_cast<Uint8>((data >> 56) & 0xFF),
|
||||
static_cast<Uint8>((data >> 48) & 0xFF),
|
||||
static_cast<Uint8>((data >> 40) & 0xFF),
|
||||
static_cast<Uint8>((data >> 32) & 0xFF),
|
||||
static_cast<Uint8>((data >> 24) & 0xFF),
|
||||
static_cast<Uint8>((data >> 16) & 0xFF),
|
||||
static_cast<Uint8>((data >> 8) & 0xFF),
|
||||
static_cast<Uint8>((data ) & 0xFF)
|
||||
};
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Uint64 data)
|
||||
{
|
||||
// Since htonll is not available everywhere, we have to convert
|
||||
// to network byte order (big endian) manually
|
||||
Uint8 toWrite[] =
|
||||
{
|
||||
static_cast<Uint8>((data >> 56) & 0xFF),
|
||||
static_cast<Uint8>((data >> 48) & 0xFF),
|
||||
static_cast<Uint8>((data >> 40) & 0xFF),
|
||||
static_cast<Uint8>((data >> 32) & 0xFF),
|
||||
static_cast<Uint8>((data >> 24) & 0xFF),
|
||||
static_cast<Uint8>((data >> 16) & 0xFF),
|
||||
static_cast<Uint8>((data >> 8) & 0xFF),
|
||||
static_cast<Uint8>((data ) & 0xFF)
|
||||
};
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(float data)
|
||||
{
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(double data)
|
||||
{
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const char* data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = static_cast<Uint32>(std::strlen(data));
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
append(data, length * sizeof(char));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const std::string& data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = static_cast<Uint32>(data.size());
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
if (length > 0)
|
||||
append(data.c_str(), length * sizeof(std::string::value_type));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const wchar_t* data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = static_cast<Uint32>(std::wcslen(data));
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
for (const wchar_t* c = data; *c != L'\0'; ++c)
|
||||
*this << static_cast<Uint32>(*c);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const std::wstring& data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = static_cast<Uint32>(data.size());
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
if (length > 0)
|
||||
{
|
||||
for (std::wstring::const_iterator c = data.begin(); c != data.end(); ++c)
|
||||
*this << static_cast<Uint32>(*c);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const String& data)
|
||||
{
|
||||
// First insert the string length
|
||||
Uint32 length = static_cast<Uint32>(data.getSize());
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
if (length > 0)
|
||||
{
|
||||
for (String::ConstIterator c = data.begin(); c != data.end(); ++c)
|
||||
*this << *c;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Packet::checkSize(std::size_t size)
|
||||
{
|
||||
m_isValid = m_isValid && (m_readPos + size <= m_data.size());
|
||||
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const void* Packet::onSend(std::size_t& size)
|
||||
{
|
||||
size = getDataSize();
|
||||
return getData();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Packet::onReceive(const void* data, std::size_t size)
|
||||
{
|
||||
append(data, size);
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,151 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Socket(Type type) :
|
||||
m_type (type),
|
||||
m_socket (priv::SocketImpl::invalidSocket()),
|
||||
m_isBlocking(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::~Socket()
|
||||
{
|
||||
// Close the socket before it gets destructed
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::setBlocking(bool blocking)
|
||||
{
|
||||
// Apply if the socket is already created
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
priv::SocketImpl::setBlocking(m_socket, blocking);
|
||||
|
||||
m_isBlocking = blocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Socket::isBlocking() const
|
||||
{
|
||||
return m_isBlocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle Socket::getHandle() const
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create()
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||
|
||||
if (handle == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
err() << "Failed to create socket" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
create(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create(SocketHandle handle)
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Assign the new handle
|
||||
m_socket = handle;
|
||||
|
||||
// Set the current blocking state
|
||||
setBlocking(m_isBlocking);
|
||||
|
||||
if (m_type == Tcp)
|
||||
{
|
||||
// Disable the Nagle algorithm (i.e. removes buffering of TCP packets)
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"TCP_NODELAY\" ; "
|
||||
<< "all your TCP packets will be buffered" << std::endl;
|
||||
}
|
||||
|
||||
// On Mac OS X, disable the SIGPIPE signal on disconnection
|
||||
#ifdef SFML_SYSTEM_MACOS
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable broadcast by default for UDP sockets
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to enable broadcast on UDP socket" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::close()
|
||||
{
|
||||
// Close the socket
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
priv::SocketImpl::close(m_socket);
|
||||
m_socket = priv::SocketImpl::invalidSocket();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,39 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
|
||||
#else
|
||||
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
|
||||
#endif
|
|
@ -1,205 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/SocketSelector.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SocketSelector::SocketSelectorImpl
|
||||
{
|
||||
fd_set allSockets; ///< Set containing all the sockets handles
|
||||
fd_set socketsReady; ///< Set containing handles of the sockets that are ready
|
||||
int maxSocket; ///< Maximum socket handle
|
||||
int socketCount; ///< Number of socket handles
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector() :
|
||||
m_impl(new SocketSelectorImpl)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector(const SocketSelector& copy) :
|
||||
m_impl(new SocketSelectorImpl(*copy.m_impl))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::~SocketSelector()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::add(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (m_impl->socketCount >= FD_SETSIZE)
|
||||
{
|
||||
err() << "The socket can't be added to the selector because the "
|
||||
<< "selector is full. This is a limitation of your operating "
|
||||
<< "system's FD_SETSIZE setting.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (FD_ISSET(handle, &m_impl->allSockets))
|
||||
return;
|
||||
|
||||
m_impl->socketCount++;
|
||||
|
||||
#else
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
{
|
||||
err() << "The socket can't be added to the selector because its "
|
||||
<< "ID is too high. This is a limitation of your operating "
|
||||
<< "system's FD_SETSIZE setting.";
|
||||
return;
|
||||
}
|
||||
|
||||
// SocketHandle is an int in POSIX
|
||||
m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
|
||||
|
||||
#endif
|
||||
|
||||
FD_SET(handle, &m_impl->allSockets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::remove(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (!FD_ISSET(handle, &m_impl->allSockets))
|
||||
return;
|
||||
|
||||
m_impl->socketCount--;
|
||||
|
||||
#else
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
FD_CLR(handle, &m_impl->allSockets);
|
||||
FD_CLR(handle, &m_impl->socketsReady);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::clear()
|
||||
{
|
||||
FD_ZERO(&m_impl->allSockets);
|
||||
FD_ZERO(&m_impl->socketsReady);
|
||||
|
||||
m_impl->maxSocket = 0;
|
||||
m_impl->socketCount = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::wait(Time timeout)
|
||||
{
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Initialize the set that will contain the sockets that are ready
|
||||
m_impl->socketsReady = m_impl->allSockets;
|
||||
|
||||
// Wait until one of the sockets is ready for reading, or timeout is reached
|
||||
// The first parameter is ignored on Windows
|
||||
int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::isReady(Socket& socket) const
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if !defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
return FD_ISSET(handle, &m_impl->socketsReady) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
|
||||
{
|
||||
SocketSelector temp(right);
|
||||
|
||||
std::swap(m_impl, temp.m_impl);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,131 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/TcpListener.hpp>
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpListener::TcpListener() :
|
||||
Socket(Tcp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpListener::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address)
|
||||
{
|
||||
// Close the socket if it is already bound
|
||||
close();
|
||||
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Check if the address is valid
|
||||
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
|
||||
return Error;
|
||||
|
||||
// Bind the socket to the specified port
|
||||
sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
|
||||
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
|
||||
{
|
||||
// Not likely to happen, but...
|
||||
err() << "Failed to bind listener socket to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Listen to the bound port
|
||||
if (::listen(getHandle(), SOMAXCONN) == -1)
|
||||
{
|
||||
// Oops, socket is deaf
|
||||
err() << "Failed to listen to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpListener::close()
|
||||
{
|
||||
// Simply close the socket
|
||||
Socket::close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpListener::accept(TcpSocket& socket)
|
||||
{
|
||||
// Make sure that we're listening
|
||||
if (getHandle() == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Accept a new connection
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength length = sizeof(address);
|
||||
SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
|
||||
|
||||
// Check for errors
|
||||
if (remote == priv::SocketImpl::invalidSocket())
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Initialize the new connected socket
|
||||
socket.close();
|
||||
socket.create(remote);
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,416 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Define the low-level send/receive flags, which depend on the OS
|
||||
#ifdef SFML_SYSTEM_LINUX
|
||||
const int flags = MSG_NOSIGNAL;
|
||||
#else
|
||||
const int flags = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::TcpSocket() :
|
||||
Socket(Tcp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpSocket::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress TcpSocket::getRemoteAddress() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the remote end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the address
|
||||
return IpAddress::None;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpSocket::getRemotePort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the remote end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
|
||||
{
|
||||
// Disconnect the socket if it is already connected
|
||||
disconnect();
|
||||
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Create the remote address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
if (timeout <= Time::Zero)
|
||||
{
|
||||
// ----- We're not using a timeout: just try to connect -----
|
||||
|
||||
// Connect the socket
|
||||
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Connection succeeded
|
||||
return Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ----- We're using a timeout: we'll need a few tricks to make it work -----
|
||||
|
||||
// Save the previous blocking state
|
||||
bool blocking = isBlocking();
|
||||
|
||||
// Switch to non-blocking to enable our connection timeout
|
||||
if (blocking)
|
||||
setBlocking(false);
|
||||
|
||||
// Try to connect to the remote address
|
||||
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
|
||||
{
|
||||
// We got instantly connected! (it may no happen a lot...)
|
||||
setBlocking(blocking);
|
||||
return Done;
|
||||
}
|
||||
|
||||
// Get the error status
|
||||
Status status = priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// If we were in non-blocking mode, return immediately
|
||||
if (!blocking)
|
||||
return status;
|
||||
|
||||
// Otherwise, wait until something happens to our socket (success, timeout or error)
|
||||
if (status == Socket::NotReady)
|
||||
{
|
||||
// Setup the selector
|
||||
fd_set selector;
|
||||
FD_ZERO(&selector);
|
||||
FD_SET(getHandle(), &selector);
|
||||
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Wait for something to write on our socket (which means that the connection request has returned)
|
||||
if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0)
|
||||
{
|
||||
// At this point the connection may have been either accepted or refused.
|
||||
// To know whether it's a success or a failure, we must check the address of the connected peer
|
||||
if (getRemoteAddress() != IpAddress::None)
|
||||
{
|
||||
// Connection accepted
|
||||
status = Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connection refused
|
||||
status = priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to connect before timeout is over
|
||||
status = priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// Switch back to blocking mode
|
||||
setBlocking(true);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpSocket::disconnect()
|
||||
{
|
||||
// Close the socket
|
||||
close();
|
||||
|
||||
// Reset the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(const void* data, std::size_t size)
|
||||
{
|
||||
if (!isBlocking())
|
||||
err() << "Warning: Partial sends might not be handled properly." << std::endl;
|
||||
|
||||
std::size_t sent;
|
||||
|
||||
return send(data, size, sent);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(const void* data, std::size_t size, std::size_t& sent)
|
||||
{
|
||||
// Check the parameters
|
||||
if (!data || (size == 0))
|
||||
{
|
||||
err() << "Cannot send data over the network (no data to send)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Loop until every byte has been sent
|
||||
int result = 0;
|
||||
for (sent = 0; sent < size; sent += result)
|
||||
{
|
||||
// Send a chunk of data
|
||||
result = ::send(getHandle(), static_cast<const char*>(data) + sent, size - sent, flags);
|
||||
|
||||
// Check for errors
|
||||
if (result < 0)
|
||||
{
|
||||
Status status = priv::SocketImpl::getErrorStatus();
|
||||
|
||||
if ((status == NotReady) && sent)
|
||||
return Partial;
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Receive a chunk of bytes
|
||||
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
|
||||
|
||||
// Check the number of bytes received
|
||||
if (sizeReceived > 0)
|
||||
{
|
||||
received = static_cast<std::size_t>(sizeReceived);
|
||||
return Done;
|
||||
}
|
||||
else if (sizeReceived == 0)
|
||||
{
|
||||
return Socket::Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(Packet& packet)
|
||||
{
|
||||
// TCP is a stream protocol, it doesn't preserve messages boundaries.
|
||||
// This means that we have to send the packet size first, so that the
|
||||
// receiver knows the actual end of the packet in the data stream.
|
||||
|
||||
// We allocate an extra memory block so that the size can be sent
|
||||
// together with the data in a single call. This may seem inefficient,
|
||||
// but it is actually required to avoid partial send, which could cause
|
||||
// data corruption on the receiving end.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// First convert the packet size to network byte order
|
||||
Uint32 packetSize = htonl(static_cast<Uint32>(size));
|
||||
|
||||
// Allocate memory for the data block to send
|
||||
std::vector<char> blockToSend(sizeof(packetSize) + size);
|
||||
|
||||
// Copy the packet size and data into the block to send
|
||||
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
|
||||
if (size > 0)
|
||||
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
|
||||
|
||||
// Send the data block
|
||||
std::size_t sent;
|
||||
Status status = send(&blockToSend[0] + packet.m_sendPos, blockToSend.size() - packet.m_sendPos, sent);
|
||||
|
||||
// In the case of a partial send, record the location to resume from
|
||||
if (status == Partial)
|
||||
{
|
||||
packet.m_sendPos += sent;
|
||||
}
|
||||
else if (status == Done)
|
||||
{
|
||||
packet.m_sendPos = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(Packet& packet)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
packet.clear();
|
||||
|
||||
// We start by getting the size of the incoming packet
|
||||
Uint32 packetSize = 0;
|
||||
std::size_t received = 0;
|
||||
if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
// Loop until we've received the entire size of the packet
|
||||
// (even a 4 byte variable may be received in more than one call)
|
||||
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
|
||||
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
|
||||
m_pendingPacket.SizeReceived += received;
|
||||
|
||||
if (status != Done)
|
||||
return status;
|
||||
}
|
||||
|
||||
// The packet size has been fully received
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The packet size has already been received in a previous call
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
|
||||
// Loop until we receive all the packet data
|
||||
char buffer[1024];
|
||||
while (m_pendingPacket.Data.size() < packetSize)
|
||||
{
|
||||
// Receive a chunk of data
|
||||
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
|
||||
Status status = receive(buffer, sizeToGet, received);
|
||||
if (status != Done)
|
||||
return status;
|
||||
|
||||
// Append it into the packet
|
||||
if (received > 0)
|
||||
{
|
||||
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
|
||||
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
|
||||
std::memcpy(begin, buffer, received);
|
||||
}
|
||||
}
|
||||
|
||||
// We have received all the packet data: we can copy it to the user packet
|
||||
if (!m_pendingPacket.Data.empty())
|
||||
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
|
||||
|
||||
// Clear the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::PendingPacket::PendingPacket() :
|
||||
Size (0),
|
||||
SizeReceived(0),
|
||||
Data ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,200 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/UdpSocket.hpp>
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
UdpSocket::UdpSocket() :
|
||||
Socket (Udp),
|
||||
m_buffer(MaxDatagramSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short UdpSocket::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::bind(unsigned short port, const IpAddress& address)
|
||||
{
|
||||
// Close the socket if it is already bound
|
||||
close();
|
||||
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Check if the address is valid
|
||||
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
|
||||
return Error;
|
||||
|
||||
// Bind the socket
|
||||
sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
|
||||
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
|
||||
{
|
||||
err() << "Failed to bind socket to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void UdpSocket::unbind()
|
||||
{
|
||||
// Simply close the socket
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Make sure that all the data will fit in one datagram
|
||||
if (size > MaxDatagramSize)
|
||||
{
|
||||
err() << "Cannot send data over the network "
|
||||
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Build the target address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
// Send the data (unlike TCP, all the data is always sent in one call)
|
||||
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
remoteAddress = IpAddress();
|
||||
remotePort = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Data that will be filled with the other computer's address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0);
|
||||
|
||||
// Receive a chunk of bytes
|
||||
priv::SocketImpl::AddrLength addressSize = sizeof(address);
|
||||
int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
|
||||
|
||||
// Check for errors
|
||||
if (sizeReceived < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Fill the sender informations
|
||||
received = static_cast<std::size_t>(sizeReceived);
|
||||
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
remotePort = ntohs(address.sin_port);
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
|
||||
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
|
||||
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
|
||||
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
|
||||
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
|
||||
// This also removes the overhead associated to packets -- there's no size to send in addition
|
||||
// to the packet's data.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// Send it
|
||||
return send(data, size, remoteAddress, remotePort);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// See the detailed comment in send(Packet) above.
|
||||
|
||||
// Receive the datagram
|
||||
std::size_t received = 0;
|
||||
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
|
||||
|
||||
// If we received valid data, we can copy it to the user packet
|
||||
packet.clear();
|
||||
if ((status == Done) && (received > 0))
|
||||
packet.onReceive(&m_buffer[0], received);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
|
@ -1,112 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
#if defined(SFML_SYSTEM_MACOS)
|
||||
addr.sin_len = sizeof(addr);
|
||||
#endif
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle SocketImpl::invalidSocket()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
::close(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
int status = fcntl(sock, F_GETFL);
|
||||
if (block)
|
||||
{
|
||||
if (fcntl(sock, F_SETFL, status & ~O_NONBLOCK) == -1)
|
||||
err() << "Failed to set file status flags: " << errno << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fcntl(sock, F_SETFL, status | O_NONBLOCK) == -1)
|
||||
err() << "Failed to set file status flags: " << errno << std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
// The followings are sometimes equal to EWOULDBLOCK,
|
||||
// so we have to make a special case for them in order
|
||||
// to avoid having double values in the switch case
|
||||
if ((errno == EAGAIN) || (errno == EINPROGRESS))
|
||||
return Socket::NotReady;
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EWOULDBLOCK: return Socket::NotReady;
|
||||
case ECONNABORTED: return Socket::Disconnected;
|
||||
case ECONNRESET: return Socket::Disconnected;
|
||||
case ETIMEDOUT: return Socket::Disconnected;
|
||||
case ENETRESET: return Socket::Disconnected;
|
||||
case ENOTCONN: return Socket::Disconnected;
|
||||
case EPIPE: return Socket::Disconnected;
|
||||
default: return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -1,109 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Unix version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef socklen_t AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void close(SocketHandle sock);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a socket as blocking or non-blocking
|
||||
///
|
||||
/// \param sock Handle of the socket
|
||||
/// \param block New blocking state of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void setBlocking(SocketHandle sock, bool block);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
|
@ -1,112 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle SocketImpl::invalidSocket()
|
||||
{
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
u_long blocking = block ? 0 : 1;
|
||||
ioctlsocket(sock, FIONBIO, &blocking);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
case WSAEWOULDBLOCK: return Socket::NotReady;
|
||||
case WSAEALREADY: return Socket::NotReady;
|
||||
case WSAECONNABORTED: return Socket::Disconnected;
|
||||
case WSAECONNRESET: return Socket::Disconnected;
|
||||
case WSAETIMEDOUT: return Socket::Disconnected;
|
||||
case WSAENETRESET: return Socket::Disconnected;
|
||||
case WSAENOTCONN: return Socket::Disconnected;
|
||||
case WSAEISCONN: return Socket::Done; // when connecting a non-blocking socket
|
||||
default: return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Windows needs some initialization and cleanup to get
|
||||
// sockets working properly... so let's create a class that will
|
||||
// do it automatically
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SocketInitializer
|
||||
{
|
||||
SocketInitializer()
|
||||
{
|
||||
WSADATA init;
|
||||
WSAStartup(MAKEWORD(2, 2), &init);
|
||||
}
|
||||
|
||||
~SocketInitializer()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
};
|
||||
|
||||
SocketInitializer globalInitializer;
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -1,112 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef _WIN32_WINDOWS
|
||||
#undef _WIN32_WINDOWS
|
||||
#endif
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINDOWS 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Windows version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef int AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void close(SocketHandle sock);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a socket as blocking or non-blocking
|
||||
///
|
||||
/// \param sock Handle of the socket
|
||||
/// \param block New blocking state of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void setBlocking(SocketHandle sock, bool block);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
|
@ -1,110 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <streambuf>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// This class will be used as the default streambuf of sf::Err,
|
||||
// it outputs to stderr by default (to keep the default behavior)
|
||||
class DefaultErrStreamBuf : public std::streambuf
|
||||
{
|
||||
public:
|
||||
|
||||
DefaultErrStreamBuf()
|
||||
{
|
||||
// Allocate the write buffer
|
||||
static const int size = 64;
|
||||
char* buffer = new char[size];
|
||||
setp(buffer, buffer + size);
|
||||
}
|
||||
|
||||
~DefaultErrStreamBuf()
|
||||
{
|
||||
// Synchronize
|
||||
sync();
|
||||
|
||||
// Delete the write buffer
|
||||
delete[] pbase();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual int overflow(int character)
|
||||
{
|
||||
if ((character != EOF) && (pptr() != epptr()))
|
||||
{
|
||||
// Valid character
|
||||
return sputc(static_cast<char>(character));
|
||||
}
|
||||
else if (character != EOF)
|
||||
{
|
||||
// Not enough space in the buffer: synchronize output and try again
|
||||
sync();
|
||||
return overflow(character);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid character: synchronize output
|
||||
return sync();
|
||||
}
|
||||
}
|
||||
|
||||
virtual int sync()
|
||||
{
|
||||
// Check if there is something into the write buffer
|
||||
if (pbase() != pptr())
|
||||
{
|
||||
// Print the contents of the write buffer into the standard error output
|
||||
std::size_t size = static_cast<int>(pptr() - pbase());
|
||||
fwrite(pbase(), 1, size, stderr);
|
||||
|
||||
// Reset the pointer position to the beginning of the write buffer
|
||||
setp(pbase(), epptr());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& err()
|
||||
{
|
||||
static DefaultErrStreamBuf buffer;
|
||||
static std::ostream stream(&buffer);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
|
@ -1,400 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(char ansiChar, const std::locale& locale)
|
||||
{
|
||||
m_string += Utf32::decodeAnsi(ansiChar, locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(wchar_t wideChar)
|
||||
{
|
||||
m_string += Utf32::decodeWide(wideChar);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(Uint32 utf32Char)
|
||||
{
|
||||
m_string += utf32Char;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const char* ansiString, const std::locale& locale)
|
||||
{
|
||||
if (ansiString)
|
||||
{
|
||||
std::size_t length = strlen(ansiString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::string& ansiString, const std::locale& locale)
|
||||
{
|
||||
m_string.reserve(ansiString.length() + 1);
|
||||
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const wchar_t* wideString)
|
||||
{
|
||||
if (wideString)
|
||||
{
|
||||
std::size_t length = std::wcslen(wideString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::wstring& wideString)
|
||||
{
|
||||
m_string.reserve(wideString.length() + 1);
|
||||
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const Uint32* utf32String)
|
||||
{
|
||||
if (utf32String)
|
||||
m_string = utf32String;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::basic_string<Uint32>& utf32String) :
|
||||
m_string(utf32String)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const String& copy) :
|
||||
m_string(copy.m_string)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::string() const
|
||||
{
|
||||
return toAnsiString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::wstring() const
|
||||
{
|
||||
return toWideString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string String::toAnsiString(const std::locale& locale) const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::string output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::wstring String::toWideString() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::wstring output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint8> String::toUtf8() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::basic_string<Uint8> output;
|
||||
output.reserve(m_string.length());
|
||||
|
||||
// Convert
|
||||
Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint16> String::toUtf16() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::basic_string<Uint16> output;
|
||||
output.reserve(m_string.length());
|
||||
|
||||
// Convert
|
||||
Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint32> String::toUtf32() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator =(const String& right)
|
||||
{
|
||||
m_string = right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator +=(const String& right)
|
||||
{
|
||||
m_string += right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 String::operator [](std::size_t index) const
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32& String::operator [](std::size_t index)
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::clear()
|
||||
{
|
||||
m_string.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::getSize() const
|
||||
{
|
||||
return m_string.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool String::isEmpty() const
|
||||
{
|
||||
return m_string.empty();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::erase(std::size_t position, std::size_t count)
|
||||
{
|
||||
m_string.erase(position, count);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::insert(std::size_t position, const String& str)
|
||||
{
|
||||
m_string.insert(position, str.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::find(const String& str, std::size_t start) const
|
||||
{
|
||||
return m_string.find(str.m_string, start);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::replace(std::size_t position, std::size_t length, const String& replaceWith)
|
||||
{
|
||||
m_string.replace(position, length, replaceWith.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::replace(const String& searchFor, const String& replaceWith)
|
||||
{
|
||||
std::size_t step = replaceWith.getSize();
|
||||
std::size_t len = searchFor.getSize();
|
||||
std::size_t pos = find(searchFor);
|
||||
|
||||
// Replace each occurrence of search
|
||||
while (pos != InvalidPos)
|
||||
{
|
||||
replace(pos, len, replaceWith);
|
||||
pos = find(searchFor, pos + step);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String String::substring(std::size_t position, std::size_t length) const
|
||||
{
|
||||
return m_string.substr(position, length);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint32* String::getData() const
|
||||
{
|
||||
return m_string.c_str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::begin()
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::begin() const
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::end()
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::end() const
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string == right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const String& left, const String& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string < right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const String& left, const String& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const String& left, const String& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const String& left, const String& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String operator +(const String& left, const String& right)
|
||||
{
|
||||
String string = left;
|
||||
string += right;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -1,260 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const Time Time::Zero;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time::Time() :
|
||||
m_microseconds(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float Time::asSeconds() const
|
||||
{
|
||||
return m_microseconds / 1000000.f;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int32 Time::asMilliseconds() const
|
||||
{
|
||||
return static_cast<Int32>(m_microseconds / 1000);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 Time::asMicroseconds() const
|
||||
{
|
||||
return m_microseconds;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time::Time(Int64 microseconds) :
|
||||
m_microseconds(microseconds)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time seconds(float amount)
|
||||
{
|
||||
return Time(static_cast<Int64>(amount * 1000000));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time milliseconds(Int32 amount)
|
||||
{
|
||||
return Time(static_cast<Int64>(amount) * 1000);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time microseconds(Int64 amount)
|
||||
{
|
||||
return Time(amount);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() == right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() != right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() < right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() > right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() <= right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() >= right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator -(Time right)
|
||||
{
|
||||
return microseconds(-right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator +(Time left, Time right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() + right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator +=(Time& left, Time right)
|
||||
{
|
||||
return left = left + right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator -(Time left, Time right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() - right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator -=(Time& left, Time right)
|
||||
{
|
||||
return left = left - right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(Time left, float right)
|
||||
{
|
||||
return seconds(left.asSeconds() * right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(Time left, Int64 right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() * right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(float left, Time right)
|
||||
{
|
||||
return right * left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(Int64 left, Time right)
|
||||
{
|
||||
return right * left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator *=(Time& left, float right)
|
||||
{
|
||||
return left = left * right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator *=(Time& left, Int64 right)
|
||||
{
|
||||
return left = left * right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator /(Time left, float right)
|
||||
{
|
||||
return seconds(left.asSeconds() / right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator /(Time left, Int64 right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() / right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator /=(Time& left, float right)
|
||||
{
|
||||
return left = left / right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator /=(Time& left, Int64 right)
|
||||
{
|
||||
return left = left / right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float operator /(Time left, Time right)
|
||||
{
|
||||
return left.asSeconds() / right.asSeconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator %(Time left, Time right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() % right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator %=(Time& left, Time right)
|
||||
{
|
||||
return left = left % right;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -23,7 +23,7 @@ sf::Packet& operator>>(sf::Packet& packet, Common::BigEndianValue<u32>& data)
|
|||
|
||||
sf::Packet& operator>>(sf::Packet& packet, Common::BigEndianValue<u64>& data)
|
||||
{
|
||||
sf::Uint64 tmp;
|
||||
u64 tmp;
|
||||
packet >> tmp;
|
||||
data = tmp;
|
||||
return packet;
|
||||
|
@ -35,7 +35,7 @@ namespace Common
|
|||
// so we have this for cleaner code.
|
||||
u64 PacketReadU64(sf::Packet& packet)
|
||||
{
|
||||
sf::Uint64 value;
|
||||
u64 value;
|
||||
packet >> value;
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include "Core/HW/EXI/BBA/BuiltIn.h"
|
||||
|
||||
#include <bit>
|
||||
#include <optional>
|
||||
#include "SFML/Network/IpAddress.hpp"
|
||||
#include "SFML/Network/Socket.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2ipdef.h>
|
||||
|
@ -81,8 +84,9 @@ bool CEXIETHERNET::BuiltInBBAInterface::Activate()
|
|||
// Workaround to get the host IP (might not be accurate)
|
||||
// TODO: Fix the JNI crash and use GetSystemDefaultInterface()
|
||||
// - https://pastebin.com/BFpmnxby (see https://dolp.in/pr10920)
|
||||
const u32 ip = m_local_ip.empty() ? sf::IpAddress::getLocalAddress().toInteger() :
|
||||
sf::IpAddress(m_local_ip).toInteger();
|
||||
const u32 ip = sf::IpAddress::resolve(m_local_ip)
|
||||
.value_or(sf::IpAddress::getLocalAddress().value_or(sf::IpAddress::Any))
|
||||
.toInteger();
|
||||
m_current_ip = htonl(ip);
|
||||
m_current_mac = Common::BitCastPtr<Common::MACAddress>(&m_eth_ref->mBbaMem[BBA_NAFR_PAR0]);
|
||||
m_arp_table[m_current_ip] = m_current_mac;
|
||||
|
@ -92,7 +96,7 @@ bool CEXIETHERNET::BuiltInBBAInterface::Activate()
|
|||
|
||||
m_network_ref.Clear();
|
||||
|
||||
m_upnp_httpd.listen(Common::SSDP_PORT, sf::IpAddress(ip));
|
||||
(void)m_upnp_httpd.listen(Common::SSDP_PORT, sf::IpAddress(ip));
|
||||
m_upnp_httpd.setBlocking(false);
|
||||
|
||||
return RecvInit();
|
||||
|
@ -256,11 +260,12 @@ CEXIETHERNET::BuiltInBBAInterface::TryGetDataFromSocket(StackRef* ref)
|
|||
case IPPROTO_UDP:
|
||||
{
|
||||
std::array<u8, MAX_UDP_LENGTH> buffer;
|
||||
ref->udp_socket.receive(buffer.data(), MAX_UDP_LENGTH, datasize, ref->target, remote_port);
|
||||
std::optional<sf::IpAddress> target;
|
||||
(void)ref->udp_socket.receive(buffer.data(), MAX_UDP_LENGTH, datasize, target, remote_port);
|
||||
if (datasize > 0)
|
||||
{
|
||||
ref->from.sin_port = htons(remote_port);
|
||||
const u32 remote_ip = htonl(ref->target.toInteger());
|
||||
const u32 remote_ip = htonl(target->toInteger());
|
||||
ref->from.sin_addr.s_addr = remote_ip;
|
||||
ref->my_mac = ResolveAddress(remote_ip);
|
||||
const std::vector<u8> udp_data(buffer.begin(), buffer.begin() + datasize);
|
||||
|
@ -325,7 +330,7 @@ CEXIETHERNET::BuiltInBBAInterface::TryGetDataFromSocket(StackRef* ref)
|
|||
}
|
||||
if (GetTickCountStd() - ref->delay > 3000)
|
||||
{
|
||||
if (st == sf::Socket::Disconnected || st == sf::Socket::Error)
|
||||
if (st == sf::Socket::Status::Disconnected || st == sf::Socket::Status::Error)
|
||||
{
|
||||
ref->ip = 0;
|
||||
ref->tcp_socket.disconnect();
|
||||
|
@ -341,7 +346,6 @@ CEXIETHERNET::BuiltInBBAInterface::TryGetDataFromSocket(StackRef* ref)
|
|||
void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket& packet)
|
||||
{
|
||||
const auto& [hwdata, ip_header, tcp_header, ip_options, tcp_options, data] = packet;
|
||||
sf::IpAddress target;
|
||||
StackRef* ref = m_network_ref.GetTCPSlot(tcp_header.source_port, tcp_header.destination_port,
|
||||
std::bit_cast<u32>(ip_header.destination_addr));
|
||||
const u16 flags = ntohs(tcp_header.properties) & 0xfff;
|
||||
|
@ -354,7 +358,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket&
|
|||
WriteToQueue(BuildFINFrame(ref));
|
||||
ref->ip = 0;
|
||||
if (!data.empty())
|
||||
ref->tcp_socket.send(data.data(), data.size());
|
||||
(void)ref->tcp_socket.send(data.data(), data.size());
|
||||
ref->tcp_socket.disconnect();
|
||||
}
|
||||
else if (flags == (TCP_FLAG_SIN | TCP_FLAG_ACK))
|
||||
|
@ -395,7 +399,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket&
|
|||
ref->ready = false;
|
||||
ref->ip = std::bit_cast<u32>(ip_header.destination_addr);
|
||||
|
||||
target = sf::IpAddress(ntohl(destination_ip));
|
||||
sf::IpAddress target = sf::IpAddress(ntohl(destination_ip));
|
||||
ref->tcp_socket.Connect(target, ntohs(tcp_header.destination_port), m_current_ip);
|
||||
}
|
||||
else
|
||||
|
@ -414,7 +418,7 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleTCPFrame(const Common::TCPPacket&
|
|||
if (static_cast<int>(this_seq - ref->ack_num) >= 0 &&
|
||||
data.size() >= static_cast<std::size_t>(size))
|
||||
{
|
||||
ref->tcp_socket.send(data.data(), size);
|
||||
(void)ref->tcp_socket.send(data.data(), size);
|
||||
ref->ack_num += size;
|
||||
}
|
||||
|
||||
|
@ -476,7 +480,7 @@ void CEXIETHERNET::BuiltInBBAInterface::InitUDPPort(u16 port)
|
|||
ref->to.sin_addr.s_addr = m_current_ip;
|
||||
ref->to.sin_port = htons(port);
|
||||
ref->udp_socket.setBlocking(false);
|
||||
if (ref->udp_socket.Bind(port, m_current_ip) != sf::Socket::Done)
|
||||
if (ref->udp_socket.Bind(port, m_current_ip) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Couldn't open UDP socket");
|
||||
PanicAlertFmt("Could't open port {:x}, this game might not work proprely in LAN mode.", port);
|
||||
|
@ -487,7 +491,7 @@ void CEXIETHERNET::BuiltInBBAInterface::InitUDPPort(u16 port)
|
|||
void CEXIETHERNET::BuiltInBBAInterface::HandleUDPFrame(const Common::UDPPacket& packet)
|
||||
{
|
||||
const auto& [hwdata, ip_header, udp_header, ip_options, data] = packet;
|
||||
sf::IpAddress target;
|
||||
sf::IpAddress target = sf::IpAddress::Any;
|
||||
const u32 destination_addr = ip_header.destination_addr == Common::IP_ADDR_ANY ?
|
||||
m_router_ip : // dns request
|
||||
std::bit_cast<u32>(ip_header.destination_addr);
|
||||
|
@ -506,12 +510,13 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleUDPFrame(const Common::UDPPacket&
|
|||
ref->to.sin_addr.s_addr = std::bit_cast<u32>(ip_header.source_addr);
|
||||
ref->to.sin_port = udp_header.source_port;
|
||||
ref->udp_socket.setBlocking(false);
|
||||
if (ref->udp_socket.Bind(ntohs(udp_header.source_port), m_current_ip) != sf::Socket::Done)
|
||||
if (ref->udp_socket.Bind(ntohs(udp_header.source_port), m_current_ip) !=
|
||||
sf::Socket::Status::Done)
|
||||
{
|
||||
PanicAlertFmt(
|
||||
"Port {:x} is already in use, this game might not work as intented in LAN Mode.",
|
||||
htons(udp_header.source_port));
|
||||
if (ref->udp_socket.Bind(sf::Socket::AnyPort, m_current_ip) != sf::Socket::Done)
|
||||
if (ref->udp_socket.Bind(sf::Socket::AnyPort, m_current_ip) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Couldn't open UDP socket");
|
||||
return;
|
||||
|
@ -529,16 +534,18 @@ void CEXIETHERNET::BuiltInBBAInterface::HandleUDPFrame(const Common::UDPPacket&
|
|||
}
|
||||
}
|
||||
if (ntohs(udp_header.destination_port) == 53)
|
||||
target = sf::IpAddress(m_dns_ip.c_str()); // dns server ip
|
||||
// DNS server IP
|
||||
target = sf::IpAddress::resolve(m_dns_ip.c_str()).value_or(sf::IpAddress::Any);
|
||||
else
|
||||
target = sf::IpAddress(ntohl(std::bit_cast<u32>(ip_header.destination_addr)));
|
||||
ref->udp_socket.send(data.data(), data.size(), target, ntohs(udp_header.destination_port));
|
||||
|
||||
(void)ref->udp_socket.send(data.data(), data.size(), target, ntohs(udp_header.destination_port));
|
||||
}
|
||||
|
||||
void CEXIETHERNET::BuiltInBBAInterface::HandleUPnPClient()
|
||||
{
|
||||
StackRef* ref = m_network_ref.GetAvailableSlot(0);
|
||||
if (ref == nullptr || m_upnp_httpd.accept(ref->tcp_socket) != sf::Socket::Done)
|
||||
if (ref == nullptr || m_upnp_httpd.accept(ref->tcp_socket) != sf::Socket::Status::Done)
|
||||
return;
|
||||
|
||||
if (ref->tcp_socket.GetPeerName(&ref->from) != sf::Socket::Status::Done ||
|
||||
|
@ -795,7 +802,7 @@ sf::Socket::Status BbaTcpSocket::Connect(const sf::IpAddress& dest, u16 port, u3
|
|||
addr.sin_addr.s_addr = net_ip;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
::bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
|
||||
(void)::bind(getNativeHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
|
||||
m_connecting_state = ConnectingState::Connecting;
|
||||
return this->connect(dest, port);
|
||||
}
|
||||
|
@ -803,7 +810,7 @@ sf::Socket::Status BbaTcpSocket::Connect(const sf::IpAddress& dest, u16 port, u3
|
|||
sf::Socket::Status BbaTcpSocket::GetPeerName(sockaddr_in* addr) const
|
||||
{
|
||||
socklen_t size = sizeof(*addr);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(addr), &size) == -1)
|
||||
if (getpeername(getNativeHandle(), reinterpret_cast<sockaddr*>(addr), &size) == -1)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "getpeername failed: {}", Common::StrNetworkError());
|
||||
return sf::Socket::Status::Error;
|
||||
|
@ -814,7 +821,7 @@ sf::Socket::Status BbaTcpSocket::GetPeerName(sockaddr_in* addr) const
|
|||
sf::Socket::Status BbaTcpSocket::GetSockName(sockaddr_in* addr) const
|
||||
{
|
||||
socklen_t size = sizeof(*addr);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(addr), &size) == -1)
|
||||
if (getsockname(getNativeHandle(), reinterpret_cast<sockaddr*>(addr), &size) == -1)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "getsockname failed: {}", Common::StrNetworkError());
|
||||
return sf::Socket::Status::Error;
|
||||
|
@ -829,7 +836,7 @@ BbaTcpSocket::ConnectingState BbaTcpSocket::Connected(StackRef* ref)
|
|||
{
|
||||
case ConnectingState::Connecting:
|
||||
{
|
||||
const int fd = getHandle();
|
||||
const int fd = getNativeHandle();
|
||||
const s32 nfds = fd + 1;
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
|
@ -914,20 +921,20 @@ sf::Socket::Status BbaUdpSocket::Bind(u16 port, u32 net_ip)
|
|||
// Handle SSDP multicast
|
||||
create();
|
||||
const int on = 1;
|
||||
if (setsockopt(getHandle(), SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&on),
|
||||
if (setsockopt(getNativeHandle(), SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&on),
|
||||
sizeof(on)) != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "setsockopt failed to reuse SSDP address: {}", Common::StrNetworkError());
|
||||
}
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(getHandle(), SOL_SOCKET, SO_REUSEPORT, reinterpret_cast<const char*>(&on),
|
||||
if (setsockopt(getNativeHandle(), SOL_SOCKET, SO_REUSEPORT, reinterpret_cast<const char*>(&on),
|
||||
sizeof(on)) != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "setsockopt failed to reuse SSDP port: {}", Common::StrNetworkError());
|
||||
}
|
||||
#endif
|
||||
if (const char loop = 1;
|
||||
setsockopt(getHandle(), IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != 0)
|
||||
setsockopt(getNativeHandle(), IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "setsockopt failed to set SSDP loopback: {}", Common::StrNetworkError());
|
||||
}
|
||||
|
@ -938,11 +945,11 @@ sf::Socket::Status BbaUdpSocket::Bind(u16 port, u32 net_ip)
|
|||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(Common::SSDP_PORT);
|
||||
Common::ScopeGuard error_guard([this] { close(); });
|
||||
if (::bind(getHandle(), reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)) != 0)
|
||||
if (::bind(getNativeHandle(), reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)) != 0)
|
||||
{
|
||||
WARN_LOG_FMT(SP1, "bind with SSDP port and INADDR_ANY failed: {}", Common::StrNetworkError());
|
||||
addr.sin_addr.s_addr = net_ip;
|
||||
if (::bind(getHandle(), reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)) != 0)
|
||||
if (::bind(getNativeHandle(), reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)) != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "bind with SSDP port failed: {}", Common::StrNetworkError());
|
||||
return sf::Socket::Status::Error;
|
||||
|
@ -955,7 +962,7 @@ sf::Socket::Status BbaUdpSocket::Bind(u16 port, u32 net_ip)
|
|||
INFO_LOG_FMT(SP1, "SSDP bind successful");
|
||||
|
||||
// Bind to the right interface
|
||||
if (setsockopt(getHandle(), IPPROTO_IP, IP_MULTICAST_IF,
|
||||
if (setsockopt(getNativeHandle(), IPPROTO_IP, IP_MULTICAST_IF,
|
||||
reinterpret_cast<const char*>(&addr.sin_addr), sizeof(addr.sin_addr)) != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "setsockopt failed to bind to the network interface: {}",
|
||||
|
@ -968,8 +975,8 @@ sf::Socket::Status BbaUdpSocket::Bind(u16 port, u32 net_ip)
|
|||
ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = std::bit_cast<u32>(Common::IP_ADDR_SSDP);
|
||||
mreq.imr_interface.s_addr = net_ip;
|
||||
if (setsockopt(getHandle(), IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<const char*>(&mreq),
|
||||
sizeof(mreq)) != 0)
|
||||
if (setsockopt(getNativeHandle(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
reinterpret_cast<const char*>(&mreq), sizeof(mreq)) != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "setsockopt failed to subscribe to SSDP multicast group: {}",
|
||||
Common::StrNetworkError());
|
||||
|
|
|
@ -76,7 +76,6 @@ struct StackRef
|
|||
u16 local;
|
||||
u16 remote;
|
||||
u16 type;
|
||||
sf::IpAddress target;
|
||||
u32 seq_num;
|
||||
u32 ack_num;
|
||||
u32 ack_base;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright 2020 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <optional>
|
||||
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
|
||||
#include "SFML/Network/IpAddress.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
@ -67,13 +69,14 @@ static int ConnectToDestination(const std::string& destination)
|
|||
}
|
||||
|
||||
sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss);
|
||||
const sf::IpAddress dest_ip(destination.substr(0, colon_offset));
|
||||
if (dest_ip == sf::IpAddress::None || dest_ip == sf::IpAddress::Any)
|
||||
const std::optional<sf::IpAddress> dest_ip =
|
||||
sf::IpAddress::resolve(destination.substr(0, colon_offset));
|
||||
if (!dest_ip)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Destination IP address is not valid\n");
|
||||
return -1;
|
||||
}
|
||||
sin->sin_addr.s_addr = htonl(dest_ip.toInteger());
|
||||
sin->sin_addr.s_addr = htonl(dest_ip->toInteger());
|
||||
sin->sin_family = AF_INET;
|
||||
const std::string port_str = destination.substr(colon_offset + 1);
|
||||
const int dest_port = std::atoi(port_str.c_str());
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
#include "Core/HW/EXI/EXI_Device.h"
|
||||
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
|
||||
|
||||
#include "SFML/Network/IpAddress.hpp"
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
// BBA implementation with UDP interface to XLink Kai PC/MAC/RaspberryPi client
|
||||
// For more information please see: https://www.teamxlink.co.uk/wiki/Emulator_Integration_Protocol
|
||||
|
@ -26,13 +28,13 @@ bool CEXIETHERNET::XLinkNetworkInterface::Activate()
|
|||
if (IsActivated())
|
||||
return true;
|
||||
|
||||
if (m_sf_socket.bind(sf::Socket::AnyPort) != sf::Socket::Done)
|
||||
if (m_sf_socket.bind(sf::Socket::AnyPort) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Couldn't open XLink Kai UDP socket, unable to initialize BBA");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sf_recipient_ip = m_dest_ip.c_str();
|
||||
m_sf_recipient_ip = sf::IpAddress::resolve(m_dest_ip.c_str()).value_or(sf::IpAddress::Any);
|
||||
|
||||
// Send connect command with unique local name
|
||||
// connect;locally_unique_name;emulator_name;optional_padding
|
||||
|
@ -45,7 +47,7 @@ bool CEXIETHERNET::XLinkNetworkInterface::Activate()
|
|||
|
||||
DEBUG_LOG_FMT(SP1, "SendCommandPayload {:x}\n{}", size, ArrayToString(buffer, size, 0x10));
|
||||
|
||||
if (m_sf_socket.send(buffer, size, m_sf_recipient_ip, m_dest_port) != sf::Socket::Done)
|
||||
if (m_sf_socket.send(buffer, size, m_sf_recipient_ip, m_dest_port) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Activate(): failed to send connect message to XLink Kai client");
|
||||
}
|
||||
|
@ -71,7 +73,7 @@ void CEXIETHERNET::XLinkNetworkInterface::Deactivate()
|
|||
|
||||
DEBUG_LOG_FMT(SP1, "SendCommandPayload {:x}\n{}", size, ArrayToString(buffer, size, 0x10));
|
||||
|
||||
if (m_sf_socket.send(buffer, size, m_sf_recipient_ip, m_dest_port) != sf::Socket::Done)
|
||||
if (m_sf_socket.send(buffer, size, m_sf_recipient_ip, m_dest_port) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Deactivate(): failed to send disconnect message to XLink Kai client");
|
||||
}
|
||||
|
@ -123,7 +125,8 @@ bool CEXIETHERNET::XLinkNetworkInterface::SendFrame(const u8* frame, u32 size)
|
|||
// Only uncomment for debugging, the performance hit is too big otherwise
|
||||
// INFO_LOG_FMT(SP1, "SendFrame {}\n{}", size, ArrayToString(m_out_frame, size, 0x10)));
|
||||
|
||||
if (m_sf_socket.send(m_out_frame, size, m_sf_recipient_ip, m_dest_port) != sf::Socket::Done)
|
||||
if (m_sf_socket.send(m_out_frame, size, m_sf_recipient_ip, m_dest_port) !=
|
||||
sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "SendFrame(): expected to write {} bytes, but failed, errno {}", size,
|
||||
errno);
|
||||
|
@ -139,7 +142,7 @@ bool CEXIETHERNET::XLinkNetworkInterface::SendFrame(const u8* frame, u32 size)
|
|||
void CEXIETHERNET::XLinkNetworkInterface::ReadThreadHandler(
|
||||
CEXIETHERNET::XLinkNetworkInterface* self)
|
||||
{
|
||||
sf::IpAddress sender;
|
||||
std::optional<sf::IpAddress> sender;
|
||||
u16 port;
|
||||
|
||||
while (!self->m_read_thread_shutdown.IsSet())
|
||||
|
@ -151,7 +154,7 @@ void CEXIETHERNET::XLinkNetworkInterface::ReadThreadHandler(
|
|||
// *here* because XLink *could* send one
|
||||
std::size_t bytes_read = 0;
|
||||
if (self->m_sf_socket.receive(self->m_in_frame, std::size(self->m_in_frame), bytes_read, sender,
|
||||
port) != sf::Socket::Done &&
|
||||
port) != sf::Socket::Status::Done &&
|
||||
self->m_bba_link_up)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "Failed to read from BBA, err={}", bytes_read);
|
||||
|
@ -218,7 +221,7 @@ void CEXIETHERNET::XLinkNetworkInterface::ReadThreadHandler(
|
|||
ArrayToString(buffer, size, 0x10));
|
||||
|
||||
if (self->m_sf_socket.send(buffer, size, self->m_sf_recipient_ip, self->m_dest_port) !=
|
||||
sf::Socket::Done)
|
||||
sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(
|
||||
SP1, "ReadThreadHandler(): failed to send setting message to XLink Kai client");
|
||||
|
@ -256,7 +259,7 @@ void CEXIETHERNET::XLinkNetworkInterface::ReadThreadHandler(
|
|||
|
||||
// Reply (using the message that came in!)
|
||||
if (self->m_sf_socket.send(self->m_in_frame, 10, self->m_sf_recipient_ip,
|
||||
self->m_dest_port) != sf::Socket::Done)
|
||||
self->m_dest_port) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(SP1, "ReadThreadHandler(): failed to reply to XLink Kai client keepalive");
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "SFML/Network/IpAddress.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
|
@ -413,7 +414,7 @@ private:
|
|||
#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
sf::UdpSocket m_sf_socket;
|
||||
sf::IpAddress m_sf_recipient_ip;
|
||||
sf::IpAddress m_sf_recipient_ip = sf::IpAddress::Any;
|
||||
char m_in_frame[9004]{};
|
||||
char m_out_frame[9004]{};
|
||||
std::thread m_read_thread;
|
||||
|
|
|
@ -58,7 +58,7 @@ void GeckoSockServer::GeckoConnectionWaiter()
|
|||
server_port = 0xd6ec; // "dolphin gecko"
|
||||
for (int bind_tries = 0; bind_tries <= 10 && !server_running.IsSet(); bind_tries++)
|
||||
{
|
||||
server_running.Set(server.listen(server_port) == sf::Socket::Done);
|
||||
server_running.Set(server.listen(server_port) == sf::Socket::Status::Done);
|
||||
if (!server_running.IsSet())
|
||||
server_port++;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ void GeckoSockServer::GeckoConnectionWaiter()
|
|||
auto new_client = std::make_unique<sf::TcpSocket>();
|
||||
while (server_running.IsSet())
|
||||
{
|
||||
if (server.accept(*new_client) == sf::Socket::Done)
|
||||
if (server.accept(*new_client) == sf::Socket::Status::Done)
|
||||
{
|
||||
std::lock_guard lk(connection_lock);
|
||||
waiting_socks.push(std::move(new_client));
|
||||
|
@ -130,7 +130,7 @@ void GeckoSockServer::ClientThread()
|
|||
std::array<char, 128> buffer;
|
||||
std::size_t got = 0;
|
||||
|
||||
if (client->receive(buffer.data(), buffer.size(), got) == sf::Socket::Disconnected)
|
||||
if (client->receive(buffer.data(), buffer.size(), got) == sf::Socket::Status::Disconnected)
|
||||
client_running.Clear();
|
||||
|
||||
if (got != 0)
|
||||
|
@ -147,7 +147,7 @@ void GeckoSockServer::ClientThread()
|
|||
std::vector<char> packet(send_fifo.begin(), send_fifo.end());
|
||||
send_fifo.clear();
|
||||
|
||||
if (client->send(&packet[0], packet.size()) == sf::Socket::Disconnected)
|
||||
if (client->send(&packet[0], packet.size()) == sf::Socket::Status::Disconnected)
|
||||
client_running.Clear();
|
||||
}
|
||||
} // unlock transfer
|
||||
|
|
|
@ -49,11 +49,11 @@ static void GBAConnectionWaiter()
|
|||
sf::TcpListener clock_server;
|
||||
|
||||
// "dolphin gba"
|
||||
if (server.listen(0xd6ba) != sf::Socket::Done)
|
||||
if (server.listen(0xd6ba) != sf::Socket::Status::Done)
|
||||
return;
|
||||
|
||||
// "clock"
|
||||
if (clock_server.listen(0xc10c) != sf::Socket::Done)
|
||||
if (clock_server.listen(0xc10c) != sf::Socket::Status::Done)
|
||||
return;
|
||||
|
||||
server.setBlocking(false);
|
||||
|
@ -62,14 +62,14 @@ static void GBAConnectionWaiter()
|
|||
auto new_client = std::make_unique<sf::TcpSocket>();
|
||||
while (s_server_running.IsSet())
|
||||
{
|
||||
if (server.accept(*new_client) == sf::Socket::Done)
|
||||
if (server.accept(*new_client) == sf::Socket::Status::Done)
|
||||
{
|
||||
std::lock_guard lk(s_cs_gba);
|
||||
s_waiting_socks.push(std::move(new_client));
|
||||
|
||||
new_client = std::make_unique<sf::TcpSocket>();
|
||||
}
|
||||
if (clock_server.accept(*new_client) == sf::Socket::Done)
|
||||
if (clock_server.accept(*new_client) == sf::Socket::Status::Done)
|
||||
{
|
||||
std::lock_guard lk(s_cs_gba_clk);
|
||||
s_waiting_clocks.push(std::move(new_client));
|
||||
|
@ -170,7 +170,7 @@ void GBASockServer::ClockSync(Core::System& system)
|
|||
bytes[3] = time_slice & 0xff;
|
||||
|
||||
sf::Socket::Status status = m_clock_sync->send(bytes, 4);
|
||||
if (status == sf::Socket::Disconnected)
|
||||
if (status == sf::Socket::Status::Disconnected)
|
||||
{
|
||||
m_clock_sync->disconnect();
|
||||
m_clock_sync = nullptr;
|
||||
|
@ -210,7 +210,7 @@ void GBASockServer::Send(const u8* si_buffer)
|
|||
else
|
||||
status = m_client->send(send_data.data(), 1);
|
||||
|
||||
if (status == sf::Socket::Disconnected)
|
||||
if (status == sf::Socket::Status::Disconnected)
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
|
@ -223,19 +223,19 @@ int GBASockServer::Receive(u8* si_buffer, u8 bytes)
|
|||
{
|
||||
sf::SocketSelector selector;
|
||||
selector.add(*m_client);
|
||||
selector.wait(sf::milliseconds(1000));
|
||||
(void)selector.wait(sf::milliseconds(1000));
|
||||
}
|
||||
|
||||
size_t num_received = 0;
|
||||
std::array<u8, RECV_MAX_SIZE> recv_data;
|
||||
sf::Socket::Status recv_stat = m_client->receive(recv_data.data(), bytes, num_received);
|
||||
if (recv_stat == sf::Socket::Disconnected)
|
||||
if (recv_stat == sf::Socket::Status::Disconnected)
|
||||
{
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (recv_stat == sf::Socket::NotReady || num_received == 0)
|
||||
if (recv_stat == sf::Socket::Status::NotReady || num_received == 0)
|
||||
{
|
||||
m_booted = false;
|
||||
return 0;
|
||||
|
@ -257,7 +257,7 @@ void GBASockServer::Flush()
|
|||
while (num_received)
|
||||
{
|
||||
sf::Socket::Status recv_stat = m_client->receive(&byte, 1, num_received);
|
||||
if (recv_stat != sf::Socket::Done)
|
||||
if (recv_stat != sf::Socket::Status::Done)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -318,8 +318,8 @@ void Wiimote::Read()
|
|||
if (m_balance_board_dump_port > 0 && m_index == WIIMOTE_BALANCE_BOARD)
|
||||
{
|
||||
static sf::UdpSocket Socket;
|
||||
Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost,
|
||||
m_balance_board_dump_port);
|
||||
(void)Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost,
|
||||
m_balance_board_dump_port);
|
||||
}
|
||||
|
||||
// Add it to queue
|
||||
|
@ -339,7 +339,8 @@ bool Wiimote::Write()
|
|||
if (m_balance_board_dump_port > 0 && m_index == WIIMOTE_BALANCE_BOARD)
|
||||
{
|
||||
static sf::UdpSocket Socket;
|
||||
Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost, m_balance_board_dump_port);
|
||||
(void)Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost,
|
||||
m_balance_board_dump_port);
|
||||
}
|
||||
int ret = IOWrite(rpt.data(), rpt.size());
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ bool NetPlayClient::Connect()
|
|||
static void ReceiveSyncIdentifier(sf::Packet& spac, SyncIdentifier& sync_identifier)
|
||||
{
|
||||
// We use a temporary variable here due to a potential long vs long long mismatch
|
||||
sf::Uint64 dol_elf_size;
|
||||
u64 dol_elf_size;
|
||||
spac >> dol_elf_size;
|
||||
sync_identifier.dol_elf_size = dol_elf_size;
|
||||
|
||||
|
@ -607,7 +607,7 @@ void NetPlayClient::OnChunkedDataPayload(sf::Packet& packet)
|
|||
sf::Packet progress_packet;
|
||||
progress_packet << MessageID::ChunkedDataProgress;
|
||||
progress_packet << cid;
|
||||
progress_packet << sf::Uint64{data_packet.getDataSize()};
|
||||
progress_packet << u64{data_packet.getDataSize()};
|
||||
Send(progress_packet, CHUNKED_DATA_CHANNEL);
|
||||
}
|
||||
|
||||
|
@ -2526,7 +2526,7 @@ void NetPlayClient::SendTimeBase()
|
|||
|
||||
if (netplay_client->m_timebase_frame % 60 == 0)
|
||||
{
|
||||
const sf::Uint64 timebase = Core::System::GetInstance().GetSystemTimers().GetFakeTimeBase();
|
||||
const u64 timebase = Core::System::GetInstance().GetSystemTimers().GetFakeTimeBase();
|
||||
|
||||
sf::Packet packet;
|
||||
packet << MessageID::TimeBase;
|
||||
|
|
|
@ -27,7 +27,7 @@ bool CompressFileIntoPacket(const std::string& file_path, sf::Packet& packet)
|
|||
return false;
|
||||
}
|
||||
|
||||
const sf::Uint64 size = file.GetSize();
|
||||
const u64 size = file.GetSize();
|
||||
packet << size;
|
||||
|
||||
if (size == 0)
|
||||
|
@ -89,7 +89,7 @@ bool CompressFileIntoPacket(const std::string& file_path, sf::Packet& packet)
|
|||
|
||||
static bool CompressFolderIntoPacketInternal(const File::FSTEntry& folder, sf::Packet& packet)
|
||||
{
|
||||
const sf::Uint64 size = folder.children.size();
|
||||
const u64 size = folder.children.size();
|
||||
packet << size;
|
||||
for (const auto& child : folder.children)
|
||||
{
|
||||
|
@ -118,7 +118,7 @@ bool CompressFolderIntoPacket(const std::string& folder_path, sf::Packet& packet
|
|||
|
||||
bool CompressBufferIntoPacket(const std::vector<u8>& in_buffer, sf::Packet& packet)
|
||||
{
|
||||
const sf::Uint64 size = in_buffer.size();
|
||||
const u64 size = in_buffer.size();
|
||||
packet << size;
|
||||
|
||||
if (size == 0)
|
||||
|
@ -224,7 +224,7 @@ static bool DecompressPacketIntoFolderInternal(sf::Packet& packet, const std::st
|
|||
if (!File::CreateFullPath(folder_path + "/"))
|
||||
return false;
|
||||
|
||||
sf::Uint64 size;
|
||||
u64 size;
|
||||
packet >> size;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
|
|
|
@ -425,7 +425,7 @@ void NetPlayServer::ThreadFunc()
|
|||
static void SendSyncIdentifier(sf::Packet& spac, const SyncIdentifier& sync_identifier)
|
||||
{
|
||||
// We cast here due to a potential long vs long long mismatch
|
||||
spac << static_cast<sf::Uint64>(sync_identifier.dol_elf_size);
|
||||
spac << static_cast<u64>(sync_identifier.dol_elf_size);
|
||||
|
||||
spac << sync_identifier.game_id;
|
||||
spac << sync_identifier.revision;
|
||||
|
@ -1574,7 +1574,7 @@ bool NetPlayServer::StartGame()
|
|||
m_current_golfer = 1;
|
||||
m_pending_golfer = 0;
|
||||
|
||||
const sf::Uint64 initial_rtc = GetInitialNetPlayRTC();
|
||||
const u64 initial_rtc = GetInitialNetPlayRTC();
|
||||
|
||||
const std::string region = Config::GetDirectoryForRegion(
|
||||
Config::ToGameCubeRegion(m_dialog->FindGameFile(m_selected_game_identifier)->GetRegion()));
|
||||
|
@ -1851,7 +1851,7 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
|||
// No file, so we'll say the size is 0
|
||||
INFO_LOG_FMT(NETPLAY, "Sending empty marker for raw memcard {} in slot {}.", path,
|
||||
is_slot_a ? 'A' : 'B');
|
||||
pac << sf::Uint64{0};
|
||||
pac << u64{0};
|
||||
}
|
||||
|
||||
SendChunkedToClients(std::move(pac), 1,
|
||||
|
@ -1925,7 +1925,7 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
|||
|
||||
for (const auto& [title_id, storage] : sync_info.wii_saves)
|
||||
{
|
||||
pac << sf::Uint64{title_id};
|
||||
pac << u64{title_id};
|
||||
|
||||
if (storage->SaveExists())
|
||||
{
|
||||
|
@ -1942,7 +1942,7 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
|||
pac << true; // save exists
|
||||
|
||||
// Header
|
||||
pac << sf::Uint64{header->tid};
|
||||
pac << u64{header->tid};
|
||||
pac << header->banner_size << header->permissions << header->unk1;
|
||||
for (u8 byte : header->md5)
|
||||
pac << byte;
|
||||
|
@ -1956,7 +1956,7 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
|||
<< bk_header->total_size;
|
||||
for (u8 byte : bk_header->unk3)
|
||||
pac << byte;
|
||||
pac << sf::Uint64{bk_header->tid};
|
||||
pac << u64{bk_header->tid};
|
||||
for (u8 byte : bk_header->mac_address)
|
||||
pac << byte;
|
||||
|
||||
|
@ -2024,7 +2024,7 @@ bool NetPlayServer::SyncSaveData(const SaveSyncInfo& sync_info)
|
|||
{
|
||||
// No file, so we'll say the size is 0
|
||||
INFO_LOG_FMT(NETPLAY, "Sending empty marker for GBA save at {} for slot {}.", path, i);
|
||||
pac << sf::Uint64{0};
|
||||
pac << u64{0};
|
||||
}
|
||||
|
||||
SendChunkedToClients(std::move(pac), 1,
|
||||
|
@ -2436,7 +2436,7 @@ void NetPlayServer::ChunkedDataThreadFunc()
|
|||
|
||||
sf::Packet pac;
|
||||
pac << MessageID::ChunkedDataStart;
|
||||
pac << id << e.title << sf::Uint64{e.packet.getDataSize()};
|
||||
pac << id << e.title << u64{e.packet.getDataSize()};
|
||||
|
||||
ChunkedDataSend(std::move(pac), e.target_pid, e.target_mode);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Core/CoreTiming.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPProto.h"
|
||||
#include "SFML/Network/IpAddress.hpp"
|
||||
|
||||
namespace ciface::DualShockUDPClient
|
||||
{
|
||||
|
@ -263,8 +264,9 @@ void InputBackend::HotplugThreadFunc()
|
|||
list_ports.pad_request_count = SERVER_ASKED_PADS;
|
||||
list_ports.pad_ids = {0, 1, 2, 3};
|
||||
msg.Finish();
|
||||
if (server.m_socket.send(&list_ports, sizeof list_ports, server.m_address, server.m_port) !=
|
||||
sf::Socket::Status::Done)
|
||||
if (server.m_socket.send(&list_ports, sizeof list_ports,
|
||||
sf::IpAddress::resolve(server.m_address).value(),
|
||||
server.m_port) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DualShockUDPClient HotplugThreadFunc send failed");
|
||||
}
|
||||
|
@ -304,7 +306,7 @@ void InputBackend::HotplugThreadFunc()
|
|||
|
||||
Proto::Message<Proto::MessageType::FromServer> msg;
|
||||
std::size_t received_bytes;
|
||||
sf::IpAddress sender;
|
||||
std::optional<sf::IpAddress> sender;
|
||||
u16 port;
|
||||
if (server.m_socket.receive(&msg, sizeof(msg), received_bytes, sender, port) !=
|
||||
sf::Socket::Status::Done)
|
||||
|
@ -627,8 +629,8 @@ Core::DeviceRemoval Device::UpdateInput()
|
|||
data_req.register_flags = Proto::RegisterFlags::PadID;
|
||||
data_req.pad_id_to_register = m_index;
|
||||
msg.Finish();
|
||||
if (m_socket.send(&data_req, sizeof(data_req), m_server_address, m_server_port) !=
|
||||
sf::Socket::Status::Done)
|
||||
if (m_socket.send(&data_req, sizeof(data_req), sf::IpAddress::resolve(m_server_address).value(),
|
||||
m_server_port) != sf::Socket::Status::Done)
|
||||
{
|
||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DualShockUDPClient UpdateInput send failed");
|
||||
}
|
||||
|
@ -637,7 +639,7 @@ Core::DeviceRemoval Device::UpdateInput()
|
|||
// Receive and handle controller data
|
||||
Proto::Message<Proto::MessageType::FromServer> msg;
|
||||
std::size_t received_bytes;
|
||||
sf::IpAddress sender;
|
||||
std::optional<sf::IpAddress> sender;
|
||||
u16 port;
|
||||
while (m_socket.receive(&msg, sizeof msg, received_bytes, sender, port) ==
|
||||
sf::Socket::Status::Done)
|
||||
|
|
|
@ -39,7 +39,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "..\Externals\mbe
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SCMRevGen", "Core\Common\SCMRevGen.vcxproj", "{41279555-F94F-4EBC-99DE-AF863C10C5C4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SFML_Network", "..\Externals\SFML\build\vc2010\SFML_Network.vcxproj", "{93D73454-2512-424E-9CDA-4BB357FE13DD}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SFML", "..\Externals\SFML\SFML.vcxproj", "{93D73454-2512-424E-9CDA-4BB357FE13DD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libusb-1.0", "..\Externals\libusb\libusb-1.0.vcxproj", "{349EE8F9-7D25-4909-AAF5-FF3FADE72187}"
|
||||
EndProject
|
||||
|
|
Loading…
Reference in New Issue