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:
Rafael Kitover 2025-01-07 02:34:15 +00:00
parent c6da07feb3
commit cec8f57400
No known key found for this signature in database
GPG Key ID: 08AB596679D86240
106 changed files with 16426 additions and 431 deletions

View File

@ -25,7 +25,6 @@ endif()
set(VCPKG_DEPS pkgconf zlib pthreads "sdl2[samplerate]" gettext wxwidgets) set(VCPKG_DEPS pkgconf zlib pthreads "sdl2[samplerate]" gettext wxwidgets)
set(VCPKG_DEPS_OPTIONAL set(VCPKG_DEPS_OPTIONAL
sfml ENABLE_LINK
ffmpeg ENABLE_FFMPEG ffmpeg ENABLE_FFMPEG
faudio ENABLE_FAUDIO faudio ENABLE_FAUDIO
) )

View File

@ -166,7 +166,6 @@ And the following development libraries:
- [ffmpeg](https://ffmpeg.org/) (optional, at least version `4.0.4`, for game recording) - [ffmpeg](https://ffmpeg.org/) (optional, at least version `4.0.4`, for game recording)
- [gettext](https://www.gnu.org/software/gettext/) and gettext-tools - [gettext](https://www.gnu.org/software/gettext/) and gettext-tools
- [SDL2](https://www.libsdl.org/) (required) - [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) - [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) - [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` | 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_ASM_SCALERS` | Enable x86 ASM graphic filters | ON for 32 bit builds |
| `ENABLE_MMX` | Enable MMX | 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_LIRC` | Enable LIRC support | OFF |
| `ENABLE_FFMPEG` | Enable ffmpeg A/V recording | AUTO | | `ENABLE_FFMPEG` | Enable ffmpeg A/V recording | AUTO |
| `ENABLE_ONLINEUPDATES` | Enable online update checks | ON | | `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 | | `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 | | `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 | | `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 | | `FFMPEG_STATIC` | Try to link static ffmpeg libraries | OFF |
| `OPENAL_STATIC` | Try to link static OpenAL libraries | OFF | | `OPENAL_STATIC` | Try to link static OpenAL libraries | OFF |
| `TRANSLATIONS_ONLY` | Build only the translations.zip and nothing else | OFF | | `TRANSLATIONS_ONLY` | Build only the translations.zip and nothing else | OFF |

View File

@ -120,3 +120,9 @@ if(ENABLE_LINK OR ENABLE_WX)
endif() endif()
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()

View File

@ -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()

View File

@ -30,7 +30,6 @@ option(VBAM_STATIC "Try to link all libraries statically" ${VBAM_STATIC_DEFAULT}
if(VBAM_STATIC) if(VBAM_STATIC)
set(SDL2_STATIC ON) set(SDL2_STATIC ON)
set(SFML_STATIC_LIBRARIES ON)
set(FFMPEG_STATIC ON) set(FFMPEG_STATIC ON)
set(OPENAL_STATIC ON) set(OPENAL_STATIC ON)
set_property(GLOBAL PROPERTY LINK_SEARCH_START_STATIC ON) set_property(GLOBAL PROPERTY LINK_SEARCH_START_STATIC ON)
@ -68,14 +67,9 @@ endif()
find_package(PkgConfig) find_package(PkgConfig)
# Link / SFML # Link / SFML
if(TRANSLATIONS_ONLY) set(ENABLE_LINK_DEFAULT OFF)
set(ENABLE_LINK_DEFAULT OFF) if(NOT TRANSLATIONS_ONLY)
else() set(ENABLE_LINK_DEFAULT ON)
find_package(SFML 2.4 COMPONENTS network system)
set(ENABLE_LINK_DEFAULT OFF)
if(SFML_FOUND)
set(ENABLE_LINK_DEFAULT ON)
endif()
endif() endif()
option(ENABLE_LINK "Enable GBA linking functionality" ${ENABLE_LINK_DEFAULT}) option(ENABLE_LINK "Enable GBA linking functionality" ${ENABLE_LINK_DEFAULT})

View File

@ -2,7 +2,7 @@ with import <nixpkgs> {};
stdenv.mkDerivation { stdenv.mkDerivation {
name = "visualboyadvance-m"; name = "visualboyadvance-m";
buildInputs = if stdenv.isDarwin then 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 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 ];
} }

View File

@ -191,7 +191,7 @@ freebsd_installdeps() {
check sudo pkg update 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" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"
@ -318,12 +318,6 @@ debian_installdeps() {
if [ -z "$target" ]; then if [ -z "$target" ]; then
sudo apt-get -qq -y update 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) 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) sdl_lib=$(apt-cache search '^libsdl2-2.0' | sed 's/ - .*//' | sort -r | head -1)
@ -350,7 +344,7 @@ debian_installdeps() {
;; ;;
esac 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" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs libavcodec-dev libavformat-dev libswscale-dev libavutil-dev $libswresample_dev"
@ -401,7 +395,7 @@ debian_installdeps() {
fi fi
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" [ -n "$ENABLE_FFMPEG" ] && deps="$deps ffmpeg"
set -- set --
@ -498,7 +492,7 @@ fedora_installdeps() {
# this is sometimes necessary for rawhide # this is sometimes necessary for rawhide
set -- --exclude='glibc32*' set -- --exclude='glibc32*'
fi 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 case $pkg in
*ffmpeg*) *ffmpeg*)
[ -z "$ENABLE_FFMPEG" ] && continue [ -z "$ENABLE_FFMPEG" ] && continue
@ -597,8 +591,6 @@ fedora_installdeps() {
# get the necessary win32 headers # get the necessary win32 headers
git submodule update --init --remote --recursive 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 fi
[ -z "$rpms_installed" ] && check sudo dnf -y --nogpgcheck --best --allowerasing install "$@" [ -z "$rpms_installed" ] && check sudo dnf -y --nogpgcheck --best --allowerasing install "$@"
@ -684,8 +676,6 @@ rhel_installdeps() {
set -- --exclude='glibc32*' set -- --exclude='glibc32*'
fi 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 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 case $pkg in
*ffmpeg*) *ffmpeg*)
@ -777,8 +767,6 @@ rhel_installdeps() {
# get the necessary win32 headers # get the necessary win32 headers
git submodule update --init --remote --recursive 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 fi
[ -z "$rpms_installed" ] && check sudo yum -y install "$@" [ -z "$rpms_installed" ] && check sudo yum -y install "$@"
@ -797,7 +785,7 @@ suse_installdeps() {
check_cross check_cross
installing 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 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 $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" [ -n "$ENABLE_FFMPEG" ] && libs="$libs ffmpeg"
@ -884,7 +872,7 @@ archlinux_installdeps() {
else else
# try to build 32 bit binaries # try to build 32 bit binaries
# lib32-sfml and lib32-ffmpeg are in AUR # lib32-ffmpeg is in AUR
archlinux_require_yaourt archlinux_require_yaourt
# enable multilib repos if not enabled # enable multilib repos if not enabled
@ -978,8 +966,6 @@ EOF
# get the necessary win32 headers # get the necessary win32 headers
git submodule update --init --remote --recursive 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 fi
build_instructions build_instructions
@ -1042,13 +1028,12 @@ solus_installdeps() {
done done
else else
# no 32bit versions of these # no 32bit versions of these
set -- "$@" SFML-devel ffmpeg-devel set -- "$@" ffmpeg-devel
fi fi
check sudo eopkg -y install "$@" check sudo eopkg -y install "$@"
if [ -n "$amd64" -a "$target" = m32 ]; then 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' 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 fi
@ -1070,7 +1055,6 @@ gentoo_installdeps() {
dev-util/ccache \ dev-util/ccache \
sys-devel/binutils \ sys-devel/binutils \
media-libs/libsdl2 \ media-libs/libsdl2 \
media-libs/libsfml \
media-libs/openal \ media-libs/openal \
x11-libs/wxGTK:$wx_slot \ x11-libs/wxGTK:$wx_slot \
sys-libs/zlib \ sys-libs/zlib \
@ -1088,7 +1072,7 @@ gentoo_installdeps() {
alpine_installdeps() { alpine_installdeps() {
installing 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 build_instructions
} }
@ -1123,7 +1107,7 @@ windows_installdeps() {
;; ;;
esac 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 case "$target" in
*x86_64) *x86_64)
@ -1199,11 +1183,6 @@ brew_installdeps() {
[ -n "$ENABLE_FFMPEG" ] && brews="$brews ffmpeg" [ -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: # This is necessary for the GitHub Actions CI:
brew -v install python brew -v install python
brew link --overwrite python brew link --overwrite python
@ -1226,7 +1205,7 @@ macports_installdeps() {
check sudo port -v selfupdate 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" [ -n "$ENABLE_FFMPEG" ] && ports="$ports ffmpeg"
@ -1242,7 +1221,7 @@ fink_installdeps() {
check sudo fink -vy selfupdate 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" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"

View File

@ -19,8 +19,6 @@ parts:
cmake-generator: Ninja cmake-generator: Ninja
stage-packages: stage-packages:
- libsdl2-2.0-0 - libsdl2-2.0-0
- libsfml-network2.5
- libsfml-system2.5
- libnotify4 - libnotify4
- libsm6 - libsm6
- libopenal1 - libopenal1
@ -46,7 +44,6 @@ parts:
- zip - zip
- libnotify-dev - libnotify-dev
- libsdl2-dev - libsdl2-dev
- libsfml-dev
- libgtk-3-dev - libgtk-3-dev
- libopenal-dev - libopenal-dev
- libwxgtk3.0-gtk3-dev - libwxgtk3.0-gtk3-dev

View File

@ -127,6 +127,10 @@ if(ENABLE_LINK)
target_link_libraries(vbam-core target_link_libraries(vbam-core
PRIVATE ${SFML_LIBRARIES} PRIVATE ${SFML_LIBRARIES}
) )
target_compile_definitions(vbam-core
PRIVATE SFML_STATIC
)
# Add libintl.h # Add libintl.h
target_include_directories(vbam-core target_include_directories(vbam-core

248
third_party/sfml/include/SFML/Config.hpp vendored Normal file
View File

@ -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

View File

@ -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).
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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;
}

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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))
{
}

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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
///
////////////////////////////////////////////////////////////

View File

@ -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)
///
////////////////////////////////////////////////////////////

View File

@ -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;
}

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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);
}

View File

@ -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.
///
////////////////////////////////////////////////////////////

View File

@ -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);
}

21
third_party/sfml/license.md vendored Normal file
View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

110
third_party/sfml/src/SFML/System/Err.cpp vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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