build: bundle SFML 2.x sys/network in third_party
Remove the SFML external dependency, include the SFML 2.6.2 system and network libraries in third_party and adjust the build code, tools and documentation accordingly. Signed-off-by: Rafael Kitover <rkitover@gmail.com>
This commit is contained in:
parent
c6da07feb3
commit
cec8f57400
|
@ -25,7 +25,6 @@ endif()
|
|||
set(VCPKG_DEPS pkgconf zlib pthreads "sdl2[samplerate]" gettext wxwidgets)
|
||||
|
||||
set(VCPKG_DEPS_OPTIONAL
|
||||
sfml ENABLE_LINK
|
||||
ffmpeg ENABLE_FFMPEG
|
||||
faudio ENABLE_FAUDIO
|
||||
)
|
||||
|
|
|
@ -166,7 +166,6 @@ And the following development libraries:
|
|||
- [ffmpeg](https://ffmpeg.org/) (optional, at least version `4.0.4`, for game recording)
|
||||
- [gettext](https://www.gnu.org/software/gettext/) and gettext-tools
|
||||
- [SDL2](https://www.libsdl.org/) (required)
|
||||
- [SFML](https://www.sfml-dev.org/) (optional, for link)
|
||||
- [openal-soft](https://kcat.strangesoft.net/openal.html) (required, a sound interface)
|
||||
- [wxWidgets](https://wxwidgets.org/) (required for GUI, 2.8 and non-stl builds are no longer supported)
|
||||
|
||||
|
@ -211,7 +210,7 @@ cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_LINK=NO -G Ninja
|
|||
| `ENABLE_ASM` | Enable the following two ASM options | ON for 32 bit builds |
|
||||
| `ENABLE_ASM_SCALERS` | Enable x86 ASM graphic filters | ON for 32 bit builds |
|
||||
| `ENABLE_MMX` | Enable MMX | ON for 32 bit builds |
|
||||
| `ENABLE_LINK` | Enable GBA linking functionality (requires SFML) | AUTO |
|
||||
| `ENABLE_LINK` | Enable GBA linking functionality | AUTO |
|
||||
| `ENABLE_LIRC` | Enable LIRC support | OFF |
|
||||
| `ENABLE_FFMPEG` | Enable ffmpeg A/V recording | AUTO |
|
||||
| `ENABLE_ONLINEUPDATES` | Enable online update checks | ON |
|
||||
|
@ -224,7 +223,6 @@ cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_LINK=NO -G Ninja
|
|||
| `BUILD_TESTING` | Build the tests and enable ctest support. | ON |
|
||||
| `VBAM_STATIC` | Try link all libs statically (the following are set to ON if ON) | OFF |
|
||||
| `SDL2_STATIC` | Try to link static SDL2 libraries | OFF |
|
||||
| `SFML_STATIC_LIBRARIES` | Try to link static SFML libraries | OFF |
|
||||
| `FFMPEG_STATIC` | Try to link static ffmpeg libraries | OFF |
|
||||
| `OPENAL_STATIC` | Try to link static OpenAL libraries | OFF |
|
||||
| `TRANSLATIONS_ONLY` | Build only the translations.zip and nothing else | OFF |
|
||||
|
|
|
@ -120,3 +120,9 @@ if(ENABLE_LINK OR ENABLE_WX)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_LINK)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/sfml/src/SFML/System EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/sfml/src/SFML/Network EXCLUDE_FROM_ALL)
|
||||
set(SFML_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/third_party/sfml/include)
|
||||
set(SFML_LIBRARIES sfml-system sfml-network)
|
||||
endif()
|
||||
|
|
|
@ -1,365 +0,0 @@
|
|||
# This script locates the SFML library
|
||||
# ------------------------------------
|
||||
#
|
||||
# Usage
|
||||
# -----
|
||||
#
|
||||
# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main).
|
||||
# If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing.
|
||||
# example:
|
||||
# find_package(SFML COMPONENTS graphics window system) # find the graphics, window and system modules
|
||||
#
|
||||
# You can enforce a specific version, either MAJOR.MINOR or only MAJOR.
|
||||
# If nothing is specified, the version won't be checked (i.e. any version will be accepted).
|
||||
# example:
|
||||
# find_package(SFML COMPONENTS ...) # no specific version required
|
||||
# find_package(SFML 2 COMPONENTS ...) # any 2.x version
|
||||
# find_package(SFML 2.4 COMPONENTS ...) # version 2.4 or greater
|
||||
#
|
||||
# By default, the dynamic libraries of SFML will be found. To find the static ones instead,
|
||||
# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...).
|
||||
# Since you have to link yourself all the SFML dependencies when you link it statically, the following
|
||||
# additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed
|
||||
# description below).
|
||||
# In case of static linking, the SFML_STATIC macro will also be defined by this script.
|
||||
# example:
|
||||
# set(SFML_STATIC_LIBRARIES TRUE)
|
||||
# find_package(SFML 2 COMPONENTS network system)
|
||||
#
|
||||
# On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless
|
||||
# CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details.
|
||||
# Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which
|
||||
# are available for both release and debug modes.
|
||||
#
|
||||
# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable
|
||||
# to tell CMake where SFML is.
|
||||
#
|
||||
# Output
|
||||
# ------
|
||||
#
|
||||
# This script defines the following variables:
|
||||
# - For each specified module XXX (system, window, graphics, network, audio, main):
|
||||
# - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found)
|
||||
# - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found)
|
||||
# - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary)
|
||||
# - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found
|
||||
# - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking
|
||||
# - SFML_LIBRARIES: the list of all libraries corresponding to the required modules
|
||||
# - SFML_FOUND: true if all the required modules are found
|
||||
# - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file)
|
||||
# - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking
|
||||
#
|
||||
# example:
|
||||
# find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED)
|
||||
# include_directories(${SFML_INCLUDE_DIR})
|
||||
# add_executable(myapp ...)
|
||||
# target_link_libraries(myapp ${SFML_LIBRARIES})
|
||||
|
||||
# define the SFML_STATIC macro if static build was chosen
|
||||
if(SFML_STATIC_LIBRARIES)
|
||||
add_compile_definitions(SFML_STATIC)
|
||||
endif()
|
||||
|
||||
# define the list of search paths for headers and libraries
|
||||
set(FIND_SFML_PATHS
|
||||
${SFML_ROOT}
|
||||
$ENV{SFML_ROOT}
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt)
|
||||
|
||||
# find the SFML include directory
|
||||
find_path(SFML_INCLUDE_DIR SFML/Config.hpp
|
||||
PATH_SUFFIXES include
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
|
||||
# check the version number
|
||||
set(SFML_VERSION_OK TRUE)
|
||||
if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
|
||||
# extract the major and minor version numbers from SFML/Config.hpp
|
||||
# we have to handle framework a little bit differently:
|
||||
if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework")
|
||||
set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp")
|
||||
else()
|
||||
set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp")
|
||||
endif()
|
||||
FILE(READ "${SFML_CONFIG_HPP_INPUT}" 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 REPLACE ".*#define *SFML_VERSION_PATCH *([0-9]+).*" "\\1" SFML_VERSION_PATCH "${SFML_CONFIG_HPP_CONTENTS}")
|
||||
if (NOT "${SFML_VERSION_PATCH}" MATCHES "^[0-9]+$")
|
||||
set(SFML_VERSION_PATCH 0)
|
||||
endif()
|
||||
math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10000 + ${SFML_FIND_VERSION_MINOR} * 100 + ${SFML_FIND_VERSION_PATCH}")
|
||||
|
||||
# if we could extract them, compare with the requested version number
|
||||
if (SFML_VERSION_MAJOR)
|
||||
# transform version numbers to an integer
|
||||
math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10000 + ${SFML_VERSION_MINOR} * 100 + ${SFML_VERSION_PATCH}")
|
||||
|
||||
# compare them
|
||||
if(SFML_VERSION LESS SFML_REQUESTED_VERSION)
|
||||
set(SFML_VERSION_OK FALSE)
|
||||
endif()
|
||||
else()
|
||||
# SFML version is < 2.0
|
||||
if (SFML_REQUESTED_VERSION GREATER 10900)
|
||||
set(SFML_VERSION_OK FALSE)
|
||||
set(SFML_VERSION_MAJOR 1)
|
||||
set(SFML_VERSION_MINOR x)
|
||||
set(SFML_VERSION_PATCH x)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# find the requested modules
|
||||
set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found
|
||||
foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS})
|
||||
string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER)
|
||||
string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER)
|
||||
set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER})
|
||||
|
||||
# no suffix for sfml-main, it is always a static library
|
||||
if(FIND_SFML_COMPONENT_LOWER STREQUAL "main")
|
||||
# release library
|
||||
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
|
||||
NAMES ${FIND_SFML_COMPONENT_NAME}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
|
||||
# debug library
|
||||
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
|
||||
NAMES ${FIND_SFML_COMPONENT_NAME}-d
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
else()
|
||||
# static release library
|
||||
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE
|
||||
NAMES ${FIND_SFML_COMPONENT_NAME}-s
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
|
||||
# static debug library
|
||||
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG
|
||||
NAMES ${FIND_SFML_COMPONENT_NAME}-s-d
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
|
||||
# dynamic release library
|
||||
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE
|
||||
NAMES ${FIND_SFML_COMPONENT_NAME}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
|
||||
# dynamic debug library
|
||||
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG
|
||||
NAMES ${FIND_SFML_COMPONENT_NAME}-d
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${FIND_SFML_PATHS})
|
||||
|
||||
# choose the entries that fit the requested link type
|
||||
if(SFML_STATIC_LIBRARIES)
|
||||
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE})
|
||||
endif()
|
||||
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG})
|
||||
endif()
|
||||
else()
|
||||
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE})
|
||||
endif()
|
||||
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
|
||||
# library found
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE)
|
||||
|
||||
# if both are found, set SFML_XXX_LIBRARY to contain both
|
||||
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}
|
||||
optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
|
||||
endif()
|
||||
|
||||
# if only one debug/release variant is found, set the other to be equal to the found one
|
||||
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
|
||||
# debug and not release
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
|
||||
endif()
|
||||
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG)
|
||||
# release and not debug
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
|
||||
endif()
|
||||
else()
|
||||
# library not found
|
||||
set(SFML_FOUND FALSE)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE)
|
||||
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "")
|
||||
set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY")
|
||||
endif()
|
||||
|
||||
# mark as advanced
|
||||
MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY
|
||||
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
|
||||
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
|
||||
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE
|
||||
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG
|
||||
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE
|
||||
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG)
|
||||
|
||||
# add to the global list of libraries
|
||||
set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}")
|
||||
endforeach()
|
||||
|
||||
# in case of static linking, we must also define the list of all the dependencies of SFML libraries
|
||||
if(SFML_STATIC_LIBRARIES)
|
||||
|
||||
# detect the OS
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(FIND_SFML_OS_WINDOWS 1)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(FIND_SFML_OS_LINUX 1)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
set(FIND_SFML_OS_FREEBSD 1)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(FIND_SFML_OS_MACOSX 1)
|
||||
endif()
|
||||
|
||||
# start with an empty list
|
||||
set(SFML_DEPENDENCIES)
|
||||
set(FIND_SFML_DEPENDENCIES_NOTFOUND)
|
||||
|
||||
# macro that searches for a 3rd-party library
|
||||
macro(find_sfml_dependency output friendlyname)
|
||||
# No lookup in environment variables (PATH on Windows), as they may contain wrong library versions
|
||||
find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib NO_SYSTEM_ENVIRONMENT_PATH)
|
||||
if(${${output}} STREQUAL "${output}-NOTFOUND")
|
||||
unset(output)
|
||||
set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# sfml-system
|
||||
list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT)
|
||||
if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1)
|
||||
|
||||
# update the list -- these are only system libraries, no need to find them
|
||||
if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX)
|
||||
set(SFML_SYSTEM_DEPENDENCIES "pthread")
|
||||
endif()
|
||||
if(FIND_SFML_OS_LINUX)
|
||||
set(SFML_SYSTEM_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} "rt")
|
||||
endif()
|
||||
if(FIND_SFML_OS_WINDOWS)
|
||||
set(SFML_SYSTEM_DEPENDENCIES "winmm")
|
||||
endif()
|
||||
set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES})
|
||||
endif()
|
||||
|
||||
# sfml-network
|
||||
list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT)
|
||||
if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1)
|
||||
|
||||
# update the list -- these are only system libraries, no need to find them
|
||||
if(FIND_SFML_OS_WINDOWS)
|
||||
set(SFML_NETWORK_DEPENDENCIES "ws2_32")
|
||||
endif()
|
||||
set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES})
|
||||
endif()
|
||||
|
||||
# sfml-window
|
||||
list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT)
|
||||
if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1)
|
||||
|
||||
# find libraries
|
||||
if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD)
|
||||
find_sfml_dependency(X11_LIBRARY "X11" X11)
|
||||
find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr)
|
||||
endif()
|
||||
|
||||
if(FIND_SFML_OS_LINUX)
|
||||
find_sfml_dependency(UDEV_LIBRARIES "UDev" udev libudev)
|
||||
endif()
|
||||
|
||||
# update the list
|
||||
if(FIND_SFML_OS_WINDOWS)
|
||||
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32")
|
||||
elseif(FIND_SFML_OS_LINUX)
|
||||
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} ${UDEV_LIBRARIES})
|
||||
elseif(FIND_SFML_OS_FREEBSD)
|
||||
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} "usbhid")
|
||||
elseif(FIND_SFML_OS_MACOSX)
|
||||
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon")
|
||||
endif()
|
||||
set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES})
|
||||
endif()
|
||||
|
||||
# sfml-graphics
|
||||
list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT)
|
||||
if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1)
|
||||
|
||||
# find libraries
|
||||
find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype)
|
||||
find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg)
|
||||
|
||||
# update the list
|
||||
set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
|
||||
set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES})
|
||||
endif()
|
||||
|
||||
# sfml-audio
|
||||
list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT)
|
||||
if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1)
|
||||
|
||||
# find libraries
|
||||
find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32)
|
||||
find_sfml_dependency(OGG_LIBRARY "Ogg" ogg)
|
||||
find_sfml_dependency(VORBIS_LIBRARY "Vorbis" vorbis)
|
||||
find_sfml_dependency(VORBISFILE_LIBRARY "VorbisFile" vorbisfile)
|
||||
find_sfml_dependency(VORBISENC_LIBRARY "VorbisEnc" vorbisenc)
|
||||
find_sfml_dependency(FLAC_LIBRARY "FLAC" FLAC)
|
||||
|
||||
# update the list
|
||||
set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${FLAC_LIBRARY} ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
|
||||
set(SFML_DEPENDENCIES ${SFML_DEPENDENCIES} ${SFML_AUDIO_DEPENDENCIES})
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
# handle errors
|
||||
if(NOT SFML_VERSION_OK)
|
||||
# SFML version not ok
|
||||
set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH})")
|
||||
set(SFML_FOUND FALSE)
|
||||
elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND)
|
||||
set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})")
|
||||
set(SFML_FOUND FALSE)
|
||||
elseif(NOT SFML_FOUND)
|
||||
# include directory or library not found
|
||||
set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})")
|
||||
endif()
|
||||
if (NOT SFML_FOUND)
|
||||
if(SFML_FIND_REQUIRED)
|
||||
# fatal error
|
||||
message(FATAL_ERROR ${FIND_SFML_ERROR})
|
||||
elseif(NOT SFML_FIND_QUIETLY)
|
||||
# error but continue
|
||||
message("${FIND_SFML_ERROR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# handle success
|
||||
if(SFML_FOUND AND NOT SFML_FIND_QUIETLY)
|
||||
message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH} in ${SFML_INCLUDE_DIR}")
|
||||
endif()
|
|
@ -30,7 +30,6 @@ option(VBAM_STATIC "Try to link all libraries statically" ${VBAM_STATIC_DEFAULT}
|
|||
|
||||
if(VBAM_STATIC)
|
||||
set(SDL2_STATIC ON)
|
||||
set(SFML_STATIC_LIBRARIES ON)
|
||||
set(FFMPEG_STATIC ON)
|
||||
set(OPENAL_STATIC ON)
|
||||
set_property(GLOBAL PROPERTY LINK_SEARCH_START_STATIC ON)
|
||||
|
@ -68,14 +67,9 @@ endif()
|
|||
find_package(PkgConfig)
|
||||
|
||||
# Link / SFML
|
||||
if(TRANSLATIONS_ONLY)
|
||||
set(ENABLE_LINK_DEFAULT OFF)
|
||||
else()
|
||||
find_package(SFML 2.4 COMPONENTS network system)
|
||||
set(ENABLE_LINK_DEFAULT OFF)
|
||||
if(SFML_FOUND)
|
||||
set(ENABLE_LINK_DEFAULT ON)
|
||||
endif()
|
||||
set(ENABLE_LINK_DEFAULT OFF)
|
||||
if(NOT TRANSLATIONS_ONLY)
|
||||
set(ENABLE_LINK_DEFAULT ON)
|
||||
endif()
|
||||
option(ENABLE_LINK "Enable GBA linking functionality" ${ENABLE_LINK_DEFAULT})
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ with import <nixpkgs> {};
|
|||
stdenv.mkDerivation {
|
||||
name = "visualboyadvance-m";
|
||||
buildInputs = if stdenv.isDarwin then
|
||||
[ ninja cmake gcc nasm faudio gettext libintl pkg-config zip sfml zlib openal ffmpeg wxGTK32 SDL2 pcre pcre2 darwin.apple_sdk.frameworks.System darwin.apple_sdk.frameworks.IOKit darwin.apple_sdk.frameworks.Carbon darwin.apple_sdk.frameworks.Cocoa darwin.apple_sdk.frameworks.QuartzCore darwin.apple_sdk.frameworks.AudioToolbox darwin.apple_sdk.frameworks.OpenGL darwin.apple_sdk.frameworks.OpenAL llvmPackages_latest.clang llvmPackages_latest.bintools ]
|
||||
[ ninja cmake gcc nasm faudio gettext libintl pkg-config zip zlib openal ffmpeg wxGTK32 SDL2 pcre pcre2 darwin.apple_sdk.frameworks.System darwin.apple_sdk.frameworks.IOKit darwin.apple_sdk.frameworks.Carbon darwin.apple_sdk.frameworks.Cocoa darwin.apple_sdk.frameworks.QuartzCore darwin.apple_sdk.frameworks.AudioToolbox darwin.apple_sdk.frameworks.OpenGL darwin.apple_sdk.frameworks.OpenAL llvmPackages_latest.clang llvmPackages_latest.bintools ]
|
||||
else
|
||||
[ ninja cmake gcc nasm faudio gettext libintl pkg-config zip sfml zlib openal ffmpeg wxGTK32 libGL libGLU glfw SDL2 gtk3-x11 pcre pcre2 util-linuxMinimal libselinux libsepol libthai libdatrie xorg.libXdmcp xorg.libXtst libxkbcommon epoxy dbus at-spi2-core ];
|
||||
[ ninja cmake gcc nasm faudio gettext libintl pkg-config zip zlib openal ffmpeg wxGTK32 libGL libGLU glfw SDL2 gtk3-x11 pcre pcre2 util-linuxMinimal libselinux libsepol libthai libdatrie xorg.libXdmcp xorg.libXtst libxkbcommon epoxy dbus at-spi2-core ];
|
||||
}
|
||||
|
|
45
installdeps
45
installdeps
|
@ -191,7 +191,7 @@ freebsd_installdeps() {
|
|||
|
||||
check sudo pkg update
|
||||
|
||||
pkgs="llvm-devel cmake ccache nasm ffmpeg gettext-tools gettext pkgconf sdl2 sfml wx31-gtk3 iconv zip ninja"
|
||||
pkgs="llvm-devel cmake ccache nasm ffmpeg gettext-tools gettext pkgconf sdl2 wx31-gtk3 iconv zip ninja"
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"
|
||||
|
||||
|
@ -318,12 +318,6 @@ debian_installdeps() {
|
|||
if [ -z "$target" ]; then
|
||||
sudo apt-get -qq -y update
|
||||
|
||||
sfml_libs=
|
||||
|
||||
for lib in graphics window network; do
|
||||
sfml_libs="$sfml_libs $(apt-cache search "libsfml-$lib" | sed 's/ - .*//' | sort -r | head -1)"
|
||||
done
|
||||
|
||||
glew_lib=$(apt-cache search libglew | grep '^libglew[0-9]' | sed 's/ - .*//' | sort -r | head -1)
|
||||
|
||||
sdl_lib=$(apt-cache search '^libsdl2-2.0' | sed 's/ - .*//' | sort -r | head -1)
|
||||
|
@ -350,7 +344,7 @@ debian_installdeps() {
|
|||
;;
|
||||
esac
|
||||
|
||||
pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev libsdl2-dev $sdl_lib libglu1-mesa-dev libglu1-mesa libgles2-mesa-dev libsfml-dev $sfml_libs $glew_lib $wx_libs libgtk2.0-dev libgtk-3-dev ccache zip ninja-build libopenal-dev"
|
||||
pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev libsdl2-dev $sdl_lib libglu1-mesa-dev libglu1-mesa libgles2-mesa-dev $glew_lib $wx_libs libgtk2.0-dev libgtk-3-dev ccache zip ninja-build libopenal-dev"
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs libavcodec-dev libavformat-dev libswscale-dev libavutil-dev $libswresample_dev"
|
||||
|
||||
|
@ -401,7 +395,7 @@ debian_installdeps() {
|
|||
fi
|
||||
fi
|
||||
|
||||
deps="gcc zlib ffmpeg gettext sdl2 sfml openal wxwidgets openal"
|
||||
deps="gcc zlib ffmpeg gettext sdl2 openal wxwidgets openal"
|
||||
[ -n "$ENABLE_FFMPEG" ] && deps="$deps ffmpeg"
|
||||
|
||||
set --
|
||||
|
@ -498,7 +492,7 @@ fedora_installdeps() {
|
|||
# this is sometimes necessary for rawhide
|
||||
set -- --exclude='glibc32*'
|
||||
fi
|
||||
for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel SFML-devel openal-soft-devel wxGTK-devel gtk3-devel; do
|
||||
for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel openal-soft-devel wxGTK-devel gtk3-devel; do
|
||||
case $pkg in
|
||||
*ffmpeg*)
|
||||
[ -z "$ENABLE_FFMPEG" ] && continue
|
||||
|
@ -597,8 +591,6 @@ fedora_installdeps() {
|
|||
|
||||
# get the necessary win32 headers
|
||||
git submodule update --init --remote --recursive
|
||||
|
||||
warning='SFML is required for LINK support, Fedora does not currently have a MinGW SFML package, if you want LINK support you will need to install it manually'
|
||||
fi
|
||||
|
||||
[ -z "$rpms_installed" ] && check sudo dnf -y --nogpgcheck --best --allowerasing install "$@"
|
||||
|
@ -684,8 +676,6 @@ rhel_installdeps() {
|
|||
set -- --exclude='glibc32*'
|
||||
fi
|
||||
|
||||
warning='RHEL does not currently have SFML packages, LINK support will be disabled'
|
||||
|
||||
for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel openal-soft-devel wxGTK3-devel gtk3-devel; do
|
||||
case $pkg in
|
||||
*ffmpeg*)
|
||||
|
@ -777,8 +767,6 @@ rhel_installdeps() {
|
|||
|
||||
# get the necessary win32 headers
|
||||
git submodule update --init --remote --recursive
|
||||
|
||||
warning='SFML is required for LINK support, RHEL/EPEL does not currently have a MinGW SFML package, if you want LINK support you will need to install it manually'
|
||||
fi
|
||||
|
||||
[ -z "$rpms_installed" ] && check sudo yum -y install "$@"
|
||||
|
@ -797,7 +785,7 @@ suse_installdeps() {
|
|||
check_cross
|
||||
installing
|
||||
|
||||
tools="make cmake ccache nasm gettext-tools pkg-config ccache zip sfml2-devel ninja"
|
||||
tools="make cmake ccache nasm gettext-tools pkg-config ccache zip ninja"
|
||||
|
||||
libs="gcc gcc-c++ libSDL2-devel wxWidgets-3_0-devel openal-soft-devel" # ffmpeg-devel
|
||||
|
||||
|
@ -868,7 +856,7 @@ archlinux_installdeps() {
|
|||
|
||||
$pacman -Q gtk3-classic >/dev/null 2>&1 && gtk=gtk3-classic
|
||||
|
||||
libs="zlib mesa gettext sdl2 wxgtk3 $gtk sfml openal"
|
||||
libs="zlib mesa gettext sdl2 wxgtk3 $gtk openal"
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && libs="$libs ffmpeg"
|
||||
|
||||
|
@ -884,7 +872,7 @@ archlinux_installdeps() {
|
|||
else
|
||||
# try to build 32 bit binaries
|
||||
|
||||
# lib32-sfml and lib32-ffmpeg are in AUR
|
||||
# lib32-ffmpeg is in AUR
|
||||
archlinux_require_yaourt
|
||||
|
||||
# enable multilib repos if not enabled
|
||||
|
@ -978,8 +966,6 @@ EOF
|
|||
|
||||
# get the necessary win32 headers
|
||||
git submodule update --init --remote --recursive
|
||||
|
||||
warning 'SFML is required for LINK support, the SFML package in AUR is currently broken, if you want LINK support you will need to install it manually'
|
||||
fi
|
||||
|
||||
build_instructions
|
||||
|
@ -1042,13 +1028,12 @@ solus_installdeps() {
|
|||
done
|
||||
else
|
||||
# no 32bit versions of these
|
||||
set -- "$@" SFML-devel ffmpeg-devel
|
||||
set -- "$@" ffmpeg-devel
|
||||
fi
|
||||
|
||||
check sudo eopkg -y install "$@"
|
||||
|
||||
if [ -n "$amd64" -a "$target" = m32 ]; then
|
||||
warning 'SFML is required for LINK support, there is no 32 bit SFML package in Solus currently, if you want LINK support you will need to install it manually'
|
||||
warning 'ffmpeg is required for game recording, there is no 32 bit ffmpeg package in Solus currently, you may wish to install it manually'
|
||||
fi
|
||||
|
||||
|
@ -1070,7 +1055,6 @@ gentoo_installdeps() {
|
|||
dev-util/ccache \
|
||||
sys-devel/binutils \
|
||||
media-libs/libsdl2 \
|
||||
media-libs/libsfml \
|
||||
media-libs/openal \
|
||||
x11-libs/wxGTK:$wx_slot \
|
||||
sys-libs/zlib \
|
||||
|
@ -1088,7 +1072,7 @@ gentoo_installdeps() {
|
|||
alpine_installdeps() {
|
||||
installing
|
||||
|
||||
check sudo apk add cmake ninja g++ ccache nasm gettext-dev zlib-dev mesa-dev sdl2-dev glu-dev sfml-dev wxwidgets-dev gtk+3.0-dev zip
|
||||
check sudo apk add cmake ninja g++ ccache nasm gettext-dev zlib-dev mesa-dev sdl2-dev glu-dev wxwidgets-dev gtk+3.0-dev zip
|
||||
|
||||
build_instructions
|
||||
}
|
||||
|
@ -1123,7 +1107,7 @@ windows_installdeps() {
|
|||
;;
|
||||
esac
|
||||
|
||||
pkgs="$pkgs SDL2 sfml wxWidgets3.2 zlib binutils cmake crt-git headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache openal"
|
||||
pkgs="$pkgs SDL2 wxWidgets3.2 zlib binutils cmake crt-git headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache openal"
|
||||
|
||||
case "$target" in
|
||||
*x86_64)
|
||||
|
@ -1199,11 +1183,6 @@ brew_installdeps() {
|
|||
|
||||
[ -n "$ENABLE_FFMPEG" ] && brews="$brews ffmpeg"
|
||||
|
||||
# sfml brew currently broken in the travis mac environment
|
||||
# if [ -z "$TRAVIS" ]; then
|
||||
brews="$brews sfml"
|
||||
# fi
|
||||
|
||||
# This is necessary for the GitHub Actions CI:
|
||||
brew -v install python
|
||||
brew link --overwrite python
|
||||
|
@ -1226,7 +1205,7 @@ macports_installdeps() {
|
|||
|
||||
check sudo port -v selfupdate
|
||||
|
||||
ports="cmake ccache nasm gettext pkgconfig libsdl2 sfml wxWidgets-3.0 libiconv ninja"
|
||||
ports="cmake ccache nasm gettext pkgconfig libsdl2 wxWidgets-3.0 libiconv ninja"
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && ports="$ports ffmpeg"
|
||||
|
||||
|
@ -1242,7 +1221,7 @@ fink_installdeps() {
|
|||
|
||||
check sudo fink -vy selfupdate
|
||||
|
||||
pkgs="cmake ccache nasm libgettext8-dev gettext-tools pkgconfig sdl2 wxwidgets300-osxcocoa libiconv-dev sfml24-dev ccache ninja"
|
||||
pkgs="cmake ccache nasm libgettext8-dev gettext-tools pkgconfig sdl2 wxwidgets300-osxcocoa libiconv-dev ccache ninja"
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ parts:
|
|||
cmake-generator: Ninja
|
||||
stage-packages:
|
||||
- libsdl2-2.0-0
|
||||
- libsfml-network2.5
|
||||
- libsfml-system2.5
|
||||
- libnotify4
|
||||
- libsm6
|
||||
- libopenal1
|
||||
|
@ -46,7 +44,6 @@ parts:
|
|||
- zip
|
||||
- libnotify-dev
|
||||
- libsdl2-dev
|
||||
- libsfml-dev
|
||||
- libgtk-3-dev
|
||||
- libopenal-dev
|
||||
- libwxgtk3.0-gtk3-dev
|
||||
|
|
|
@ -127,6 +127,10 @@ if(ENABLE_LINK)
|
|||
target_link_libraries(vbam-core
|
||||
PRIVATE ${SFML_LIBRARIES}
|
||||
)
|
||||
|
||||
target_compile_definitions(vbam-core
|
||||
PRIVATE SFML_STATIC
|
||||
)
|
||||
|
||||
# Add libintl.h
|
||||
target_include_directories(vbam-core
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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 6
|
||||
#define SFML_VERSION_PATCH 2
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Identify the operating system
|
||||
// see https://sourceforge.net/p/predef/wiki/Home/
|
||||
////////////////////////////////////////////////////////////
|
||||
#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
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
|
||||
// NetBSD
|
||||
#define SFML_SYSTEM_NETBSD
|
||||
|
||||
#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
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wc++11-long-long"
|
||||
#endif
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long Uint64;
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_CONFIG_HPP
|
|
@ -0,0 +1,53 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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>
|
||||
#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).
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,48 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,616 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_FTP_HPP
|
||||
#define SFML_FTP_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Export.hpp>
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class IpAddress;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief A FTP client
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Ftp : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Enumeration of transfer modes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum TransferMode
|
||||
{
|
||||
Binary, //!< Binary mode (file is transfered as a sequence of bytes)
|
||||
Ascii, //!< Text mode using ASCII encoding
|
||||
Ebcdic //!< Text mode using EBCDIC encoding
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Define a FTP response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API Response
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Status codes possibly returned by a FTP response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
enum Status
|
||||
{
|
||||
// 1xx: the requested action is being initiated,
|
||||
// expect another reply before proceeding with a new command
|
||||
RestartMarkerReply = 110, //!< Restart marker reply
|
||||
ServiceReadySoon = 120, //!< Service ready in N minutes
|
||||
DataConnectionAlreadyOpened = 125, //!< Data connection already opened, transfer starting
|
||||
OpeningDataConnection = 150, //!< File status ok, about to open data connection
|
||||
|
||||
// 2xx: the requested action has been successfully completed
|
||||
Ok = 200, //!< Command ok
|
||||
PointlessCommand = 202, //!< Command not implemented
|
||||
SystemStatus = 211, //!< System status, or system help reply
|
||||
DirectoryStatus = 212, //!< Directory status
|
||||
FileStatus = 213, //!< File status
|
||||
HelpMessage = 214, //!< Help message
|
||||
SystemType = 215, //!< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document
|
||||
ServiceReady = 220, //!< Service ready for new user
|
||||
ClosingConnection = 221, //!< Service closing control connection
|
||||
DataConnectionOpened = 225, //!< Data connection open, no transfer in progress
|
||||
ClosingDataConnection = 226, //!< Closing data connection, requested file action successful
|
||||
EnteringPassiveMode = 227, //!< Entering passive mode
|
||||
LoggedIn = 230, //!< User logged in, proceed. Logged out if appropriate
|
||||
FileActionOk = 250, //!< Requested file action ok
|
||||
DirectoryOk = 257, //!< PATHNAME created
|
||||
|
||||
// 3xx: the command has been accepted, but the requested action
|
||||
// is dormant, pending receipt of further information
|
||||
NeedPassword = 331, //!< User name ok, need password
|
||||
NeedAccountToLogIn = 332, //!< Need account for login
|
||||
NeedInformation = 350, //!< Requested file action pending further information
|
||||
|
||||
// 4xx: the command was not accepted and the requested action did not take place,
|
||||
// but the error condition is temporary and the action may be requested again
|
||||
ServiceUnavailable = 421, //!< Service not available, closing control connection
|
||||
DataConnectionUnavailable = 425, //!< Can't open data connection
|
||||
TransferAborted = 426, //!< Connection closed, transfer aborted
|
||||
FileActionAborted = 450, //!< Requested file action not taken
|
||||
LocalError = 451, //!< Requested action aborted, local error in processing
|
||||
InsufficientStorageSpace = 452, //!< Requested action not taken; insufficient storage space in system, file unavailable
|
||||
|
||||
// 5xx: the command was not accepted and
|
||||
// the requested action did not take place
|
||||
CommandUnknown = 500, //!< Syntax error, command unrecognized
|
||||
ParametersUnknown = 501, //!< Syntax error in parameters or arguments
|
||||
CommandNotImplemented = 502, //!< Command not implemented
|
||||
BadCommandSequence = 503, //!< Bad sequence of commands
|
||||
ParameterNotImplemented = 504, //!< Command not implemented for that parameter
|
||||
NotLoggedIn = 530, //!< Not logged in
|
||||
NeedAccountToStore = 532, //!< Need account for storing files
|
||||
FileUnavailable = 550, //!< Requested action not taken, file unavailable
|
||||
PageTypeUnknown = 551, //!< Requested action aborted, page type unknown
|
||||
NotEnoughMemory = 552, //!< Requested file action aborted, exceeded storage allocation
|
||||
FilenameNotAllowed = 553, //!< Requested action not taken, file name not allowed
|
||||
|
||||
// 10xx: SFML custom codes
|
||||
InvalidResponse = 1000, //!< Not part of the FTP standard, generated by SFML when a received response cannot be parsed
|
||||
ConnectionFailed = 1001, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection with the server fails
|
||||
ConnectionClosed = 1002, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection is unexpectedly closed
|
||||
InvalidFile = 1003 //!< Not part of the FTP standard, generated by SFML when a local file cannot be read or written
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor is used by the FTP client to build
|
||||
/// the response.
|
||||
///
|
||||
/// \param code Response status code
|
||||
/// \param message Response message
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit Response(Status code = InvalidResponse, const std::string& message = "");
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if the status code means a success
|
||||
///
|
||||
/// This function is defined for convenience, it is
|
||||
/// equivalent to testing if the status code is < 400.
|
||||
///
|
||||
/// \return True if the status is a success, false if it is a failure
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool isOk() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the status code of the response
|
||||
///
|
||||
/// \return Status code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Status getStatus() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the full message contained in the response
|
||||
///
|
||||
/// \return The response message
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& getMessage() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Status m_status; //!< Status code returned from the server
|
||||
std::string m_message; //!< Last message received from the server
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of FTP response returning a directory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API DirectoryResponse : public Response
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// \param response Source response
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
DirectoryResponse(const Response& response);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the directory returned in the response
|
||||
///
|
||||
/// \return Directory name
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& getDirectory() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string m_directory; //!< Directory extracted from the response message
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of FTP response returning a
|
||||
/// filename listing
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_NETWORK_API ListingResponse : public Response
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// \param response Source response
|
||||
/// \param data Data containing the raw listing
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ListingResponse(const Response& response, const std::string& data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the array of directory/file names
|
||||
///
|
||||
/// \return Array containing the requested listing
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::vector<std::string>& getListing() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::vector<std::string> m_listing; //!< Directory/file names extracted from the data
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
/// Automatically closes the connection with the server if
|
||||
/// it is still opened.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~Ftp();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Connect to the specified FTP server
|
||||
///
|
||||
/// The port has a default value of 21, which is the standard
|
||||
/// port used by the FTP protocol. You shouldn't use a different
|
||||
/// value, unless you really know what you do.
|
||||
/// This function tries to connect to the server so it may take
|
||||
/// a while to complete, especially if the server is not
|
||||
/// reachable. To avoid blocking your application for too long,
|
||||
/// you can use a timeout. The default value, Time::Zero, means that the
|
||||
/// system timeout will be used (which is usually pretty long).
|
||||
///
|
||||
/// \param server Name or address of the FTP server to connect to
|
||||
/// \param port Port used for the connection
|
||||
/// \param timeout Maximum time to wait
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see disconnect
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response connect(const IpAddress& server, unsigned short port = 21, Time timeout = Time::Zero);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close the connection with the server
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see connect
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response disconnect();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Log in using an anonymous account
|
||||
///
|
||||
/// Logging in is mandatory after connecting to the server.
|
||||
/// Users that are not logged in cannot perform any operation.
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response login();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Log in using a username and a password
|
||||
///
|
||||
/// Logging in is mandatory after connecting to the server.
|
||||
/// Users that are not logged in cannot perform any operation.
|
||||
///
|
||||
/// \param name User name
|
||||
/// \param password Password
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response login(const std::string& name, const std::string& password);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send a null command to keep the connection alive
|
||||
///
|
||||
/// This command is useful because the server may close the
|
||||
/// connection automatically if no command is sent.
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response keepAlive();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current working directory
|
||||
///
|
||||
/// The working directory is the root path for subsequent
|
||||
/// operations involving directories and/or filenames.
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see getDirectoryListing, changeDirectory, parentDirectory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
DirectoryResponse getWorkingDirectory();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the contents of the given directory
|
||||
///
|
||||
/// This function retrieves the sub-directories and files
|
||||
/// contained in the given directory. It is not recursive.
|
||||
/// The \a directory parameter is relative to the current
|
||||
/// working directory.
|
||||
///
|
||||
/// \param directory Directory to list
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see getWorkingDirectory, changeDirectory, parentDirectory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ListingResponse getDirectoryListing(const std::string& directory = "");
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current working directory
|
||||
///
|
||||
/// The new directory must be relative to the current one.
|
||||
///
|
||||
/// \param directory New working directory
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see getWorkingDirectory, getDirectoryListing, parentDirectory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response changeDirectory(const std::string& directory);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Go to the parent directory of the current one
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see getWorkingDirectory, getDirectoryListing, changeDirectory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response parentDirectory();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new directory
|
||||
///
|
||||
/// The new directory is created as a child of the current
|
||||
/// working directory.
|
||||
///
|
||||
/// \param name Name of the directory to create
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see deleteDirectory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response createDirectory(const std::string& name);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Remove an existing directory
|
||||
///
|
||||
/// The directory to remove must be relative to the
|
||||
/// current working directory.
|
||||
/// Use this function with caution, the directory will
|
||||
/// be removed permanently!
|
||||
///
|
||||
/// \param name Name of the directory to remove
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see createDirectory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response deleteDirectory(const std::string& name);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Rename an existing file
|
||||
///
|
||||
/// The filenames must be relative to the current working
|
||||
/// directory.
|
||||
///
|
||||
/// \param file File to rename
|
||||
/// \param newName New name of the file
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see deleteFile
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response renameFile(const std::string& file, const std::string& newName);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Remove an existing file
|
||||
///
|
||||
/// The file name must be relative to the current working
|
||||
/// directory.
|
||||
/// Use this function with caution, the file will be
|
||||
/// removed permanently!
|
||||
///
|
||||
/// \param name File to remove
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see renameFile
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response deleteFile(const std::string& name);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Download a file from the server
|
||||
///
|
||||
/// The filename of the distant file is relative to the
|
||||
/// current working directory of the server, and the local
|
||||
/// destination path is relative to the current directory
|
||||
/// of your application.
|
||||
/// If a file with the same filename as the distant file
|
||||
/// already exists in the local destination path, it will
|
||||
/// be overwritten.
|
||||
///
|
||||
/// \param remoteFile Filename of the distant file to download
|
||||
/// \param localPath The directory in which to put the file on the local computer
|
||||
/// \param mode Transfer mode
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see upload
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Upload a file to the server
|
||||
///
|
||||
/// The name of the local file is relative to the current
|
||||
/// working directory of your application, and the
|
||||
/// remote path is relative to the current directory of the
|
||||
/// FTP server.
|
||||
///
|
||||
/// The append parameter controls whether the remote file is
|
||||
/// appended to or overwritten if it already exists.
|
||||
///
|
||||
/// \param localFile Path of the local file to upload
|
||||
/// \param remotePath The directory in which to put the file on the server
|
||||
/// \param mode Transfer mode
|
||||
/// \param append Pass true to append to or false to overwrite the remote file if it already exists
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
/// \see download
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary, bool append = false);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Send a command to the FTP server
|
||||
///
|
||||
/// While the most often used commands are provided as member
|
||||
/// functions in the sf::Ftp class, this method can be used
|
||||
/// to send any FTP command to the server. If the command
|
||||
/// requires one or more parameters, they can be specified
|
||||
/// in \a parameter. If the server returns information, you
|
||||
/// can extract it from the response using Response::getMessage().
|
||||
///
|
||||
/// \param command Command to send
|
||||
/// \param parameter Command parameter
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response sendCommand(const std::string& command, const std::string& parameter = "");
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Receive a response from the server
|
||||
///
|
||||
/// This function must be called after each call to
|
||||
/// sendCommand that expects a response.
|
||||
///
|
||||
/// \return Server response to the request
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Response getResponse();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility class for exchanging datas with the server
|
||||
/// on the data channel
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class DataChannel;
|
||||
|
||||
friend class DataChannel;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket m_commandSocket; //!< Socket holding the control connection with the server
|
||||
std::string m_receiveBuffer; //!< Received command data that is yet to be processed
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_FTP_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Ftp
|
||||
/// \ingroup network
|
||||
///
|
||||
/// sf::Ftp is a very simple FTP client that allows you
|
||||
/// to communicate with a FTP server. The FTP protocol allows
|
||||
/// you to manipulate a remote file system (list files,
|
||||
/// upload, download, create, remove, ...).
|
||||
///
|
||||
/// Using the FTP client consists of 4 parts:
|
||||
/// \li Connecting to the FTP server
|
||||
/// \li Logging in (either as a registered user or anonymously)
|
||||
/// \li Sending commands to the server
|
||||
/// \li Disconnecting (this part can be done implicitly by the destructor)
|
||||
///
|
||||
/// Every command returns a FTP response, which contains the
|
||||
/// status code as well as a message from the server. Some
|
||||
/// commands such as getWorkingDirectory() and getDirectoryListing()
|
||||
/// return additional data, and use a class derived from
|
||||
/// sf::Ftp::Response to provide this data. The most often used
|
||||
/// commands are directly provided as member functions, but it is
|
||||
/// also possible to use specific commands with the sendCommand() function.
|
||||
///
|
||||
/// Note that response statuses >= 1000 are not part of the FTP standard,
|
||||
/// they are generated by SFML when an internal error occurs.
|
||||
///
|
||||
/// All commands, especially upload and download, may take some
|
||||
/// time to complete. This is important to know if you don't want
|
||||
/// to block your application while the server is completing
|
||||
/// the task.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // Create a new FTP client
|
||||
/// sf::Ftp ftp;
|
||||
///
|
||||
/// // Connect to the server
|
||||
/// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com");
|
||||
/// if (response.isOk())
|
||||
/// std::cout << "Connected" << std::endl;
|
||||
///
|
||||
/// // Log in
|
||||
/// response = ftp.login("laurent", "dF6Zm89D");
|
||||
/// if (response.isOk())
|
||||
/// std::cout << "Logged in" << std::endl;
|
||||
///
|
||||
/// // Print the working directory
|
||||
/// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory();
|
||||
/// if (directory.isOk())
|
||||
/// std::cout << "Working directory: " << directory.getDirectory() << std::endl;
|
||||
///
|
||||
/// // Create a new directory
|
||||
/// response = ftp.createDirectory("files");
|
||||
/// if (response.isOk())
|
||||
/// std::cout << "Created new directory" << std::endl;
|
||||
///
|
||||
/// // Upload a file to this new directory
|
||||
/// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::Ascii);
|
||||
/// if (response.isOk())
|
||||
/// std::cout << "File uploaded" << std::endl;
|
||||
///
|
||||
/// // Send specific commands (here: FEAT to list supported FTP features)
|
||||
/// response = ftp.sendCommand("FEAT");
|
||||
/// if (response.isOk())
|
||||
/// std::cout << "Feature list:\n" << response.getMessage() << std::endl;
|
||||
///
|
||||
/// // Disconnect from the server (optional)
|
||||
/// ftp.disconnect();
|
||||
/// \endcode
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,482 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,328 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,545 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
/// \see getReadPosition
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void append(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current reading position in the packet
|
||||
///
|
||||
/// The next read operation will read data from this position
|
||||
///
|
||||
/// \return The byte offset of the current read position
|
||||
///
|
||||
/// \see append
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t getReadPosition() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,219 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,57 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,263 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,170 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
///
|
||||
/// When providing sf::Socket::AnyPort as port, the listener
|
||||
/// will request an available port from the system.
|
||||
/// The chosen port can be retrieved by calling getLocalPort().
|
||||
///
|
||||
/// \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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,316 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
///
|
||||
/// If 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,292 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
///
|
||||
/// When providing sf::Socket::AnyPort as port, the listener
|
||||
/// will request an available port from the system.
|
||||
/// The chosen port can be retrieved by calling getLocalPort().
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,60 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/FileInputStream.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/MemoryInputStream.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Sleep.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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,117 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_CLOCK_HPP
|
||||
#define SFML_CLOCK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility class that measures the elapsed time
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API Clock
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// The clock starts automatically after being constructed.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Clock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the elapsed time
|
||||
///
|
||||
/// This function returns the time elapsed since the last call
|
||||
/// to restart() (or the construction of the instance if restart()
|
||||
/// has not been called).
|
||||
///
|
||||
/// \return Time elapsed
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Time getElapsedTime() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Restart the clock
|
||||
///
|
||||
/// This function puts the time counter back to zero.
|
||||
/// It also returns the time elapsed since the clock was started.
|
||||
///
|
||||
/// \return Time elapsed
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Time restart();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Time m_startTime; //!< Time of last reset, in microseconds
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_CLOCK_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Clock
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::Clock is a lightweight class for measuring time.
|
||||
///
|
||||
/// Its provides the most precise time that the underlying
|
||||
/// OS can achieve (generally microseconds or nanoseconds).
|
||||
/// It also ensures monotonicity, which means that the returned
|
||||
/// time can never go backward, even if the system time is
|
||||
/// changed.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::Clock clock;
|
||||
/// ...
|
||||
/// Time time1 = clock.getElapsedTime();
|
||||
/// ...
|
||||
/// Time time2 = clock.restart();
|
||||
/// \endcode
|
||||
///
|
||||
/// The sf::Time value returned by the clock can then be
|
||||
/// converted to a number of seconds, milliseconds or even
|
||||
/// microseconds.
|
||||
///
|
||||
/// \see sf::Time
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,80 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,48 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,169 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_FILEINPUTSTREAM_HPP
|
||||
#define SFML_FILEINPUTSTREAM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class SFML_SYSTEM_API ResourceStream;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implementation of input stream based on a file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API FileInputStream : public InputStream, NonCopyable
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
FileInputStream();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~FileInputStream();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open the stream from a file path
|
||||
///
|
||||
/// \param filename Name of the file to open
|
||||
///
|
||||
/// \return True on success, false on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool open(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read data from the stream
|
||||
///
|
||||
/// After reading, the stream's reading position must be
|
||||
/// advanced by the amount of bytes read.
|
||||
///
|
||||
/// \param data Buffer where to copy the read data
|
||||
/// \param size Desired number of bytes to read
|
||||
///
|
||||
/// \return The number of bytes actually read, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 read(void* data, Int64 size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current reading position
|
||||
///
|
||||
/// \param position The position to seek to, from the beginning
|
||||
///
|
||||
/// \return The position actually sought to, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 seek(Int64 position);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current reading position in the stream
|
||||
///
|
||||
/// \return The current position, or -1 on error.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 tell();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the size of the stream
|
||||
///
|
||||
/// \return The total number of bytes available in the stream, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 getSize();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
priv::ResourceStream* m_file;
|
||||
#else
|
||||
std::FILE* m_file; //!< stdio file stream
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_FILEINPUTSTREAM_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::FileInputStream
|
||||
/// \ingroup system
|
||||
///
|
||||
/// This class is a specialization of InputStream that
|
||||
/// reads from a file on disk.
|
||||
///
|
||||
/// It wraps a file in the common InputStream interface
|
||||
/// and therefore allows to use generic classes or functions
|
||||
/// that accept such a stream, with a file on disk as the data
|
||||
/// source.
|
||||
///
|
||||
/// In addition to the virtual functions inherited from
|
||||
/// InputStream, FileInputStream adds a function to
|
||||
/// specify the file to open.
|
||||
///
|
||||
/// SFML resource classes can usually be loaded directly from
|
||||
/// a filename, so this class shouldn't be useful to you unless
|
||||
/// you create your own algorithms that operate on an InputStream.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// void process(InputStream& stream);
|
||||
///
|
||||
/// FileInputStream stream;
|
||||
/// if (stream.open("some_file.dat"))
|
||||
/// process(stream);
|
||||
/// \endcode
|
||||
///
|
||||
/// InputStream, MemoryInputStream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,152 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_INPUTSTREAM_HPP
|
||||
#define SFML_INPUTSTREAM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Export.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Abstract class for custom file input streams
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API InputStream
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Virtual destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~InputStream() {}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read data from the stream
|
||||
///
|
||||
/// After reading, the stream's reading position must be
|
||||
/// advanced by the amount of bytes read.
|
||||
///
|
||||
/// \param data Buffer where to copy the read data
|
||||
/// \param size Desired number of bytes to read
|
||||
///
|
||||
/// \return The number of bytes actually read, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 read(void* data, Int64 size) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current reading position
|
||||
///
|
||||
/// \param position The position to seek to, from the beginning
|
||||
///
|
||||
/// \return The position actually sought to, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 seek(Int64 position) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current reading position in the stream
|
||||
///
|
||||
/// \return The current position, or -1 on error.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 tell() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the size of the stream
|
||||
///
|
||||
/// \return The total number of bytes available in the stream, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 getSize() = 0;
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_INPUTSTREAM_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::InputStream
|
||||
/// \ingroup system
|
||||
///
|
||||
/// This class allows users to define their own file input sources
|
||||
/// from which SFML can load resources.
|
||||
///
|
||||
/// SFML resource classes like sf::Texture and
|
||||
/// sf::SoundBuffer provide loadFromFile and loadFromMemory functions,
|
||||
/// which read data from conventional sources. However, if you
|
||||
/// have data coming from a different source (over a network,
|
||||
/// embedded, encrypted, compressed, etc) you can derive your
|
||||
/// own class from sf::InputStream and load SFML resources with
|
||||
/// their loadFromStream function.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // custom stream class that reads from inside a zip file
|
||||
/// class ZipStream : public sf::InputStream
|
||||
/// {
|
||||
/// public:
|
||||
///
|
||||
/// ZipStream(std::string archive);
|
||||
///
|
||||
/// bool open(std::string filename);
|
||||
///
|
||||
/// Int64 read(void* data, Int64 size);
|
||||
///
|
||||
/// Int64 seek(Int64 position);
|
||||
///
|
||||
/// Int64 tell();
|
||||
///
|
||||
/// Int64 getSize();
|
||||
///
|
||||
/// private:
|
||||
///
|
||||
/// ...
|
||||
/// };
|
||||
///
|
||||
/// // now you can load textures...
|
||||
/// sf::Texture texture;
|
||||
/// ZipStream stream("resources.zip");
|
||||
/// stream.open("images/img.png");
|
||||
/// texture.loadFromStream(stream);
|
||||
///
|
||||
/// // musics...
|
||||
/// sf::Music music;
|
||||
/// ZipStream stream("resources.zip");
|
||||
/// stream.open("musics/msc.ogg");
|
||||
/// music.openFromStream(stream);
|
||||
///
|
||||
/// // etc.
|
||||
/// \endcode
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,139 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_LOCK_HPP
|
||||
#define SFML_LOCK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Mutex;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Automatic wrapper for locking and unlocking mutexes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API Lock : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the lock with a target mutex
|
||||
///
|
||||
/// The mutex passed to sf::Lock is automatically locked.
|
||||
///
|
||||
/// \param mutex Mutex to lock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit Lock(Mutex& mutex);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
/// The destructor of sf::Lock automatically unlocks its mutex.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~Lock();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex& m_mutex; //!< Mutex to lock / unlock
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_LOCK_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Lock
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::Lock is a RAII wrapper for sf::Mutex. By unlocking
|
||||
/// it in its destructor, it ensures that the mutex will
|
||||
/// always be released when the current scope (most likely
|
||||
/// a function) ends.
|
||||
/// This is even more important when an exception or an early
|
||||
/// return statement can interrupt the execution flow of the
|
||||
/// function.
|
||||
///
|
||||
/// For maximum robustness, sf::Lock should always be used
|
||||
/// to lock/unlock a mutex.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::Mutex mutex;
|
||||
///
|
||||
/// void function()
|
||||
/// {
|
||||
/// sf::Lock lock(mutex); // mutex is now locked
|
||||
///
|
||||
/// functionThatMayThrowAnException(); // mutex is unlocked if this function throws
|
||||
///
|
||||
/// if (someCondition)
|
||||
/// return; // mutex is unlocked
|
||||
///
|
||||
/// } // mutex is unlocked
|
||||
/// \endcode
|
||||
///
|
||||
/// Because the mutex is not explicitly unlocked in the code,
|
||||
/// it may remain locked longer than needed. If the region
|
||||
/// of the code that needs to be protected by the mutex is
|
||||
/// not the entire function, a good practice is to create a
|
||||
/// smaller, inner scope so that the lock is limited to this
|
||||
/// part of the code.
|
||||
///
|
||||
/// \code
|
||||
/// sf::Mutex mutex;
|
||||
///
|
||||
/// void function()
|
||||
/// {
|
||||
/// {
|
||||
/// sf::Lock lock(mutex);
|
||||
/// codeThatRequiresProtection();
|
||||
///
|
||||
/// } // mutex is unlocked here
|
||||
///
|
||||
/// codeThatDoesntCareAboutTheMutex();
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Having a mutex locked longer than required is a bad practice
|
||||
/// which can lead to bad performances. Don't forget that when
|
||||
/// a mutex is locked, other threads may be waiting doing nothing
|
||||
/// until it is released.
|
||||
///
|
||||
/// \see sf::Mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,148 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_MEMORYINPUTSTREAM_HPP
|
||||
#define SFML_MEMORYINPUTSTREAM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implementation of input stream based on a memory chunk
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API MemoryInputStream : public InputStream
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MemoryInputStream();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open the stream from its data
|
||||
///
|
||||
/// \param data Pointer to the data in memory
|
||||
/// \param sizeInBytes Size of the data, in bytes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void open(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read data from the stream
|
||||
///
|
||||
/// After reading, the stream's reading position must be
|
||||
/// advanced by the amount of bytes read.
|
||||
///
|
||||
/// \param data Buffer where to copy the read data
|
||||
/// \param size Desired number of bytes to read
|
||||
///
|
||||
/// \return The number of bytes actually read, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 read(void* data, Int64 size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current reading position
|
||||
///
|
||||
/// \param position The position to seek to, from the beginning
|
||||
///
|
||||
/// \return The position actually sought to, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 seek(Int64 position);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current reading position in the stream
|
||||
///
|
||||
/// \return The current position, or -1 on error.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 tell();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the size of the stream
|
||||
///
|
||||
/// \return The total number of bytes available in the stream, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual Int64 getSize();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
const char* m_data; //!< Pointer to the data in memory
|
||||
Int64 m_size; //!< Total size of the data
|
||||
Int64 m_offset; //!< Current reading position
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MEMORYINPUTSTREAM_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::MemoryInputStream
|
||||
/// \ingroup system
|
||||
///
|
||||
/// This class is a specialization of InputStream that
|
||||
/// reads from data in memory.
|
||||
///
|
||||
/// It wraps a memory chunk in the common InputStream interface
|
||||
/// and therefore allows to use generic classes or functions
|
||||
/// that accept such a stream, with content already loaded in memory.
|
||||
///
|
||||
/// In addition to the virtual functions inherited from
|
||||
/// InputStream, MemoryInputStream adds a function to
|
||||
/// specify the pointer and size of the data in memory.
|
||||
///
|
||||
/// SFML resource classes can usually be loaded directly from
|
||||
/// memory, so this class shouldn't be useful to you unless
|
||||
/// you create your own algorithms that operate on an InputStream.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// void process(InputStream& stream);
|
||||
///
|
||||
/// MemoryInputStream stream;
|
||||
/// stream.open(thePtr, theSize);
|
||||
/// process(stream);
|
||||
/// \endcode
|
||||
///
|
||||
/// InputStream, FileInputStream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,148 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_MUTEX_HPP
|
||||
#define SFML_MUTEX_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class MutexImpl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Blocks concurrent access to shared resources
|
||||
/// from multiple threads
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API Mutex : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~Mutex();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
/// If the mutex is already locked in another thread,
|
||||
/// this call will block the execution until the mutex
|
||||
/// is released.
|
||||
///
|
||||
/// \see unlock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
/// \see lock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
priv::MutexImpl* m_mutexImpl; //!< OS-specific implementation
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEX_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Mutex
|
||||
/// \ingroup system
|
||||
///
|
||||
/// Mutex stands for "MUTual EXclusion". A mutex is a
|
||||
/// synchronization object, used when multiple threads are involved.
|
||||
///
|
||||
/// When you want to protect a part of the code from being accessed
|
||||
/// simultaneously by multiple threads, you typically use a
|
||||
/// mutex. When a thread is locked by a mutex, any other thread
|
||||
/// trying to lock it will be blocked until the mutex is released
|
||||
/// by the thread that locked it. This way, you can allow only
|
||||
/// one thread at a time to access a critical region of your code.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// Database database; // this is a critical resource that needs some protection
|
||||
/// sf::Mutex mutex;
|
||||
///
|
||||
/// void thread1()
|
||||
/// {
|
||||
/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread2
|
||||
/// database.write(...);
|
||||
/// mutex.unlock(); // if thread2 was waiting, it will now be unblocked
|
||||
/// }
|
||||
///
|
||||
/// void thread2()
|
||||
/// {
|
||||
/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread1
|
||||
/// database.write(...);
|
||||
/// mutex.unlock(); // if thread1 was waiting, it will now be unblocked
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// Be very careful with mutexes. A bad usage can lead to bad problems,
|
||||
/// like deadlocks (two threads are waiting for each other and the
|
||||
/// application is globally stuck).
|
||||
///
|
||||
/// To make the usage of mutexes more robust, particularly in
|
||||
/// environments where exceptions can be thrown, you should
|
||||
/// use the helper class sf::Lock to lock/unlock mutexes.
|
||||
///
|
||||
/// SFML mutexes are recursive, which means that you can lock
|
||||
/// a mutex multiple times in the same thread without creating
|
||||
/// a deadlock. In this case, the first call to lock() behaves
|
||||
/// as usual, and the following ones have no effect.
|
||||
/// However, you must call unlock() exactly as many times as you
|
||||
/// called lock(). If you don't, the mutex won't be released.
|
||||
///
|
||||
/// \see sf::Lock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,62 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_NATIVEACTIVITY_HPP
|
||||
#define SFML_NATIVEACTIVITY_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
|
||||
|
||||
#if !defined(SFML_SYSTEM_ANDROID)
|
||||
#error NativeActivity.hpp: This header is Android only.
|
||||
#endif
|
||||
|
||||
|
||||
struct ANativeActivity;
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \ingroup system
|
||||
/// \brief Return a pointer to the Android native activity
|
||||
///
|
||||
/// You shouldn't have to use this function, unless you want
|
||||
/// to implement very specific details, that SFML doesn't
|
||||
/// support, or to use a workaround for a known issue.
|
||||
///
|
||||
/// \return Pointer to Android native activity structure
|
||||
///
|
||||
/// \sfplatform{Android,SFML/System/NativeActivity.hpp}
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SFML_SYSTEM_API ANativeActivity* getNativeActivity();
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_NATIVEACTIVITY_HPP
|
|
@ -0,0 +1,129 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,52 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_SLEEP_HPP
|
||||
#define SFML_SLEEP_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \ingroup system
|
||||
/// \brief Make the current thread sleep for a given duration
|
||||
///
|
||||
/// sf::sleep is the best way to block a program or one of its
|
||||
/// threads, as it doesn't consume any CPU power.
|
||||
///
|
||||
/// \param duration Time to sleep
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void SFML_SYSTEM_API sleep(Time duration);
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SLEEP_HPP
|
|
@ -0,0 +1,669 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,53 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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;
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_THREAD_HPP
|
||||
#define SFML_THREAD_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class ThreadImpl;
|
||||
struct ThreadFunc;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility class to manipulate threads
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API Thread : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the thread from a functor with no argument
|
||||
///
|
||||
/// This constructor works for function objects, as well
|
||||
/// as free functions.
|
||||
///
|
||||
/// Use this constructor for this kind of function:
|
||||
/// \code
|
||||
/// void function();
|
||||
///
|
||||
/// // --- or ----
|
||||
///
|
||||
/// struct Functor
|
||||
/// {
|
||||
/// void operator()();
|
||||
/// };
|
||||
/// \endcode
|
||||
/// Note: this does *not* run the thread, use launch().
|
||||
///
|
||||
/// \param function Functor or free function to use as the entry point of the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename F>
|
||||
Thread(F function);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the thread from a functor with an argument
|
||||
///
|
||||
/// This constructor works for function objects, as well
|
||||
/// as free functions.
|
||||
/// It is a template, which means that the argument can
|
||||
/// have any type (int, std::string, void*, Toto, ...).
|
||||
///
|
||||
/// Use this constructor for this kind of function:
|
||||
/// \code
|
||||
/// void function(int arg);
|
||||
///
|
||||
/// // --- or ----
|
||||
///
|
||||
/// struct Functor
|
||||
/// {
|
||||
/// void operator()(std::string arg);
|
||||
/// };
|
||||
/// \endcode
|
||||
/// Note: this does *not* run the thread, use launch().
|
||||
///
|
||||
/// \param function Functor or free function to use as the entry point of the thread
|
||||
/// \param argument argument to forward to the function
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename F, typename A>
|
||||
Thread(F function, A argument);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the thread from a member function and an object
|
||||
///
|
||||
/// This constructor is a template, which means that you can
|
||||
/// use it with any class.
|
||||
/// Use this constructor for this kind of function:
|
||||
/// \code
|
||||
/// class MyClass
|
||||
/// {
|
||||
/// public:
|
||||
///
|
||||
/// void function();
|
||||
/// };
|
||||
/// \endcode
|
||||
/// Note: this does *not* run the thread, use launch().
|
||||
///
|
||||
/// \param function Entry point of the thread
|
||||
/// \param object Pointer to the object to use
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename C>
|
||||
Thread(void(C::*function)(), C* object);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
/// This destructor calls wait(), so that the internal thread
|
||||
/// cannot survive after its sf::Thread instance is destroyed.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~Thread();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Run the thread
|
||||
///
|
||||
/// This function starts the entry point passed to the
|
||||
/// thread's constructor, and returns immediately.
|
||||
/// After this function returns, the thread's function is
|
||||
/// running in parallel to the calling code.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void launch();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
/// This function will block the execution until the
|
||||
/// thread's function ends.
|
||||
/// Warning: if the thread function never ends, the calling
|
||||
/// thread will block forever.
|
||||
/// If this function is called from its owner thread, it
|
||||
/// returns without doing anything.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
/// This function immediately stops the thread, without waiting
|
||||
/// for its function to finish.
|
||||
/// Terminating a thread with this function is not safe,
|
||||
/// and can lead to local variables not being destroyed
|
||||
/// on some operating systems. You should rather try to make
|
||||
/// the thread function terminate by itself.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
|
||||
friend class priv::ThreadImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Internal entry point of the thread
|
||||
///
|
||||
/// This function is called by the thread implementation.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void run();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
priv::ThreadImpl* m_impl; //!< OS-specific implementation of the thread
|
||||
priv::ThreadFunc* m_entryPoint; //!< Abstraction of the function to run
|
||||
};
|
||||
|
||||
#include <SFML/System/Thread.inl>
|
||||
|
||||
} // namespace sf
|
||||
|
||||
#endif // SFML_THREAD_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Thread
|
||||
/// \ingroup system
|
||||
///
|
||||
/// Threads provide a way to run multiple parts of the code
|
||||
/// in parallel. When you launch a new thread, the execution
|
||||
/// is split and both the new thread and the caller run
|
||||
/// in parallel.
|
||||
///
|
||||
/// To use a sf::Thread, you construct it directly with the
|
||||
/// function to execute as the entry point of the thread.
|
||||
/// sf::Thread has multiple template constructors, which means
|
||||
/// that you can use several types of entry points:
|
||||
/// \li non-member functions with no argument
|
||||
/// \li non-member functions with one argument of any type
|
||||
/// \li functors with no argument (this one is particularly useful for compatibility with boost/std::%bind)
|
||||
/// \li functors with one argument of any type
|
||||
/// \li member functions from any class with no argument
|
||||
///
|
||||
/// The function argument, if any, is copied in the sf::Thread
|
||||
/// instance, as well as the functor (if the corresponding
|
||||
/// constructor is used). Class instances, however, are passed
|
||||
/// by pointer so you must make sure that the object won't be
|
||||
/// destroyed while the thread is still using it.
|
||||
///
|
||||
/// The thread ends when its function is terminated. If the
|
||||
/// owner sf::Thread instance is destroyed before the
|
||||
/// thread is finished, the destructor will wait (see wait())
|
||||
///
|
||||
/// Usage examples:
|
||||
/// \code
|
||||
/// // example 1: non member function with one argument
|
||||
///
|
||||
/// void threadFunc(int argument)
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// sf::Thread thread(&threadFunc, 5);
|
||||
/// thread.launch(); // start the thread (internally calls threadFunc(5))
|
||||
/// \endcode
|
||||
///
|
||||
/// \code
|
||||
/// // example 2: member function
|
||||
///
|
||||
/// class Task
|
||||
/// {
|
||||
/// public:
|
||||
/// void run()
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// Task task;
|
||||
/// sf::Thread thread(&Task::run, &task);
|
||||
/// thread.launch(); // start the thread (internally calls task.run())
|
||||
/// \endcode
|
||||
///
|
||||
/// \code
|
||||
/// // example 3: functor
|
||||
///
|
||||
/// struct Task
|
||||
/// {
|
||||
/// void operator()()
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// sf::Thread thread(Task());
|
||||
/// thread.launch(); // start the thread (internally calls operator() on the Task instance)
|
||||
/// \endcode
|
||||
///
|
||||
/// Creating parallel threads of execution can be dangerous:
|
||||
/// all threads inside the same process share the same memory space,
|
||||
/// which means that you may end up accessing the same variable
|
||||
/// from multiple threads at the same time. To prevent this
|
||||
/// kind of situations, you can use mutexes (see sf::Mutex).
|
||||
///
|
||||
/// \see sf::Mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,90 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
namespace priv
|
||||
{
|
||||
// Base class for abstract thread functions
|
||||
struct ThreadFunc
|
||||
{
|
||||
virtual ~ThreadFunc() {}
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
// Specialization using a functor (including free functions) with no argument
|
||||
template <typename T>
|
||||
struct ThreadFunctor : ThreadFunc
|
||||
{
|
||||
ThreadFunctor(T functor) : m_functor(functor) {}
|
||||
virtual void run() {m_functor();}
|
||||
T m_functor;
|
||||
};
|
||||
|
||||
// Specialization using a functor (including free functions) with one argument
|
||||
template <typename F, typename A>
|
||||
struct ThreadFunctorWithArg : ThreadFunc
|
||||
{
|
||||
ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {}
|
||||
virtual void run() {m_function(m_arg);}
|
||||
F m_function;
|
||||
A m_arg;
|
||||
};
|
||||
|
||||
// Specialization using a member function
|
||||
template <typename C>
|
||||
struct ThreadMemberFunc : ThreadFunc
|
||||
{
|
||||
ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {}
|
||||
virtual void run() {(m_object->*m_function)();}
|
||||
void(C::*m_function)();
|
||||
C* m_object;
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename F>
|
||||
Thread::Thread(F functor) :
|
||||
m_impl (NULL),
|
||||
m_entryPoint(new priv::ThreadFunctor<F>(functor))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename F, typename A>
|
||||
Thread::Thread(F function, A argument) :
|
||||
m_impl (NULL),
|
||||
m_entryPoint(new priv::ThreadFunctorWithArg<F, A>(function, argument))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename C>
|
||||
Thread::Thread(void(C::*function)(), C* object) :
|
||||
m_impl (NULL),
|
||||
m_entryPoint(new priv::ThreadMemberFunc<C>(function, object))
|
||||
{
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_THREADLOCAL_HPP
|
||||
#define SFML_THREADLOCAL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class ThreadLocalImpl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Defines variables with thread-local storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API ThreadLocal : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// \param value Optional value to initialize the variable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal(void* value = NULL);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadLocal();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the thread-specific value of the variable
|
||||
///
|
||||
/// \param value Value of the variable for the current thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setValue(void* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the thread-specific value of the variable
|
||||
///
|
||||
/// \return Value of the variable for the current thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void* getValue() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
priv::ThreadLocalImpl* m_impl; //!< Pointer to the OS specific implementation
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCAL_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::ThreadLocal
|
||||
/// \ingroup system
|
||||
///
|
||||
/// This class manipulates void* parameters and thus is not
|
||||
/// appropriate for strongly-typed variables. You should rather
|
||||
/// use the sf::ThreadLocalPtr template class.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,158 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_THREADLOCALPTR_HPP
|
||||
#define SFML_THREADLOCALPTR_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/ThreadLocal.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Pointer to a thread-local variable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class ThreadLocalPtr : private ThreadLocal
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// \param value Optional value to initialize the variable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalPtr(T* value = NULL);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of unary operator *
|
||||
///
|
||||
/// Like raw pointers, applying the * operator returns a
|
||||
/// reference to the pointed-to object.
|
||||
///
|
||||
/// \return Reference to the thread-local variable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
T& operator *() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of operator ->
|
||||
///
|
||||
/// Similarly to raw pointers, applying the -> operator
|
||||
/// returns the pointed-to object.
|
||||
///
|
||||
/// \return Pointer to the thread-local variable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
T* operator ->() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Conversion operator to implicitly convert the
|
||||
/// pointer to its raw pointer type (T*)
|
||||
///
|
||||
/// \return Pointer to the actual object
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
operator T*() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Assignment operator for a raw pointer parameter
|
||||
///
|
||||
/// \param value Pointer to assign
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalPtr<T>& operator =(T* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Assignment operator for a ThreadLocalPtr parameter
|
||||
///
|
||||
/// \param right ThreadLocalPtr to assign
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalPtr<T>& operator =(const ThreadLocalPtr<T>& right);
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
#include <SFML/System/ThreadLocalPtr.inl>
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCALPTR_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::ThreadLocalPtr
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::ThreadLocalPtr is a type-safe wrapper for storing
|
||||
/// pointers to thread-local variables. A thread-local
|
||||
/// variable holds a different value for each different
|
||||
/// thread, unlike normal variables that are shared.
|
||||
///
|
||||
/// Its usage is completely transparent, so that it is similar
|
||||
/// to manipulating the raw pointer directly (like any smart pointer).
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// MyClass object1;
|
||||
/// MyClass object2;
|
||||
/// sf::ThreadLocalPtr<MyClass> objectPtr;
|
||||
///
|
||||
/// void thread1()
|
||||
/// {
|
||||
/// objectPtr = &object1; // doesn't impact thread2
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// void thread2()
|
||||
/// {
|
||||
/// objectPtr = &object2; // doesn't impact thread1
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
/// // Create and launch the two threads
|
||||
/// sf::Thread t1(&thread1);
|
||||
/// sf::Thread t2(&thread2);
|
||||
/// t1.launch();
|
||||
/// t2.launch();
|
||||
///
|
||||
/// return 0;
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// ThreadLocalPtr is designed for internal use; however you
|
||||
/// can use it if you feel like it fits well your implementation.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,77 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
ThreadLocalPtr<T>::ThreadLocalPtr(T* value) :
|
||||
ThreadLocal(value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
T& ThreadLocalPtr<T>::operator *() const
|
||||
{
|
||||
return *static_cast<T*>(getValue());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
T* ThreadLocalPtr<T>::operator ->() const
|
||||
{
|
||||
return static_cast<T*>(getValue());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
ThreadLocalPtr<T>::operator T*() const
|
||||
{
|
||||
return static_cast<T*>(getValue());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
ThreadLocalPtr<T>& ThreadLocalPtr<T>::operator =(T* value)
|
||||
{
|
||||
setValue(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
ThreadLocalPtr<T>& ThreadLocalPtr<T>::operator =(const ThreadLocalPtr<T>& right)
|
||||
{
|
||||
setValue(right.getValue());
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,488 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,763 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,752 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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; // fallthrough
|
||||
case 4: output += static_cast<Uint8>(*begin++); output <<= 6; // fallthrough
|
||||
case 3: output += static_cast<Uint8>(*begin++); output <<= 6; // fallthrough
|
||||
case 2: output += static_cast<Uint8>(*begin++); output <<= 6; // fallthrough
|
||||
case 1: output += static_cast<Uint8>(*begin++); output <<= 6; // fallthrough
|
||||
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 = std::copy(&replacement, &replacement + 1, output);
|
||||
}
|
||||
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; // fallthrough
|
||||
case 3: bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; // fallthrough
|
||||
case 2: bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; // fallthrough
|
||||
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 = ((first - 0xD800u) << 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 static_cast<Uint32>(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;
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_VECTOR2_HPP
|
||||
#define SFML_VECTOR2_HPP
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility template class for manipulating
|
||||
/// 2-dimensional vectors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class Vector2
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// Creates a Vector2(0, 0).
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the vector from its coordinates
|
||||
///
|
||||
/// \param X X coordinate
|
||||
/// \param Y Y coordinate
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2(T X, T Y);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the vector from another type of vector
|
||||
///
|
||||
/// This constructor doesn't replace the copy constructor,
|
||||
/// it's called only when U != T.
|
||||
/// A call to this constructor will fail to compile if U
|
||||
/// is not convertible to T.
|
||||
///
|
||||
/// \param vector Vector to convert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename U>
|
||||
explicit Vector2(const Vector2<U>& vector);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
T x; //!< X coordinate of the vector
|
||||
T y; //!< Y coordinate of the vector
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of unary operator -
|
||||
///
|
||||
/// \param right Vector to negate
|
||||
///
|
||||
/// \return Memberwise opposite of the vector
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T> operator -(const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator +=
|
||||
///
|
||||
/// This operator performs a memberwise addition of both vectors,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator -=
|
||||
///
|
||||
/// This operator performs a memberwise subtraction of both vectors,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator +
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Memberwise addition of both vectors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator -
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Memberwise subtraction of both vectors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator *
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Memberwise multiplication by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T> operator *(const Vector2<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator *
|
||||
///
|
||||
/// \param left Left operand (a scalar value)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Memberwise multiplication by \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T> operator *(T left, const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator *=
|
||||
///
|
||||
/// This operator performs a memberwise multiplication by \a right,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T>& operator *=(Vector2<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator /
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Memberwise division by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T> operator /(const Vector2<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator /=
|
||||
///
|
||||
/// This operator performs a memberwise division by \a right,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector2<T>& operator /=(Vector2<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator ==
|
||||
///
|
||||
/// This operator compares strict equality between two vectors.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return True if \a left is equal to \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
bool operator ==(const Vector2<T>& left, const Vector2<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector2
|
||||
/// \brief Overload of binary operator !=
|
||||
///
|
||||
/// This operator compares strict difference between two vectors.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return True if \a left is not equal to \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
bool operator !=(const Vector2<T>& left, const Vector2<T>& right);
|
||||
|
||||
#include <SFML/System/Vector2.inl>
|
||||
|
||||
// Define the most common types
|
||||
typedef Vector2<int> Vector2i;
|
||||
typedef Vector2<unsigned int> Vector2u;
|
||||
typedef Vector2<float> Vector2f;
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_VECTOR2_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Vector2
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::Vector2 is a simple class that defines a mathematical
|
||||
/// vector with two coordinates (x and y). It can be used to
|
||||
/// represent anything that has two dimensions: a size, a point,
|
||||
/// a velocity, etc.
|
||||
///
|
||||
/// The template parameter T is the type of the coordinates. It
|
||||
/// can be any type that supports arithmetic operations (+, -, /, *)
|
||||
/// and comparisons (==, !=), for example int or float.
|
||||
///
|
||||
/// You generally don't have to care about the templated form (sf::Vector2<T>),
|
||||
/// the most common specializations have special typedefs:
|
||||
/// \li sf::Vector2<float> is sf::Vector2f
|
||||
/// \li sf::Vector2<int> is sf::Vector2i
|
||||
/// \li sf::Vector2<unsigned int> is sf::Vector2u
|
||||
///
|
||||
/// The sf::Vector2 class has a small and simple interface, its x and y members
|
||||
/// can be accessed directly (there are no accessors like setX(), getX()) and it
|
||||
/// contains no mathematical function like dot product, cross product, length, etc.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::Vector2f v1(16.5f, 24.f);
|
||||
/// v1.x = 18.2f;
|
||||
/// float y = v1.y;
|
||||
///
|
||||
/// sf::Vector2f v2 = v1 * 5.f;
|
||||
/// sf::Vector2f v3;
|
||||
/// v3 = v1 + v2;
|
||||
///
|
||||
/// bool different = (v2 != v3);
|
||||
/// \endcode
|
||||
///
|
||||
/// Note: for 3-dimensional vectors, see sf::Vector3.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,161 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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>
|
||||
inline Vector2<T>::Vector2() :
|
||||
x(0),
|
||||
y(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T>::Vector2(T X, T Y) :
|
||||
x(X),
|
||||
y(Y)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
inline Vector2<T>::Vector2(const Vector2<U>& vector) :
|
||||
x(static_cast<T>(vector.x)),
|
||||
y(static_cast<T>(vector.y))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T> operator -(const Vector2<T>& right)
|
||||
{
|
||||
return Vector2<T>(-right.x, -right.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right)
|
||||
{
|
||||
left.x += right.x;
|
||||
left.y += right.y;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right)
|
||||
{
|
||||
left.x -= right.x;
|
||||
left.y -= right.y;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right)
|
||||
{
|
||||
return Vector2<T>(left.x + right.x, left.y + right.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right)
|
||||
{
|
||||
return Vector2<T>(left.x - right.x, left.y - right.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T> operator *(const Vector2<T>& left, T right)
|
||||
{
|
||||
return Vector2<T>(left.x * right, left.y * right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T> operator *(T left, const Vector2<T>& right)
|
||||
{
|
||||
return Vector2<T>(right.x * left, right.y * left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T>& operator *=(Vector2<T>& left, T right)
|
||||
{
|
||||
left.x *= right;
|
||||
left.y *= right;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T> operator /(const Vector2<T>& left, T right)
|
||||
{
|
||||
return Vector2<T>(left.x / right, left.y / right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector2<T>& operator /=(Vector2<T>& left, T right)
|
||||
{
|
||||
left.x /= right;
|
||||
left.y /= right;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline bool operator ==(const Vector2<T>& left, const Vector2<T>& right)
|
||||
{
|
||||
return (left.x == right.x) && (left.y == right.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline bool operator !=(const Vector2<T>& left, const Vector2<T>& right)
|
||||
{
|
||||
return (left.x != right.x) || (left.y != right.y);
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_VECTOR3_HPP
|
||||
#define SFML_VECTOR3_HPP
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Utility template class for manipulating
|
||||
/// 3-dimensional vectors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class Vector3
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// Creates a Vector3(0, 0, 0).
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the vector from its coordinates
|
||||
///
|
||||
/// \param X X coordinate
|
||||
/// \param Y Y coordinate
|
||||
/// \param Z Z coordinate
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3(T X, T Y, T Z);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the vector from another type of vector
|
||||
///
|
||||
/// This constructor doesn't replace the copy constructor,
|
||||
/// it's called only when U != T.
|
||||
/// A call to this constructor will fail to compile if U
|
||||
/// is not convertible to T.
|
||||
///
|
||||
/// \param vector Vector to convert
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename U>
|
||||
explicit Vector3(const Vector3<U>& vector);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
T x; //!< X coordinate of the vector
|
||||
T y; //!< Y coordinate of the vector
|
||||
T z; //!< Z coordinate of the vector
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of unary operator -
|
||||
///
|
||||
/// \param left Vector to negate
|
||||
///
|
||||
/// \return Memberwise opposite of the vector
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T> operator -(const Vector3<T>& left);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator +=
|
||||
///
|
||||
/// This operator performs a memberwise addition of both vectors,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator -=
|
||||
///
|
||||
/// This operator performs a memberwise subtraction of both vectors,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator +
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Memberwise addition of both vectors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator -
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Memberwise subtraction of both vectors
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator *
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Memberwise multiplication by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T> operator *(const Vector3<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator *
|
||||
///
|
||||
/// \param left Left operand (a scalar value)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return Memberwise multiplication by \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T> operator *(T left, const Vector3<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator *=
|
||||
///
|
||||
/// This operator performs a memberwise multiplication by \a right,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T>& operator *=(Vector3<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator /
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Memberwise division by \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T> operator /(const Vector3<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator /=
|
||||
///
|
||||
/// This operator performs a memberwise division by \a right,
|
||||
/// and assigns the result to \a left.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a scalar value)
|
||||
///
|
||||
/// \return Reference to \a left
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
Vector3<T>& operator /=(Vector3<T>& left, T right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator ==
|
||||
///
|
||||
/// This operator compares strict equality between two vectors.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return True if \a left is equal to \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
bool operator ==(const Vector3<T>& left, const Vector3<T>& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \relates Vector3
|
||||
/// \brief Overload of binary operator !=
|
||||
///
|
||||
/// This operator compares strict difference between two vectors.
|
||||
///
|
||||
/// \param left Left operand (a vector)
|
||||
/// \param right Right operand (a vector)
|
||||
///
|
||||
/// \return True if \a left is not equal to \a right
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
bool operator !=(const Vector3<T>& left, const Vector3<T>& right);
|
||||
|
||||
#include <SFML/System/Vector3.inl>
|
||||
|
||||
// Define the most common types
|
||||
typedef Vector3<int> Vector3i;
|
||||
typedef Vector3<float> Vector3f;
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_VECTOR3_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Vector3
|
||||
/// \ingroup system
|
||||
///
|
||||
/// sf::Vector3 is a simple class that defines a mathematical
|
||||
/// vector with three coordinates (x, y and z). It can be used to
|
||||
/// represent anything that has three dimensions: a size, a point,
|
||||
/// a velocity, etc.
|
||||
///
|
||||
/// The template parameter T is the type of the coordinates. It
|
||||
/// can be any type that supports arithmetic operations (+, -, /, *)
|
||||
/// and comparisons (==, !=), for example int or float.
|
||||
///
|
||||
/// You generally don't have to care about the templated form (sf::Vector3<T>),
|
||||
/// the most common specializations have special typedefs:
|
||||
/// \li sf::Vector3<float> is sf::Vector3f
|
||||
/// \li sf::Vector3<int> is sf::Vector3i
|
||||
///
|
||||
/// The sf::Vector3 class has a small and simple interface, its x and y members
|
||||
/// can be accessed directly (there are no accessors like setX(), getX()) and it
|
||||
/// contains no mathematical function like dot product, cross product, length, etc.
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::Vector3f v1(16.5f, 24.f, -8.2f);
|
||||
/// v1.x = 18.2f;
|
||||
/// float y = v1.y;
|
||||
/// float z = v1.z;
|
||||
///
|
||||
/// sf::Vector3f v2 = v1 * 5.f;
|
||||
/// sf::Vector3f v3;
|
||||
/// v3 = v1 + v2;
|
||||
///
|
||||
/// bool different = (v2 != v3);
|
||||
/// \endcode
|
||||
///
|
||||
/// Note: for 2-dimensional vectors, see sf::Vector2.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,168 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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>
|
||||
inline Vector3<T>::Vector3() :
|
||||
x(0),
|
||||
y(0),
|
||||
z(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T>::Vector3(T X, T Y, T Z) :
|
||||
x(X),
|
||||
y(Y),
|
||||
z(Z)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
inline Vector3<T>::Vector3(const Vector3<U>& vector) :
|
||||
x(static_cast<T>(vector.x)),
|
||||
y(static_cast<T>(vector.y)),
|
||||
z(static_cast<T>(vector.z))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T> operator -(const Vector3<T>& left)
|
||||
{
|
||||
return Vector3<T>(-left.x, -left.y, -left.z);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right)
|
||||
{
|
||||
left.x += right.x;
|
||||
left.y += right.y;
|
||||
left.z += right.z;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right)
|
||||
{
|
||||
left.x -= right.x;
|
||||
left.y -= right.y;
|
||||
left.z -= right.z;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right)
|
||||
{
|
||||
return Vector3<T>(left.x + right.x, left.y + right.y, left.z + right.z);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right)
|
||||
{
|
||||
return Vector3<T>(left.x - right.x, left.y - right.y, left.z - right.z);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T> operator *(const Vector3<T>& left, T right)
|
||||
{
|
||||
return Vector3<T>(left.x * right, left.y * right, left.z * right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T> operator *(T left, const Vector3<T>& right)
|
||||
{
|
||||
return Vector3<T>(right.x * left, right.y * left, right.z * left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T>& operator *=(Vector3<T>& left, T right)
|
||||
{
|
||||
left.x *= right;
|
||||
left.y *= right;
|
||||
left.z *= right;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T> operator /(const Vector3<T>& left, T right)
|
||||
{
|
||||
return Vector3<T>(left.x / right, left.y / right, left.z / right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline Vector3<T>& operator /=(Vector3<T>& left, T right)
|
||||
{
|
||||
left.x /= right;
|
||||
left.y /= right;
|
||||
left.z /= right;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline bool operator ==(const Vector3<T>& left, const Vector3<T>& right)
|
||||
{
|
||||
return (left.x == right.x) && (left.y == right.y) && (left.z == right.z);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline bool operator !=(const Vector3<T>& left, const Vector3<T>& right)
|
||||
{
|
||||
return (left.x != right.x) || (left.y != right.y) || (left.z != right.z);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# SFML
|
||||
|
||||
SFML - Copyright (C) 2007-2023 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.
|
||||
|
||||
## External libraries used by SFML
|
||||
|
||||
* _OpenAL-Soft_ is under the LGPL license
|
||||
* _stb_image_ and _stb_image_write_ are public domain
|
||||
* _freetype_ is under the FreeType license or the GPL license
|
||||
* _libogg_ is under the BSD license
|
||||
* _libvorbis_ is under the BSD license
|
||||
* _libflac_ is under the BSD license
|
||||
* _minimp3_ is under the CC0 license
|
|
@ -0,0 +1,59 @@
|
|||
set(PROJECT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Ftp.cpp
|
||||
${INCROOT}/Ftp.hpp
|
||||
${SRCROOT}/Http.cpp
|
||||
${INCROOT}/Http.hpp
|
||||
${SRCROOT}/IpAddress.cpp
|
||||
${INCROOT}/IpAddress.hpp
|
||||
${SRCROOT}/Packet.cpp
|
||||
${INCROOT}/Packet.hpp
|
||||
${SRCROOT}/Socket.cpp
|
||||
${INCROOT}/Socket.hpp
|
||||
${SRCROOT}/SocketImpl.hpp
|
||||
${INCROOT}/SocketHandle.hpp
|
||||
${SRCROOT}/SocketSelector.cpp
|
||||
${INCROOT}/SocketSelector.hpp
|
||||
${SRCROOT}/TcpListener.cpp
|
||||
${INCROOT}/TcpListener.hpp
|
||||
${SRCROOT}/TcpSocket.cpp
|
||||
${INCROOT}/TcpSocket.hpp
|
||||
${SRCROOT}/UdpSocket.cpp
|
||||
${INCROOT}/UdpSocket.hpp
|
||||
)
|
||||
|
||||
# add platform specific sources
|
||||
if(WIN32)
|
||||
set(SRC
|
||||
${SRC}
|
||||
${SRCROOT}/Win32/SocketImpl.cpp
|
||||
${SRCROOT}/Win32/SocketImpl.hpp
|
||||
)
|
||||
else()
|
||||
set(SRC
|
||||
${SRC}
|
||||
${SRCROOT}/Unix/SocketImpl.cpp
|
||||
${SRCROOT}/Unix/SocketImpl.hpp
|
||||
)
|
||||
endif()
|
||||
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# define the sfml-network target
|
||||
add_library(sfml-network ${SRC})
|
||||
|
||||
target_include_directories(sfml-network PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
|
||||
|
||||
target_compile_definitions(sfml-network PRIVATE SFML_STATIC)
|
||||
|
||||
# setup dependencies
|
||||
target_link_libraries(sfml-network PUBLIC sfml-system)
|
||||
if(WIN32)
|
||||
target_link_libraries(sfml-network PRIVATE ws2_32)
|
||||
endif()
|
|
@ -0,0 +1,653 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Ftp.hpp>
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
class Ftp::DataChannel : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
DataChannel(Ftp& owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response open(Ftp::TransferMode mode);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void send(std::istream& stream);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void receive(std::ostream& stream);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp& m_ftp; //!< Reference to the owner Ftp instance
|
||||
TcpSocket m_dataSocket; //!< Socket used for data transfers
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response::Response(Status code, const std::string& message) :
|
||||
m_status (code),
|
||||
m_message(message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Ftp::Response::isOk() const
|
||||
{
|
||||
return m_status < 400;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response::Status Ftp::Response::getStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Ftp::Response::getMessage() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DirectoryResponse::DirectoryResponse(const Ftp::Response& response) :
|
||||
Ftp::Response(response)
|
||||
{
|
||||
if (isOk())
|
||||
{
|
||||
// Extract the directory from the server response
|
||||
std::string::size_type begin = getMessage().find('"', 0);
|
||||
std::string::size_type end = getMessage().find('"', begin + 1);
|
||||
m_directory = getMessage().substr(begin + 1, end - begin - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Ftp::DirectoryResponse::getDirectory() const
|
||||
{
|
||||
return m_directory;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::ListingResponse::ListingResponse(const Ftp::Response& response, const std::string& data) :
|
||||
Ftp::Response(response)
|
||||
{
|
||||
if (isOk())
|
||||
{
|
||||
// Fill the array of strings
|
||||
std::string::size_type lastPos = 0;
|
||||
for (std::string::size_type pos = data.find("\r\n"); pos != std::string::npos; pos = data.find("\r\n", lastPos))
|
||||
{
|
||||
m_listing.push_back(data.substr(lastPos, pos - lastPos));
|
||||
lastPos = pos + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::vector<std::string>& Ftp::ListingResponse::getListing() const
|
||||
{
|
||||
return m_listing;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::~Ftp()
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::connect(const IpAddress& server, unsigned short port, Time timeout)
|
||||
{
|
||||
// Connect to the server
|
||||
if (m_commandSocket.connect(server, port, timeout) != Socket::Done)
|
||||
return Response(Response::ConnectionFailed);
|
||||
|
||||
// Get the response to the connection
|
||||
return getResponse();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::login()
|
||||
{
|
||||
return login("anonymous", "user@sfml-dev.org");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::login(const std::string& name, const std::string& password)
|
||||
{
|
||||
Response response = sendCommand("USER", name);
|
||||
if (response.isOk())
|
||||
response = sendCommand("PASS", password);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::disconnect()
|
||||
{
|
||||
// Send the exit command
|
||||
Response response = sendCommand("QUIT");
|
||||
if (response.isOk())
|
||||
m_commandSocket.disconnect();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::keepAlive()
|
||||
{
|
||||
return sendCommand("NOOP");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DirectoryResponse Ftp::getWorkingDirectory()
|
||||
{
|
||||
return DirectoryResponse(sendCommand("PWD"));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::ListingResponse Ftp::getDirectoryListing(const std::string& directory)
|
||||
{
|
||||
// Open a data channel on default port (20) using ASCII transfer mode
|
||||
std::ostringstream directoryData;
|
||||
DataChannel data(*this);
|
||||
Response response = data.open(Ascii);
|
||||
if (response.isOk())
|
||||
{
|
||||
// Tell the server to send us the listing
|
||||
response = sendCommand("NLST", directory);
|
||||
if (response.isOk())
|
||||
{
|
||||
// Receive the listing
|
||||
data.receive(directoryData);
|
||||
|
||||
// Get the response from the server
|
||||
response = getResponse();
|
||||
}
|
||||
}
|
||||
|
||||
return ListingResponse(response, directoryData.str());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::changeDirectory(const std::string& directory)
|
||||
{
|
||||
return sendCommand("CWD", directory);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::parentDirectory()
|
||||
{
|
||||
return sendCommand("CDUP");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::createDirectory(const std::string& name)
|
||||
{
|
||||
return sendCommand("MKD", name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::deleteDirectory(const std::string& name)
|
||||
{
|
||||
return sendCommand("RMD", name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::renameFile(const std::string& file, const std::string& newName)
|
||||
{
|
||||
Response response = sendCommand("RNFR", file);
|
||||
if (response.isOk())
|
||||
response = sendCommand("RNTO", newName);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::deleteFile(const std::string& name)
|
||||
{
|
||||
return sendCommand("DELE", name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::download(const std::string& remoteFile, const std::string& localPath, TransferMode mode)
|
||||
{
|
||||
// Open a data channel using the given transfer mode
|
||||
DataChannel data(*this);
|
||||
Response response = data.open(mode);
|
||||
if (response.isOk())
|
||||
{
|
||||
// Tell the server to start the transfer
|
||||
response = sendCommand("RETR", remoteFile);
|
||||
if (response.isOk())
|
||||
{
|
||||
// Extract the filename from the file path
|
||||
std::string filename = remoteFile;
|
||||
std::string::size_type pos = filename.find_last_of("/\\");
|
||||
if (pos != std::string::npos)
|
||||
filename = filename.substr(pos + 1);
|
||||
|
||||
// Make sure the destination path ends with a slash
|
||||
std::string path = localPath;
|
||||
if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/'))
|
||||
path += "/";
|
||||
|
||||
// Create the file and truncate it if necessary
|
||||
std::ofstream file((path + filename).c_str(), std::ios_base::binary | std::ios_base::trunc);
|
||||
if (!file)
|
||||
return Response(Response::InvalidFile);
|
||||
|
||||
// Receive the file data
|
||||
data.receive(file);
|
||||
|
||||
// Close the file
|
||||
file.close();
|
||||
|
||||
// Get the response from the server
|
||||
response = getResponse();
|
||||
|
||||
// If the download was unsuccessful, delete the partial file
|
||||
if (!response.isOk())
|
||||
std::remove((path + filename).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::upload(const std::string& localFile, const std::string& remotePath, TransferMode mode, bool append)
|
||||
{
|
||||
// Get the contents of the file to send
|
||||
std::ifstream file(localFile.c_str(), std::ios_base::binary);
|
||||
if (!file)
|
||||
return Response(Response::InvalidFile);
|
||||
|
||||
// Extract the filename from the file path
|
||||
std::string filename = localFile;
|
||||
std::string::size_type pos = filename.find_last_of("/\\");
|
||||
if (pos != std::string::npos)
|
||||
filename = filename.substr(pos + 1);
|
||||
|
||||
// Make sure the destination path ends with a slash
|
||||
std::string path = remotePath;
|
||||
if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/'))
|
||||
path += "/";
|
||||
|
||||
// Open a data channel using the given transfer mode
|
||||
DataChannel data(*this);
|
||||
Response response = data.open(mode);
|
||||
if (response.isOk())
|
||||
{
|
||||
// Tell the server to start the transfer
|
||||
response = sendCommand(append ? "APPE" : "STOR", path + filename);
|
||||
if (response.isOk())
|
||||
{
|
||||
// Send the file data
|
||||
data.send(file);
|
||||
|
||||
// Get the response from the server
|
||||
response = getResponse();
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::sendCommand(const std::string& command, const std::string& parameter)
|
||||
{
|
||||
// Build the command string
|
||||
std::string commandStr;
|
||||
if (!parameter.empty())
|
||||
commandStr = command + " " + parameter + "\r\n";
|
||||
else
|
||||
commandStr = command + "\r\n";
|
||||
|
||||
// Send it to the server
|
||||
if (m_commandSocket.send(commandStr.c_str(), commandStr.length()) != Socket::Done)
|
||||
return Response(Response::ConnectionClosed);
|
||||
|
||||
// Get the response
|
||||
return getResponse();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::getResponse()
|
||||
{
|
||||
// We'll use a variable to keep track of the last valid code.
|
||||
// It is useful in case of multi-lines responses, because the end of such a response
|
||||
// will start by the same code
|
||||
unsigned int lastCode = 0;
|
||||
bool isInsideMultiline = false;
|
||||
std::string message;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Receive the response from the server
|
||||
char buffer[1024];
|
||||
std::size_t length;
|
||||
|
||||
if (m_receiveBuffer.empty())
|
||||
{
|
||||
if (m_commandSocket.receive(buffer, sizeof(buffer), length) != Socket::Done)
|
||||
return Response(Response::ConnectionClosed);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::copy(m_receiveBuffer.begin(), m_receiveBuffer.end(), buffer);
|
||||
length = m_receiveBuffer.size();
|
||||
m_receiveBuffer.clear();
|
||||
}
|
||||
|
||||
// There can be several lines inside the received buffer, extract them all
|
||||
std::istringstream in(std::string(buffer, length), std::ios_base::binary);
|
||||
while (in)
|
||||
{
|
||||
// Try to extract the code
|
||||
unsigned int code;
|
||||
if (in >> code)
|
||||
{
|
||||
// Extract the separator
|
||||
char separator;
|
||||
in.get(separator);
|
||||
|
||||
// The '-' character means a multiline response
|
||||
if ((separator == '-') && !isInsideMultiline)
|
||||
{
|
||||
// Set the multiline flag
|
||||
isInsideMultiline = true;
|
||||
|
||||
// Keep track of the code
|
||||
if (lastCode == 0)
|
||||
lastCode = code;
|
||||
|
||||
// Extract the line
|
||||
std::getline(in, message);
|
||||
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
message.erase(message.length() - 1);
|
||||
message = separator + message + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// We must make sure that the code is the same, otherwise it means
|
||||
// we haven't reached the end of the multiline response
|
||||
if ((separator != '-') && ((code == lastCode) || (lastCode == 0)))
|
||||
{
|
||||
// Extract the line
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
line.erase(line.length() - 1);
|
||||
|
||||
// Append it to the message
|
||||
if (code == lastCode)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << code << separator << line;
|
||||
message += out.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
message = separator + line;
|
||||
}
|
||||
|
||||
// Save the remaining data for the next time getResponse() is called
|
||||
m_receiveBuffer.assign(buffer + static_cast<std::size_t>(in.tellg()), length - static_cast<std::size_t>(in.tellg()));
|
||||
|
||||
// Return the response code and message
|
||||
return Response(static_cast<Response::Status>(code), message);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The line we just read was actually not a response,
|
||||
// only a new part of the current multiline response
|
||||
|
||||
// Extract the line
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
|
||||
if (!line.empty())
|
||||
{
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
line.erase(line.length() - 1);
|
||||
|
||||
// Append it to the current message
|
||||
std::ostringstream out;
|
||||
out << code << separator << line << "\n";
|
||||
message += out.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lastCode != 0)
|
||||
{
|
||||
// It seems we are in the middle of a multiline response
|
||||
|
||||
// Clear the error bits of the stream
|
||||
in.clear();
|
||||
|
||||
// Extract the line
|
||||
std::string line;
|
||||
std::getline(in, line);
|
||||
|
||||
if (!line.empty())
|
||||
{
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
line.erase(line.length() - 1);
|
||||
|
||||
// Append it to the current message
|
||||
message += line + "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error: cannot extract the code, and we are not in a multiline response
|
||||
return Response(Response::InvalidResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We never reach there
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DataChannel::DataChannel(Ftp& owner) :
|
||||
m_ftp(owner)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::DataChannel::open(Ftp::TransferMode mode)
|
||||
{
|
||||
// Open a data connection in active mode (we connect to the server)
|
||||
Ftp::Response response = m_ftp.sendCommand("PASV");
|
||||
if (response.isOk())
|
||||
{
|
||||
// Extract the connection address and port from the response
|
||||
std::string::size_type begin = response.getMessage().find_first_of("0123456789");
|
||||
if (begin != std::string::npos)
|
||||
{
|
||||
Uint8 data[6] = {0, 0, 0, 0, 0, 0};
|
||||
std::string str = response.getMessage().substr(begin);
|
||||
std::size_t index = 0;
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// Extract the current number
|
||||
while (isdigit(str[index]))
|
||||
{
|
||||
data[i] = static_cast<Uint8>(static_cast<Uint8>(data[i] * 10) + static_cast<Uint8>(str[index] - '0'));
|
||||
index++;
|
||||
}
|
||||
|
||||
// Skip separator
|
||||
index++;
|
||||
}
|
||||
|
||||
// Reconstruct connection port and address
|
||||
unsigned short port = static_cast<Uint16>(data[4] * 256 + data[5]);
|
||||
IpAddress address(data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
data[3]);
|
||||
|
||||
// Connect the data channel to the server
|
||||
if (m_dataSocket.connect(address, port) == Socket::Done)
|
||||
{
|
||||
// Translate the transfer mode to the corresponding FTP parameter
|
||||
std::string modeStr;
|
||||
switch (mode)
|
||||
{
|
||||
case Ftp::Binary: modeStr = "I"; break;
|
||||
case Ftp::Ascii: modeStr = "A"; break;
|
||||
case Ftp::Ebcdic: modeStr = "E"; break;
|
||||
}
|
||||
|
||||
// Set the transfer mode
|
||||
response = m_ftp.sendCommand("TYPE", modeStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to connect to the server
|
||||
response = Ftp::Response(Ftp::Response::ConnectionFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Ftp::DataChannel::receive(std::ostream& stream)
|
||||
{
|
||||
// Receive data
|
||||
char buffer[1024];
|
||||
std::size_t received;
|
||||
while (m_dataSocket.receive(buffer, sizeof(buffer), received) == Socket::Done)
|
||||
{
|
||||
stream.write(buffer, static_cast<std::streamsize>(received));
|
||||
|
||||
if (!stream.good())
|
||||
{
|
||||
err() << "FTP Error: Writing to the file has failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the data socket
|
||||
m_dataSocket.disconnect();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Ftp::DataChannel::send(std::istream& stream)
|
||||
{
|
||||
// Send data
|
||||
char buffer[1024];
|
||||
std::size_t count;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// read some data from the stream
|
||||
stream.read(buffer, sizeof(buffer));
|
||||
|
||||
if (!stream.good() && !stream.eof())
|
||||
{
|
||||
err() << "FTP Error: Reading from the file has failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
count = static_cast<std::size_t>(stream.gcount());
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
// we could read more data from the stream: send them
|
||||
if (m_dataSocket.send(buffer, count) != Socket::Done)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no more data: exit the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the data socket
|
||||
m_dataSocket.disconnect();
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,418 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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(m_uri.begin(), '/');
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
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 = static_cast<unsigned int>(version[5] - '0');
|
||||
m_minorVersion = static_cast<unsigned int>(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);
|
||||
++it; // Iterate in separate expression to work around false positive -Wnull-dereference warning in GCC 12.1.0
|
||||
}
|
||||
}
|
||||
|
||||
// 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.clear();
|
||||
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
|
|
@ -0,0 +1,273 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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(static_cast<Uint32>((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)
|
||||
{
|
||||
sockaddr_in sin;
|
||||
std::memcpy(&sin, result->ai_addr, sizeof(*result->ai_addr));
|
||||
ip = sin.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
|
|
@ -0,0 +1,609 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t Packet::getReadPosition() const
|
||||
{
|
||||
return m_readPos;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
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)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint8& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int16& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
data = static_cast<Int16>(ntohs(static_cast<Uint16>(data)));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint16& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
data = ntohs(data);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int32& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
data = static_cast<Int32>(ntohl(static_cast<Uint32>(data)));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint32& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
data = ntohl(data);
|
||||
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
|
||||
Uint8 bytes[sizeof(data)];
|
||||
std::memcpy(bytes, &m_data[m_readPos], sizeof(data));
|
||||
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
|
||||
Uint8 bytes[sizeof(data)];
|
||||
std::memcpy(bytes, &m_data[m_readPos], sizeof(data));
|
||||
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)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(double& data)
|
||||
{
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
std::memcpy(&data, &m_data[m_readPos], sizeof(data));
|
||||
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 = static_cast<Int16>(htons(static_cast<Uint16>(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 = static_cast<Int32>(htonl(static_cast<Uint32>(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
|
|
@ -0,0 +1,151 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,39 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,205 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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<int>(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
|
|
@ -0,0 +1,131 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,434 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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<int>(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 += static_cast<std::size_t>(result))
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
// Send a chunk of data
|
||||
result = static_cast<int>(::send(getHandle(), static_cast<const char*>(data) + sent, static_cast<priv::SocketImpl::Size>(size - sent), flags));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
// Receive a chunk of bytes
|
||||
int sizeReceived = static_cast<int>(recv(getHandle(), static_cast<char*>(data), static_cast<priv::SocketImpl::Size>(size), flags));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// 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
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wnull-dereference" // False positive.
|
||||
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
|
||||
#pragma GCC diagnostic pop
|
||||
if (size > 0)
|
||||
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
|
||||
|
||||
// These warnings are ignored here for portability, as even on Windows the
|
||||
// signature of `send` might change depending on whether Win32 or MinGW is
|
||||
// being used.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
// Send the data block
|
||||
std::size_t sent;
|
||||
Status status = send(&blockToSend[0] + packet.m_sendPos, static_cast<priv::SocketImpl::Size>(blockToSend.size() - packet.m_sendPos), sent);
|
||||
#pragma GCC diagnostic pop
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// 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(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
|
|
@ -0,0 +1,206 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
// Send the data (unlike TCP, all the data is always sent in one call)
|
||||
int sent = static_cast<int>(sendto(getHandle(), static_cast<const char*>(data), static_cast<priv::SocketImpl::Size>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address)));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// 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);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
// Receive a chunk of bytes
|
||||
priv::SocketImpl::AddrLength addressSize = sizeof(address);
|
||||
int sizeReceived = static_cast<int>(recvfrom(getHandle(), static_cast<char*>(data), static_cast<priv::SocketImpl::Size>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// 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
|
|
@ -0,0 +1,112 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,110 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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;
|
||||
typedef size_t Size;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \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
|
|
@ -0,0 +1,112 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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, static_cast<long>(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
|
|
@ -0,0 +1,113 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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;
|
||||
typedef int Size;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \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
|
|
@ -0,0 +1,80 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 Laurent Gomila (laurent@sfml-dev.org)
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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/Android/Activity.hpp>
|
||||
#include <android/log.h>
|
||||
#include <cassert>
|
||||
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "sfml-error", __VA_ARGS__))
|
||||
|
||||
LogcatStream::LogcatStream() :
|
||||
std::streambuf()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
std::streambuf::int_type LogcatStream::overflow (std::streambuf::int_type c)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
m_message.push_back(static_cast<char>(c));
|
||||
LOGE("%s", m_message.c_str());
|
||||
m_message.clear();
|
||||
}
|
||||
|
||||
m_message.push_back(static_cast<char>(c));
|
||||
|
||||
return traits_type::not_eof(c);
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
|
||||
ActivityStates*& getActivityStatesPtr()
|
||||
{
|
||||
static ActivityStates* states = NULL;
|
||||
return states;
|
||||
}
|
||||
|
||||
void resetActivity(ActivityStates* initializedStates)
|
||||
{
|
||||
getActivityStatesPtr() = initializedStates;
|
||||
}
|
||||
|
||||
ActivityStates& getActivity()
|
||||
{
|
||||
ActivityStates* const states = getActivityStatesPtr();
|
||||
assert(states != NULL);
|
||||
return *states;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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_ACTIVITY_HPP
|
||||
#define SFML_ACTIVITY_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/Event.hpp>
|
||||
#include <SFML/Window/EglContext.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <android/native_activity.h>
|
||||
#include <android/configuration.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
class SFML_SYSTEM_API LogcatStream : public std::streambuf
|
||||
{
|
||||
public:
|
||||
LogcatStream();
|
||||
|
||||
std::streambuf::int_type overflow (std::streambuf::int_type c);
|
||||
|
||||
private:
|
||||
std::string m_message;
|
||||
};
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
struct ActivityStates
|
||||
{
|
||||
ANativeActivity* activity;
|
||||
ANativeWindow* window;
|
||||
|
||||
ALooper* looper;
|
||||
AInputQueue* inputQueue;
|
||||
AConfiguration* config;
|
||||
|
||||
EGLDisplay display;
|
||||
EglContext* context;
|
||||
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
|
||||
Mutex mutex;
|
||||
|
||||
void (*forwardEvent)(const Event& event);
|
||||
int (*processEvent)(int fd, int events, void* data);
|
||||
|
||||
std::map<int, Vector2i> touchEvents;
|
||||
Vector2i mousePosition;
|
||||
bool isButtonPressed[Mouse::ButtonCount];
|
||||
|
||||
bool mainOver;
|
||||
|
||||
Vector2i screenSize;
|
||||
Vector2i fullScreenSize;
|
||||
|
||||
bool initialized;
|
||||
bool terminated;
|
||||
|
||||
bool fullscreen;
|
||||
|
||||
bool updated;
|
||||
|
||||
LogcatStream logcat;
|
||||
};
|
||||
|
||||
SFML_SYSTEM_API ActivityStates*& getActivityStatesPtr();
|
||||
SFML_SYSTEM_API void resetActivity(ActivityStates* initializedStates);
|
||||
SFML_SYSTEM_API ActivityStates& getActivity();
|
||||
|
||||
} // namespace priv
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_ACTIVITY_HPP
|
|
@ -0,0 +1,39 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/NativeActivity.hpp>
|
||||
#include <SFML/System/Android/Activity.hpp>
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ANativeActivity* getNativeActivity()
|
||||
{
|
||||
return priv::getActivity().activity;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,116 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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/Android/ResourceStream.hpp>
|
||||
#include <SFML/System/Android/Activity.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ResourceStream::ResourceStream(const std::string& filename) :
|
||||
m_file (NULL)
|
||||
{
|
||||
ActivityStates& states = getActivity();
|
||||
Lock lock(states.mutex);
|
||||
m_file = AAssetManager_open(states.activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ResourceStream::~ResourceStream()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
AAsset_close(m_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 ResourceStream::read(void *data, Int64 size)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
return AAsset_read(m_file, data, static_cast<size_t>(size));
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 ResourceStream::seek(Int64 position)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
return AAsset_seek(m_file, static_cast<off_t>(position), SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 ResourceStream::tell()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
return getSize() - AAsset_getRemainingLength(m_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 ResourceStream::getSize()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
return AAsset_getLength(m_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace priv
|
||||
} // namespace sf
|
|
@ -0,0 +1,113 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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_RESOURCESTREAM_HPP
|
||||
#define SFML_RESOURCESTREAM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Export.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <android/asset_manager.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read from Android asset files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API ResourceStream : public InputStream
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// \param filename Filename of the asset
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ResourceStream(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ResourceStream();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read data from the asset
|
||||
///
|
||||
/// \param data Buffer where the asset data is copied
|
||||
/// \param size Number of bytes read
|
||||
///
|
||||
/// \return The number of bytes actually read, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 read(void *data, Int64 size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current reading position in the asset file
|
||||
///
|
||||
/// \param position The position to seek to, from the beginning
|
||||
///
|
||||
/// \return The position actually sought to, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 seek(Int64 position);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current reading position in the asset file
|
||||
///
|
||||
/// \return The current position, or -1 on error.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 tell();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the size of the asset file
|
||||
///
|
||||
/// \return The total number of bytes available in the asset, or -1 on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 getSize();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
AAsset* m_file; ///< The asset file to read
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_RESOURCESTREAM_HPP
|
|
@ -0,0 +1,111 @@
|
|||
set(PROJECT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/Clock.cpp
|
||||
${INCROOT}/Clock.hpp
|
||||
${SRCROOT}/Err.cpp
|
||||
${INCROOT}/Err.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${INCROOT}/InputStream.hpp
|
||||
${SRCROOT}/Lock.cpp
|
||||
${INCROOT}/Lock.hpp
|
||||
${SRCROOT}/Mutex.cpp
|
||||
${INCROOT}/Mutex.hpp
|
||||
${INCROOT}/NativeActivity.hpp
|
||||
${INCROOT}/NonCopyable.hpp
|
||||
${SRCROOT}/Sleep.cpp
|
||||
${INCROOT}/Sleep.hpp
|
||||
${SRCROOT}/String.cpp
|
||||
${INCROOT}/String.hpp
|
||||
${INCROOT}/String.inl
|
||||
${SRCROOT}/Thread.cpp
|
||||
${INCROOT}/Thread.hpp
|
||||
${INCROOT}/Thread.inl
|
||||
${SRCROOT}/ThreadLocal.cpp
|
||||
${INCROOT}/ThreadLocal.hpp
|
||||
${INCROOT}/ThreadLocalPtr.hpp
|
||||
${INCROOT}/ThreadLocalPtr.inl
|
||||
${SRCROOT}/Time.cpp
|
||||
${INCROOT}/Time.hpp
|
||||
${INCROOT}/Utf.hpp
|
||||
${INCROOT}/Utf.inl
|
||||
${INCROOT}/Vector2.hpp
|
||||
${INCROOT}/Vector2.inl
|
||||
${INCROOT}/Vector3.hpp
|
||||
${INCROOT}/Vector3.inl
|
||||
${SRCROOT}/FileInputStream.cpp
|
||||
${INCROOT}/FileInputStream.hpp
|
||||
${SRCROOT}/MemoryInputStream.cpp
|
||||
${INCROOT}/MemoryInputStream.hpp
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# add platform specific sources
|
||||
if(WIN32)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Win32/ClockImpl.cpp
|
||||
${SRCROOT}/Win32/ClockImpl.hpp
|
||||
${SRCROOT}/Win32/MutexImpl.cpp
|
||||
${SRCROOT}/Win32/MutexImpl.hpp
|
||||
${SRCROOT}/Win32/SleepImpl.cpp
|
||||
${SRCROOT}/Win32/SleepImpl.hpp
|
||||
${SRCROOT}/Win32/ThreadImpl.cpp
|
||||
${SRCROOT}/Win32/ThreadImpl.hpp
|
||||
${SRCROOT}/Win32/ThreadLocalImpl.cpp
|
||||
${SRCROOT}/Win32/ThreadLocalImpl.hpp
|
||||
)
|
||||
source_group("windows" FILES ${PLATFORM_SRC})
|
||||
else()
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Unix/ClockImpl.cpp
|
||||
${SRCROOT}/Unix/ClockImpl.hpp
|
||||
${SRCROOT}/Unix/MutexImpl.cpp
|
||||
${SRCROOT}/Unix/MutexImpl.hpp
|
||||
${SRCROOT}/Unix/SleepImpl.cpp
|
||||
${SRCROOT}/Unix/SleepImpl.hpp
|
||||
${SRCROOT}/Unix/ThreadImpl.cpp
|
||||
${SRCROOT}/Unix/ThreadImpl.hpp
|
||||
${SRCROOT}/Unix/ThreadLocalImpl.cpp
|
||||
${SRCROOT}/Unix/ThreadLocalImpl.hpp
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
set(PLATFORM_SRC ${PLATFORM_SRC}
|
||||
${SRCROOT}/Android/Activity.hpp
|
||||
${SRCROOT}/Android/Activity.cpp
|
||||
${SRCROOT}/Android/NativeActivity.cpp
|
||||
${SRCROOT}/Android/ResourceStream.cpp
|
||||
${SRCROOT}/Android/ResourceStream.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
source_group("unix" FILES ${PLATFORM_SRC})
|
||||
endif()
|
||||
|
||||
# define the sfml-system target
|
||||
add_library(sfml-system STATIC ${SRC} ${PLATFORM_SRC})
|
||||
|
||||
target_include_directories(sfml-system PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
|
||||
|
||||
target_compile_definitions(sfml-system PRIVATE SFML_STATIC)
|
||||
|
||||
if(ANDROID)
|
||||
# glad sources
|
||||
target_include_directories(sfml-system PRIVATE "${PROJECT_SOURCE_DIR}/extlibs/headers/glad/include")
|
||||
endif()
|
||||
|
||||
# setup dependencies
|
||||
if(UNIX OR APPLE)
|
||||
target_link_libraries(sfml-system PRIVATE pthread)
|
||||
endif()
|
||||
if(UNIX)
|
||||
target_link_libraries(sfml-system PRIVATE rt)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(sfml-system PRIVATE winmm)
|
||||
elseif(ANDROID)
|
||||
target_link_libraries(sfml-system PRIVATE android log)
|
||||
endif()
|
|
@ -0,0 +1,63 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Clock.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ClockImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ClockImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Clock::Clock() :
|
||||
m_startTime(priv::ClockImpl::getCurrentTime())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Clock::getElapsedTime() const
|
||||
{
|
||||
return priv::ClockImpl::getCurrentTime() - m_startTime;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Clock::restart()
|
||||
{
|
||||
Time now = priv::ClockImpl::getCurrentTime();
|
||||
Time elapsed = now - m_startTime;
|
||||
m_startTime = now;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,110 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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<std::size_t>(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
|
|
@ -0,0 +1,146 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/FileInputStream.hpp>
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
#include <SFML/System/Android/ResourceStream.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
FileInputStream::FileInputStream()
|
||||
: m_file(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FileInputStream::~FileInputStream()
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
if (m_file)
|
||||
delete m_file;
|
||||
#else
|
||||
if (m_file)
|
||||
std::fclose(m_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool FileInputStream::open(const std::string& filename)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
if (m_file)
|
||||
delete m_file;
|
||||
m_file = new priv::ResourceStream(filename);
|
||||
return m_file->tell() != -1;
|
||||
#else
|
||||
if (m_file)
|
||||
std::fclose(m_file);
|
||||
|
||||
m_file = std::fopen(filename.c_str(), "rb");
|
||||
|
||||
return m_file != NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::read(void* data, Int64 size)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
return m_file->read(data, size);
|
||||
#else
|
||||
if (m_file)
|
||||
return static_cast<Int64>(std::fread(data, 1, static_cast<std::size_t>(size), m_file));
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::seek(Int64 position)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
return m_file->seek(position);
|
||||
#else
|
||||
if (m_file)
|
||||
{
|
||||
if (std::fseek(m_file, static_cast<long>(position), SEEK_SET))
|
||||
return -1;
|
||||
|
||||
return tell();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::tell()
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
return m_file->tell();
|
||||
#else
|
||||
if (m_file)
|
||||
return std::ftell(m_file);
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::getSize()
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
return m_file->getSize();
|
||||
#else
|
||||
if (m_file)
|
||||
{
|
||||
Int64 position = tell();
|
||||
std::fseek(m_file, 0, SEEK_END);
|
||||
Int64 size = tell();
|
||||
seek(position);
|
||||
return size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,48 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Lock.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Lock::Lock(Mutex& mutex) :
|
||||
m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Lock::~Lock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,101 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/MemoryInputStream.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MemoryInputStream::MemoryInputStream() :
|
||||
m_data (NULL),
|
||||
m_size (0),
|
||||
m_offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MemoryInputStream::open(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
m_data = static_cast<const char*>(data);
|
||||
m_size = static_cast<Int64>(sizeInBytes);
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::read(void* data, Int64 size)
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
Int64 endPosition = m_offset + size;
|
||||
Int64 count = endPosition <= m_size ? size : m_size - m_offset;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
std::memcpy(data, m_data + m_offset, static_cast<std::size_t>(count));
|
||||
m_offset += count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::seek(Int64 position)
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
m_offset = position < m_size ? position : m_size;
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::tell()
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::getSize()
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
return m_size;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,66 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Mutex.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/MutexImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/MutexImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex::Mutex()
|
||||
{
|
||||
m_mutexImpl = new priv::MutexImpl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
delete m_mutexImpl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Mutex::lock()
|
||||
{
|
||||
m_mutexImpl->lock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Mutex::unlock()
|
||||
{
|
||||
m_mutexImpl->unlock();
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,46 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Sleep.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/SleepImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/SleepImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleep(Time duration)
|
||||
{
|
||||
if (duration >= Time::Zero)
|
||||
priv::sleepImpl(duration);
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,400 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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
|
|
@ -0,0 +1,86 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Thread.hpp>
|
||||
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ThreadImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ThreadImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Thread::~Thread()
|
||||
{
|
||||
wait();
|
||||
delete m_entryPoint;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::launch()
|
||||
{
|
||||
wait();
|
||||
m_impl = new priv::ThreadImpl(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::wait()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->wait();
|
||||
delete m_impl;
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::terminate()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->terminate();
|
||||
delete m_impl;
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::run()
|
||||
{
|
||||
m_entryPoint->run();
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,67 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/ThreadLocal.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal::ThreadLocal(void* value)
|
||||
{
|
||||
m_impl = new priv::ThreadLocalImpl;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal::~ThreadLocal()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocal::setValue(void* value)
|
||||
{
|
||||
m_impl->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocal::getValue() const
|
||||
{
|
||||
return m_impl->getValue();
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,260 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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 static_cast<float>(static_cast<double>(m_microseconds) / 1000000.0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
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
|
|
@ -0,0 +1,64 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Unix/ClockImpl.hpp>
|
||||
#if defined(SFML_SYSTEM_MACOS) || defined(SFML_SYSTEM_IOS)
|
||||
#include <mach/mach_time.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Time ClockImpl::getCurrentTime()
|
||||
{
|
||||
#if defined(SFML_SYSTEM_MACOS) || defined(SFML_SYSTEM_IOS)
|
||||
|
||||
// Mac OS X specific implementation (it doesn't support clock_gettime)
|
||||
static mach_timebase_info_data_t frequency = {0, 0};
|
||||
if (frequency.denom == 0)
|
||||
mach_timebase_info(&frequency);
|
||||
Uint64 nanoseconds = mach_absolute_time() * frequency.numer / frequency.denom;
|
||||
return sf::microseconds(nanoseconds / 1000);
|
||||
|
||||
#else
|
||||
|
||||
// POSIX implementation
|
||||
timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
return sf::microseconds(time.tv_sec * 1000000 + time.tv_nsec / 1000);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,61 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_CLOCKIMPLUNIX_HPP
|
||||
#define SFML_CLOCKIMPLUNIX_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of sf::Clock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class ClockImpl
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current time
|
||||
///
|
||||
/// \return Current time
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Time getCurrentTime();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_CLOCKIMPLUNIX_HPP
|
|
@ -0,0 +1,69 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Unix/MutexImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
// Make it recursive to follow the expected behavior
|
||||
pthread_mutexattr_t attributes;
|
||||
pthread_mutexattr_init(&attributes);
|
||||
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&m_mutex, &attributes);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,83 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_MUTEXIMPL_HPP
|
||||
#define SFML_MUTEXIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of mutexes
|
||||
////////////////////////////////////////////////////////////
|
||||
class MutexImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_mutex_t m_mutex; ///< pthread handle of the mutex
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEXIMPL_HPP
|
|
@ -0,0 +1,59 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Unix/SleepImpl.hpp>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleepImpl(Time time)
|
||||
{
|
||||
Int64 usecs = time.asMicroseconds();
|
||||
|
||||
// Construct the time to wait
|
||||
timespec ti;
|
||||
ti.tv_nsec = static_cast<long>((usecs % 1000000) * 1000);
|
||||
ti.tv_sec = static_cast<time_t>(usecs / 1000000);
|
||||
|
||||
// Wait...
|
||||
// If nanosleep returns -1, we check errno. If it is EINTR
|
||||
// nanosleep was interrupted and has set ti to the remaining
|
||||
// duration. We continue sleeping until the complete duration
|
||||
// has passed. We stop sleeping if it was due to an error.
|
||||
while ((nanosleep(&ti, &ti) == -1) && (errno == EINTR))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,52 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_SLEEPIMPLUNIX_HPP
|
||||
#define SFML_SLEEPIMPLUNIX_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of sf::Sleep
|
||||
///
|
||||
/// \param time Time to sleep
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleepImpl(Time time);
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SLEEPIMPLUNIX_HPP
|
|
@ -0,0 +1,95 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Unix/ThreadImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::ThreadImpl(Thread* owner) :
|
||||
m_isActive(true)
|
||||
{
|
||||
m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0;
|
||||
|
||||
if (!m_isActive)
|
||||
err() << "Failed to create thread" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::wait()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself!
|
||||
pthread_join(m_thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::terminate()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
pthread_cancel(m_thread);
|
||||
#else
|
||||
// See https://stackoverflow.com/questions/4610086/pthread-cancel-al
|
||||
pthread_kill(m_thread, SIGUSR1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadImpl::entryPoint(void* userData)
|
||||
{
|
||||
// The Thread instance is stored in the user data
|
||||
Thread* owner = static_cast<Thread*>(userData);
|
||||
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
// Tell the thread to handle cancel requests immediately
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
#endif
|
||||
|
||||
// Forward to the owner
|
||||
owner->run();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,93 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_THREADIMPL_HPP
|
||||
#define SFML_THREADIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Thread;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of threads
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor, launch the thread
|
||||
///
|
||||
/// \param owner The Thread instance to run
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl(Thread* owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Global entry point for all threads
|
||||
///
|
||||
/// \param userData User-defined data (contains the Thread instance)
|
||||
///
|
||||
/// \return Os specific error code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void* entryPoint(void* userData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_t m_thread; ///< pthread thread instance
|
||||
bool m_isActive; ///< Thread state (active or inactive)
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADIMPL_HPP
|
|
@ -0,0 +1,65 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Unix/ThreadLocalImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::ThreadLocalImpl() :
|
||||
m_key(0)
|
||||
{
|
||||
pthread_key_create(&m_key, NULL);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::~ThreadLocalImpl()
|
||||
{
|
||||
pthread_key_delete(m_key);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocalImpl::setValue(void* value)
|
||||
{
|
||||
pthread_setspecific(m_key, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocalImpl::getValue() const
|
||||
{
|
||||
return pthread_getspecific(m_key);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,87 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_THREADLOCALIMPL_HPP
|
||||
#define SFML_THREADLOCALIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of thread-local storage
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadLocalImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor -- allocate the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor -- free the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the thread-specific value of the variable
|
||||
///
|
||||
/// \param value Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setValue(void* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the thread-specific value of the variable
|
||||
///
|
||||
/// \return Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void* getValue() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_key_t m_key; ///< Index of our thread-local storage slot
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCALIMPL_HPP
|
|
@ -0,0 +1,88 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Win32/ClockImpl.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
LARGE_INTEGER getFrequency()
|
||||
{
|
||||
LARGE_INTEGER frequency;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
return frequency;
|
||||
}
|
||||
|
||||
bool isWindowsXpOrOlder()
|
||||
{
|
||||
// Windows XP was the last 5.x version of Windows
|
||||
return static_cast<DWORD>(LOBYTE(LOWORD(GetVersion()))) < 6;
|
||||
}
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Time ClockImpl::getCurrentTime()
|
||||
{
|
||||
// Calculate inverse of frequency multiplied by 1000000 to prevent overflow in final calculation
|
||||
// Frequency is constant across the program lifetime
|
||||
static double inverse = 1000000.0 / static_cast<double>(getFrequency().QuadPart);
|
||||
|
||||
// Detect if we are on Windows XP or older
|
||||
static bool oldWindows = isWindowsXpOrOlder();
|
||||
|
||||
LARGE_INTEGER time;
|
||||
|
||||
if (oldWindows)
|
||||
{
|
||||
static sf::Mutex oldWindowsMutex;
|
||||
|
||||
// Acquire a lock (CRITICAL_SECTION) to prevent travelling back in time
|
||||
Lock lock(oldWindowsMutex);
|
||||
|
||||
// Get the current time
|
||||
QueryPerformanceCounter(&time);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the current time
|
||||
QueryPerformanceCounter(&time);
|
||||
}
|
||||
|
||||
// Return the current time as microseconds
|
||||
return sf::microseconds(static_cast<sf::Int64>(static_cast<double>(time.QuadPart) * inverse));
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,61 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_CLOCKIMPLWIN32_HPP
|
||||
#define SFML_CLOCKIMPLWIN32_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of sf::Clock
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class ClockImpl
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current time
|
||||
///
|
||||
/// \return Current time
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Time getCurrentTime();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_CLOCKIMPLWIN32_HPP
|
|
@ -0,0 +1,64 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Win32/MutexImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
InitializeCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::lock()
|
||||
{
|
||||
EnterCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,83 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_MUTEXIMPL_HPP
|
||||
#define SFML_MUTEXIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of mutexes
|
||||
////////////////////////////////////////////////////////////
|
||||
class MutexImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
CRITICAL_SECTION m_mutex; //!< Win32 handle of the mutex
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEXIMPL_HPP
|
|
@ -0,0 +1,55 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Win32/SleepImpl.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleepImpl(Time time)
|
||||
{
|
||||
// Get the supported timer resolutions on this system
|
||||
TIMECAPS tc;
|
||||
timeGetDevCaps(&tc, sizeof(TIMECAPS));
|
||||
|
||||
// Set the timer resolution to the minimum for the Sleep call
|
||||
timeBeginPeriod(tc.wPeriodMin);
|
||||
|
||||
// Wait...
|
||||
::Sleep(static_cast<DWORD>(time.asMilliseconds()));
|
||||
|
||||
// Reset the timer resolution back to the system default
|
||||
timeEndPeriod(tc.wPeriodMin);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,52 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_SLEEPIMPLWIN32_HPP
|
||||
#define SFML_SLEEPIMPLWIN32_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of sf::Sleep
|
||||
///
|
||||
/// \param time Time to sleep
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleepImpl(Time time);
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SLEEPIMPLWIN32_HPP
|
|
@ -0,0 +1,93 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Win32/ThreadImpl.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cassert>
|
||||
#include <process.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::ThreadImpl(Thread* owner)
|
||||
{
|
||||
m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId));
|
||||
|
||||
if (!m_thread)
|
||||
err() << "Failed to create thread" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::~ThreadImpl()
|
||||
{
|
||||
if (m_thread)
|
||||
CloseHandle(m_thread);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::wait()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself!
|
||||
WaitForSingleObject(m_thread, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::terminate()
|
||||
{
|
||||
if (m_thread)
|
||||
TerminateThread(m_thread, 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int __stdcall ThreadImpl::entryPoint(void* userData)
|
||||
{
|
||||
// The Thread instance is stored in the user data
|
||||
Thread* owner = static_cast<Thread*>(userData);
|
||||
|
||||
// Forward to the owner
|
||||
owner->run();
|
||||
|
||||
// Optional, but it is cleaner
|
||||
_endthreadex(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
|
@ -0,0 +1,109 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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_THREADIMPL_HPP
|
||||
#define SFML_THREADIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
// Fix for unaligned stack with clang and GCC on Windows XP 32-bit
|
||||
#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__))
|
||||
|
||||
#define ALIGN_STACK __attribute__((__force_align_arg_pointer__))
|
||||
|
||||
#else
|
||||
|
||||
#define ALIGN_STACK
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Thread;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of threads
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor, launch the thread
|
||||
///
|
||||
/// \param owner The Thread instance to run
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl(Thread* owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Global entry point for all threads
|
||||
///
|
||||
/// \param userData User-defined data (contains the Thread instance)
|
||||
///
|
||||
/// \return OS specific error code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
HANDLE m_thread; //!< Win32 thread handle
|
||||
unsigned int m_threadId; //!< Win32 thread identifier
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADIMPL_HPP
|
|
@ -0,0 +1,64 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2023 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/Win32/ThreadLocalImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::ThreadLocalImpl()
|
||||
{
|
||||
m_index = TlsAlloc();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::~ThreadLocalImpl()
|
||||
{
|
||||
TlsFree(m_index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocalImpl::setValue(void* value)
|
||||
{
|
||||
TlsSetValue(m_index, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocalImpl::getValue() const
|
||||
{
|
||||
return TlsGetValue(m_index);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue