diff --git a/CMakeLists.txt b/CMakeLists.txt index 514f403ab9..2039279edc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -600,16 +600,15 @@ if(LIBUSB_FOUND) include_directories(${LIBUSB_INCLUDE_DIR}) endif(LIBUSB_FOUND) -set(SFML_FIND_VERSION TRUE) -set(SFML_FIND_VERSION_MAJOR 1) -set(SFML_FIND_VERSION_MINOR 5) +set(SFML_REQD_VERSION 2.1) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) - include(FindSFML OPTIONAL) + find_package(SFML ${SFML_REQD_VERSION} COMPONENTS network system) endif() -if(SFML_FOUND AND NOT SFML_VERSION_MAJOR) # SFML 1.x doesn't define SFML_VERSION_MAJOR +if(SFML_FOUND) message("Using shared SFML") else() - message("Using static SFML ${SFML_FIND_VERSION_MAJOR}.${SFML_FIND_VERSION_MINOR} from Externals") + message("Using static SFML ${SFML_REQD_VERSION} from Externals") + add_definitions(-DSFML_STATIC) add_subdirectory(Externals/SFML) include_directories(BEFORE Externals/SFML/include) endif() diff --git a/CMakeTests/FindSFML.cmake b/CMakeTests/FindSFML.cmake index fd5f5fff48..b99e137881 100644 --- a/CMakeTests/FindSFML.cmake +++ b/CMakeTests/FindSFML.cmake @@ -1,20 +1,59 @@ -# Locate the SFML library +# This script locates the SFML library +# ------------------------------------ # -# This module defines the following variables: -# - For each 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_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) +# 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 (ie. 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 ...). +# 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) # -# If SFML is not installed in a standard path, you can use the SFMLDIR CMake variable or environment variable +# 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_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) +# +# 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_definitions(-DSFML_STATIC) +endif() # deduce the libraries suffix from the options set(FIND_SFML_LIB_SUFFIX "") @@ -26,6 +65,8 @@ endif() find_path(SFML_INCLUDE_DIR SFML/Config.hpp PATH_SUFFIXES include PATHS + ${SFML_ROOT} + $ENV{SFML_ROOT} ~/Library/Frameworks /Library/Frameworks /usr/local/ @@ -33,19 +74,19 @@ find_path(SFML_INCLUDE_DIR SFML/Config.hpp /sw # Fink /opt/local/ # DarwinPorts /opt/csw/ # Blastwave - /opt/ - ${SFMLDIR} - $ENV{SFMLDIR}) - - -# will be set to false if one of the required modules is not found -set(SFML_FOUND TRUE) -set(SFML_VERSION_OK TRUE) + /opt/) # check the version number -if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR AND NOT (SFML_INCLUDE_DIR STREQUAL "SFML_INCLUDE_DIR-NOTFOUND")) +set(SFML_VERSION_OK TRUE) +if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) # extract the major and minor version numbers from SFML/Config.hpp - FILE(READ "${SFML_INCLUDE_DIR}/SFML/Config.hpp" SFML_CONFIG_HPP_CONTENTS) + # 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 MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") @@ -68,22 +109,21 @@ if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR AND NOT (SFML_INCLUDE_DIR STREQUAL "SF set(SFML_VERSION_MINOR x) endif() endif() -elseif(SFML_INCLUDE_DIR STREQUAL "SFML_INCLUDE_DIR-NOTFOUND") - set(SFML_FOUND FALSE) - set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_INCLUDE_DIR") endif() # find the requested modules -set(FIND_SFML_LIB_PATHS ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt - ${SFMLDIR} - $ENV{SFMLDIR}) +set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found +set(FIND_SFML_LIB_PATHS + ${SFML_ROOT} + $ENV{SFML_ROOT} + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw + /opt/local + /opt/csw + /opt) 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) @@ -109,7 +149,7 @@ foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS}) 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} @@ -165,5 +205,5 @@ endif() # handle success if(SFML_FOUND) - message("Found SFML: ${SFML_INCLUDE_DIR}") + message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR} in ${SFML_INCLUDE_DIR}") endif() diff --git a/Externals/SFML/CMakeLists.txt b/Externals/SFML/CMakeLists.txt index b03bd713c0..0e82eae1ec 100644 --- a/Externals/SFML/CMakeLists.txt +++ b/Externals/SFML/CMakeLists.txt @@ -1,17 +1,27 @@ -include_directories(BEFORE include) +include_directories(BEFORE include src) -set(SRCS src/SFML/Network/Ftp.cpp - src/SFML/Network/Http.cpp - src/SFML/Network/IPAddress.cpp - src/SFML/Network/Packet.cpp - src/SFML/Network/SelectorBase.cpp - src/SFML/Network/SocketTCP.cpp - src/SFML/Network/SocketUDP.cpp) +set(SRC_NETWORK + src/SFML/Network/Http.cpp + src/SFML/Network/IPAddress.cpp + src/SFML/Network/Packet.cpp + src/SFML/Network/Socket.cpp + src/SFML/Network/SocketSelector.cpp + src/SFML/Network/TcpListener.cpp + src/SFML/Network/TcpSocket.cpp + src/SFML/Network/UdpSocket.cpp +) -if(UNIX) - set(SRCS ${SRCS} src/SFML/Network/Unix/SocketHelper.cpp) -elseif(WIN32) - set(SRCS ${SRCS} src/SFML/Network/Win32/SocketHelper.cpp) +if(WIN32) + list(APPEND SRC_NETWORK src/SFML/Network/Win32/SocketImpl.cpp) +else() + list(APPEND SRC_NETWORK src/SFML/Network/Unix/SocketImpl.cpp) endif() -add_library(sfml-network ${SRCS}) +set(SRC_SYSTEM + src/SFML/System/Err.cpp + src/SFML/System/String.cpp + src/SFML/System/Time.cpp +) + +add_library(sfml-network ${SRC_NETWORK}) +add_library(sfml-system ${SRC_SYSTEM}) diff --git a/Externals/SFML/build/vc2010/SFML_Network.vcxproj b/Externals/SFML/build/vc2010/SFML_Network.vcxproj index 78620e6564..18a955cc3f 100644 --- a/Externals/SFML/build/vc2010/SFML_Network.vcxproj +++ b/Externals/SFML/build/vc2010/SFML_Network.vcxproj @@ -42,33 +42,50 @@ + + + ..\..\src;%(AdditionalIncludeDirectories) + + - - - - - + + + + + + + + + - + + + - - - - - - - - - - + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/Externals/SFML/build/vc2010/SFML_Network.vcxproj.filters b/Externals/SFML/build/vc2010/SFML_Network.vcxproj.filters index 56ab9101fb..c80b82db38 100644 --- a/Externals/SFML/build/vc2010/SFML_Network.vcxproj.filters +++ b/Externals/SFML/build/vc2010/SFML_Network.vcxproj.filters @@ -1,38 +1,50 @@ - - - - - + + + + + + Win32 + + + - + + + - - - - - - - + + + + + + + + + + + + + + + + Win32 - - - {8280ecca-24fc-48a2-b7f5-6aca41826b66} - \ No newline at end of file + diff --git a/Externals/SFML/include/SFML/Config.hpp b/Externals/SFML/include/SFML/Config.hpp index 2a8cf123b3..d825a5af85 100644 --- a/Externals/SFML/include/SFML/Config.hpp +++ b/Externals/SFML/include/SFML/Config.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -25,6 +25,14 @@ #ifndef SFML_CONFIG_HPP #define SFML_CONFIG_HPP + +//////////////////////////////////////////////////////////// +// Define the SFML version +//////////////////////////////////////////////////////////// +#define SFML_VERSION_MAJOR 2 +#define SFML_VERSION_MINOR 1 + + //////////////////////////////////////////////////////////// // Identify the operating system //////////////////////////////////////////////////////////// @@ -32,9 +40,6 @@ // Windows #define SFML_SYSTEM_WINDOWS - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif #ifndef NOMINMAX #define NOMINMAX #endif @@ -49,8 +54,7 @@ // MacOS #define SFML_SYSTEM_MACOS -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ - defined(__NetBSD__) || defined(__OpenBSD__) +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) // FreeBSD #define SFML_SYSTEM_FREEBSD @@ -74,45 +78,47 @@ //////////////////////////////////////////////////////////// -// Define portable import / export macros +// Define helpers to create portable import / export macros for each module //////////////////////////////////////////////////////////// -#if defined(SFML_SYSTEM_WINDOWS) +#if !defined(SFML_STATIC) - #ifdef SFML_DYNAMIC + #if defined(SFML_SYSTEM_WINDOWS) - // Windows platforms - #ifdef SFML_EXPORTS + // Windows compilers need specific (and different) keywords for export and import + #define SFML_API_EXPORT __declspec(dllexport) + #define SFML_API_IMPORT __declspec(dllimport) - // From DLL side, we must export - #define SFML_API __declspec(dllexport) - - #else - - // From client application side, we must import - #define SFML_API __declspec(dllimport) - - #endif - - // For Visual C++ compilers, we also need to turn off this annoying C4251 warning. - // You can read lots ot different things about it, but the point is the code will - // just work fine, and so the simplest way to get rid of this warning is to disable it + // For Visual C++ compilers, we also need to turn off this annoying C4251 warning #ifdef _MSC_VER #pragma warning(disable : 4251) #endif - #else + #else // Linux, FreeBSD, Mac OS X - // No specific directive needed for static build - #define SFML_API + #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 - // Other platforms don't need to define anything - #define SFML_API + // Static build doesn't need import/export macros + #define SFML_API_EXPORT + #define SFML_API_IMPORT #endif @@ -120,44 +126,31 @@ //////////////////////////////////////////////////////////// // Define portable fixed-size types //////////////////////////////////////////////////////////// -#include - 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 - #if UCHAR_MAX == 0xFF - typedef signed char Int8; - typedef unsigned char Uint8; - #else - #error No 8 bits integer type for this platform - #endif + typedef signed char Int8; + typedef unsigned char Uint8; // 16 bits integer types - #if USHRT_MAX == 0xFFFF - typedef signed short Int16; - typedef unsigned short Uint16; - #elif UINT_MAX == 0xFFFF - typedef signed int Int16; - typedef unsigned int Uint16; - #elif ULONG_MAX == 0xFFFF - typedef signed long Int16; - typedef unsigned long Uint16; - #else - #error No 16 bits integer type for this platform - #endif + typedef signed short Int16; + typedef unsigned short Uint16; // 32 bits integer types - #if USHRT_MAX == 0xFFFFFFFF - typedef signed short Int32; - typedef unsigned short Uint32; - #elif UINT_MAX == 0xFFFFFFFF - typedef signed int Int32; - typedef unsigned int Uint32; - #elif ULONG_MAX == 0xFFFFFFFF - typedef signed long Int32; - typedef unsigned long Uint32; + 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 - #error No 32 bits integer type for this platform + typedef signed long long Int64; + typedef unsigned long long Uint64; #endif } // namespace sf diff --git a/Externals/SFML/include/SFML/Network.hpp b/Externals/SFML/include/SFML/Network.hpp index b0ca47d2b1..62f1286e0e 100644 --- a/Externals/SFML/include/SFML/Network.hpp +++ b/Externals/SFML/include/SFML/Network.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -30,13 +30,24 @@ //////////////////////////////////////////////////////////// #include -#include +//#include #include + +// This file is "IpAddress.hpp" upstream #include #include -#include -#include -#include +#include +#include +#include +#include #endif // SFML_NETWORK_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup network Network module +/// +/// Socket-based communication, utilities and higher-level +/// network protocols (HTTP, FTP). +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/Export.hpp b/Externals/SFML/include/SFML/Network/Export.hpp new file mode 100644 index 0000000000..7dcd1d074f --- /dev/null +++ b/Externals/SFML/include/SFML/Network/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_NETWORK_EXPORT_HPP +#define SFML_NETWORK_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// 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 diff --git a/Externals/SFML/include/SFML/Network/Ftp.hpp b/Externals/SFML/include/SFML/Network/Ftp.hpp deleted file mode 100644 index efc3a819b7..0000000000 --- a/Externals/SFML/include/SFML/Network/Ftp.hpp +++ /dev/null @@ -1,448 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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_FTP_HPP -#define SFML_FTP_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -class IPAddress; - -//////////////////////////////////////////////////////////// -/// This class provides methods for manipulating the FTP -/// protocol (described in RFC 959). -/// It provides easy access and transfers to remote -/// directories and files on a FTP server -//////////////////////////////////////////////////////////// -class SFML_API Ftp : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// 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 - }; - - //////////////////////////////////////////////////////////// - /// This class wraps a FTP response, which is basically : - /// - a status code - /// - a message - //////////////////////////////////////////////////////////// - class SFML_API Response - { - public : - - //////////////////////////////////////////////////////////// - /// Enumerate all the valid status codes returned in - /// 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, ///< Response is not a valid FTP one - ConnectionFailed = 1001, ///< Connection with server failed - ConnectionClosed = 1002, ///< Connection with server closed - InvalidFile = 1003 ///< Invalid file to upload / download - }; - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - /// \param Code : Response status code (InvalidResponse by default) - /// \param Message : Response message (empty by default) - /// - //////////////////////////////////////////////////////////// - Response(Status Code = InvalidResponse, const std::string& Message = ""); - - //////////////////////////////////////////////////////////// - /// Convenience function to check if the response status code - /// means a success - /// - /// \return True if status is success (code < 400) - /// - //////////////////////////////////////////////////////////// - bool IsOk() const; - - //////////////////////////////////////////////////////////// - /// Get the response status code - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Status GetStatus() const; - - //////////////////////////////////////////////////////////// - /// Get the full message contained in the response - /// - /// \return The response message - /// - //////////////////////////////////////////////////////////// - const std::string& GetMessage() const; - - private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Status myStatus; ///< Status code returned from the server - std::string myMessage; ///< Last message received from the server - }; - - //////////////////////////////////////////////////////////// - /// Specialization of FTP response returning a directory - //////////////////////////////////////////////////////////// - class SFML_API DirectoryResponse : public Response - { - public : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - /// \param Resp : Source response - /// - //////////////////////////////////////////////////////////// - DirectoryResponse(Response Resp); - - //////////////////////////////////////////////////////////// - /// Get the directory returned in the response - /// - /// \return Directory name - /// - //////////////////////////////////////////////////////////// - const std::string& GetDirectory() const; - - private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::string myDirectory; ///< Directory extracted from the response message - }; - - - //////////////////////////////////////////////////////////// - /// Specialization of FTP response returning a filename lisiting - //////////////////////////////////////////////////////////// - class SFML_API ListingResponse : public Response - { - public : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - /// \param Resp : Source response - /// \param Data : Data containing the raw listing - /// - //////////////////////////////////////////////////////////// - ListingResponse(Response Resp, const std::vector& Data); - - //////////////////////////////////////////////////////////// - /// Get the number of filenames in the listing - /// - /// \return Total number of filenames - /// - //////////////////////////////////////////////////////////// - std::size_t GetCount() const; - - //////////////////////////////////////////////////////////// - /// Get the Index-th filename in the directory - /// - /// \param Index : Index of the filename to get - /// - /// \return Index-th filename - /// - //////////////////////////////////////////////////////////// - const std::string& GetFilename(std::size_t Index) const; - - private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - std::vector myFilenames; ///< Filenames extracted from the data - }; - - - //////////////////////////////////////////////////////////// - /// Destructor -- close the connection with the server - /// - //////////////////////////////////////////////////////////// - ~Ftp(); - - //////////////////////////////////////////////////////////// - /// Connect to the specified FTP server - /// - /// \param Server : FTP server to connect to - /// \param Port : Port used for connection (21 by default, standard FTP port) - /// \param Timeout : Maximum time to wait, in seconds (0 by default, means no timeout) - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response Connect(const IPAddress& Server, unsigned short Port = 21, float Timeout = 0.f); - - //////////////////////////////////////////////////////////// - /// Log in using anonymous account - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response Login(); - - //////////////////////////////////////////////////////////// - /// Log in using a username and a password - /// - /// \param UserName : User name - /// \param Password : Password - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response Login(const std::string& UserName, const std::string& Password); - - //////////////////////////////////////////////////////////// - /// Close the connection with FTP server - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response Disconnect(); - - //////////////////////////////////////////////////////////// - /// Send a null command just to prevent from being disconnected - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response KeepAlive(); - - //////////////////////////////////////////////////////////// - /// Get the current working directory - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - DirectoryResponse GetWorkingDirectory(); - - //////////////////////////////////////////////////////////// - /// Get the contents of the given directory - /// (subdirectories and files) - /// - /// \param Directory : Directory to list ("" by default, the current one) - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - ListingResponse GetDirectoryListing(const std::string& Directory = ""); - - //////////////////////////////////////////////////////////// - /// Change the current working directory - /// - /// \param Directory : New directory, relative to the current one - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response ChangeDirectory(const std::string& Directory); - - //////////////////////////////////////////////////////////// - /// Go to the parent directory of the current one - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response ParentDirectory(); - - //////////////////////////////////////////////////////////// - /// Create a new directory - /// - /// \param Name : Name of the directory to create - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response MakeDirectory(const std::string& Name); - - //////////////////////////////////////////////////////////// - /// Remove an existing directory - /// - /// \param Name : Name of the directory to remove - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response DeleteDirectory(const std::string& Name); - - //////////////////////////////////////////////////////////// - /// Rename a file - /// - /// \param File : File to rename - /// \param NewName : New name - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response RenameFile(const std::string& File, const std::string& NewName); - - //////////////////////////////////////////////////////////// - /// Remove an existing file - /// - /// \param Name : File to remove - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response DeleteFile(const std::string& Name); - - //////////////////////////////////////////////////////////// - /// Download a file from the server - /// - /// \param DistantFile : Path of the distant file to download - /// \param DestPath : Where to put to file on the local computer - /// \param Mode : Transfer mode (binary by default) - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response Download(const std::string& DistantFile, const std::string& DestPath, TransferMode Mode = Binary); - - //////////////////////////////////////////////////////////// - /// Upload a file to the server - /// - /// \param LocalFile : Path of the local file to upload - /// \param DestPath : Where to put to file on the server - /// \param Mode : Transfer mode (binary by default) - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response Upload(const std::string& LocalFile, const std::string& DestPath, TransferMode Mode = Binary); - -private : - - //////////////////////////////////////////////////////////// - /// Send a command to the FTP server - /// - /// \param Command : Command to send - /// \param Parameter : Command parameter ("" by default) - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response SendCommand(const std::string& Command, const std::string& Parameter = ""); - - //////////////////////////////////////////////////////////// - /// Receive a response from the server - /// (usually after a command has been sent) - /// - /// \return Server response to the request - /// - //////////////////////////////////////////////////////////// - Response GetResponse(); - - //////////////////////////////////////////////////////////// - /// Utility class for exchanging datas with the server - /// on the data channel - //////////////////////////////////////////////////////////// - class DataChannel; - - friend class DataChannel; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - SocketTCP myCommandSocket; ///< Socket holding the control connection with the server -}; - -} // namespace sf - - -#endif // SFML_FTP_HPP diff --git a/Externals/SFML/include/SFML/Network/Http.hpp b/Externals/SFML/include/SFML/Network/Http.hpp index 137bf97130..58299051b8 100644 --- a/Externals/SFML/include/SFML/Network/Http.hpp +++ b/Externals/SFML/include/SFML/Network/Http.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -28,9 +28,11 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include -#include +#include +#include +#include #include #include @@ -38,25 +40,24 @@ namespace sf { //////////////////////////////////////////////////////////// -/// This class provides methods for manipulating the HTTP -/// protocol (described in RFC 1945). -/// It can connect to a website, get its files, send requests, etc. +/// \brief A HTTP client +/// //////////////////////////////////////////////////////////// -class SFML_API Http : NonCopyable +class SFML_NETWORK_API Http : NonCopyable { public : //////////////////////////////////////////////////////////// - /// This class wraps an HTTP request, which is basically : - /// - a header with a method, a target URI, and a set of field/value pairs - /// - an optional body (for POST requests) + /// \brief Define a HTTP request + /// //////////////////////////////////////////////////////////// - class SFML_API Request + class SFML_NETWORK_API Request { public : //////////////////////////////////////////////////////////// - /// Enumerate the available HTTP methods for a request + /// \brief Enumerate the available HTTP methods for a request + /// //////////////////////////////////////////////////////////// enum Method { @@ -66,83 +67,106 @@ public : }; //////////////////////////////////////////////////////////// - /// Default constructor + /// \brief Default constructor /// - /// \param RequestMethod : Method to use for the request (Get by default) - /// \param URI : Target URI ("/" by default -- index page) - /// \param Body : Content of the request's body (empty by default) + /// 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(Method RequestMethod = Get, const std::string& URI = "/", const std::string& Body = ""); + Request(const std::string& uri = "/", Method method = Get, const std::string& body = ""); //////////////////////////////////////////////////////////// - /// Set the value of a field; the field is added if it doesn't exist + /// \brief Set the value of a field /// - /// \param Field : Name of the field to set (case-insensitive) - /// \param Value : Value of the 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); + void setField(const std::string& field, const std::string& value); //////////////////////////////////////////////////////////// - /// Set the request method. - /// This parameter is Http::Request::Get by default + /// \brief Set the request method /// - /// \param RequestMethod : Method to use for the request + /// 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 RequestMethod); + void setMethod(Method method); //////////////////////////////////////////////////////////// - /// Set the target URI of the request. - /// This parameter is "/" by default + /// \brief Set the requested URI /// - /// \param URI : URI to request, local to the host + /// 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); + void setUri(const std::string& uri); //////////////////////////////////////////////////////////// - /// Set the HTTP version of the request. - /// This parameter is 1.0 by default + /// \brief Set the HTTP version for the request /// - /// \param Major : Major version number - /// \param Minor : Minor version number + /// 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); + void setHttpVersion(unsigned int major, unsigned int minor); //////////////////////////////////////////////////////////// - /// Set the body of the request. This parameter is optional and - /// makes sense only for POST requests. - /// This parameter is empty by default + /// \brief Set the body of the request /// - /// \param Body : Content of the request body + /// 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); + void setBody(const std::string& body); private : friend class Http; //////////////////////////////////////////////////////////// - /// Get the string representation of the request header + /// \brief Prepare the final request to send to the server /// - /// \return String containing the request + /// 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 ToString() const; + std::string prepare() const; //////////////////////////////////////////////////////////// - /// Check if the given field has been defined + /// \brief Check if the request defines a field /// - /// \param Field : Name of the field to check (case-insensitive) + /// This function uses case-insensitive comparisons. /// - /// \return True if the field exists + /// \param field Name of the field to test + /// + /// \return True if the field exists, false otherwise /// //////////////////////////////////////////////////////////// - bool HasField(const std::string& Field) const; + bool hasField(const std::string& field) const; //////////////////////////////////////////////////////////// // Types @@ -152,34 +176,35 @@ public : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - FieldTable myFields; ///< Fields of the header - Method myMethod; ///< Method to use for the request - std::string myURI; ///< Target URI of the request - unsigned int myMajorVersion; ///< Major HTTP version - unsigned int myMinorVersion; ///< Minor HTTP version - std::string myBody; ///< Body of the request + 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 }; //////////////////////////////////////////////////////////// - /// This class wraps an HTTP response, which is basically : - /// - a header with a status code and a set of field/value pairs - /// - a body (the content of the requested resource) + /// \brief Define a HTTP response + /// //////////////////////////////////////////////////////////// - class SFML_API Response + class SFML_NETWORK_API Response { public : //////////////////////////////////////////////////////////// - /// Enumerate all the valid status codes returned in - /// a HTTP response + /// \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, ///< Sent when the server didn't send any data in return + 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 @@ -188,16 +213,19 @@ public : NotModified = 304, ///< For conditionnal 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 authentification to be accessed - Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification - NotFound = 404, ///< The requested page doesn't exist + BadRequest = 400, ///< The server couldn't understand the request (syntax error) + Unauthorized = 401, ///< The requested page needs an authentification to be accessed + Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification + 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 @@ -205,68 +233,88 @@ public : }; //////////////////////////////////////////////////////////// - /// Default constructor + /// \brief Default constructor + /// + /// Constructs an empty response. /// //////////////////////////////////////////////////////////// Response(); //////////////////////////////////////////////////////////// - /// Get the value of a field + /// \brief Get the value of a field /// - /// \param Field : Name of the field to get (case-insensitive) + /// 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; + const std::string& getField(const std::string& field) const; //////////////////////////////////////////////////////////// - /// Get the header's status code + /// \brief Get the response status code /// - /// \return Header's 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; + Status getStatus() const; //////////////////////////////////////////////////////////// - /// Get the major HTTP version number of the response + /// \brief Get the major HTTP version number of the response /// - /// \return Major version number + /// \return Major HTTP version number + /// + /// \see getMinorHttpVersion /// //////////////////////////////////////////////////////////// - unsigned int GetMajorHttpVersion() const; + unsigned int getMajorHttpVersion() const; //////////////////////////////////////////////////////////// - /// Get the major HTTP version number of the response + /// \brief Get the minor HTTP version number of the response /// - /// \return Major version number + /// \return Minor HTTP version number + /// + /// \see getMajorHttpVersion /// //////////////////////////////////////////////////////////// - unsigned int GetMinorHttpVersion() const; + unsigned int getMinorHttpVersion() const; //////////////////////////////////////////////////////////// - /// Get the body of the response. The body can contain : - /// - the requested page (for GET requests) - /// - a response from the server (for POST requests) - /// - nothing (for HEAD requests) - /// - an error message (in case of an error) + /// \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; + const std::string& getBody() const; private : friend class Http; //////////////////////////////////////////////////////////// - /// Construct the header from a response string + /// \brief Construct the header from a response string /// - /// \param Data : Content of the response's header to parse + /// This function is used by Http to build the response + /// of a request. + /// + /// \param data Content of the response to parse /// //////////////////////////////////////////////////////////// - void FromString(const std::string& Data); + void parse(const std::string& data); //////////////////////////////////////////////////////////// // Types @@ -276,65 +324,144 @@ public : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - FieldTable myFields; ///< Fields of the header - Status myStatus; ///< Status code - unsigned int myMajorVersion; ///< Major HTTP version - unsigned int myMinorVersion; ///< Minor HTTP version - std::string myBody; ///< Body of the response + 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 }; //////////////////////////////////////////////////////////// - /// Default constructor + /// \brief Default constructor /// //////////////////////////////////////////////////////////// Http(); //////////////////////////////////////////////////////////// - /// Construct the Http instance with the target host + /// \brief Construct the HTTP client with the target host /// - /// \param Host : Web server to connect to - /// \param Port : Port to use for connection (0 by default -- use the standard port of the protocol used) + /// 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, 443 for HTTPS). 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); + Http(const std::string& host, unsigned short port = 0); //////////////////////////////////////////////////////////// - /// Set the target host + /// \brief Set the target host /// - /// \param Host : Web server to connect to - /// \param Port : Port to use for connection (0 by default -- use the standard port of the protocol used) + /// 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, 443 for HTTPS). 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); + void setHost(const std::string& host, unsigned short port = 0); //////////////////////////////////////////////////////////// - /// Send a HTTP request and return the server's response. - /// You must be connected to a host before sending requests. - /// Any missing mandatory header field will be added with an appropriate value. - /// Warning : this function waits for the server's response and may + /// \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. + /// application, or use a timeout to limit the time to wait. A value + /// of Time::Zero means that the client will use the system defaut timeout + /// (which is usually pretty long). /// - /// \param Req : Request to send - /// \param Timeout : Maximum time to wait, in seconds (0 by default, means no timeout) + /// \param request Request to send + /// \param timeout Maximum time to wait /// /// \return Server's response /// //////////////////////////////////////////////////////////// - Response SendRequest(const Request& Req, float Timeout = 0.f); + Response sendRequest(const Request& request, Time timeout = Time::Zero); private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - SocketTCP myConnection; ///< Connection to the host - IPAddress myHost; ///< Web host address - std::string myHostName; ///< Web host name - unsigned short myPort; ///< Port used for connection with host + 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 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/IPAddress.hpp b/Externals/SFML/include/SFML/Network/IPAddress.hpp index 0e560d9da3..d2fdda4321 100644 --- a/Externals/SFML/include/SFML/Network/IPAddress.hpp +++ b/Externals/SFML/include/SFML/Network/IPAddress.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -28,7 +28,8 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include +#include #include #include #include @@ -37,195 +38,279 @@ namespace sf { //////////////////////////////////////////////////////////// -/// IPAddress provides easy manipulation of IP v4 addresses +/// \brief Encapsulate an IPv4 network address +/// //////////////////////////////////////////////////////////// -class SFML_API IPAddress +class SFML_NETWORK_API IpAddress { public : //////////////////////////////////////////////////////////// - /// Default constructor -- constructs an invalid address + /// \brief Default constructor + /// + /// This constructor creates an empty (invalid) address /// //////////////////////////////////////////////////////////// - IPAddress(); + IpAddress(); //////////////////////////////////////////////////////////// - /// Construct the address from a string + /// \brief Construct the address from a string /// - /// \param Address : IP address ("xxx.xxx.xxx.xxx") or network name + /// 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); + IpAddress(const std::string& address); //////////////////////////////////////////////////////////// - /// Construct the address from a C-style string ; - /// Needed for implicit conversions from literal strings to IPAddress to work + /// \brief Construct the address from a string /// - /// \param Address : IP address ("xxx.xxx.xxx.xxx") or network name + /// 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); + IpAddress(const char* address); //////////////////////////////////////////////////////////// - /// Construct the address from 4 bytes + /// \brief Construct the address from 4 bytes /// - /// \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 + /// 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); + IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3); //////////////////////////////////////////////////////////// - /// Construct the address from a 32-bits integer + /// \brief Construct the address from a 32-bits integer /// - /// \param Address : 4 bytes of the address packed into 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 /// //////////////////////////////////////////////////////////// - IPAddress(Uint32 Address); + explicit IpAddress(Uint32 address); //////////////////////////////////////////////////////////// - /// Tell if the address is a valid one + /// \brief Get a string representation of the address /// - /// \return True if address has a valid syntax + /// 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 /// //////////////////////////////////////////////////////////// - bool IsValid() const; + std::string toString() const; //////////////////////////////////////////////////////////// - /// Get a string representation of the address + /// \brief Get an integer representation of the address /// - /// \return String representation of the IP address ("xxx.xxx.xxx.xxx") + /// 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 /// //////////////////////////////////////////////////////////// - std::string ToString() const; + Uint32 toInteger() const; //////////////////////////////////////////////////////////// - /// Get an integer representation of the address + /// \brief Get the computer's local address /// - /// \return 32-bits integer containing the 4 bytes of the address, in system endianness + /// 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 /// //////////////////////////////////////////////////////////// - Uint32 ToInteger() const; + static IpAddress getLocalAddress(); //////////////////////////////////////////////////////////// - /// Get the computer's local IP address (from the LAN point of view) + /// \brief Get the computer's public address /// - /// \return Local IP address - /// - //////////////////////////////////////////////////////////// - static IPAddress GetLocalAddress(); - - //////////////////////////////////////////////////////////// - /// Get the computer's public IP address (from the web point of view). + /// 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 may be - /// very slow -- use it as few as possible ! + /// 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, in seconds (0 by default : no timeout) + /// \param timeout Maximum time to wait /// - /// \return Public IP address + /// \return Public IP address of the computer + /// + /// \see getLocalAddress /// //////////////////////////////////////////////////////////// - static IPAddress GetPublicAddress(float Timeout = 0.f); - - //////////////////////////////////////////////////////////// - /// Comparison operator == - /// - /// \param Other : Address to compare - /// - /// \return True if *this == Other - /// - //////////////////////////////////////////////////////////// - bool operator ==(const IPAddress& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator != - /// - /// \param Other : Address to compare - /// - /// \return True if *this != Other - /// - //////////////////////////////////////////////////////////// - bool operator !=(const IPAddress& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator < - /// - /// \param Other : Address to compare - /// - /// \return True if *this < Other - /// - //////////////////////////////////////////////////////////// - bool operator <(const IPAddress& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator > - /// - /// \param Other : Address to compare - /// - /// \return True if *this > Other - /// - //////////////////////////////////////////////////////////// - bool operator >(const IPAddress& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator <= - /// - /// \param Other : Address to compare - /// - /// \return True if *this <= Other - /// - //////////////////////////////////////////////////////////// - bool operator <=(const IPAddress& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator >= - /// - /// \param Other : Address to compare - /// - /// \return True if *this >= Other - /// - //////////////////////////////////////////////////////////// - bool operator >=(const IPAddress& Other) const; + static IpAddress getPublicAddress(Time timeout = Time::Zero); //////////////////////////////////////////////////////////// // Static member data //////////////////////////////////////////////////////////// - static const IPAddress LocalHost; ///< Local host address (to connect to the same computer) + static const IpAddress None; ///< Value representing an empty/invalid address + 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 : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Uint32 myAddress; ///< Address stored as an unsigned 32 bits integer + Uint32 m_address; ///< Address stored as an unsigned 32 bits integer }; //////////////////////////////////////////////////////////// -/// Operator >> overload to extract an address from an input stream +/// \brief Overload of == operator to compare two IP addresses /// -/// \param Stream : Input stream -/// \param Address : Address to extract +/// \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_API std::istream& operator >>(std::istream& Stream, IPAddress& Address); +SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address); //////////////////////////////////////////////////////////// -/// Operator << overload to print an address to an output stream +/// \brief Overload of << operator to print an IP address to an output stream /// -/// \param Stream : Output stream -/// \param Address : Address to print +/// \param stream Output stream +/// \param address IP address to print /// /// \return Reference to the output stream /// //////////////////////////////////////////////////////////// -SFML_API std::ostream& operator <<(std::ostream& Stream, const IPAddress& Address); +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. +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/Packet.hpp b/Externals/SFML/include/SFML/Network/Packet.hpp index a4af131ae7..4b67852c18 100644 --- a/Externals/SFML/include/SFML/Network/Packet.hpp +++ b/Externals/SFML/include/SFML/Network/Packet.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -28,160 +28,380 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include #include namespace sf { +class String; +class TcpSocket; +class UdpSocket; + //////////////////////////////////////////////////////////// -/// Packet wraps data to send / to receive through the network +/// \brief Utility class to build blocks of data to transfer +/// over the network +/// //////////////////////////////////////////////////////////// -class SFML_API Packet +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 : //////////////////////////////////////////////////////////// - /// Default constructor + /// \brief Default constructor + /// + /// Creates an empty packet. /// //////////////////////////////////////////////////////////// Packet(); //////////////////////////////////////////////////////////// - /// Virtual destructor + /// \brief Virtual destructor /// //////////////////////////////////////////////////////////// virtual ~Packet(); //////////////////////////////////////////////////////////// - /// Append data to the end of the packet + /// \brief Append data to the end of the packet /// - /// \param Data : Pointer to the bytes to append - /// \param SizeInBytes : Number of bytes to append + /// \param data Pointer to the sequence of bytes to append + /// \param sizeInBytes Number of bytes to append + /// + /// \see clear /// //////////////////////////////////////////////////////////// - void Append(const void* Data, std::size_t SizeInBytes); + void append(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// - /// Clear the packet data + /// \brief Clear the packet + /// + /// After calling Clear, the packet is empty. + /// + /// \see append /// //////////////////////////////////////////////////////////// - void Clear(); + void clear(); //////////////////////////////////////////////////////////// - /// Get a pointer to the data contained in the packet - /// Warning : the returned pointer may be invalid after you - /// append data to the packet + /// \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 char* GetData() const; + const void* getData() const; //////////////////////////////////////////////////////////// - /// Get the size of the data contained in the packet + /// \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 /// - //////////////////////////////////////////////////////////// - std::size_t GetDataSize() const; - - //////////////////////////////////////////////////////////// - /// Tell if the reading position has reached the end of the packet - /// - /// \return True if all data have been read into the packet + /// \see getData /// //////////////////////////////////////////////////////////// - bool EndOfPacket() const; + std::size_t getDataSize() const; //////////////////////////////////////////////////////////// - /// Return the validity of packet + /// \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 behaviour 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 /// - //////////////////////////////////////////////////////////// - operator bool() const; - - //////////////////////////////////////////////////////////// - /// Operator >> overloads to extract data from the packet + /// \see endOfPacket /// //////////////////////////////////////////////////////////// - Packet& operator >>(bool& Data); - Packet& operator >>(Int8& Data); - Packet& operator >>(Uint8& Data); - Packet& operator >>(Int16& Data); - Packet& operator >>(Uint16& Data); - Packet& operator >>(Int32& Data); - Packet& operator >>(Uint32& Data); - Packet& operator >>(float& Data); - Packet& operator >>(double& Data); - Packet& operator >>(char* Data); - Packet& operator >>(std::string& Data); - Packet& operator >>(wchar_t* Data); - Packet& operator >>(std::wstring& Data); + operator BoolType() const; //////////////////////////////////////////////////////////// - /// Operator << overloads to put data into the packet + /// Overloads of operator >> to read data from the packet /// //////////////////////////////////////////////////////////// - Packet& operator <<(bool Data); - Packet& operator <<(Int8 Data); - Packet& operator <<(Uint8 Data); - Packet& operator <<(Int16 Data); - Packet& operator <<(Uint16 Data); - Packet& operator <<(Int32 Data); - Packet& operator <<(Uint32 Data); - Packet& operator <<(float Data); - Packet& operator <<(double Data); - Packet& operator <<(const char* Data); - Packet& operator <<(const std::string& Data); - Packet& operator <<(const wchar_t* Data); - Packet& operator <<(const std::wstring& Data); - -private : - - friend class SocketTCP; - friend class SocketUDP; + Packet& operator >>(bool& data); + Packet& operator >>(Int8& data); + Packet& operator >>(Uint8& data); + Packet& operator >>(Int16& data); + Packet& operator >>(Uint16& data); + Packet& operator >>(Int32& data); + Packet& operator >>(Uint32& data); + Packet& operator >>(float& data); + Packet& operator >>(double& data); + Packet& operator >>(char* data); + Packet& operator >>(std::string& data); + Packet& operator >>(wchar_t* data); + Packet& operator >>(std::wstring& data); + Packet& operator >>(String& data); //////////////////////////////////////////////////////////// - /// Check if the packet can extract a given size of bytes - /// - /// \param Size : Size to check - /// - /// \return True if Size bytes can be read from the packet's data + /// Overloads of operator << to write data into the packet /// //////////////////////////////////////////////////////////// - bool CheckSize(std::size_t Size); + Packet& operator <<(bool data); + Packet& operator <<(Int8 data); + Packet& operator <<(Uint8 data); + Packet& operator <<(Int16 data); + Packet& operator <<(Uint16 data); + Packet& operator <<(Int32 data); + Packet& operator <<(Uint32 data); + Packet& operator <<(float data); + Packet& operator <<(double data); + Packet& operator <<(const char* data); + Packet& operator <<(const std::string& data); + Packet& operator <<(const wchar_t* data); + Packet& operator <<(const std::wstring& data); + Packet& operator <<(const String& data); + +protected: + + friend class TcpSocket; + friend class UdpSocket; //////////////////////////////////////////////////////////// - /// Called before the packet is sent to the network + /// \brief Called before the packet is sent over the network /// - /// \param DataSize : Variable to fill with the size of data to send + /// 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 char* OnSend(std::size_t& DataSize); + virtual const void* onSend(std::size_t& size); //////////////////////////////////////////////////////////// - /// Called after the packet has been received from the network + /// \brief Called after the packet is received over the network /// - /// \param Data : Pointer to the array of received bytes - /// \param DataSize : Size of the array of bytes + /// This function can be defined by derived classes to + /// transform the data after it is received; this can be + /// used for uncompression, 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 char* Data, std::size_t DataSize); + 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 myData; ///< Data stored in the packet - std::size_t myReadPos; ///< Current reading position in the packet - bool myIsValid; ///< Reading state of the packet + std::vector m_data; ///< Data stored in the packet + std::size_t m_readPos; ///< Current reading position in the packet + 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 +/// transfering 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 behaviour 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/Selector.hpp b/Externals/SFML/include/SFML/Network/Selector.hpp deleted file mode 100644 index 83c766eb7c..0000000000 --- a/Externals/SFML/include/SFML/Network/Selector.hpp +++ /dev/null @@ -1,116 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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_SELECTOR_HPP -#define SFML_SELECTOR_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// Selector allow reading from multiple sockets -/// without blocking. It's a kind of multiplexer -//////////////////////////////////////////////////////////// -template -class Selector : private SelectorBase -{ -public : - - //////////////////////////////////////////////////////////// - /// Add a socket to watch - /// - /// \param Socket : Socket to add - /// - //////////////////////////////////////////////////////////// - void Add(Type Socket); - - //////////////////////////////////////////////////////////// - /// Remove a socket - /// - /// \param Socket : Socket to remove - /// - //////////////////////////////////////////////////////////// - void Remove(Type Socket); - - //////////////////////////////////////////////////////////// - /// Remove all sockets - /// - //////////////////////////////////////////////////////////// - void Clear(); - - //////////////////////////////////////////////////////////// - /// Wait and collect sockets which are ready for reading. - /// This functions will return either when at least one socket - /// is ready, or when the given time is out - /// - /// \param Timeout : Timeout, in seconds (0 by default : no timeout) - /// - /// \return Number of sockets ready to be read - /// - //////////////////////////////////////////////////////////// - unsigned int Wait(float Timeout = 0.f); - - //////////////////////////////////////////////////////////// - /// After a call to Wait(), get the Index-th socket which is - /// ready for reading. The total number of sockets ready - /// is the integer returned by the previous call to Wait() - /// - /// \param Index : Index of the socket to get - /// - /// \return The Index-th socket - /// - //////////////////////////////////////////////////////////// - Type GetSocketReady(unsigned int Index); - -private : - - //////////////////////////////////////////////////////////// - // Types - //////////////////////////////////////////////////////////// - typedef std::map SocketTable; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - SocketTable mySockets; ///< Table matching the SFML socket instances with their low-level handles -}; - -#include - -// Let's define the two only valid types of Selector -typedef Selector SelectorUDP; -typedef Selector SelectorTCP; - -} // namespace sf - - -#endif // SFML_SELECTOR_HPP diff --git a/Externals/SFML/include/SFML/Network/Selector.inl b/Externals/SFML/include/SFML/Network/Selector.inl deleted file mode 100644 index e234a05bbb..0000000000 --- a/Externals/SFML/include/SFML/Network/Selector.inl +++ /dev/null @@ -1,97 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -/// Add a socket to watch -//////////////////////////////////////////////////////////// -template -void Selector::Add(Type Socket) -{ - if (Socket.IsValid()) - { - SelectorBase::Add(Socket.mySocket); - mySockets[Socket.mySocket] = Socket; - } -} - - -//////////////////////////////////////////////////////////// -/// Remove a socket -//////////////////////////////////////////////////////////// -template -void Selector::Remove(Type Socket) -{ - typename SocketTable::iterator It = mySockets.find(Socket.mySocket); - if (It != mySockets.end()) - { - SelectorBase::Remove(Socket.mySocket); - mySockets.erase(It); - } -} - - -//////////////////////////////////////////////////////////// -/// Remove all sockets -//////////////////////////////////////////////////////////// -template -void Selector::Clear() -{ - SelectorBase::Clear(); - mySockets.clear(); -} - - -//////////////////////////////////////////////////////////// -/// Wait and collect sockets which are ready for reading. -/// This functions will return either when at least one socket -/// is ready, or when the given time is out -//////////////////////////////////////////////////////////// -template -unsigned int Selector::Wait(float Timeout) -{ - // No socket in the selector : return 0 - if (mySockets.empty()) - return 0; - - return SelectorBase::Wait(Timeout); -} - - -//////////////////////////////////////////////////////////// -/// After a call to Wait(), get the Index-th socket which is -/// ready for reading. The total number of sockets ready -/// is the integer returned by the previous call to Wait() -//////////////////////////////////////////////////////////// -template -Type Selector::GetSocketReady(unsigned int Index) -{ - SocketHelper::SocketType Socket = SelectorBase::GetSocketReady(Index); - - typename SocketTable::const_iterator It = mySockets.find(Socket); - if (It != mySockets.end()) - return It->second; - else - return Type(Socket); -} diff --git a/Externals/SFML/include/SFML/Network/SelectorBase.hpp b/Externals/SFML/include/SFML/Network/SelectorBase.hpp deleted file mode 100644 index c85a4feec7..0000000000 --- a/Externals/SFML/include/SFML/Network/SelectorBase.hpp +++ /dev/null @@ -1,112 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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_SELECTORBASE_HPP -#define SFML_SELECTORBASE_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// Private base class for selectors. -/// As Selector is a template class, this base is needed so that -/// every system call get compiled in SFML (not inlined) -//////////////////////////////////////////////////////////// -class SFML_API SelectorBase -{ -public : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - SelectorBase(); - - //////////////////////////////////////////////////////////// - /// Add a socket to watch - /// - /// \param Socket : Socket to add - /// - //////////////////////////////////////////////////////////// - void Add(SocketHelper::SocketType Socket); - - //////////////////////////////////////////////////////////// - /// Remove a socket - /// - /// \param Socket : Socket to remove - /// - //////////////////////////////////////////////////////////// - void Remove(SocketHelper::SocketType Socket); - - //////////////////////////////////////////////////////////// - /// Remove all sockets - /// - //////////////////////////////////////////////////////////// - void Clear(); - - //////////////////////////////////////////////////////////// - /// Wait and collect sockets which are ready for reading. - /// This functions will return either when at least one socket - /// is ready, or when the given time is out - /// - /// \param Timeout : Timeout, in seconds (0 by default : no timeout) - /// - /// \return Number of sockets ready to be read - /// - //////////////////////////////////////////////////////////// - unsigned int Wait(float Timeout = 0.f); - - //////////////////////////////////////////////////////////// - /// After a call to Wait(), get the Index-th socket which is - /// ready for reading. The total number of sockets ready - /// is the integer returned by the previous call to Wait() - /// - /// \param Index : Index of the socket to get - /// - /// \return The Index-th socket - /// - //////////////////////////////////////////////////////////// - SocketHelper::SocketType GetSocketReady(unsigned int Index); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - fd_set mySet; ///< Set of socket to watch - fd_set mySetReady; ///< Set of socket which are ready for reading - int myMaxSocket; ///< Maximum socket index -}; - -} // namespace sf - - -#endif // SFML_SELECTORBASE_HPP diff --git a/Externals/SFML/include/SFML/Network/Socket.hpp b/Externals/SFML/include/SFML/Network/Socket.hpp new file mode 100644 index 0000000000..c58e8ad184 --- /dev/null +++ b/Externals/SFML/include/SFML/Network/Socket.hpp @@ -0,0 +1,218 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_SOCKET_HPP +#define SFML_SOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +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 + 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/SocketHelper.hpp b/Externals/SFML/include/SFML/Network/SocketHandle.hpp similarity index 61% rename from Externals/SFML/include/SFML/Network/SocketHelper.hpp rename to Externals/SFML/include/SFML/Network/SocketHandle.hpp index a9fb8ed65a..c05a6354cd 100644 --- a/Externals/SFML/include/SFML/Network/SocketHelper.hpp +++ b/Externals/SFML/include/SFML/Network/SocketHandle.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -22,43 +22,36 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_SOCKETHELPER_HPP -#define SFML_SOCKETHELPER_HPP +#ifndef SFML_SOCKETHANDLE_HPP +#define SFML_SOCKETHANDLE_HPP //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// #include +#if defined(SFML_SYSTEM_WINDOWS) + #include +#endif + namespace sf { -namespace Socket -{ - //////////////////////////////////////////////////////////// - /// Enumeration of status 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 - Disconnected, ///< The TCP socket has been disconnected - Error ///< An unexpected error happened - }; -} +//////////////////////////////////////////////////////////// +// 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 -#ifdef SFML_SYSTEM_WINDOWS - - #include - -#else - - #include - -#endif - - -#endif // SFML_SOCKETHELPER_HPP +#endif // SFML_SOCKETHANDLE_HPP diff --git a/Externals/SFML/include/SFML/Network/SocketSelector.hpp b/Externals/SFML/include/SFML/Network/SocketSelector.hpp new file mode 100644 index 0000000000..668b59fb79 --- /dev/null +++ b/Externals/SFML/include/SFML/Network/SocketSelector.hpp @@ -0,0 +1,263 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_SOCKETSELECTOR_HPP +#define SFML_SOCKETSELECTOR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +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 oustide 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 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::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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/SocketTCP.hpp b/Externals/SFML/include/SFML/Network/SocketTCP.hpp deleted file mode 100644 index 810a36b346..0000000000 --- a/Externals/SFML/include/SFML/Network/SocketTCP.hpp +++ /dev/null @@ -1,227 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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_SOCKETTCP_HPP -#define SFML_SOCKETTCP_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class Packet; -class IPAddress; -template class Selector; - -//////////////////////////////////////////////////////////// -/// SocketTCP wraps a socket using TCP protocol to -/// send data safely (but a bit slower) -//////////////////////////////////////////////////////////// -class SFML_API SocketTCP -{ -public : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - SocketTCP(); - - //////////////////////////////////////////////////////////// - /// Change the blocking state of the socket. - /// The default behaviour of a socket is blocking - /// - /// \param Blocking : Pass true to set the socket as blocking, or false for non-blocking - /// - //////////////////////////////////////////////////////////// - void SetBlocking(bool Blocking); - - //////////////////////////////////////////////////////////// - /// Connect to another computer on a specified port - /// - /// \param Port : Port to use for transfers (warning : ports < 1024 are reserved) - /// \param HostAddress : IP Address of the host to connect to - /// \param Timeout : Maximum time to wait, in seconds (0 by default : no timeout) (this parameter is ignored for non-blocking sockets) - /// - /// \return True if operation has been successful - /// - //////////////////////////////////////////////////////////// - Socket::Status Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout = 0.f); - - //////////////////////////////////////////////////////////// - /// Listen to a specified port for incoming data or connections - /// - /// \param Port : Port to listen to - /// - /// \return True if operation has been successful - /// - //////////////////////////////////////////////////////////// - bool Listen(unsigned short Port); - - //////////////////////////////////////////////////////////// - /// Wait for a connection (must be listening to a port). - /// This function will block if the socket is blocking - /// - /// \param Connected : Socket containing the connection with the connected client - /// \param Address : Pointer to an address to fill with client infos (NULL by default) - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Accept(SocketTCP& Connected, IPAddress* Address = NULL); - - //////////////////////////////////////////////////////////// - /// Send an array of bytes to the host (must be connected first) - /// - /// \param Data : Pointer to the bytes to send - /// \param Size : Number of bytes to send - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Send(const char* Data, std::size_t Size); - - //////////////////////////////////////////////////////////// - /// Receive an array of bytes from the host (must be connected first). - /// This function will block if the socket is blocking - /// - /// \param Data : Pointer to a byte array to fill (make sure it is big enough) - /// \param MaxSize : Maximum number of bytes to read - /// \param SizeReceived : Number of bytes received - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived); - - //////////////////////////////////////////////////////////// - /// Send a packet of data to the host (must be connected first) - /// - /// \param PacketToSend : Packet to send - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Send(Packet& PacketToSend); - - //////////////////////////////////////////////////////////// - /// Receive a packet from the host (must be connected first). - /// This function will block if the socket is blocking - /// - /// \param PacketToReceive : Packet to fill with received data - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Receive(Packet& PacketToReceive); - - //////////////////////////////////////////////////////////// - /// Close the socket - /// - /// \return True if operation has been successful - /// - //////////////////////////////////////////////////////////// - bool Close(); - - //////////////////////////////////////////////////////////// - /// Check if the socket is in a valid state ; this function - /// can be called any time to check if the socket is OK - /// - /// \return True if the socket is valid - /// - //////////////////////////////////////////////////////////// - bool IsValid() const; - - //////////////////////////////////////////////////////////// - /// Comparison operator == - /// - /// \param Other : Socket to compare - /// - /// \return True if *this == Other - /// - //////////////////////////////////////////////////////////// - bool operator ==(const SocketTCP& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator != - /// - /// \param Other : Socket to compare - /// - /// \return True if *this != Other - /// - //////////////////////////////////////////////////////////// - bool operator !=(const SocketTCP& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator <. - /// Provided for compatibility with standard containers, as - /// comparing two sockets doesn't make much sense... - /// - /// \param Other : Socket to compare - /// - /// \return True if *this < Other - /// - //////////////////////////////////////////////////////////// - bool operator <(const SocketTCP& Other) const; - -private : - - friend class Selector; - - //////////////////////////////////////////////////////////// - /// Construct the socket from a socket descriptor - /// (for internal use only) - /// - /// \param Descriptor : Socket descriptor - /// - //////////////////////////////////////////////////////////// - SocketTCP(SocketHelper::SocketType Descriptor); - - //////////////////////////////////////////////////////////// - /// Create the socket - /// - /// \param Descriptor : System socket descriptor to use (0 by default -- create a new socket) - /// - //////////////////////////////////////////////////////////// - void Create(SocketHelper::SocketType Descriptor = 0); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - SocketHelper::SocketType mySocket; ///< Socket descriptor - Uint32 myPendingHeader; ///< Data of the current pending packet header, if any - Uint32 myPendingHeaderSize; ///< Size of the current pending packet header, if any - std::vector myPendingPacket; ///< Data of the current pending packet, if any - Int32 myPendingPacketSize; ///< Size of the current pending packet, if any - bool myIsBlocking; ///< Is the socket blocking or non-blocking ? -}; - -} // namespace sf - - -#endif // SFML_SOCKETTCP_HPP diff --git a/Externals/SFML/include/SFML/Network/SocketUDP.hpp b/Externals/SFML/include/SFML/Network/SocketUDP.hpp deleted file mode 100644 index 4653f56b91..0000000000 --- a/Externals/SFML/include/SFML/Network/SocketUDP.hpp +++ /dev/null @@ -1,228 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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_SOCKETUDP_HPP -#define SFML_SOCKETUDP_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class Packet; -class IPAddress; -template class Selector; - -//////////////////////////////////////////////////////////// -/// SocketUDP wraps a socket using UDP protocol to -/// send data fastly (but with less safety) -//////////////////////////////////////////////////////////// -class SFML_API SocketUDP -{ -public : - - //////////////////////////////////////////////////////////// - /// Default constructor - /// - //////////////////////////////////////////////////////////// - SocketUDP(); - - //////////////////////////////////////////////////////////// - /// Change the blocking state of the socket. - /// The default behaviour of a socket is blocking - /// - /// \param Blocking : Pass true to set the socket as blocking, or false for non-blocking - /// - //////////////////////////////////////////////////////////// - void SetBlocking(bool Blocking); - - //////////////////////////////////////////////////////////// - /// Bind the socket to a specific port - /// - /// \param Port : Port to bind the socket to - /// - /// \return True if operation has been successful - /// - //////////////////////////////////////////////////////////// - bool Bind(unsigned short Port); - - //////////////////////////////////////////////////////////// - /// Unbind the socket from its previous port, if any - /// - /// \return True if operation has been successful - /// - //////////////////////////////////////////////////////////// - bool Unbind(); - - //////////////////////////////////////////////////////////// - /// Send an array of bytes - /// - /// \param Data : Pointer to the bytes to send - /// \param Size : Number of bytes to send - /// \param Address : Address of the computer to send the packet to - /// \param Port : Port to send the data to - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Send(const char* Data, std::size_t Size, const IPAddress& Address, unsigned short Port); - - //////////////////////////////////////////////////////////// - /// Receive an array of bytes. - /// This function will block if the socket is blocking - /// - /// \param Data : Pointer to a byte array to fill (make sure it is big enough) - /// \param MaxSize : Maximum number of bytes to read - /// \param SizeReceived : Number of bytes received - /// \param Address : Address of the computer which sent the data - /// \param Port : Port on which the remote computer sent the data - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived, IPAddress& Address, unsigned short& Port); - - //////////////////////////////////////////////////////////// - /// Send a packet of data - /// - /// \param PacketToSend : Packet to send - /// \param Address : Address of the computer to send the packet to - /// \param Port : Port to send the data to - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Send(Packet& PacketToSend, const IPAddress& Address, unsigned short Port); - - //////////////////////////////////////////////////////////// - /// Receive a packet. - /// This function will block if the socket is blocking - /// - /// \param PacketToReceive : Packet to fill with received data - /// \param Address : Address of the computer which sent the packet - /// \param Port : Port on which the remote computer sent the data - /// - /// \return Status code - /// - //////////////////////////////////////////////////////////// - Socket::Status Receive(Packet& PacketToReceive, IPAddress& Address, unsigned short& Port); - - //////////////////////////////////////////////////////////// - /// Close the socket - /// - /// \return True if operation has been successful - /// - //////////////////////////////////////////////////////////// - bool Close(); - - //////////////////////////////////////////////////////////// - /// Check if the socket is in a valid state ; this function - /// can be called any time to check if the socket is OK - /// - /// \return True if the socket is valid - /// - //////////////////////////////////////////////////////////// - bool IsValid() const; - - //////////////////////////////////////////////////////////// - /// Get the port the socket is currently bound to - /// - /// \return Current port (0 means the socket is not bound) - /// - //////////////////////////////////////////////////////////// - unsigned short GetPort() const; - - //////////////////////////////////////////////////////////// - /// Comparison operator == - /// - /// \param Other : Socket to compare - /// - /// \return True if *this == Other - /// - //////////////////////////////////////////////////////////// - bool operator ==(const SocketUDP& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator != - /// - /// \param Other : Socket to compare - /// - /// \return True if *this != Other - /// - //////////////////////////////////////////////////////////// - bool operator !=(const SocketUDP& Other) const; - - //////////////////////////////////////////////////////////// - /// Comparison operator <. - /// Provided for compatibility with standard containers, as - /// comparing two sockets doesn't make much sense... - /// - /// \param Other : Socket to compare - /// - /// \return True if *this < Other - /// - //////////////////////////////////////////////////////////// - bool operator <(const SocketUDP& Other) const; - -private : - - friend class Selector; - - //////////////////////////////////////////////////////////// - /// Construct the socket from a socket descriptor - /// (for internal use only) - /// - /// \param Descriptor : Socket descriptor - /// - //////////////////////////////////////////////////////////// - SocketUDP(SocketHelper::SocketType Descriptor); - - //////////////////////////////////////////////////////////// - /// Create the socket - /// - /// \param Descriptor : System socket descriptor to use (0 by default -- create a new socket) - /// - //////////////////////////////////////////////////////////// - void Create(SocketHelper::SocketType Descriptor = 0); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - SocketHelper::SocketType mySocket; ///< Socket identifier - unsigned short myPort; ///< Port to which the socket is bound - Uint32 myPendingHeader; ///< Data of the current pending packet header, if any - Uint32 myPendingHeaderSize; ///< Size of the current pending packet header, if any - std::vector myPendingPacket; ///< Data of the current pending packet, if any - Int32 myPendingPacketSize; ///< Size of the current pending packet, if any - bool myIsBlocking; ///< Is the socket blocking or non-blocking ? -}; - -} // namespace sf - - -#endif // SFML_SOCKETUDP_HPP diff --git a/Externals/SFML/include/SFML/Network/TcpListener.hpp b/Externals/SFML/include/SFML/Network/TcpListener.hpp new file mode 100644 index 0000000000..c72facddaf --- /dev/null +++ b/Externals/SFML/include/SFML/Network/TcpListener.hpp @@ -0,0 +1,162 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_TCPLISTENER_HPP +#define SFML_TCPLISTENER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +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 connections + /// + /// This functions makes the socket listen to the specified + /// port, waiting for new connections. + /// If the socket was previously listening to another port, + /// it will be stopped first and bound to the new port. + /// + /// \param port Port to listen for new connections + /// + /// \return Status code + /// + /// \see accept, close + /// + //////////////////////////////////////////////////////////// + Status listen(unsigned short port); + + //////////////////////////////////////////////////////////// + /// \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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/TcpSocket.hpp b/Externals/SFML/include/SFML/Network/TcpSocket.hpp new file mode 100644 index 0000000000..ff4ee95f25 --- /dev/null +++ b/Externals/SFML/include/SFML/Network/TcpSocket.hpp @@ -0,0 +1,292 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_TCPSOCKET_HPP +#define SFML_TCPSOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class TcpListener; +class IpAddress; +class Packet; + +//////////////////////////////////////////////////////////// +/// \brief Specialized socket using the TCP protocol +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API TcpSocket : public Socket +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + TcpSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not connected, this function returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see connect, getRemotePort + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the address of the connected peer + /// + /// It the socket is not connected, this function returns + /// sf::IpAddress::None. + /// + /// \return Address of the remote peer + /// + /// \see getRemotePort + /// + //////////////////////////////////////////////////////////// + IpAddress getRemoteAddress() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the port of the connected peer to which + /// the socket is connected + /// + /// If the socket is not connected, this function returns 0. + /// + /// \return Remote port to which the socket is connected + /// + /// \see getRemoteAddress + /// + //////////////////////////////////////////////////////////// + unsigned short getRemotePort() const; + + //////////////////////////////////////////////////////////// + /// \brief Connect the socket to a remote peer + /// + /// In blocking mode, this function may take a while, especially + /// if the remote peer is not reachable. The last parameter allows + /// you to stop trying to connect after a given timeout. + /// If the socket was previously connected, it is first disconnected. + /// + /// \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 + /// + /// 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 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 + /// + /// 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 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 explicitely 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/Network/UdpSocket.hpp b/Externals/SFML/include/SFML/Network/UdpSocket.hpp new file mode 100644 index 0000000000..eab815123f --- /dev/null +++ b/Externals/SFML/include/SFML/Network/UdpSocket.hpp @@ -0,0 +1,283 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_UDPSOCKET_HPP +#define SFML_UDPSOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class IpAddress; +class Packet; + +//////////////////////////////////////////////////////////// +/// \brief Specialized socket using the UDP protocol +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API UdpSocket : public Socket +{ +public : + + //////////////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////////////// + enum + { + MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + UdpSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not bound to a port, this function + /// returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see bind + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Bind the socket to a specific port + /// + /// Binding the socket to a port is necessary for being + /// able to receive data on that port. + /// You can use the special value Socket::AnyPort to tell the + /// system to automatically pick an available port, and then + /// call getLocalPort to retrieve the chosen port. + /// + /// \param port Port to bind the socket to + /// + /// \return Status code + /// + /// \see unbind, getLocalPort + /// + //////////////////////////////////////////////////////////// + Status bind(unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Unbind the socket from the local port to which it is bound + /// + /// The port that the socket was previously using is immediately + /// available after this function is called. 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 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 explicitely 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System.hpp b/Externals/SFML/include/SFML/System.hpp index 4b2b938eec..6c2ee2eaa3 100644 --- a/Externals/SFML/include/SFML/System.hpp +++ b/Externals/SFML/include/SFML/System.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -30,14 +30,27 @@ //////////////////////////////////////////////////////////// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include +//#include +#include +//#include +//#include +//#include +//#include +#include +//#include +//#include +//#include +#include +//#include +//#include #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. +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System/Err.hpp b/Externals/SFML/include/SFML/System/Err.hpp new file mode 100644 index 0000000000..590c635f4a --- /dev/null +++ b/Externals/SFML/include/SFML/System/Err.hpp @@ -0,0 +1,78 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_ERR_HPP +#define SFML_ERR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +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, independantly +/// 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System/Export.hpp b/Externals/SFML/include/SFML/System/Export.hpp new file mode 100644 index 0000000000..ec08fbe297 --- /dev/null +++ b/Externals/SFML/include/SFML/System/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_SYSTEM_EXPORT_HPP +#define SFML_SYSTEM_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// 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 diff --git a/Externals/SFML/include/SFML/System/NonCopyable.hpp b/Externals/SFML/include/SFML/System/NonCopyable.hpp index b61e989cca..b856ae952a 100644 --- a/Externals/SFML/include/SFML/System/NonCopyable.hpp +++ b/Externals/SFML/include/SFML/System/NonCopyable.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -28,21 +28,26 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include namespace sf { //////////////////////////////////////////////////////////// -/// Utility base class to easily declare non-copyable classes. -/// Just inherit from NonCopyable to get a non-copyable class +/// \brief Utility class that makes any derived +/// class non-copyable +/// //////////////////////////////////////////////////////////// -struct SFML_API NonCopyable +class SFML_SYSTEM_API NonCopyable { protected : //////////////////////////////////////////////////////////// - /// The default constructor won't be generated, so provide it + /// \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 explicitely. /// //////////////////////////////////////////////////////////// NonCopyable() {} @@ -50,15 +55,25 @@ protected : private : //////////////////////////////////////////////////////////// - /// Copy constructor : declare it private and don't implement - /// it to prevent from calling it + /// \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&); //////////////////////////////////////////////////////////// - /// Assignment operator : declare it private and don't implement - /// it to prevent from calling it + /// \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&); @@ -68,3 +83,37 @@ private : #endif // SFML_NONCOPYABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::NonCopyable +/// \ingroup system +/// +/// This class makes its instances non-copyable, by explicitely +/// 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. +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System/String.hpp b/Externals/SFML/include/SFML/System/String.hpp new file mode 100644 index 0000000000..5eb52a0f9f --- /dev/null +++ b/Externals/SFML/include/SFML/System/String.hpp @@ -0,0 +1,543 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_STRING_HPP +#define SFML_STRING_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +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::iterator Iterator; ///< Iterator type + typedef std::basic_string::const_iterator ConstIterator; ///< Constant 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& utf32String); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + String(const String& copy); + + //////////////////////////////////////////////////////////// + /// \brief Implicit cast operator to std::string (ANSI string) + /// + /// The current global locale is used for conversion. If you + /// want to explicitely 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 cast 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 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: this function doesn't throw 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: this function doesn't throw 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 + /// into 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 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 beginning 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 beginning 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 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 alphabetically lesser than \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 alphabetically greater than \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 alphabetically lesser or equal than \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 alphabetically greater or equal than \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); + +} // 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. +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System/Time.hpp b/Externals/SFML/include/SFML/System/Time.hpp new file mode 100644 index 0000000000..5043ae6c02 --- /dev/null +++ b/Externals/SFML/include/SFML/System/Time.hpp @@ -0,0 +1,452 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_TIME_HPP +#define SFML_TIME_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +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); + +} // 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 +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System/Utf.hpp b/Externals/SFML/include/SFML/System/Utf.hpp new file mode 100644 index 0000000000..0b965dc91f --- /dev/null +++ b/Externals/SFML/include/SFML/System/Utf.hpp @@ -0,0 +1,763 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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_UTF_HPP +#define SFML_UTF_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +template +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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + static Out encodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0); +}; + +#include + +// 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 functions are all static, these classes are not meant to +/// be instanciated. 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) +/// +//////////////////////////////////////////////////////////// diff --git a/Externals/SFML/include/SFML/System/Utf.inl b/Externals/SFML/include/SFML/System/Utf.inl new file mode 100644 index 0000000000..bf897dfee4 --- /dev/null +++ b/Externals/SFML/include/SFML/System/Utf.inl @@ -0,0 +1,752 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@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. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// References : +// +// http://www.unicode.org/ +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h +// http://people.w3.org/rishida/scripts/uniview/conversion +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +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(*begin)]; + if (begin + trailingBytes < end) + { + output = 0; + switch (trailingBytes) + { + case 5 : output += static_cast(*begin++); output <<= 6; + case 4 : output += static_cast(*begin++); output <<= 6; + case 3 : output += static_cast(*begin++); output <<= 6; + case 2 : output += static_cast(*begin++); output <<= 6; + case 1 : output += static_cast(*begin++); output <<= 6; + case 0 : output += static_cast(*begin++); + } + output -= offsets[trailingBytes]; + } + else + { + // Incomplete character + begin = end; + output = replacement; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::encode(Uint32 input, Out output, Uint8 replacement) +{ + // Some useful precomputed data + static const Uint8 firstBytes[7] = + { + 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC + }; + + // encode the character + if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF))) + { + // Invalid character + if (replacement) + *output++ = replacement; + } + else + { + // Valid character + + // Get the number of bytes to write + std::size_t bytestoWrite = 1; + if (input < 0x80) bytestoWrite = 1; + else if (input < 0x800) bytestoWrite = 2; + else if (input < 0x10000) bytestoWrite = 3; + else if (input <= 0x0010FFFF) bytestoWrite = 4; + + // Extract the bytes to write + Uint8 bytes[4]; + switch (bytestoWrite) + { + case 4 : bytes[3] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 3 : bytes[2] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 2 : bytes[1] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 1 : bytes[0] = static_cast (input | firstBytes[bytestoWrite]); + } + + // Add them to the output + output = std::copy(bytes, bytes + bytestoWrite, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<8>::next(In begin, In end) +{ + Uint32 codepoint; + return decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +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 +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 +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 +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 +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(codepoint) : replacement; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf8(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +In Utf<16>::decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + Uint16 first = *begin++; + + // If it's a surrogate pair, first convert to a single UTF-32 character + if ((first >= 0xD800) && (first <= 0xDBFF)) + { + if (begin < end) + { + Uint32 second = *begin++; + if ((second >= 0xDC00) && (second <= 0xDFFF)) + { + // The second element is valid: convert the two elements to a UTF-32 character + output = static_cast(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000); + } + else + { + // Invalid character + output = replacement; + } + } + else + { + // Invalid character + begin = end; + output = replacement; + } + } + else + { + // We can make a direct copy + output = first; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +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(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((input >> 10) + 0xD800); + *output++ = static_cast((input & 0x3FFUL) + 0xDC00); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<16>::next(In begin, In end) +{ + Uint32 codepoint; + return decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +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 +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 +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 +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 +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(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +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 +Out Utf<16>::toUtf16(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +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 +In Utf<32>::decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/) +{ + output = *begin++; + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encode(Uint32 input, Out output, Uint32 /*replacement*/) +{ + *output++ = input; + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<32>::next(In begin, In /*end*/) +{ + return ++begin; +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<32>::count(In begin, In end) +{ + return begin - end; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + *output++ = decodeAnsi(*begin++, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + *output++ = decodeWide(*begin++); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +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 +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 +Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + output = encodeWide(*begin++, output, replacement); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +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(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<8>::encode(*begin++, output); + + return output; +} + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf16(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<16>::encode(*begin++, output); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf32(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +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(character); + + #else + + // Get the facet of the locale which deals with character conversion + const std::ctype& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + return static_cast(facet.widen(input)); + + #endif +} + + +//////////////////////////////////////////////////////////// +template +Uint32 Utf<32>::decodeWide(In input) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, + // and UCS-4 *is* UTF-32). + + return input; +} + + +//////////////////////////////////////////////////////////// +template +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(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& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + *output++ = facet.narrow(static_cast(codepoint), replacement); + + return output; + + #endif +} + + +//////////////////////////////////////////////////////////// +template +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(codepoint); + break; + } + + default: + { + if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) + { + *output++ = static_cast(codepoint); + } + else if (replacement) + { + *output++ = replacement; + } + break; + } + } + + return output; +} diff --git a/Externals/SFML/license.txt b/Externals/SFML/license.txt new file mode 100644 index 0000000000..1d0ae1a38b --- /dev/null +++ b/Externals/SFML/license.txt @@ -0,0 +1,24 @@ +SFML +---- + +SFML - Copyright (C) 2007-2013 Laurent Gomila - laurent.gom@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. diff --git a/Externals/SFML/src/SFML/Network/Ftp.cpp b/Externals/SFML/src/SFML/Network/Ftp.cpp deleted file mode 100644 index 4cf93d5fb7..0000000000 --- a/Externals/SFML/src/SFML/Network/Ftp.cpp +++ /dev/null @@ -1,712 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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 -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -// Utility class for exchanging stuff with the server -// on the data channel -//////////////////////////////////////////////////////////// -class Ftp::DataChannel : NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////////////////// - DataChannel(Ftp& Owner); - - //////////////////////////////////////////////////////////// - // Destructor - //////////////////////////////////////////////////////////// - ~DataChannel(); - - //////////////////////////////////////////////////////////// - // Open the data channel using the specified mode and port - //////////////////////////////////////////////////////////// - Ftp::Response Open(Ftp::TransferMode Mode); - - //////////////////////////////////////////////////////////// - // Send data on the data channel - //////////////////////////////////////////////////////////// - void Send(const std::vector& Data); - - //////////////////////////////////////////////////////////// - // Receive data on the data channel until it is closed - //////////////////////////////////////////////////////////// - void Receive(std::vector& Data); - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Ftp& myFtp; ///< Reference to the owner Ftp instance - SocketTCP myDataSocket; ///< Socket used for data transfers -}; - - -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -Ftp::Response::Response(Status Code, const std::string& Message) : -myStatus (Code), -myMessage(Message) -{ - -} - - -//////////////////////////////////////////////////////////// -/// Convenience function to check if the response status code -/// means a success -//////////////////////////////////////////////////////////// -bool Ftp::Response::IsOk() const -{ - return myStatus < 400; -} - - -//////////////////////////////////////////////////////////// -/// Get the response status code -//////////////////////////////////////////////////////////// -Ftp::Response::Status Ftp::Response::GetStatus() const -{ - return myStatus; -} - - -//////////////////////////////////////////////////////////// -/// Get the full message contained in the response -//////////////////////////////////////////////////////////// -const std::string& Ftp::Response::GetMessage() const -{ - return myMessage; -} - - -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -Ftp::DirectoryResponse::DirectoryResponse(Ftp::Response Resp) : -Ftp::Response(Resp) -{ - if (IsOk()) - { - // Extract the directory from the server response - std::string::size_type Begin = Resp.GetMessage().find('"', 0); - std::string::size_type End = Resp.GetMessage().find('"', Begin + 1); - myDirectory = Resp.GetMessage().substr(Begin + 1, End - Begin - 1); - } -} - - -//////////////////////////////////////////////////////////// -/// Get the directory returned in the response -//////////////////////////////////////////////////////////// -const std::string& Ftp::DirectoryResponse::GetDirectory() const -{ - return myDirectory; -} - - -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -Ftp::ListingResponse::ListingResponse(Ftp::Response Resp, const std::vector& Data) : -Ftp::Response(Resp) -{ - if (IsOk()) - { - // Fill the array of strings - std::string Paths(Data.begin(), Data.end()); - std::string::size_type LastPos = 0; - for (std::string::size_type Pos = Paths.find("\r\n"); Pos != std::string::npos; Pos = Paths.find("\r\n", LastPos)) - { - myFilenames.push_back(Paths.substr(LastPos, Pos - LastPos)); - LastPos = Pos + 2; - } - } -} - - -//////////////////////////////////////////////////////////// -/// Get the number of filenames in the listing -//////////////////////////////////////////////////////////// -std::size_t Ftp::ListingResponse::GetCount() const -{ - return myFilenames.size(); -} - - -//////////////////////////////////////////////////////////// -/// Get the Index-th filename in the directory -//////////////////////////////////////////////////////////// -const std::string& Ftp::ListingResponse::GetFilename(std::size_t Index) const -{ - return myFilenames[Index]; -} - - -//////////////////////////////////////////////////////////// -/// Destructor -- close the connection with the server -//////////////////////////////////////////////////////////// -Ftp::~Ftp() -{ - Disconnect(); -} - - -//////////////////////////////////////////////////////////// -/// Connect to the specified FTP server -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::Connect(const IPAddress& Server, unsigned short Port, float Timeout) -{ - // Connect to the server - if (myCommandSocket.Connect(Port, Server, Timeout) != Socket::Done) - return Response(Response::ConnectionFailed); - - // Get the response to the connection - return GetResponse(); -} - - -//////////////////////////////////////////////////////////// -/// Log in using anonymous account -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::Login() -{ - return Login("anonymous", "user@sfml-dev.org"); -} - - -//////////////////////////////////////////////////////////// -/// Log in using a username and a password -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::Login(const std::string& UserName, const std::string& Password) -{ - Response Resp = SendCommand("USER", UserName); - if (Resp.IsOk()) - Resp = SendCommand("PASS", Password); - - return Resp; -} - - -//////////////////////////////////////////////////////////// -/// Close the connection with FTP server -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::Disconnect() -{ - // Send the exit command - Response Resp = SendCommand("QUIT"); - if (Resp.IsOk()) - myCommandSocket.Close(); - - return Resp; -} - - -//////////////////////////////////////////////////////////// -/// Send a null command just to prevent from being disconnected -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::KeepAlive() -{ - return SendCommand("NOOP"); -} - - -//////////////////////////////////////////////////////////// -/// Get the current working directory -//////////////////////////////////////////////////////////// -Ftp::DirectoryResponse Ftp::GetWorkingDirectory() -{ - return DirectoryResponse(SendCommand("PWD")); -} - - -//////////////////////////////////////////////////////////// -/// Get the contents of the given directory -/// (subdirectories and files) -//////////////////////////////////////////////////////////// -Ftp::ListingResponse Ftp::GetDirectoryListing(const std::string& Directory) -{ - // Open a data channel on default port (20) using ASCII transfer mode - std::vector DirData; - DataChannel Data(*this); - Response Resp = Data.Open(Ascii); - if (Resp.IsOk()) - { - // Tell the server to send us the listing - Resp = SendCommand("NLST", Directory); - if (Resp.IsOk()) - { - // Receive the listing - Data.Receive(DirData); - - // Get the response from the server - Resp = GetResponse(); - } - } - - return ListingResponse(Resp, DirData); -} - - -//////////////////////////////////////////////////////////// -/// Change the current working directory -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::ChangeDirectory(const std::string& Directory) -{ - return SendCommand("CWD", Directory); -} - - -//////////////////////////////////////////////////////////// -/// Go to the parent directory of the current one -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::ParentDirectory() -{ - return SendCommand("CDUP"); -} - - -//////////////////////////////////////////////////////////// -/// Create a new directory -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::MakeDirectory(const std::string& Name) -{ - return SendCommand("MKD", Name); -} - - -//////////////////////////////////////////////////////////// -/// Remove an existing directory -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::DeleteDirectory(const std::string& Name) -{ - return SendCommand("RMD", Name); -} - - -//////////////////////////////////////////////////////////// -/// Rename a file -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::RenameFile(const std::string& File, const std::string& NewName) -{ - Response Resp = SendCommand("RNFR", File); - if (Resp.IsOk()) - Resp = SendCommand("RNTO", NewName); - - return Resp; -} - - -//////////////////////////////////////////////////////////// -/// Remove an existing file -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::DeleteFile(const std::string& Name) -{ - return SendCommand("DELE", Name); -} - - -//////////////////////////////////////////////////////////// -/// Download a file from the server -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::Download(const std::string& DistantFile, const std::string& DestPath, TransferMode Mode) -{ - // Open a data channel using the given transfer mode - DataChannel Data(*this); - Response Resp = Data.Open(Mode); - if (Resp.IsOk()) - { - // Tell the server to start the transfer - Resp = SendCommand("RETR", DistantFile); - if (Resp.IsOk()) - { - // Receive the file data - std::vector FileData; - Data.Receive(FileData); - - // Get the response from the server - Resp = GetResponse(); - if (Resp.IsOk()) - { - // Extract the filename from the file path - std::string Filename = DistantFile; - 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 = DestPath; - if (!Path.empty() && (Path[Path.size() - 1] != '\\') && (Path[Path.size() - 1] != '/')) - Path += "/"; - - // Create the file and copy the received data into it - std::ofstream File((Path + Filename).c_str(), std::ios_base::binary); - if (!File) - return Response(Response::InvalidFile); - if (!FileData.empty()) - File.write(&FileData[0], static_cast(FileData.size())); - } - } - } - - return Resp; -} - - -//////////////////////////////////////////////////////////// -/// Upload a file to the server -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::Upload(const std::string& LocalFile, const std::string& DestPath, TransferMode Mode) -{ - // Get the contents of the file to send - std::ifstream File(LocalFile.c_str(), std::ios_base::binary); - if (!File) - return Response(Response::InvalidFile); - File.seekg(0, std::ios::end); - std::size_t Length = File.tellg(); - File.seekg(0, std::ios::beg); - std::vector FileData(Length); - if (Length > 0) - File.read(&FileData[0], static_cast(Length)); - - // 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 = DestPath; - 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 Resp = Data.Open(Mode); - if (Resp.IsOk()) - { - // Tell the server to start the transfer - Resp = SendCommand("STOR", Path + Filename); - if (Resp.IsOk()) - { - // Send the file data - Data.Send(FileData); - - // Get the response from the server - Resp = GetResponse(); - } - } - - return Resp; -} - - -//////////////////////////////////////////////////////////// -/// Send a command to the FTP server -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::SendCommand(const std::string& Command, const std::string& Parameter) -{ - // Build the command string - std::string CommandStr; - if (Parameter != "") - CommandStr = Command + " " + Parameter + "\r\n"; - else - CommandStr = Command + "\r\n"; - - // Send it to the server - if (myCommandSocket.Send(CommandStr.c_str(), CommandStr.length()) != sf::Socket::Done) - return Response(Response::ConnectionClosed); - - // Get the response - return GetResponse(); -} - - -//////////////////////////////////////////////////////////// -/// Receive a response from the server -/// (usually after a command has been sent) -//////////////////////////////////////////////////////////// -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 (myCommandSocket.Receive(Buffer, sizeof(Buffer), Length) != sf::Socket::Done) - return Response(Response::ConnectionClosed); - - // 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 Sep = 0; - In.get(Sep); - - // The '-' character means a multiline response - if ((Sep == '-') && !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 = Sep + 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 ((Sep != '-') && ((Code == LastCode) || (LastCode == 0))) - { - // Clear the multiline flag - IsInsideMultiline = false; - - // 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 << Sep << Line; - Message += Out.str(); - } - else - { - Message = Sep + Line; - } - - // Return the response code and message - return Response(static_cast(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 << Sep << 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 -} - - -//////////////////////////////////////////////////////////// -/// Constructor -//////////////////////////////////////////////////////////// -Ftp::DataChannel::DataChannel(Ftp& Owner) : -myFtp(Owner) -{ - -} - - -//////////////////////////////////////////////////////////// -/// Destructor -//////////////////////////////////////////////////////////// -Ftp::DataChannel::~DataChannel() -{ - // Close the data socket - myDataSocket.Close(); -} - - -//////////////////////////////////////////////////////////// -/// Open the data channel using the specified mode and port -//////////////////////////////////////////////////////////// -Ftp::Response Ftp::DataChannel::Open(Ftp::TransferMode Mode) -{ - // Open a data connection in active mode (we connect to the server) - Ftp::Response Resp = myFtp.SendCommand("PASV"); - if (Resp.IsOk()) - { - // Extract the connection address and port from the response - std::string::size_type begin = Resp.GetMessage().find_first_of("0123456789"); - if (begin != std::string::npos) - { - sf::Uint8 Data[6] = {0, 0, 0, 0, 0, 0}; - std::string Str = Resp.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] = Data[i] * 10 + (Str[Index] - '0'); - Index++; - } - - // Skip separator - Index++; - } - - // Reconstruct connection port and address - unsigned short Port = Data[4] * 256 + Data[5]; - sf::IPAddress Address(static_cast(Data[0]), - static_cast(Data[1]), - static_cast(Data[2]), - static_cast(Data[3])); - - // Connect the data channel to the server - if (myDataSocket.Connect(Port, Address) == 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 - Resp = myFtp.SendCommand("TYPE", ModeStr); - } - else - { - // Failed to connect to the server - Resp = Ftp::Response(Ftp::Response::ConnectionFailed); - } - } - } - - return Resp; -} - - -//////////////////////////////////////////////////////////// -/// Receive data on the data channel until it is closed -//////////////////////////////////////////////////////////// -void Ftp::DataChannel::Receive(std::vector& Data) -{ - // Receive data - Data.clear(); - char Buffer[1024]; - std::size_t Received; - while (myDataSocket.Receive(Buffer, sizeof(Buffer), Received) == sf::Socket::Done) - { - std::copy(Buffer, Buffer + Received, std::back_inserter(Data)); - } - - // Close the data socket - myDataSocket.Close(); -} - - -//////////////////////////////////////////////////////////// -/// Send data on the data channel -//////////////////////////////////////////////////////////// -void Ftp::DataChannel::Send(const std::vector& Data) -{ - // Send data - if (!Data.empty()) - myDataSocket.Send(&Data[0], Data.size()); - - // Close the data socket - myDataSocket.Close(); -} - -} // namespace sf diff --git a/Externals/SFML/src/SFML/Network/Http.cpp b/Externals/SFML/src/SFML/Network/Http.cpp index e9bc403683..404a1ab259 100644 --- a/Externals/SFML/src/SFML/Network/Http.cpp +++ b/Externals/SFML/src/SFML/Network/Http.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -26,7 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include #include #include @@ -34,16 +34,12 @@ namespace { - //////////////////////////////////////////////////////////// - // Convenience function to convert a string to lower case - //////////////////////////////////////////////////////////// - std::string ToLower(const std::string& Str) + // Convert a string to lower case + std::string toLower(std::string str) { - std::string Ret = Str; - for (std::string::iterator i = Ret.begin(); i != Ret.end(); ++i) - *i = static_cast(tolower(*i)); - - return Ret; + for (std::string::iterator i = str.begin(); i != str.end(); ++i) + *i = static_cast(std::tolower(*i)); + return str; } } @@ -51,382 +47,330 @@ namespace namespace sf { //////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -Http::Request::Request(Method RequestMethod, const std::string& URI, const std::string& Body) +Http::Request::Request(const std::string& uri, Method method, const std::string& body) { - SetMethod(RequestMethod); - SetURI(URI); - SetHttpVersion(1, 0); - SetBody(Body); + setMethod(method); + setUri(uri); + setHttpVersion(1, 0); + setBody(body); } //////////////////////////////////////////////////////////// -/// Set the value of a field; the field is added if it doesn't exist -//////////////////////////////////////////////////////////// -void Http::Request::SetField(const std::string& Field, const std::string& Value) +void Http::Request::setField(const std::string& field, const std::string& value) { - myFields[ToLower(Field)] = Value; + m_fields[toLower(field)] = value; } //////////////////////////////////////////////////////////// -/// Set the request method. -/// This parameter is Get by default -//////////////////////////////////////////////////////////// -void Http::Request::SetMethod(Http::Request::Method RequestMethod) +void Http::Request::setMethod(Http::Request::Method method) { - myMethod = RequestMethod; + m_method = method; } //////////////////////////////////////////////////////////// -/// Set the target URI of the request. -/// This parameter is "/" by default -//////////////////////////////////////////////////////////// -void Http::Request::SetURI(const std::string& URI) +void Http::Request::setUri(const std::string& uri) { - myURI = URI; + m_uri = uri; // Make sure it starts with a '/' - if (myURI.empty() || (myURI[0] != '/')) - myURI.insert(0, "/"); + if (m_uri.empty() || (m_uri[0] != '/')) + m_uri.insert(0, "/"); } //////////////////////////////////////////////////////////// -/// Set the HTTP version of the request. -/// This parameter is 1.0 by default -//////////////////////////////////////////////////////////// -void Http::Request::SetHttpVersion(unsigned int Major, unsigned int Minor) +void Http::Request::setHttpVersion(unsigned int major, unsigned int minor) { - myMajorVersion = Major; - myMinorVersion = Minor; + m_majorVersion = major; + m_minorVersion = minor; } //////////////////////////////////////////////////////////// -/// Set the body of the request. This parameter is optional and -/// makes sense only for POST requests. -/// This parameter is empty by default -//////////////////////////////////////////////////////////// -void Http::Request::SetBody(const std::string& Body) +void Http::Request::setBody(const std::string& body) { - myBody = Body; + m_body = body; } //////////////////////////////////////////////////////////// -/// Get the string representation of a request header -//////////////////////////////////////////////////////////// -std::string Http::Request::ToString() const +std::string Http::Request::prepare() const { - std::ostringstream Out; + std::ostringstream out; // Convert the method to its string representation - std::string RequestMethod; - switch (myMethod) + std::string method; + switch (m_method) { default : - case Get : RequestMethod = "GET"; break; - case Post : RequestMethod = "POST"; break; - case Head : RequestMethod = "HEAD"; break; + case Get : method = "GET"; break; + case Post : method = "POST"; break; + case Head : method = "HEAD"; break; } // Write the first line containing the request type - Out << RequestMethod << " " << myURI << " "; - Out << "HTTP/" << myMajorVersion << "." << myMinorVersion << "\r\n"; + out << method << " " << m_uri << " "; + out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n"; // Write fields - for (FieldTable::const_iterator i = myFields.begin(); i != myFields.end(); ++i) + for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i) { - Out << i->first << ": " << i->second << "\r\n"; + out << i->first << ": " << i->second << "\r\n"; } // Use an extra \r\n to separate the header from the body - Out << "\r\n"; + out << "\r\n"; // Add the body - Out << myBody; + out << m_body; - return Out.str(); + return out.str(); } //////////////////////////////////////////////////////////// -/// Check if the given field has been defined -//////////////////////////////////////////////////////////// -bool Http::Request::HasField(const std::string& Field) const +bool Http::Request::hasField(const std::string& field) const { - return myFields.find(Field) != myFields.end(); + return m_fields.find(toLower(field)) != m_fields.end(); } -//////////////////////////////////////////////////////////// -/// Default constructor //////////////////////////////////////////////////////////// Http::Response::Response() : -myStatus (ConnectionFailed), -myMajorVersion(0), -myMinorVersion(0) +m_status (ConnectionFailed), +m_majorVersion(0), +m_minorVersion(0) { } //////////////////////////////////////////////////////////// -/// Get the value of a field -//////////////////////////////////////////////////////////// -const std::string& Http::Response::GetField(const std::string& Field) const +const std::string& Http::Response::getField(const std::string& field) const { - FieldTable::const_iterator It = myFields.find(ToLower(Field)); - if (It != myFields.end()) + FieldTable::const_iterator it = m_fields.find(toLower(field)); + if (it != m_fields.end()) { - return It->second; + return it->second; } else { - static const std::string Empty = ""; - return Empty; + static const std::string empty = ""; + return empty; } } //////////////////////////////////////////////////////////// -/// Get the header's status code -//////////////////////////////////////////////////////////// -Http::Response::Status Http::Response::GetStatus() const +Http::Response::Status Http::Response::getStatus() const { - return myStatus; + return m_status; } //////////////////////////////////////////////////////////// -/// Get the major HTTP version number of the response -//////////////////////////////////////////////////////////// -unsigned int Http::Response::GetMajorHttpVersion() const +unsigned int Http::Response::getMajorHttpVersion() const { - return myMajorVersion; + return m_majorVersion; } //////////////////////////////////////////////////////////// -/// Get the major HTTP version number of the response -//////////////////////////////////////////////////////////// -unsigned int Http::Response::GetMinorHttpVersion() const +unsigned int Http::Response::getMinorHttpVersion() const { - return myMinorVersion; + return m_minorVersion; } //////////////////////////////////////////////////////////// -/// Get the body of the response. The body can contain : -/// - the requested page (for GET requests) -/// - a response from the server (for POST requests) -/// - nothing (for HEAD requests) -/// - an error message (in case of an error) -//////////////////////////////////////////////////////////// -const std::string& Http::Response::GetBody() const +const std::string& Http::Response::getBody() const { - return myBody; + return m_body; } //////////////////////////////////////////////////////////// -/// Construct the header from a response string -//////////////////////////////////////////////////////////// -void Http::Response::FromString(const std::string& Data) +void Http::Response::parse(const std::string& data) { - std::istringstream In(Data); + std::istringstream in(data); // Extract the HTTP version from the first line - std::string Version; - if (In >> Version) + std::string version; + if (in >> version) { - if ((Version.size() >= 8) && (Version[6] == '.') && - (ToLower(Version.substr(0, 5)) == "http/") && - isdigit(Version[5]) && isdigit(Version[7])) + if ((version.size() >= 8) && (version[6] == '.') && + (toLower(version.substr(0, 5)) == "http/") && + isdigit(version[5]) && isdigit(version[7])) { - myMajorVersion = Version[5] - '0'; - myMinorVersion = Version[7] - '0'; + m_majorVersion = version[5] - '0'; + m_minorVersion = version[7] - '0'; } else { // Invalid HTTP version - myStatus = InvalidResponse; + m_status = InvalidResponse; return; } } // Extract the status code from the first line - int StatusCode = 0; - if (In >> StatusCode) + int status; + if (in >> status) { - myStatus = static_cast(StatusCode); + m_status = static_cast(status); } else { // Invalid status code - myStatus = InvalidResponse; + m_status = InvalidResponse; return; } // Ignore the end of the first line - In.ignore(10000, '\n'); + in.ignore(10000, '\n'); // Parse the other lines, which contain fields, one by one - std::string Line; - while (std::getline(In, Line) && (Line.size() > 2)) + std::string line; + while (std::getline(in, line) && (line.size() > 2)) { - std::string::size_type Pos = Line.find(": "); - if (Pos != std::string::npos) + 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); + 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); + if (!value.empty() && (*value.rbegin() == '\r')) + value.erase(value.size() - 1); // Add the field - myFields[ToLower(Field)] = Value; + m_fields[toLower(field)] = value; } } // Finally extract the body - myBody.clear(); - std::copy(std::istreambuf_iterator(In), std::istreambuf_iterator(), std::back_inserter(myBody)); + m_body.clear(); + std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(m_body)); } -//////////////////////////////////////////////////////////// -/// Default constructor //////////////////////////////////////////////////////////// Http::Http() : -myHost(), -myPort(0) +m_host(), +m_port(0) { } //////////////////////////////////////////////////////////// -/// Construct the Http instance with the target host -//////////////////////////////////////////////////////////// -Http::Http(const std::string& Host, unsigned short Port) +Http::Http(const std::string& host, unsigned short port) { - SetHost(Host, Port); + setHost(host, port); } //////////////////////////////////////////////////////////// -/// Set the target host -//////////////////////////////////////////////////////////// -void Http::SetHost(const std::string& Host, unsigned short Port) +void Http::setHost(const std::string& host, unsigned short port) { // Detect the protocol used - std::string Protocol = ToLower(Host.substr(0, 8)); - if (Protocol.substr(0, 7) == "http://") + std::string protocol = toLower(host.substr(0, 8)); + if (protocol.substr(0, 7) == "http://") { // HTTP protocol - myHostName = Host.substr(7); - myPort = (Port != 0 ? Port : 80); + m_hostName = host.substr(7); + m_port = (port != 0 ? port : 80); } - else if (Protocol == "https://") + else if (protocol == "https://") { // HTTPS protocol - myHostName = Host.substr(8); - myPort = (Port != 0 ? Port : 443); + m_hostName = host.substr(8); + m_port = (port != 0 ? port : 443); } else { // Undefined protocol - use HTTP - myHostName = Host; - myPort = (Port != 0 ? Port : 80); + m_hostName = host; + m_port = (port != 0 ? port : 80); } // Remove any trailing '/' from the host name - if (!myHostName.empty() && (*myHostName.rbegin() == '/')) - myHostName.erase(myHostName.size() - 1); + if (!m_hostName.empty() && (*m_hostName.rbegin() == '/')) + m_hostName.erase(m_hostName.size() - 1); - myHost = sf::IPAddress(myHostName); + m_host = IpAddress(m_hostName); } //////////////////////////////////////////////////////////// -/// Send a HTTP request and return the server's response. -/// You must be connected to a host before sending requests. -/// Any missing mandatory header field 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. -//////////////////////////////////////////////////////////// -Http::Response Http::SendRequest(const Http::Request& Req, float Timeout) +Http::Response Http::sendRequest(const Http::Request& request, Time timeout) { - // First make sure the request is valid -- add missing mandatory fields - Request ToSend(Req); - if (!ToSend.HasField("From")) + // 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"); + toSend.setField("From", "user@sfml-dev.org"); } - if (!ToSend.HasField("User-Agent")) + if (!toSend.hasField("User-Agent")) { - ToSend.SetField("User-Agent", "libsfml-network/1.x"); + toSend.setField("User-Agent", "libsfml-network/2.x"); } - if (!ToSend.HasField("Host")) + if (!toSend.hasField("Host")) { - ToSend.SetField("Host", myHostName); + toSend.setField("Host", m_hostName); } - if (!ToSend.HasField("Content-Length")) + if (!toSend.hasField("Content-Length")) { - std::ostringstream Out; - Out << ToSend.myBody.size(); - ToSend.SetField("Content-Length", Out.str()); + std::ostringstream out; + out << toSend.m_body.size(); + toSend.setField("Content-Length", out.str()); } - if ((ToSend.myMethod == Request::Post) && !ToSend.HasField("Content-Type")) + if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type")) { - ToSend.SetField("Content-Type", "application/x-www-form-urlencoded"); + toSend.setField("Content-Type", "application/x-www-form-urlencoded"); } - if ((ToSend.myMajorVersion * 10 + ToSend.myMinorVersion >= 11) && !ToSend.HasField("Connection")) + if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection")) { - ToSend.SetField("Connection", "close"); + toSend.setField("Connection", "close"); } // Prepare the response - Response Received; + Response received; // Connect the socket to the host - if (myConnection.Connect(myPort, myHost, Timeout) == Socket::Done) + 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.ToString(); + std::string requestStr = toSend.prepare(); - if (!RequestStr.empty()) + if (!requestStr.empty()) { // Send it through the socket - if (myConnection.Send(RequestStr.c_str(), RequestStr.size()) == sf::Socket::Done) + 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 (myConnection.Receive(Buffer, sizeof(Buffer), Size) == sf::Socket::Done) + 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); + receivedStr.append(buffer, buffer + size); } // Build the Response object from the received data - Received.FromString(ReceivedStr); + received.parse(receivedStr); } } // Close the connection - myConnection.Close(); + m_connection.disconnect(); } - return Received; + return received; } } // namespace sf diff --git a/Externals/SFML/src/SFML/Network/IPAddress.cpp b/Externals/SFML/src/SFML/Network/IPAddress.cpp index 18bf3dd967..def36b1933 100644 --- a/Externals/SFML/src/SFML/Network/IPAddress.cpp +++ b/Externals/SFML/src/SFML/Network/IPAddress.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -27,272 +27,229 @@ //////////////////////////////////////////////////////////// #include #include -#include -#include +#include +#include + + +namespace +{ + sf::Uint32 resolve(const std::string& address) + { + if (address == "255.255.255.255") + { + // The broadcast address needs to be handled explicitely, + // because it is also the value returned by inet_addr on error + return INADDR_BROADCAST; + } + else + { + // Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") + sf::Uint32 ip = inet_addr(address.c_str()); + if (ip != INADDR_NONE) + return ip; + + // Not a valid address, try to convert it as a host name + addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + addrinfo* result = NULL; + if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0) + { + if (result) + { + ip = reinterpret_cast(result->ai_addr)->sin_addr.s_addr; + freeaddrinfo(result); + return ip; + } + } + + // Not a valid address nor a host name + return 0; + } + } +} namespace sf { //////////////////////////////////////////////////////////// -/// Static member data -//////////////////////////////////////////////////////////// -const IPAddress IPAddress::LocalHost("127.0.0.1"); +const IpAddress IpAddress::None; +const IpAddress IpAddress::LocalHost(127, 0, 0, 1); +const IpAddress IpAddress::Broadcast(255, 255, 255, 255); //////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -IPAddress::IPAddress() : -myAddress(INADDR_NONE) +IpAddress::IpAddress() : +m_address(0) { - + // We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address, + // because the latter is also the broadcast address (255.255.255.255); it's ok because + // SFML doesn't publicly use INADDR_ANY (it is always used implicitely) } //////////////////////////////////////////////////////////// -/// Construct the address from a string -//////////////////////////////////////////////////////////// -IPAddress::IPAddress(const std::string& Address) +IpAddress::IpAddress(const std::string& address) : +m_address(resolve(address)) { - // First try to convert it as a byte representation ("xxx.xxx.xxx.xxx") - myAddress = inet_addr(Address.c_str()); - - // If not successful, try to convert it as a host name - if (!IsValid()) - { - hostent* Host = gethostbyname(Address.c_str()); - if (Host) - { - // Host found, extract its IP address - myAddress = reinterpret_cast(Host->h_addr)->s_addr; - } - else - { - // Host name not found on the network - myAddress = INADDR_NONE; - } - } } //////////////////////////////////////////////////////////// -/// Construct the address from a C-style string ; -/// Needed for implicit conversions from literal strings to IPAddress to work -//////////////////////////////////////////////////////////// -IPAddress::IPAddress(const char* Address) +IpAddress::IpAddress(const char* address) : +m_address(resolve(address)) { - // First try to convert it as a byte representation ("xxx.xxx.xxx.xxx") - myAddress = inet_addr(Address); - - // If not successful, try to convert it as a host name - if (!IsValid()) - { - hostent* Host = gethostbyname(Address); - if (Host) - { - // Host found, extract its IP address - myAddress = reinterpret_cast(Host->h_addr)->s_addr; - } - else - { - // Host name not found on the network - myAddress = INADDR_NONE; - } - } } //////////////////////////////////////////////////////////// -/// Construct the address from 4 bytes -//////////////////////////////////////////////////////////// -IPAddress::IPAddress(Uint8 Byte0, Uint8 Byte1, Uint8 Byte2, Uint8 Byte3) +IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) : +m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)) { - myAddress = htonl((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3); } //////////////////////////////////////////////////////////// -/// Construct the address from a 32-bits integer -//////////////////////////////////////////////////////////// -IPAddress::IPAddress(Uint32 Address) +IpAddress::IpAddress(Uint32 address) : +m_address(htonl(address)) { - myAddress = htonl(Address); } //////////////////////////////////////////////////////////// -/// Tell if the address is a valid one -//////////////////////////////////////////////////////////// -bool IPAddress::IsValid() const +std::string IpAddress::toString() const { - return myAddress != INADDR_NONE; + in_addr address; + address.s_addr = m_address; + + return inet_ntoa(address); } //////////////////////////////////////////////////////////// -/// Get a string representation of the address -//////////////////////////////////////////////////////////// -std::string IPAddress::ToString() const +Uint32 IpAddress::toInteger() const { - in_addr InAddr; - InAddr.s_addr = myAddress; - - return inet_ntoa(InAddr); + return ntohl(m_address); } //////////////////////////////////////////////////////////// -/// Get an integer representation of the address -//////////////////////////////////////////////////////////// -Uint32 IPAddress::ToInteger() const -{ - return ntohl(myAddress); -} - - -//////////////////////////////////////////////////////////// -/// Get the computer's local IP address (from the LAN point of view) -//////////////////////////////////////////////////////////// -IPAddress IPAddress::GetLocalAddress() +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; + IpAddress localAddress; // Create the socket - SocketHelper::SocketType Socket = socket(PF_INET, SOCK_DGRAM, 0); - if (Socket == SocketHelper::InvalidSocket()) - return LocalAddress; + SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock == priv::SocketImpl::invalidSocket()) + return localAddress; - // Build the host address (use a random port) - sockaddr_in SockAddr; - memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero)); - SockAddr.sin_addr.s_addr = INADDR_LOOPBACK; - SockAddr.sin_family = AF_INET; - SockAddr.sin_port = htons(4567); - - // Connect the socket - if (connect(Socket, reinterpret_cast(&SockAddr), sizeof(SockAddr)) == -1) + // Connect the socket to localhost on any port + sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 0); + if (connect(sock, reinterpret_cast(&address), sizeof(address)) == -1) { - SocketHelper::Close(Socket); - return LocalAddress; + priv::SocketImpl::close(sock); + return localAddress; } - + // Get the local address of the socket connection - SocketHelper::LengthType Size = sizeof(SockAddr); - if (getsockname(Socket, reinterpret_cast(&SockAddr), &Size) == -1) + priv::SocketImpl::AddrLength size = sizeof(address); + if (getsockname(sock, reinterpret_cast(&address), &size) == -1) { - SocketHelper::Close(Socket); - return LocalAddress; + priv::SocketImpl::close(sock); + return localAddress; } // Close the socket - SocketHelper::Close(Socket); + priv::SocketImpl::close(sock); // Finally build the IP address - LocalAddress.myAddress = SockAddr.sin_addr.s_addr; + localAddress = IpAddress(ntohl(address.sin_addr.s_addr)); - return LocalAddress; + return localAddress; } //////////////////////////////////////////////////////////// -/// Get the computer's public IP address (from the web point of view) -//////////////////////////////////////////////////////////// -IPAddress IPAddress::GetPublicAddress(float Timeout) +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). + // (not very hard: the web page contains only our IP address). - Http Server("www.sfml-dev.org"); - Http::Request Request(Http::Request::Get, "/ip-provider.php"); - Http::Response Page = Server.SendRequest(Request, Timeout); - if (Page.GetStatus() == Http::Response::Ok) - return IPAddress(Page.GetBody()); + 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(); + return IpAddress(); } //////////////////////////////////////////////////////////// -/// Comparison operator == -//////////////////////////////////////////////////////////// -bool IPAddress::operator ==(const IPAddress& Other) const +bool operator ==(const IpAddress& left, const IpAddress& right) { - return myAddress == Other.myAddress; + return left.toInteger() == right.toInteger(); } //////////////////////////////////////////////////////////// -/// Comparison operator != -//////////////////////////////////////////////////////////// -bool IPAddress::operator !=(const IPAddress& Other) const +bool operator !=(const IpAddress& left, const IpAddress& right) { - return myAddress != Other.myAddress; + return !(left == right); } //////////////////////////////////////////////////////////// -/// Comparison operator < -//////////////////////////////////////////////////////////// -bool IPAddress::operator <(const IPAddress& Other) const +bool operator <(const IpAddress& left, const IpAddress& right) { - return myAddress < Other.myAddress; + return left.toInteger() < right.toInteger(); } //////////////////////////////////////////////////////////// -/// Comparison operator > -//////////////////////////////////////////////////////////// -bool IPAddress::operator >(const IPAddress& Other) const +bool operator >(const IpAddress& left, const IpAddress& right) { - return myAddress > Other.myAddress; + return right < left; } //////////////////////////////////////////////////////////// -/// Comparison operator <= -//////////////////////////////////////////////////////////// -bool IPAddress::operator <=(const IPAddress& Other) const +bool operator <=(const IpAddress& left, const IpAddress& right) { - return myAddress <= Other.myAddress; + return !(right < left); } //////////////////////////////////////////////////////////// -/// Comparison operator >= -//////////////////////////////////////////////////////////// -bool IPAddress::operator >=(const IPAddress& Other) const +bool operator >=(const IpAddress& left, const IpAddress& right) { - return myAddress >= Other.myAddress; + return !(left < right); } //////////////////////////////////////////////////////////// -/// Operator >> overload to extract an address from an input stream -//////////////////////////////////////////////////////////// -std::istream& operator >>(std::istream& Stream, IPAddress& Address) +std::istream& operator >>(std::istream& stream, IpAddress& address) { - std::string Str; - Stream >> Str; - Address = IPAddress(Str); + std::string str; + stream >> str; + address = IpAddress(str); - return Stream; + return stream; } //////////////////////////////////////////////////////////// -/// Operator << overload to print an address to an output stream -//////////////////////////////////////////////////////////// -std::ostream& operator <<(std::ostream& Stream, const IPAddress& Address) +std::ostream& operator <<(std::ostream& stream, const IpAddress& address) { - return Stream << Address.ToString(); + return stream << address.toString(); } } // namespace sf diff --git a/Externals/SFML/src/SFML/Network/Packet.cpp b/Externals/SFML/src/SFML/Network/Packet.cpp index 61edec100c..b4af9dccc5 100644 --- a/Externals/SFML/src/SFML/Network/Packet.cpp +++ b/Externals/SFML/src/SFML/Network/Packet.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -26,25 +26,23 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include +#include +#include +#include +#include namespace sf { //////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// Packet::Packet() : -myReadPos(0), -myIsValid(true) +m_readPos(0), +m_isValid(true) { } -//////////////////////////////////////////////////////////// -/// Virtual destructor //////////////////////////////////////////////////////////// Packet::~Packet() { @@ -53,230 +51,250 @@ Packet::~Packet() //////////////////////////////////////////////////////////// -/// Append data to the end of the packet -//////////////////////////////////////////////////////////// -void Packet::Append(const void* Data, std::size_t SizeInBytes) +void Packet::append(const void* data, std::size_t sizeInBytes) { - if (Data && (SizeInBytes > 0)) + if (data && (sizeInBytes > 0)) { - std::size_t Start = myData.size(); - myData.resize(Start + SizeInBytes); - memcpy(&myData[Start], Data, SizeInBytes); + std::size_t start = m_data.size(); + m_data.resize(start + sizeInBytes); + std::memcpy(&m_data[start], data, sizeInBytes); } } //////////////////////////////////////////////////////////// -/// Clear the packet data -//////////////////////////////////////////////////////////// -void Packet::Clear() +void Packet::clear() { - myData.clear(); - myReadPos = 0; - myIsValid = true; + m_data.clear(); + m_readPos = 0; + m_isValid = true; } //////////////////////////////////////////////////////////// -/// Get a pointer to the data contained in the packet -/// Warning : the returned pointer may be invalid after you -/// append data to the packet -//////////////////////////////////////////////////////////// -const char* Packet::GetData() const +const void* Packet::getData() const { - return !myData.empty() ? &myData[0] : NULL; + return !m_data.empty() ? &m_data[0] : NULL; } //////////////////////////////////////////////////////////// -/// Get the size of the data contained in the packet -//////////////////////////////////////////////////////////// -std::size_t Packet::GetDataSize() const +std::size_t Packet::getDataSize() const { - return myData.size(); + return m_data.size(); } //////////////////////////////////////////////////////////// -/// Tell if the reading position has reached the end of the packet -//////////////////////////////////////////////////////////// -bool Packet::EndOfPacket() const +bool Packet::endOfPacket() const { - return myReadPos >= myData.size(); + return m_readPos >= m_data.size(); } //////////////////////////////////////////////////////////// -/// Tell if the packet is valid for reading -//////////////////////////////////////////////////////////// -Packet::operator bool() const +Packet::operator BoolType() const { - return myIsValid; + return m_isValid ? &Packet::checkSize : NULL; } //////////////////////////////////////////////////////////// -/// Operator >> overloads to extract data from the packet -//////////////////////////////////////////////////////////// -Packet& Packet::operator >>(bool& Data) +Packet& Packet::operator >>(bool& data) { - Uint8 Value; - if (*this >> Value) - Data = (Value != 0); + Uint8 value; + if (*this >> value) + data = (value != 0); return *this; } -Packet& Packet::operator >>(Int8& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Int8& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = *reinterpret_cast(GetData() + myReadPos); - myReadPos += sizeof(Data); + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(Uint8& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Uint8& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = *reinterpret_cast(GetData() + myReadPos); - myReadPos += sizeof(Data); + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(Int16& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Int16& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = ntohs(*reinterpret_cast(GetData() + myReadPos)); - myReadPos += sizeof(Data); + data = ntohs(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(Uint16& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Uint16& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = ntohs(*reinterpret_cast(GetData() + myReadPos)); - myReadPos += sizeof(Data); + data = ntohs(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(Int32& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Int32& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = ntohl(*reinterpret_cast(GetData() + myReadPos)); - myReadPos += sizeof(Data); + data = ntohl(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(Uint32& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(Uint32& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = ntohl(*reinterpret_cast(GetData() + myReadPos)); - myReadPos += sizeof(Data); + data = ntohl(*reinterpret_cast(&m_data[m_readPos])); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(float& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(float& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = *reinterpret_cast(GetData() + myReadPos); - myReadPos += sizeof(Data); + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(double& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(double& data) { - if (CheckSize(sizeof(Data))) + if (checkSize(sizeof(data))) { - Data = *reinterpret_cast(GetData() + myReadPos); - myReadPos += sizeof(Data); + data = *reinterpret_cast(&m_data[m_readPos]); + m_readPos += sizeof(data); } return *this; } -Packet& Packet::operator >>(char* Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(char* data) { // First extract string length - Uint32 Length = 0; - *this >> Length; + Uint32 length = 0; + *this >> length; - if ((Length > 0) && CheckSize(Length)) + if ((length > 0) && checkSize(length)) { // Then extract characters - memcpy(Data, GetData() + myReadPos, Length); - Data[Length] = '\0'; + std::memcpy(data, &m_data[m_readPos], length); + data[length] = '\0'; // Update reading position - myReadPos += Length; + m_readPos += length; } return *this; } -Packet& Packet::operator >>(std::string& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(std::string& data) { // First extract string length - Uint32 Length = 0; - *this >> Length; + Uint32 length = 0; + *this >> length; - Data.clear(); - if ((Length > 0) && CheckSize(Length)) + data.clear(); + if ((length > 0) && checkSize(length)) { // Then extract characters - Data.assign(GetData() + myReadPos, Length); + data.assign(&m_data[m_readPos], length); // Update reading position - myReadPos += Length; + m_readPos += length; } return *this; } -Packet& Packet::operator >>(wchar_t* Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(wchar_t* data) { // First extract string length - Uint32 Length = 0; - *this >> Length; + Uint32 length = 0; + *this >> length; - if ((Length > 0) && CheckSize(Length * sizeof(Int32))) + if ((length > 0) && checkSize(length * sizeof(Uint32))) { // Then extract characters - for (Uint32 i = 0; i < Length; ++i) + for (Uint32 i = 0; i < length; ++i) { - Uint32 c = 0; - *this >> c; - Data[i] = static_cast(c); + Uint32 character = 0; + *this >> character; + data[i] = static_cast(character); } - Data[Length] = L'\0'; + data[length] = L'\0'; } return *this; } -Packet& Packet::operator >>(std::wstring& Data) + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator >>(std::wstring& data) { // First extract string length - Uint32 Length = 0; - *this >> Length; + Uint32 length = 0; + *this >> length; - Data.clear(); - if ((Length > 0) && CheckSize(Length * sizeof(Int32))) + data.clear(); + if ((length > 0) && checkSize(length * sizeof(Uint32))) { // Then extract characters - for (Uint32 i = 0; i < Length; ++i) + for (Uint32 i = 0; i < length; ++i) { - Uint32 c = 0; - *this >> c; - Data += static_cast(c); + Uint32 character = 0; + *this >> character; + data += static_cast(character); } } @@ -285,109 +303,22 @@ Packet& Packet::operator >>(std::wstring& Data) //////////////////////////////////////////////////////////// -/// Operator << overloads to put data into the packet -//////////////////////////////////////////////////////////// -Packet& Packet::operator <<(bool Data) +Packet& Packet::operator >>(String& data) { - *this << static_cast(Data); - return *this; -} -Packet& Packet::operator <<(Int8 Data) -{ - Append(&Data, sizeof(Data)); - return *this; -} -Packet& Packet::operator <<(Uint8 Data) -{ - Append(&Data, sizeof(Data)); - return *this; -} -Packet& Packet::operator <<(Int16 Data) -{ - Int16 ToWrite = htons(Data); - Append(&ToWrite, sizeof(ToWrite)); - return *this; -} -Packet& Packet::operator <<(Uint16 Data) -{ - Uint16 ToWrite = htons(Data); - Append(&ToWrite, sizeof(ToWrite)); - return *this; -} -Packet& Packet::operator <<(Int32 Data) -{ - Int32 ToWrite = htonl(Data); - Append(&ToWrite, sizeof(ToWrite)); - return *this; -} -Packet& Packet::operator <<(Uint32 Data) -{ - Uint32 ToWrite = htonl(Data); - Append(&ToWrite, sizeof(ToWrite)); - return *this; -} -Packet& Packet::operator <<(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 = 0; - for (const char* c = Data; *c != '\0'; ++c) - ++Length; - *this << Length; + // First extract the string length + Uint32 length = 0; + *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(Data.size()); - *this << Length; - - // Then insert characters - if (Length > 0) + data.clear(); + if ((length > 0) && checkSize(length * sizeof(Uint32))) { - 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 = 0; - for (const wchar_t* c = Data; *c != L'\0'; ++c) - ++Length; - *this << Length; - - // Then insert characters - for (const wchar_t* c = Data; *c != L'\0'; ++c) - *this << static_cast(*c); - - return *this; -} -Packet& Packet::operator <<(const std::wstring& Data) -{ - // First insert string length - Uint32 Length = static_cast(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(*c); + // Then extract characters + for (Uint32 i = 0; i < length; ++i) + { + Uint32 character = 0; + *this >> character; + data += character; + } } return *this; @@ -395,32 +326,182 @@ Packet& Packet::operator <<(const std::wstring& Data) //////////////////////////////////////////////////////////// -/// Check if the packet can extract a given size of bytes -//////////////////////////////////////////////////////////// -bool Packet::CheckSize(std::size_t Size) +Packet& Packet::operator <<(bool data) { - myIsValid = myIsValid && (myReadPos + Size <= myData.size()); - - return myIsValid; + *this << static_cast(data); + return *this; } //////////////////////////////////////////////////////////// -/// Called before the packet is sent to the network -//////////////////////////////////////////////////////////// -const char* Packet::OnSend(std::size_t& DataSize) +Packet& Packet::operator <<(Int8 data) { - DataSize = GetDataSize(); - return GetData(); + append(&data, sizeof(data)); + return *this; } //////////////////////////////////////////////////////////// -/// Called after the packet has been received from the network -//////////////////////////////////////////////////////////// -void Packet::OnReceive(const char* Data, std::size_t DataSize) +Packet& Packet::operator <<(Uint8 data) { - Append(Data, DataSize); + append(&data, sizeof(data)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Int16 data) +{ + Int16 toWrite = htons(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Uint16 data) +{ + Uint16 toWrite = htons(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Int32 data) +{ + Int32 toWrite = htonl(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(Uint32 data) +{ + Uint32 toWrite = htonl(data); + append(&toWrite, sizeof(toWrite)); + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(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 = 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(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 = std::wcslen(data); + *this << length; + + // Then insert characters + for (const wchar_t* c = data; *c != L'\0'; ++c) + *this << static_cast(*c); + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const std::wstring& data) +{ + // First insert string length + Uint32 length = static_cast(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(*c); + } + + return *this; +} + + +//////////////////////////////////////////////////////////// +Packet& Packet::operator <<(const String& data) +{ + // First insert the string length + Uint32 length = static_cast(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 diff --git a/Externals/SFML/src/SFML/Network/SelectorBase.cpp b/Externals/SFML/src/SFML/Network/SelectorBase.cpp deleted file mode 100644 index 4afb893493..0000000000 --- a/Externals/SFML/src/SFML/Network/SelectorBase.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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. -// -//////////////////////////////////////////////////////////// - -#ifdef _MSC_VER - #pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro -#endif - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -SelectorBase::SelectorBase() : -myMaxSocket(0) -{ - Clear(); -} - - -//////////////////////////////////////////////////////////// -/// Add a socket to watch -//////////////////////////////////////////////////////////// -void SelectorBase::Add(SocketHelper::SocketType Socket) -{ - FD_SET(Socket, &mySet); - - int Size = static_cast(Socket); - if (Size > myMaxSocket) - myMaxSocket = Size; -} - - -//////////////////////////////////////////////////////////// -/// Remove a socket -//////////////////////////////////////////////////////////// -void SelectorBase::Remove(SocketHelper::SocketType Socket) -{ - FD_CLR(Socket, &mySet); -} - - -//////////////////////////////////////////////////////////// -/// Remove all sockets -//////////////////////////////////////////////////////////// -void SelectorBase::Clear() -{ - FD_ZERO(&mySet); - FD_ZERO(&mySetReady); - - myMaxSocket = 0; -} - - -//////////////////////////////////////////////////////////// -/// Wait and collect sockets which are ready for reading. -/// This functions will return either when at least one socket -/// is ready, or when the given time is out -//////////////////////////////////////////////////////////// -unsigned int SelectorBase::Wait(float Timeout) -{ - // Setup the timeout structure - timeval Time; - Time.tv_sec = static_cast(Timeout); - Time.tv_usec = (static_cast(Timeout * 1000) % 1000) * 1000; - - // Prepare the set of sockets to return - mySetReady = mySet; - - // Wait until one of the sockets is ready for reading, or timeout is reached - int NbSockets = select(myMaxSocket + 1, &mySetReady, NULL, NULL, Timeout > 0 ? &Time : NULL); - - return NbSockets >= 0 ? static_cast(NbSockets) : 0; -} - - -//////////////////////////////////////////////////////////// -/// After a call to Wait(), get the Index-th socket which is -/// ready for reading. The total number of sockets ready -/// is the integer returned by the previous call to Wait() -//////////////////////////////////////////////////////////// -SocketHelper::SocketType SelectorBase::GetSocketReady(unsigned int Index) -{ - // The standard FD_xxx interface doesn't define a direct access, - // so we must go through the whole set to find the socket we're looking for - for (int i = 0; i < myMaxSocket + 1; ++i) - { - if (FD_ISSET(i, &mySetReady)) - { - // Current socket is ready, but is it the Index-th one ? - if (Index > 0) - { - Index--; - } - else - { - return static_cast(i); - } - } - } - - // Invalid index : return an invalid socket - return SocketHelper::InvalidSocket(); -} - -} // namespace sf diff --git a/Externals/SFML/src/SFML/Network/Socket.cpp b/Externals/SFML/src/SFML/Network/Socket.cpp new file mode 100644 index 0000000000..89867c3faf --- /dev/null +++ b/Externals/SFML/src/SFML/Network/Socket.cpp @@ -0,0 +1,144 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include + + +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); + 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 (ie. removes buffering of TCP packets) + int yes = 1; + if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&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(&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(&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 diff --git a/Externals/SFML/include/SFML/Network/Sockets.hpp b/Externals/SFML/src/SFML/Network/SocketImpl.hpp similarity index 82% rename from Externals/SFML/include/SFML/Network/Sockets.hpp rename to Externals/SFML/src/SFML/Network/SocketImpl.hpp index 8c78d76ad6..bcfb0598ab 100644 --- a/Externals/SFML/include/SFML/Network/Sockets.hpp +++ b/Externals/SFML/src/SFML/Network/SocketImpl.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -22,24 +22,18 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_SOCKETS_HPP -#define SFML_SOCKETS_HPP - //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// #include -#ifdef SFML_SYSTEM_WINDOWS +#if defined(SFML_SYSTEM_WINDOWS) - #include + #include #else - #include + #include #endif - - -#endif // SFML_SOCKETS_HPP diff --git a/Externals/SFML/src/SFML/Network/SocketSelector.cpp b/Externals/SFML/src/SFML/Network/SocketSelector.cpp new file mode 100644 index 0000000000..9897e603cb --- /dev/null +++ b/Externals/SFML/src/SFML/Network/SocketSelector.cpp @@ -0,0 +1,141 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include +#include +#include + +#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 +}; + + +//////////////////////////////////////////////////////////// +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()) + { + FD_SET(handle, &m_impl->AllSockets); + + int size = static_cast(handle); + if (size > m_impl->MaxSocket) + m_impl->MaxSocket = size; + } +} + + +//////////////////////////////////////////////////////////// +void SocketSelector::remove(Socket& socket) +{ + FD_CLR(socket.getHandle(), &m_impl->AllSockets); + FD_CLR(socket.getHandle(), &m_impl->SocketsReady); +} + + +//////////////////////////////////////////////////////////// +void SocketSelector::clear() +{ + FD_ZERO(&m_impl->AllSockets); + FD_ZERO(&m_impl->SocketsReady); + + m_impl->MaxSocket = 0; +} + + +//////////////////////////////////////////////////////////// +bool SocketSelector::wait(Time timeout) +{ + // Setup the timeout + timeval time; + time.tv_sec = static_cast(timeout.asMicroseconds() / 1000000); + time.tv_usec = static_cast(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 + 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 +{ + return FD_ISSET(socket.getHandle(), &m_impl->SocketsReady) != 0; +} + + +//////////////////////////////////////////////////////////// +SocketSelector& SocketSelector::operator =(const SocketSelector& right) +{ + SocketSelector temp(right); + + std::swap(m_impl, temp.m_impl); + + return *this; +} + +} // namespace sf diff --git a/Externals/SFML/src/SFML/Network/SocketTCP.cpp b/Externals/SFML/src/SFML/Network/SocketTCP.cpp deleted file mode 100644 index 6cbd158aa8..0000000000 --- a/Externals/SFML/src/SFML/Network/SocketTCP.cpp +++ /dev/null @@ -1,519 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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 -#include -#include -#include -#include -#include -#include - - -#ifdef _MSC_VER - #pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -SocketTCP::SocketTCP() -{ - Create(SocketHelper::InvalidSocket()); -} - - -//////////////////////////////////////////////////////////// -/// Change the blocking state of the socket -//////////////////////////////////////////////////////////// -void SocketTCP::SetBlocking(bool Blocking) -{ - // Make sure our socket is valid - if (!IsValid()) - Create(); - - SocketHelper::SetBlocking(mySocket, Blocking); - myIsBlocking = Blocking; -} - - -//////////////////////////////////////////////////////////// -/// Connect to another computer on a specified port -//////////////////////////////////////////////////////////// -Socket::Status SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout) -{ - // Make sure our socket is valid - if (!IsValid()) - Create(); - - // Build the host address - sockaddr_in SockAddr; - memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero)); - SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str()); - SockAddr.sin_family = AF_INET; - SockAddr.sin_port = htons(Port); - - if (Timeout <= 0) - { - // ----- We're not using a timeout : just try to connect ----- - - if (connect(mySocket, reinterpret_cast(&SockAddr), sizeof(SockAddr)) == -1) - { - // Failed to connect - return SocketHelper::GetErrorStatus(); - } - - // Connection succeeded - return Socket::Done; - } - else - { - // ----- We're using a timeout : we'll need a few tricks to make it work ----- - - // Save the previous blocking state - bool IsBlocking = myIsBlocking; - - // Switch to non-blocking to enable our connection timeout - if (IsBlocking) - SetBlocking(false); - - // Try to connect to host - if (connect(mySocket, reinterpret_cast(&SockAddr), sizeof(SockAddr)) >= 0) - { - // We got instantly connected! (it may no happen a lot...) - return Socket::Done; - } - - // Get the error status - Socket::Status Status = SocketHelper::GetErrorStatus(); - - // If we were in non-blocking mode, return immediatly - if (!IsBlocking) - 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(mySocket, &Selector); - - // Setup the timeout - timeval Time; - Time.tv_sec = static_cast(Timeout); - Time.tv_usec = (static_cast(Timeout * 1000) % 1000) * 1000; - - // Wait for something to write on our socket (which means that the connection request has returned) - if (select(static_cast(mySocket + 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 try to retrieve the name of the connected peer - SocketHelper::LengthType Size = sizeof(SockAddr); - if (getpeername(mySocket, reinterpret_cast(&SockAddr), &Size) != -1) - { - // Connection accepted - Status = Socket::Done; - } - else - { - // Connection failed - Status = SocketHelper::GetErrorStatus(); - } - } - else - { - // Failed to connect before timeout is over - Status = SocketHelper::GetErrorStatus(); - } - } - - // Switch back to blocking mode - SetBlocking(true); - - return Status; - } -} - - -//////////////////////////////////////////////////////////// -/// Listen to a specified port for incoming data or connections -//////////////////////////////////////////////////////////// -bool SocketTCP::Listen(unsigned short Port) -{ - // Make sure our socket is valid - if (!IsValid()) - Create(); - - // Build the address - sockaddr_in SockAddr; - memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero)); - SockAddr.sin_addr.s_addr = htonl(INADDR_ANY); - SockAddr.sin_family = AF_INET; - SockAddr.sin_port = htons(Port); - - // Bind the socket to the specified port - if (bind(mySocket, reinterpret_cast(&SockAddr), sizeof(SockAddr)) == -1) - { - // Not likely to happen, but... - std::cerr << "Failed to bind socket to port " << Port << std::endl; - return false; - } - - // Listen to the bound port - if (listen(mySocket, 0) == -1) - { - // Oops, socket is deaf - std::cerr << "Failed to listen to port " << Port << std::endl; - return false; - } - - return true; -} - - -//////////////////////////////////////////////////////////// -/// Wait for a connection (must be listening to a port). -/// This function will block if the socket is blocking -//////////////////////////////////////////////////////////// -Socket::Status SocketTCP::Accept(SocketTCP& Connected, IPAddress* Address) -{ - // Address that will be filled with client informations - sockaddr_in ClientAddress; - SocketHelper::LengthType Length = sizeof(ClientAddress); - - // Accept a new connection - Connected = accept(mySocket, reinterpret_cast(&ClientAddress), &Length); - - // Check errors - if (!Connected.IsValid()) - { - if (Address) - *Address = IPAddress(); - - return SocketHelper::GetErrorStatus(); - } - - // Fill address if requested - if (Address) - *Address = IPAddress(inet_ntoa(ClientAddress.sin_addr)); - - return Socket::Done; -} - - -//////////////////////////////////////////////////////////// -/// Send an array of bytes to the host (must be connected first) -//////////////////////////////////////////////////////////// -Socket::Status SocketTCP::Send(const char* Data, std::size_t Size) -{ - // First check that socket is valid - if (!IsValid()) - return Socket::Error; - - // Check parameters - if (Data && Size) - { - // Loop until every byte has been sent - int Sent = 0; - int SizeToSend = static_cast(Size); - for (int Length = 0; Length < SizeToSend; Length += Sent) - { - // Send a chunk of data - Sent = send(mySocket, Data + Length, SizeToSend - Length, 0); - - // Check if an error occured - if (Sent <= 0) - return SocketHelper::GetErrorStatus(); - } - - return Socket::Done; - } - else - { - // Error... - std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl; - return Socket::Error; - } -} - - -//////////////////////////////////////////////////////////// -/// Receive an array of bytes from the host (must be connected first). -/// This function will block if the socket is blocking -//////////////////////////////////////////////////////////// -Socket::Status SocketTCP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived) -{ - // First clear the size received - SizeReceived = 0; - - // Check that socket is valid - if (!IsValid()) - return Socket::Error; - - // Check parameters - if (Data && MaxSize) - { - // Receive a chunk of bytes - int Received = recv(mySocket, Data, static_cast(MaxSize), 0); - - // Check the number of bytes received - if (Received > 0) - { - SizeReceived = static_cast(Received); - return Socket::Done; - } - else if (Received == 0) - { - return Socket::Disconnected; - } - else - { - return SocketHelper::GetErrorStatus(); - } - } - else - { - // Error... - std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl; - return Socket::Error; - } -} - - -//////////////////////////////////////////////////////////// -/// Send a packet of data to the host (must be connected first) -//////////////////////////////////////////////////////////// -Socket::Status SocketTCP::Send(Packet& PacketToSend) -{ - // Get the data to send from the packet - std::size_t DataSize = 0; - const char* Data = PacketToSend.OnSend(DataSize); - - // Send the packet size - Uint32 PacketSize = htonl(static_cast(DataSize)); - Send(reinterpret_cast(&PacketSize), sizeof(PacketSize)); - - // Send the packet data - if (PacketSize > 0) - { - return Send(Data, DataSize); - } - else - { - return Socket::Done; - } -} - - -//////////////////////////////////////////////////////////// -/// Receive a packet from the host (must be connected first). -/// This function will block if the socket is blocking -//////////////////////////////////////////////////////////// -Socket::Status SocketTCP::Receive(Packet& PacketToReceive) -{ - // We start by getting the size of the incoming packet - Uint32 PacketSize = 0; - std::size_t Received = 0; - if (myPendingPacketSize < 0) - { - // Loop until we've received the entire size of the packet - // (even a 4 bytes variable may be received in more than one call) - while (myPendingHeaderSize < sizeof(myPendingHeader)) - { - char* Data = reinterpret_cast(&myPendingHeader) + myPendingHeaderSize; - Socket::Status Status = Receive(Data, sizeof(myPendingHeader) - myPendingHeaderSize, Received); - myPendingHeaderSize += Received; - - if (Status != Socket::Done) - return Status; - } - - PacketSize = ntohl(myPendingHeader); - myPendingHeaderSize = 0; - } - else - { - // There is a pending packet : we already know its size - PacketSize = myPendingPacketSize; - } - - // Then loop until we receive all the packet data - char Buffer[1024]; - while (myPendingPacket.size() < PacketSize) - { - // Receive a chunk of data - std::size_t SizeToGet = std::min(static_cast(PacketSize - myPendingPacket.size()), sizeof(Buffer)); - Socket::Status Status = Receive(Buffer, SizeToGet, Received); - if (Status != Socket::Done) - { - // We must save the size of the pending packet until we can receive its content - if (Status == Socket::NotReady) - myPendingPacketSize = PacketSize; - return Status; - } - - // Append it into the packet - if (Received > 0) - { - myPendingPacket.resize(myPendingPacket.size() + Received); - char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received; - memcpy(Begin, Buffer, Received); - } - } - - // We have received all the datas : we can copy it to the user packet, and clear our internal packet - PacketToReceive.Clear(); - if (!myPendingPacket.empty()) - PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size()); - myPendingPacket.clear(); - myPendingPacketSize = -1; - - return Socket::Done; -} - - -//////////////////////////////////////////////////////////// -/// Close the socket -//////////////////////////////////////////////////////////// -bool SocketTCP::Close() -{ - if (IsValid()) - { - if (!SocketHelper::Close(mySocket)) - { - std::cerr << "Failed to close socket" << std::endl; - return false; - } - - mySocket = SocketHelper::InvalidSocket(); - } - - myIsBlocking = true; - - return true; -} - - -//////////////////////////////////////////////////////////// -/// Check if the socket is in a valid state ; this function -/// can be called any time to check if the socket is OK -//////////////////////////////////////////////////////////// -bool SocketTCP::IsValid() const -{ - return mySocket != SocketHelper::InvalidSocket(); -} - - -//////////////////////////////////////////////////////////// -/// Comparison operator == -//////////////////////////////////////////////////////////// -bool SocketTCP::operator ==(const SocketTCP& Other) const -{ - return mySocket == Other.mySocket; -} - - -//////////////////////////////////////////////////////////// -/// Comparison operator != -//////////////////////////////////////////////////////////// -bool SocketTCP::operator !=(const SocketTCP& Other) const -{ - return mySocket != Other.mySocket; -} - - -//////////////////////////////////////////////////////////// -/// Comparison operator <. -/// Provided for compatibility with standard containers, as -/// comparing two sockets doesn't make much sense... -//////////////////////////////////////////////////////////// -bool SocketTCP::operator <(const SocketTCP& Other) const -{ - return mySocket < Other.mySocket; -} - - -//////////////////////////////////////////////////////////// -/// Construct the socket from a socket descriptor -/// (for internal use only) -//////////////////////////////////////////////////////////// -SocketTCP::SocketTCP(SocketHelper::SocketType Descriptor) -{ - Create(Descriptor); -} - - -//////////////////////////////////////////////////////////// -/// Create the socket -//////////////////////////////////////////////////////////// -void SocketTCP::Create(SocketHelper::SocketType Descriptor) -{ - // Use the given socket descriptor, or get a new one - mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_STREAM, 0); - myIsBlocking = true; - - // Reset the pending packet - myPendingHeaderSize = 0; - myPendingPacket.clear(); - myPendingPacketSize = -1; - - // Setup default options - if (IsValid()) - { - int Yes = 1; -#ifndef SFML_SYSTEM_WINDOWS - /* We must disable this in order to detect if ports are being used by other apps, or - other instances of dolphin. This is also disabled in SFML 2.0, see -http://www.sfml-dev.org/forum/viewtopic.php?t=3388 - ...In fact, SO_REUSEADDR is only unsafe on Windows. See: - http://stackoverflow.com/questions/14388706 - */ - // To avoid the "Address already in use" error message when trying to bind to the same port - if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&Yes), sizeof(Yes)) == -1) - { - std::cerr << "Failed to set socket option \"SO_REUSEADDR\" ; " - << "binding to a same port may fail if too fast" << std::endl; - } -#endif - - // Disable the Nagle algorithm (ie. removes buffering of TCP packets) - if (setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&Yes), sizeof(Yes)) == -1) - { - std::cerr << "Failed to set socket option \"TCP_NODELAY\" ; " - << "all your TCP packets will be buffered" << std::endl; - } - - // Set blocking by default (should always be the case anyway) - SetBlocking(true); - } -} - -} // namespace sf diff --git a/Externals/SFML/src/SFML/Network/SocketUDP.cpp b/Externals/SFML/src/SFML/Network/SocketUDP.cpp deleted file mode 100644 index ec46c65864..0000000000 --- a/Externals/SFML/src/SFML/Network/SocketUDP.cpp +++ /dev/null @@ -1,433 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@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 -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// Default constructor -//////////////////////////////////////////////////////////// -SocketUDP::SocketUDP() -{ - Create(); -} - - -//////////////////////////////////////////////////////////// -/// Change the blocking state of the socket -//////////////////////////////////////////////////////////// -void SocketUDP::SetBlocking(bool Blocking) -{ - // Make sure our socket is valid - if (!IsValid()) - Create(); - - SocketHelper::SetBlocking(mySocket, Blocking); - myIsBlocking = Blocking; -} - - -//////////////////////////////////////////////////////////// -/// Bind the socket to a specific port -//////////////////////////////////////////////////////////// -bool SocketUDP::Bind(unsigned short Port) -{ - // Check if the socket is already bound to the specified port - if (myPort != Port) - { - // If the socket was previously bound to another port, we need to unbind it first - Unbind(); - - if (Port != 0) - { - // Build an address with the specified port - sockaddr_in Addr; - Addr.sin_family = AF_INET; - Addr.sin_port = htons(Port); - Addr.sin_addr.s_addr = INADDR_ANY; - memset(Addr.sin_zero, 0, sizeof(Addr.sin_zero)); - - // Bind the socket to the port - if (bind(mySocket, reinterpret_cast(&Addr), sizeof(Addr)) == -1) - { - std::cerr << "Failed to bind the socket to port " << Port << std::endl; - myPort = 0; - return false; - } - } - - // Save the new port - myPort = Port; - } - - return true; -} - - -//////////////////////////////////////////////////////////// -/// Unbind the socket to its previous port -//////////////////////////////////////////////////////////// -bool SocketUDP::Unbind() -{ - // To unbind the socket, we just recreate it - if (myPort != 0) - { - Close(); - Create(); - myPort = 0; - } - - return true; -} - - -//////////////////////////////////////////////////////////// -/// Send an array of bytes -//////////////////////////////////////////////////////////// -Socket::Status SocketUDP::Send(const char* Data, std::size_t Size, const IPAddress& Address, unsigned short Port) -{ - // Make sure the socket is valid - if (!IsValid()) - Create(); - - // Check parameters - if (Data && Size) - { - // Build the target address - sockaddr_in Target; - Target.sin_family = AF_INET; - Target.sin_port = htons(Port); - Target.sin_addr.s_addr = inet_addr(Address.ToString().c_str()); - memset(Target.sin_zero, 0, sizeof(Target.sin_zero)); - - // Loop until every byte has been sent - int Sent = 0; - int SizeToSend = static_cast(Size); - for (int Length = 0; Length < SizeToSend; Length += Sent) - { - // Send a chunk of data - Sent = sendto(mySocket, Data + Length, SizeToSend - Length, 0, reinterpret_cast(&Target), sizeof(Target)); - - // Check errors - if (Sent <= 0) - return SocketHelper::GetErrorStatus(); - } - - return Socket::Done; - } - else - { - // Error... - std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl; - return Socket::Error; - } -} - - -//////////////////////////////////////////////////////////// -/// Receive an array of bytes. -/// This function will block if the socket is blocking -//////////////////////////////////////////////////////////// -Socket::Status SocketUDP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived, IPAddress& Address, unsigned short& Port) -{ - // First clear the size received - SizeReceived = 0; - - // Make sure the socket is bound to a port - if (myPort == 0) - { - std::cerr << "Failed to receive data ; the UDP socket first needs to be bound to a port" << std::endl; - return Socket::Error; - } - - // Make sure the socket is valid - if (!IsValid()) - Create(); - - // Check parameters - if (Data && MaxSize) - { - // Data that will be filled with the other computer's address - sockaddr_in Sender; - Sender.sin_family = AF_INET; - Sender.sin_port = 0; - Sender.sin_addr.s_addr = INADDR_ANY; - memset(Sender.sin_zero, 0, sizeof(Sender.sin_zero)); - SocketHelper::LengthType SenderSize = sizeof(Sender); - - // Receive a chunk of bytes - int Received = recvfrom(mySocket, Data, static_cast(MaxSize), 0, reinterpret_cast(&Sender), &SenderSize); - - // Check the number of bytes received - if (Received > 0) - { - Address = IPAddress(inet_ntoa(Sender.sin_addr)); - Port = ntohs(Sender.sin_port); - SizeReceived = static_cast(Received); - return Socket::Done; - } - else - { - Address = IPAddress(); - Port = 0; - return Received == 0 ? Socket::Disconnected : SocketHelper::GetErrorStatus(); - } - } - else - { - // Error... - std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl; - return Socket::Error; - } -} - - -//////////////////////////////////////////////////////////// -/// Send a packet of data -//////////////////////////////////////////////////////////// -Socket::Status SocketUDP::Send(Packet& PacketToSend, const IPAddress& Address, unsigned short Port) -{ - // Get the data to send from the packet - std::size_t DataSize = 0; - const char* Data = PacketToSend.OnSend(DataSize); - - // Send the packet size - Uint32 PacketSize = htonl(static_cast(DataSize)); - Send(reinterpret_cast(&PacketSize), sizeof(PacketSize), Address, Port); - - // Send the packet data - if (PacketSize > 0) - { - return Send(Data, DataSize, Address, Port); - } - else - { - return Socket::Done; - } -} - - -//////////////////////////////////////////////////////////// -/// Receive a packet. -/// This function will block if the socket is blocking -//////////////////////////////////////////////////////////// -Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address, unsigned short& Port) -{ - // We start by getting the size of the incoming packet - Uint32 PacketSize = 0; - std::size_t Received = 0; - if (myPendingPacketSize < 0) - { - // Loop until we've received the entire size of the packet - // (even a 4 bytes variable may be received in more than one call) - while (myPendingHeaderSize < sizeof(myPendingHeader)) - { - char* Data = reinterpret_cast(&myPendingHeader) + myPendingHeaderSize; - Socket::Status Status = Receive(Data, sizeof(myPendingHeader) - myPendingHeaderSize, Received, Address, Port); - myPendingHeaderSize += Received; - - if (Status != Socket::Done) - return Status; - } - - PacketSize = ntohl(myPendingHeader); - myPendingHeaderSize = 0; - } - else - { - // There is a pending packet : we already know its size - PacketSize = myPendingPacketSize; - } - - // Use another address instance for receiving the packet data ; - // chunks of data coming from a different sender will be discarded (and lost...) - IPAddress Sender; - unsigned short SenderPort; - - // Then loop until we receive all the packet data - char Buffer[1024]; - while (myPendingPacket.size() < PacketSize) - { - // Receive a chunk of data - std::size_t SizeToGet = std::min(static_cast(PacketSize - myPendingPacket.size()), sizeof(Buffer)); - Socket::Status Status = Receive(Buffer, SizeToGet, Received, Sender, SenderPort); - if (Status != Socket::Done) - { - // We must save the size of the pending packet until we can receive its content - if (Status == Socket::NotReady) - myPendingPacketSize = PacketSize; - return Status; - } - - // Append it into the packet - if ((Sender == Address) && (SenderPort == Port) && (Received > 0)) - { - myPendingPacket.resize(myPendingPacket.size() + Received); - char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received; - memcpy(Begin, Buffer, Received); - } - } - - // We have received all the datas : we can copy it to the user packet, and clear our internal packet - PacketToReceive.Clear(); - if (!myPendingPacket.empty()) - PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size()); - myPendingPacket.clear(); - myPendingPacketSize = -1; - - return Socket::Done; -} - - -//////////////////////////////////////////////////////////// -/// Close the socket -//////////////////////////////////////////////////////////// -bool SocketUDP::Close() -{ - if (IsValid()) - { - if (!SocketHelper::Close(mySocket)) - { - std::cerr << "Failed to close socket" << std::endl; - return false; - } - - mySocket = SocketHelper::InvalidSocket(); - } - - myPort = 0; - myIsBlocking = true; - - return true; -} - - -//////////////////////////////////////////////////////////// -/// Check if the socket is in a valid state ; this function -/// can be called any time to check if the socket is OK -//////////////////////////////////////////////////////////// -bool SocketUDP::IsValid() const -{ - return mySocket != SocketHelper::InvalidSocket(); -} - - -//////////////////////////////////////////////////////////// -/// Get the port the socket is currently bound to -//////////////////////////////////////////////////////////// -unsigned short SocketUDP::GetPort() const -{ - return myPort; -} - - -//////////////////////////////////////////////////////////// -/// Comparison operator == -//////////////////////////////////////////////////////////// -bool SocketUDP::operator ==(const SocketUDP& Other) const -{ - return mySocket == Other.mySocket; -} - - -//////////////////////////////////////////////////////////// -/// Comparison operator != -//////////////////////////////////////////////////////////// -bool SocketUDP::operator !=(const SocketUDP& Other) const -{ - return mySocket != Other.mySocket; -} - - -//////////////////////////////////////////////////////////// -/// Comparison operator <. -/// Provided for compatibility with standard containers, as -/// comparing two sockets doesn't make much sense... -//////////////////////////////////////////////////////////// -bool SocketUDP::operator <(const SocketUDP& Other) const -{ - return mySocket < Other.mySocket; -} - - -//////////////////////////////////////////////////////////// -/// Construct the socket from a socket descriptor -/// (for internal use only) -//////////////////////////////////////////////////////////// -SocketUDP::SocketUDP(SocketHelper::SocketType Descriptor) -{ - Create(Descriptor); -} - - -//////////////////////////////////////////////////////////// -/// Create the socket -//////////////////////////////////////////////////////////// -void SocketUDP::Create(SocketHelper::SocketType Descriptor) -{ - // Use the given socket descriptor, or get a new one - mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_DGRAM, 0); - myIsBlocking = true; - - // Clear the last port used - myPort = 0; - - // Reset the pending packet - myPendingHeaderSize = 0; - myPendingPacket.clear(); - myPendingPacketSize = -1; - - // Setup default options - if (IsValid()) - { - // To avoid the "Address already in use" error message when trying to bind to the same port - int Yes = 1; - if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&Yes), sizeof(Yes)) == -1) - { - std::cerr << "Failed to set socket option \"reuse address\" ; " - << "binding to a same port may fail if too fast" << std::endl; - } - - // Enable broadcast by default - if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&Yes), sizeof(Yes)) == -1) - { - std::cerr << "Failed to enable broadcast on UDP socket" << std::endl; - } - - // Set blocking by default (should always be the case anyway) - SetBlocking(true); - } -} - -} // namespace sf diff --git a/Externals/SFML/src/SFML/Network/TcpListener.cpp b/Externals/SFML/src/SFML/Network/TcpListener.cpp new file mode 100644 index 0000000000..9519251350 --- /dev/null +++ b/Externals/SFML/src/SFML/Network/TcpListener.cpp @@ -0,0 +1,124 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include +#include + + +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(&address), &size) != -1) + { + return ntohs(address.sin_port); + } + } + + // We failed to retrieve the port + return 0; +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpListener::listen(unsigned short port) +{ + // Create the internal socket if it doesn't exist + create(); + + // Bind the socket to the specified port + sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port); + if (bind(getHandle(), reinterpret_cast(&address), sizeof(address)) == -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(), 0) == -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(&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 diff --git a/Externals/SFML/src/SFML/Network/TcpSocket.cpp b/Externals/SFML/src/SFML/Network/TcpSocket.cpp new file mode 100644 index 0000000000..b94e196c3b --- /dev/null +++ b/Externals/SFML/src/SFML/Network/TcpSocket.cpp @@ -0,0 +1,381 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include +#include +#include +#include +#include + +#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(&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(&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(&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) +{ + // 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(&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(&address), sizeof(address)) >= 0) + { + // We got instantly connected! (it may no happen a lot...) + return Done; + } + + // Get the error status + Status status = priv::SocketImpl::getErrorStatus(); + + // If we were in non-blocking mode, return immediatly + 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(timeout.asMicroseconds() / 1000000); + time.tv_usec = static_cast(timeout.asMicroseconds() % 1000000); + + // Wait for something to write on our socket (which means that the connection request has returned) + if (select(static_cast(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() != sf::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) +{ + // 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 sent = 0; + int sizeToSend = static_cast(size); + for (int length = 0; length < sizeToSend; length += sent) + { + // Send a chunk of data + sent = ::send(getHandle(), static_cast(data) + length, sizeToSend - length, flags); + + // Check for errors + if (sent < 0) + return priv::SocketImpl::getErrorStatus(); + } + + return Done; +} + + +//////////////////////////////////////////////////////////// +Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received) +{ + // First clear the variables to fill + received = 0; + + // Check the destination buffer + if (!data) + { + err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl; + return Error; + } + + // Receive a chunk of bytes + int sizeReceived = recv(getHandle(), static_cast(data), static_cast(size), flags); + + // Check the number of bytes received + if (sizeReceived > 0) + { + received = static_cast(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(size)); + + // Allocate memory for the data block to send + std::vector blockToSend(sizeof(packetSize) + size); + + // Copy the packet size and data into the block to send + std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize)); + if (size > 0) + std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size); + + // Send the data block + return send(&blockToSend[0], blockToSend.size()); +} + + +//////////////////////////////////////////////////////////// +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(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived; + Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received); + m_pendingPacket.SizeReceived += received; + + if (status != Done) + return status; + } + + // The packet size has been fully received + packetSize = ntohl(m_pendingPacket.Size); + } + else + { + // The packet size has already been received in a previous call + packetSize = ntohl(m_pendingPacket.Size); + } + + // Loop until we receive all the packet data + char buffer[1024]; + while (m_pendingPacket.Data.size() < packetSize) + { + // Receive a chunk of data + std::size_t sizeToGet = std::min(static_cast(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 diff --git a/Externals/SFML/src/SFML/Network/UdpSocket.cpp b/Externals/SFML/src/SFML/Network/UdpSocket.cpp new file mode 100644 index 0000000000..4653b6607c --- /dev/null +++ b/Externals/SFML/src/SFML/Network/UdpSocket.cpp @@ -0,0 +1,193 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include +#include +#include +#include + + +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(&address), &size) != -1) + { + return ntohs(address.sin_port); + } + } + + // We failed to retrieve the port + return 0; +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::bind(unsigned short port) +{ + // Create the internal socket if it doesn't exist + create(); + + // Bind the socket + sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port); + if (::bind(getHandle(), reinterpret_cast(&address), sizeof(address)) == -1) + { + err() << "Failed to bind socket to port " << port << std::endl; + return Error; + } + + return Done; +} + + +//////////////////////////////////////////////////////////// +void UdpSocket::unbind() +{ + // Simply close the socket + close(); +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort) +{ + // Create the internal socket if it doesn't exist + create(); + + // Make sure that all the data will fit in one datagram + if (size > MaxDatagramSize) + { + err() << "Cannot send data over the network " + << "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl; + return Error; + } + + // Build the target address + sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); + + // Send the data (unlike TCP, all the data is always sent in one call) + int sent = sendto(getHandle(), static_cast(data), static_cast(size), 0, reinterpret_cast(&address), sizeof(address)); + + // Check for errors + if (sent < 0) + return priv::SocketImpl::getErrorStatus(); + + return Done; +} + + +//////////////////////////////////////////////////////////// +Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort) +{ + // First clear the variables to fill + received = 0; + remoteAddress = IpAddress(); + remotePort = 0; + + // Check the destination buffer + if (!data) + { + err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl; + return Error; + } + + // Data that will be filled with the other computer's address + sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0); + + // Receive a chunk of bytes + priv::SocketImpl::AddrLength addressSize = sizeof(address); + int sizeReceived = recvfrom(getHandle(), static_cast(data), static_cast(size), 0, reinterpret_cast(&address), &addressSize); + + // Check for errors + if (sizeReceived < 0) + return priv::SocketImpl::getErrorStatus(); + + // Fill the sender informations + received = static_cast(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 diff --git a/Externals/SFML/src/SFML/Network/Unix/SocketHelper.cpp b/Externals/SFML/src/SFML/Network/Unix/SocketImpl.cpp similarity index 72% rename from Externals/SFML/src/SFML/Network/Unix/SocketHelper.cpp rename to Externals/SFML/src/SFML/Network/Unix/SocketImpl.cpp index 16df524027..7c39ee1ccd 100644 --- a/Externals/SFML/src/SFML/Network/Unix/SocketHelper.cpp +++ b/Externals/SFML/src/SFML/Network/Unix/SocketImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -25,48 +25,56 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include #include #include +#include namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// -/// Return the value of the invalid socket +sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port) +{ + sockaddr_in addr; + std::memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); + addr.sin_addr.s_addr = htonl(address); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + return addr; +} + + //////////////////////////////////////////////////////////// -SocketHelper::SocketType SocketHelper::InvalidSocket() +SocketHandle SocketImpl::invalidSocket() { return -1; } //////////////////////////////////////////////////////////// -/// Close / destroy a socket -//////////////////////////////////////////////////////////// -bool SocketHelper::Close(SocketHelper::SocketType Socket) +void SocketImpl::close(SocketHandle sock) { - return close(Socket) != -1; + ::close(sock); } //////////////////////////////////////////////////////////// -/// Set a socket as blocking or non-blocking -//////////////////////////////////////////////////////////// -void SocketHelper::SetBlocking(SocketHelper::SocketType Socket, bool Block) +void SocketImpl::setBlocking(SocketHandle sock, bool block) { - int Status = fcntl(Socket, F_GETFL); - if (Block) - fcntl(Socket, F_SETFL, Status & ~O_NONBLOCK); + int status = fcntl(sock, F_GETFL); + if (block) + fcntl(sock, F_SETFL, status & ~O_NONBLOCK); else - fcntl(Socket, F_SETFL, Status | O_NONBLOCK); + fcntl(sock, F_SETFL, status | O_NONBLOCK); } //////////////////////////////////////////////////////////// -/// Get the last socket error status -//////////////////////////////////////////////////////////// -Socket::Status SocketHelper::GetErrorStatus() +Socket::Status SocketImpl::getErrorStatus() { // The followings are sometimes equal to EWOULDBLOCK, // so we have to make a special case for them in order @@ -82,8 +90,11 @@ Socket::Status SocketHelper::GetErrorStatus() 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 diff --git a/Externals/SFML/include/SFML/Network/Unix/SocketHelper.hpp b/Externals/SFML/src/SFML/Network/Unix/SocketImpl.hpp similarity index 63% rename from Externals/SFML/include/SFML/Network/Unix/SocketHelper.hpp rename to Externals/SFML/src/SFML/Network/Unix/SocketImpl.hpp index 2f6d8965ee..372fa3c675 100644 --- a/Externals/SFML/include/SFML/Network/Unix/SocketHelper.hpp +++ b/Externals/SFML/src/SFML/Network/Unix/SocketImpl.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -22,12 +22,13 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_SOCKETHELPERUNIX_HPP -#define SFML_SOCKETHELPERUNIX_HPP +#ifndef SFML_SOCKETIMPL_HPP +#define SFML_SOCKETIMPL_HPP //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include #include #include #include @@ -39,47 +40,57 @@ namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// -/// This class defines helper functions to do all the -/// non-portable socket stuff. This class is meant for internal -/// use only +/// \brief Helper class implementing all the non-portable +/// socket stuff; this is the Unix version +/// //////////////////////////////////////////////////////////// -class SFML_API SocketHelper +class SocketImpl { public : //////////////////////////////////////////////////////////// - // Define some socket types + // Types //////////////////////////////////////////////////////////// - typedef int SocketType; - typedef socklen_t LengthType; + typedef socklen_t AddrLength; //////////////////////////////////////////////////////////// - /// Return the value of the invalid socket + /// \brief Create an internal sockaddr_in address /// - /// \return Unique value of the invalid socket + /// \param address Target address + /// \param port Target port + /// + /// \return sockaddr_in ready to be used by socket functions /// //////////////////////////////////////////////////////////// - static SocketType InvalidSocket(); + static sockaddr_in createAddress(Uint32 address, unsigned short port); //////////////////////////////////////////////////////////// - /// Close / destroy a socket + /// \brief Return the value of the invalid socket /// - /// \param Socket : Socket to close - /// - /// \return True on success + /// \return Special value of the invalid socket /// //////////////////////////////////////////////////////////// - static bool Close(SocketType Socket); + static SocketHandle invalidSocket(); //////////////////////////////////////////////////////////// - /// Set a socket as blocking or non-blocking + /// \brief Close and destroy a socket /// - /// \param Socket : Socket to modify - /// \param Block : New blocking state of the socket + /// \param sock Handle of the socket to close /// //////////////////////////////////////////////////////////// - static void SetBlocking(SocketType Socket, bool Block); + 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 @@ -87,10 +98,12 @@ public : /// \return Status corresponding to the last socket error /// //////////////////////////////////////////////////////////// - static Socket::Status GetErrorStatus(); + static Socket::Status getErrorStatus(); }; +} // namespace priv + } // namespace sf -#endif // SFML_SOCKETHELPERUNIX_HPP +#endif // SFML_SOCKETIMPL_HPP diff --git a/Externals/SFML/src/SFML/Network/Win32/SocketHelper.cpp b/Externals/SFML/src/SFML/Network/Win32/SocketImpl.cpp similarity index 70% rename from Externals/SFML/src/SFML/Network/Win32/SocketHelper.cpp rename to Externals/SFML/src/SFML/Network/Win32/SocketImpl.cpp index e4389f2e88..d6f633fad3 100644 --- a/Externals/SFML/src/SFML/Network/Win32/SocketHelper.cpp +++ b/Externals/SFML/src/SFML/Network/Win32/SocketImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -25,52 +25,62 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include +#include +#include namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// -/// Return the value of the invalid socket +sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port) +{ + sockaddr_in addr; + std::memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); + addr.sin_addr.s_addr = htonl(address); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + return addr; +} + + //////////////////////////////////////////////////////////// -SocketHelper::SocketType SocketHelper::InvalidSocket() +SocketHandle SocketImpl::invalidSocket() { return INVALID_SOCKET; } //////////////////////////////////////////////////////////// -/// Close / destroy a socket -//////////////////////////////////////////////////////////// -bool SocketHelper::Close(SocketHelper::SocketType Socket) +void SocketImpl::close(SocketHandle sock) { - return closesocket(Socket) != -1; + closesocket(sock); } //////////////////////////////////////////////////////////// -/// Set a socket as blocking or non-blocking -//////////////////////////////////////////////////////////// -void SocketHelper::SetBlocking(SocketHelper::SocketType Socket, bool Block) +void SocketImpl::setBlocking(SocketHandle sock, bool block) { - unsigned long Blocking = Block ? 0 : 1; - ioctlsocket(Socket, FIONBIO, &Blocking); + u_long blocking = block ? 0 : 1; + ioctlsocket(sock, FIONBIO, &blocking); } //////////////////////////////////////////////////////////// -/// Get the last socket error status -//////////////////////////////////////////////////////////// -Socket::Status SocketHelper::GetErrorStatus() +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; } } @@ -85,8 +95,8 @@ struct SocketInitializer { SocketInitializer() { - WSADATA InitData; - WSAStartup(MAKEWORD(2,2), &InitData); + WSADATA init; + WSAStartup(MAKEWORD(2, 2), &init); } ~SocketInitializer() @@ -95,6 +105,8 @@ struct SocketInitializer } }; -SocketInitializer GlobalInitializer; +SocketInitializer globalInitializer; + +} // namespace priv } // namespace sf diff --git a/Externals/SFML/include/SFML/Network/Win32/SocketHelper.hpp b/Externals/SFML/src/SFML/Network/Win32/SocketImpl.hpp similarity index 58% rename from Externals/SFML/include/SFML/Network/Win32/SocketHelper.hpp rename to Externals/SFML/src/SFML/Network/Win32/SocketImpl.hpp index c02d990a83..04feec4698 100644 --- a/Externals/SFML/include/SFML/Network/Win32/SocketHelper.hpp +++ b/Externals/SFML/src/SFML/Network/Win32/SocketImpl.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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. @@ -22,58 +22,78 @@ // //////////////////////////////////////////////////////////// -#ifndef SFML_SOCKETHELPERWIN32_HPP -#define SFML_SOCKETHELPERWIN32_HPP +#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 #include +#include namespace sf { +namespace priv +{ //////////////////////////////////////////////////////////// -/// This class defines helper functions to do all the -/// non-portable socket stuff. This class is meant for internal -/// use only +/// \brief Helper class implementing all the non-portable +/// socket stuff; this is the Windows version +/// //////////////////////////////////////////////////////////// -class SFML_API SocketHelper +class SocketImpl { public : //////////////////////////////////////////////////////////// - // Define some socket types + // Types //////////////////////////////////////////////////////////// - typedef SOCKET SocketType; - typedef int LengthType; + typedef int AddrLength; //////////////////////////////////////////////////////////// - /// Return the value of the invalid socket + /// \brief Create an internal sockaddr_in address /// - /// \return Unique value of the invalid socket + /// \param address Target address + /// \param port Target port + /// + /// \return sockaddr_in ready to be used by socket functions /// //////////////////////////////////////////////////////////// - static SocketType InvalidSocket(); + static sockaddr_in createAddress(Uint32 address, unsigned short port); //////////////////////////////////////////////////////////// - /// Close / destroy a socket + /// \brief Return the value of the invalid socket /// - /// \param Socket : Socket to close - /// - /// \return True on success + /// \return Special value of the invalid socket /// //////////////////////////////////////////////////////////// - static bool Close(SocketType Socket); + static SocketHandle invalidSocket(); //////////////////////////////////////////////////////////// - /// Set a socket as blocking or non-blocking + /// \brief Close and destroy a socket /// - /// \param Socket : Socket to modify - /// \param Block : New blocking state of the socket + /// \param sock Handle of the socket to close /// //////////////////////////////////////////////////////////// - static void SetBlocking(SocketType Socket, bool Block); + 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 @@ -81,10 +101,12 @@ public : /// \return Status corresponding to the last socket error /// //////////////////////////////////////////////////////////// - static Socket::Status GetErrorStatus(); + static Socket::Status getErrorStatus(); }; +} // namespace priv + } // namespace sf -#endif // SFML_SOCKETHELPERWIN32_HPP +#endif // SFML_SOCKETIMPL_HPP diff --git a/Externals/SFML/src/SFML/System/Err.cpp b/Externals/SFML/src/SFML/System/Err.cpp new file mode 100644 index 0000000000..2c95698edb --- /dev/null +++ b/Externals/SFML/src/SFML/System/Err.cpp @@ -0,0 +1,110 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include + + +namespace +{ +// This class will be used as the default streambuf of sf::Err, +// it outputs to stderr by default (to keep the default behaviour) +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(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(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 diff --git a/Externals/SFML/src/SFML/System/String.cpp b/Externals/SFML/src/SFML/System/String.cpp new file mode 100644 index 0000000000..dc191318ec --- /dev/null +++ b/Externals/SFML/src/SFML/System/String.cpp @@ -0,0 +1,335 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +const std::size_t String::InvalidPos = std::basic_string::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& 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; +} + + +//////////////////////////////////////////////////////////// +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); +} + + +//////////////////////////////////////////////////////////// +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 diff --git a/Externals/SFML/src/SFML/System/Time.cpp b/Externals/SFML/src/SFML/System/Time.cpp new file mode 100644 index 0000000000..69fd78ef1a --- /dev/null +++ b/Externals/SFML/src/SFML/System/Time.cpp @@ -0,0 +1,239 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@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 + + +namespace sf +{ +//////////////////////////////////////////////////////////// +const Time Time::Zero; + + +//////////////////////////////////////////////////////////// +Time::Time() : +m_microseconds(0) +{ +} + + +//////////////////////////////////////////////////////////// +float Time::asSeconds() const +{ + return m_microseconds / 1000000.f; +} + + +//////////////////////////////////////////////////////////// +Int32 Time::asMilliseconds() const +{ + return static_cast(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(amount * 1000000)); +} + + +//////////////////////////////////////////////////////////// +Time milliseconds(Int32 amount) +{ + return Time(static_cast(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; +} + +} // namespace sf diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 52ec66d4b8..536acd73f7 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -238,6 +238,7 @@ set(LIBS inputcommon ${LZO} sfml-network + sfml-system videoogl videosoftware z diff --git a/Source/Core/Core/HW/EXI_DeviceGecko.cpp b/Source/Core/Core/HW/EXI_DeviceGecko.cpp index 365468a6d8..00bf044fc1 100644 --- a/Source/Core/Core/HW/EXI_DeviceGecko.cpp +++ b/Source/Core/Core/HW/EXI_DeviceGecko.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include "Common/StdMakeUnique.h" #include "Core/Core.h" #include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_DeviceGecko.h" @@ -10,8 +11,8 @@ u16 GeckoSockServer::server_port; int GeckoSockServer::client_count; std::thread GeckoSockServer::connectionThread; volatile bool GeckoSockServer::server_running; -std::queue GeckoSockServer::waiting_socks; std::mutex GeckoSockServer::connection_lock; +std::queue> GeckoSockServer::waiting_socks; GeckoSockServer::GeckoSockServer() : client_running(false) @@ -41,11 +42,12 @@ void GeckoSockServer::GeckoConnectionWaiter() { Common::SetCurrentThreadName("Gecko Connection Waiter"); - sf::SocketTCP server; + sf::TcpListener server; server_port = 0xd6ec; // "dolphin gecko" for (int bind_tries = 0; bind_tries <= 10 && !server_running; bind_tries++) { - if (!(server_running = server.Listen(server_port))) + server_running = server.listen(server_port) == sf::Socket::Done; + if (!server_running) server_port++; } @@ -56,22 +58,23 @@ void GeckoSockServer::GeckoConnectionWaiter() StringFromFormat("USBGecko: Listening on TCP port %u", server_port), 5000); - server.SetBlocking(false); + server.setBlocking(false); - sf::SocketTCP new_client; + auto new_client = std::make_unique(); while (server_running) { - if (server.Accept(new_client) == sf::Socket::Done) + if (server.accept(*new_client) == sf::Socket::Done) { std::lock_guard lk(connection_lock); - waiting_socks.push(new_client); + waiting_socks.push(std::move(new_client)); + + new_client = std::make_unique(); } SLEEP(1); } - server.Close(); } -bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) +bool GeckoSockServer::GetAvailableSock() { bool sock_filled = false; @@ -79,7 +82,7 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) if (!waiting_socks.empty()) { - sock_to_fill = waiting_socks.front(); + client = std::move(waiting_socks.front()); if (clientThread.joinable()) { client_running = false; @@ -103,7 +106,7 @@ void GeckoSockServer::ClientThread() Common::SetCurrentThreadName("Gecko Client"); - client.SetBlocking(false); + client->setBlocking(false); while (client_running) { @@ -116,7 +119,7 @@ void GeckoSockServer::ClientThread() char data[128]; std::size_t got = 0; - if (client.Receive(&data[0], ArraySize(data), got) == sf::Socket::Disconnected) + if (client->receive(&data[0], ArraySize(data), got) == sf::Socket::Disconnected) client_running = false; if (got != 0) @@ -133,7 +136,7 @@ void GeckoSockServer::ClientThread() std::vector packet(send_fifo.begin(), send_fifo.end()); send_fifo.clear(); - if (client.Send(&packet[0], packet.size()) == sf::Socket::Disconnected) + if (client->send(&packet[0], packet.size()) == sf::Socket::Disconnected) client_running = false; } } // unlock transfer @@ -142,7 +145,7 @@ void GeckoSockServer::ClientThread() Common::YieldCPU(); } - client.Close(); + client->disconnect(); } void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize) @@ -150,8 +153,8 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize) // We don't really care about _uSize (void)_uSize; - if (!client.IsValid()) - GetAvailableSock(client); + if (!client || client->getLocalPort() == 0) + GetAvailableSock(); switch (_uData >> 28) { diff --git a/Source/Core/Core/HW/EXI_DeviceGecko.h b/Source/Core/Core/HW/EXI_DeviceGecko.h index 1b80b844ed..a0f2caea63 100644 --- a/Source/Core/Core/HW/EXI_DeviceGecko.h +++ b/Source/Core/Core/HW/EXI_DeviceGecko.h @@ -14,15 +14,14 @@ #include "Core/HW/EXI_Device.h" class GeckoSockServer - : public sf::SocketTCP { public: GeckoSockServer(); ~GeckoSockServer(); - bool GetAvailableSock(sf::SocketTCP &sock_to_fill); + bool GetAvailableSock(); // Client for this server object - sf::SocketTCP client; + std::unique_ptr client; void ClientThread(); std::thread clientThread; std::mutex transfer_lock; @@ -40,8 +39,8 @@ private: static u16 server_port; static volatile bool server_running; static std::thread connectionThread; - static std::queue waiting_socks; static std::mutex connection_lock; + static std::queue> waiting_socks; }; class CEXIGecko diff --git a/Source/Core/Core/HW/SI_DeviceGBA.cpp b/Source/Core/Core/HW/SI_DeviceGBA.cpp index 3526a210e6..7baeb0ffad 100644 --- a/Source/Core/Core/HW/SI_DeviceGBA.cpp +++ b/Source/Core/Core/HW/SI_DeviceGBA.cpp @@ -5,6 +5,7 @@ #include #include "Common/CommonFuncs.h" +#include "Common/StdMakeUnique.h" #include "Common/Thread.h" #include "Common/Logging/Log.h" #include "Core/HW/SI_Device.h" @@ -13,7 +14,7 @@ #include "SFML/Network.hpp" static std::thread connectionThread; -static std::queue waiting_socks; +static std::queue> waiting_socks; static std::mutex cs_gba; namespace { volatile bool server_running; } @@ -25,25 +26,25 @@ static void GBAConnectionWaiter() Common::SetCurrentThreadName("GBA Connection Waiter"); - sf::SocketTCP server; + sf::TcpListener server; // "dolphin gba" - if (!server.Listen(0xd6ba)) + if (server.listen(0xd6ba) != sf::Socket::Done) return; - server.SetBlocking(false); + server.setBlocking(false); - sf::SocketTCP new_client; + auto new_client = std::make_unique(); while (server_running) { - if (server.Accept(new_client) == sf::Socket::Done) + if (server.accept(*new_client) == sf::Socket::Done) { std::lock_guard lk(cs_gba); - waiting_socks.push(new_client); + waiting_socks.push(std::move(new_client)); + + new_client = std::make_unique(); } SLEEP(1); } - server.Close(); - return; } void GBAConnectionWaiter_Shutdown() @@ -53,7 +54,7 @@ void GBAConnectionWaiter_Shutdown() connectionThread.join(); } -static bool GetAvailableSock(sf::SocketTCP& sock_to_fill) +static bool GetAvailableSock(std::unique_ptr& sock_to_fill) { bool sock_filled = false; @@ -61,7 +62,7 @@ static bool GetAvailableSock(sf::SocketTCP& sock_to_fill) if (!waiting_socks.empty()) { - sock_to_fill = waiting_socks.front(); + sock_to_fill = std::move(waiting_socks.front()); waiting_socks.pop(); sock_filled = true; } @@ -77,13 +78,12 @@ GBASockServer::GBASockServer() GBASockServer::~GBASockServer() { - client.Close(); } // Blocking, since GBA must always send lower byte of REG_JOYSTAT void GBASockServer::Transfer(char* si_buffer) { - if (!client.IsValid()) + if (!client || client->getLocalPort() == 0) if (!GetAvailableSock(client)) return; @@ -93,9 +93,9 @@ void GBASockServer::Transfer(char* si_buffer) u8 cmd = *current_data; if (cmd == CMD_WRITE) - client.Send(current_data, sizeof(current_data)); + client->send(current_data, sizeof(current_data)); else - client.Send(current_data, 1); + client->send(current_data, 1); DEBUG_LOG(SERIALINTERFACE, "> command %02x %02x%02x%02x%02x", (u8)current_data[0], (u8)current_data[1], (u8)current_data[2], @@ -103,8 +103,8 @@ void GBASockServer::Transfer(char* si_buffer) memset(current_data, 0, sizeof(current_data)); size_t num_received = 0; - if (client.Receive(current_data, sizeof(current_data), num_received) == sf::Socket::Disconnected) - client.Close(); + if (client->receive(current_data, sizeof(current_data), num_received) == sf::Socket::Disconnected) + client->disconnect(); DEBUG_LOG(SERIALINTERFACE, "< %02x%02x%02x%02x%02x", (u8)current_data[0], (u8)current_data[1], (u8)current_data[2], diff --git a/Source/Core/Core/HW/SI_DeviceGBA.h b/Source/Core/Core/HW/SI_DeviceGBA.h index 46a8dc5e9b..1669edd315 100644 --- a/Source/Core/Core/HW/SI_DeviceGBA.h +++ b/Source/Core/Core/HW/SI_DeviceGBA.h @@ -12,7 +12,7 @@ void GBAConnectionWaiter_Shutdown(); -class GBASockServer : public sf::SocketTCP +class GBASockServer { public: GBASockServer(); @@ -29,7 +29,7 @@ private: CMD_WRITE = 0x15 }; - sf::SocketTCP client; + std::unique_ptr client; char current_data[5]; }; diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index 1eb3e88003..92e6c73c5b 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -204,10 +204,10 @@ bool Wiimote::Read() if (SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort > 0 && index == WIIMOTE_BALANCE_BOARD) { - static sf::SocketUDP Socket; - Socket.Send((char*)rpt.data(), + static sf::UdpSocket Socket; + Socket.send((char*)rpt.data(), rpt.size(), - sf::IPAddress::LocalHost, + sf::IpAddress::LocalHost, SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort); } @@ -237,8 +237,8 @@ bool Wiimote::Write() { if (SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort > 0 && index == WIIMOTE_BALANCE_BOARD) { - static sf::SocketUDP Socket; - Socket.Send((char*)rpt.data(), rpt.size(), sf::IPAddress::LocalHost, SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort); + static sf::UdpSocket Socket; + Socket.send((char*)rpt.data(), rpt.size(), sf::IpAddress::LocalHost, SConfig::GetInstance().m_LocalCoreStartupParameter.iBBDumpPort); } IOWrite(rpt.data(), rpt.size()); diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 5fffcd2197..1f664f0ccd 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -43,18 +43,18 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay is_connected = false; - if (m_socket.Connect(port, address, 5) == sf::Socket::Done) + if (m_socket.connect(address, port, sf::seconds(5)) == sf::Socket::Done) { // send connect message sf::Packet spac; spac << NETPLAY_VERSION; spac << netplay_dolphin_ver; spac << name; - m_socket.Send(spac); + m_socket.send(spac); sf::Packet rpac; // TODO: make this not hang - m_socket.Receive(rpac); + m_socket.receive(rpac); MessageId error; rpac >> error; @@ -76,7 +76,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay PanicAlertT("The server sent an unknown error message!"); break; } - m_socket.Close(); + m_socket.disconnect(); } else { @@ -96,7 +96,7 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay //PanicAlertT("Connection successful: assigned player id: %d", m_pid); is_connected = true; - m_selector.Add(m_socket); + m_selector.add(m_socket); m_thread = std::thread(&NetPlayClient::ThreadFunc, this); } } @@ -286,7 +286,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) spac << ping_key; std::lock_guard lks(m_crit.send); - m_socket.Send(spac); + m_socket.send(spac); } break; @@ -319,10 +319,10 @@ void NetPlayClient::ThreadFunc() { while (m_do_loop) { - if (m_selector.Wait(0.01f)) + if (m_selector.wait(sf::milliseconds(10))) { sf::Packet rpac; - switch (m_socket.Receive(rpac)) + switch (m_socket.receive(rpac)) { case sf::Socket::Done : OnData(rpac); @@ -340,7 +340,7 @@ void NetPlayClient::ThreadFunc() } } - m_socket.Close(); + m_socket.disconnect(); return; } @@ -403,7 +403,7 @@ void NetPlayClient::SendChatMessage(const std::string& msg) spac << msg; std::lock_guard lks(m_crit.send); - m_socket.Send(spac); + m_socket.send(spac); } // called from ---CPU--- thread @@ -416,7 +416,7 @@ void NetPlayClient::SendPadState(const PadMapping in_game_pad, const GCPadStatus spac << pad.button << pad.analogA << pad.analogB << pad.stickX << pad.stickY << pad.substickX << pad.substickY << pad.triggerLeft << pad.triggerRight; std::lock_guard lks(m_crit.send); - m_socket.Send(spac); + m_socket.send(spac); } // called from ---CPU--- thread @@ -433,7 +433,7 @@ void NetPlayClient::SendWiimoteState(const PadMapping in_game_pad, const NetWiim } std::lock_guard lks(m_crit.send); - m_socket.Send(spac); + m_socket.send(spac); } // called from ---GUI--- thread @@ -448,7 +448,7 @@ bool NetPlayClient::StartGame(const std::string &path) spac << (char *)&g_NetPlaySettings; std::lock_guard lks(m_crit.send); - m_socket.Send(spac); + m_socket.send(spac); if (m_is_running) { @@ -751,7 +751,7 @@ void NetPlayClient::Stop() { sf::Packet spac; spac << (MessageId)NP_MSG_STOP_GAME; - m_socket.Send(spac); + m_socket.send(spac); } } diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h index 478fa2695e..521b0bb63c 100644 --- a/Source/Core/Core/NetPlayClient.h +++ b/Source/Core/Core/NetPlayClient.h @@ -87,9 +87,9 @@ protected: Common::FifoQueue m_wiimote_buffer[4]; NetPlayUI* m_dialog; - sf::SocketTCP m_socket; + sf::TcpSocket m_socket; std::thread m_thread; - sf::Selector m_selector; + sf::SocketSelector m_selector; std::string m_selected_game; volatile bool m_is_running; diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 1edc6c064d..d484b97f26 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -5,6 +5,7 @@ #include #include +#include "Common/StdMakeUnique.h" #include "Common/StringUtil.h" #include "Core/NetPlayServer.h" #include "InputCommon/GCPadStatus.h" @@ -15,7 +16,7 @@ NetPlayServer::~NetPlayServer() { m_do_loop = false; m_thread.join(); - m_socket.Close(); + m_socket.close(); } #ifdef USE_UPNP @@ -31,11 +32,11 @@ NetPlayServer::NetPlayServer(const u16 port) : is_connected(false), m_is_running { memset(m_pad_map, -1, sizeof(m_pad_map)); memset(m_wiimote_map, -1, sizeof(m_wiimote_map)); - if (m_socket.Listen(port)) + if (m_socket.listen(port) == sf::Socket::Done) { is_connected = true; m_do_loop = true; - m_selector.Add(m_socket); + m_selector.add(m_socket); m_thread = std::thread(&NetPlayServer::ThreadFunc, this); m_target_buffer_size = 5; } @@ -64,17 +65,14 @@ void NetPlayServer::ThreadFunc() m_update_pings = false; } - // check which sockets need attention - const unsigned int num = m_selector.Wait(0.01f); - for (unsigned int i=0; i(); + m_socket.accept(*accept_socket); unsigned int error; { @@ -87,29 +85,34 @@ void NetPlayServer::ThreadFunc() sf::Packet spac; spac << (MessageId)error; // don't need to lock, this client isn't in the client map - accept_socket.Send(spac); - - // TODO: not sure if client gets the message if i close right away - accept_socket.Close(); + accept_socket->send(spac); + accept_socket->disconnect(); } } - // client socket - else + // client sockets + for (auto it = m_players.begin(); it != m_players.end();) { - sf::Packet rpac; - switch (ready_socket.Receive(rpac)) - { - case sf::Socket::Done : - // if a bad packet is received, disconnect the client - if (0 == OnData(rpac, ready_socket)) - break; + // move iterator on immediately so client can be removed + Client& client = *it; + it++; - //case sf::Socket::Disconnected : - default : + if (m_selector.isReady(*client.socket)) + { + sf::Packet rpac; + switch (client.socket->receive(rpac)) { - std::lock_guard lkg(m_crit.game); - OnDisconnect(ready_socket); - break; + case sf::Socket::Done : + // if a bad packet is received, disconnect the client + if (0 == OnData(rpac, client)) + break; + + //case sf::Socket::Disconnected : + default : + { + std::lock_guard lkg(m_crit.game); + OnDisconnect(client); + break; + } } } } @@ -118,15 +121,15 @@ void NetPlayServer::ThreadFunc() // close listening socket and client sockets for (auto& player_entry : m_players) - player_entry.second.socket.Close(); + player_entry.socket->disconnect(); } // called from ---NETPLAY--- thread -unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) +unsigned int NetPlayServer::OnConnect(std::unique_ptr& socket) { sf::Packet rpac; // TODO: make this not hang / check if good packet - socket.Receive(rpac); + socket->receive(rpac); std::string npver; rpac >> npver; @@ -146,7 +149,7 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) m_update_pings = true; Client player; - player.socket = socket; + player.socket = std::move(socket); rpac >> player.revision; rpac >> player.name; @@ -154,7 +157,7 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) PlayerId pid = 1; for (auto i = m_players.begin(); i != m_players.end(); ++i) { - if (i->second.pid == pid) + if (i->pid == pid) { pid++; i = m_players.begin(); @@ -182,57 +185,56 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) SendToClients(spac); // send new client success message with their id - spac.Clear(); + spac.clear(); spac << (MessageId)0; spac << player.pid; - socket.Send(spac); + player.socket->send(spac); // send new client the selected game if (m_selected_game != "") { - spac.Clear(); + spac.clear(); spac << (MessageId)NP_MSG_CHANGE_GAME; spac << m_selected_game; - socket.Send(spac); + player.socket->send(spac); } // send the pad buffer value - spac.Clear(); + spac.clear(); spac << (MessageId)NP_MSG_PAD_BUFFER; spac << (u32)m_target_buffer_size; - socket.Send(spac); + player.socket->send(spac); // sync values with new client for (const auto& p : m_players) { - spac.Clear(); + spac.clear(); spac << (MessageId)NP_MSG_PLAYER_JOIN; - spac << p.second.pid << p.second.name << p.second.revision; - socket.Send(spac); + spac << p.pid << p.name << p.revision; + player.socket->send(spac); } } // unlock send + // add client to selector/ used for receiving + m_selector.add(*player.socket); + // add client to the player list { std::lock_guard lkp(m_crit.players); - m_players[socket] = player; + m_players.push_back(std::move(player)); std::lock_guard lks(m_crit.send); UpdatePadMapping(); // sync pad mappings with everyone UpdateWiimoteMapping(); } - - // add client to selector/ used for receiving - m_selector.Add(socket); - return 0; } // called from ---NETPLAY--- thread -unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) +unsigned int NetPlayServer::OnDisconnect(Client& player) { - PlayerId pid = m_players[socket].pid; + PlayerId pid = player.pid; if (m_is_running) { @@ -258,10 +260,10 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) spac << (MessageId)NP_MSG_PLAYER_LEAVE; spac << pid; - m_selector.Remove(socket); + m_selector.remove(*player.socket); std::lock_guard lkp(m_crit.players); - m_players.erase(m_players.find(socket)); + m_players.remove(player); // alert other players of disconnect std::lock_guard lks(m_crit.send); @@ -359,14 +361,13 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size) } // called from ---NETPLAY--- thread -unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) +unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) { MessageId mid; packet >> mid; // don't need lock because this is the only thread that modifies the players // only need locks for writes to m_players in this thread - Client& player = m_players[socket]; switch (mid) { @@ -568,12 +569,11 @@ bool NetPlayServer::StartGame() // called from multiple threads void NetPlayServer::SendToClients(sf::Packet& packet, const PlayerId skip_pid) { - for (std::pair& p : m_players) + for (auto& p : m_players) { - if (p.second.pid && - p.second.pid != skip_pid) + if (p.pid && p.pid != skip_pid) { - p.second.socket.Send(packet); + p.socket->send(packet); } } } @@ -582,9 +582,9 @@ void NetPlayServer::KickPlayer(u8 player) { for (auto& current_player : m_players) { - if (current_player.second.pid == player) + if (current_player.pid == player) { - current_player.second.socket.Close(); + current_player.socket->disconnect(); return; } } @@ -613,7 +613,7 @@ void NetPlayServer::TryPortmapping(u16 port) // UPnP thread: try to map a port void NetPlayServer::mapPortThread(const u16 port) { - std::string ourIP = sf::IPAddress::GetLocalAddress().ToString(); + std::string ourIP = sf::IpAddress::getLocalAddress().toString(); if (!m_upnp_inited) if (!initUPnP()) diff --git a/Source/Core/Core/NetPlayServer.h b/Source/Core/Core/NetPlayServer.h index 09c9e33f6b..9f51f760eb 100644 --- a/Source/Core/Core/NetPlayServer.h +++ b/Source/Core/Core/NetPlayServer.h @@ -56,15 +56,30 @@ private: std::string name; std::string revision; - sf::SocketTCP socket; + std::unique_ptr socket; u32 ping; u32 current_game; + + // VS2013 does not generate the right constructors here automatically + // like GCC does, so we implement them manually + Client() = default; + Client(const Client& other) = delete; + Client(Client&& other) + : pid(other.pid), name(std::move(other.name)), revision(std::move(other.revision)), + socket(std::move(other.socket)), ping(other.ping), current_game(other.current_game) + { + } + + bool operator==(const Client& other) const + { + return this == &other; + } }; void SendToClients(sf::Packet& packet, const PlayerId skip_pid = 0); - unsigned int OnConnect(sf::SocketTCP& socket); - unsigned int OnDisconnect(sf::SocketTCP& socket); - unsigned int OnData(sf::Packet& packet, sf::SocketTCP& socket); + unsigned int OnConnect(std::unique_ptr& socket); + unsigned int OnDisconnect(Client& player); + unsigned int OnData(sf::Packet& packet, Client& player); void UpdatePadMapping(); void UpdateWiimoteMapping(); @@ -80,7 +95,7 @@ private: PadMapping m_pad_map[4]; PadMapping m_wiimote_map[4]; - std::map m_players; + std::list m_players; struct { @@ -91,9 +106,9 @@ private: std::string m_selected_game; - sf::SocketTCP m_socket; + sf::TcpListener m_socket; std::thread m_thread; - sf::Selector m_selector; + sf::SocketSelector m_selector; #ifdef USE_UPNP static void mapPortThread(const u16 port); diff --git a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp index 30e722af1d..097f22ea56 100644 --- a/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp @@ -172,20 +172,20 @@ void CodeConfigPanel::DownloadCodes(wxCommandEvent&) } sf::Http::Request req; - req.SetURI("/txt.php?txt=" + gameid); + req.setUri("/txt.php?txt=" + gameid); sf::Http http; - http.SetHost("geckocodes.org"); + http.setHost("geckocodes.org"); - const sf::Http::Response resp = http.SendRequest(req, 5.0f); + const sf::Http::Response resp = http.sendRequest(req, sf::seconds(5)); - if (sf::Http::Response::Ok == resp.GetStatus()) + if (sf::Http::Response::Ok == resp.getStatus()) { // temp vector containing parsed codes std::vector gcodes; // parse the codes - std::istringstream ss(resp.GetBody()); + std::istringstream ss(resp.getBody()); std::string line; diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 3fe3bbcba1..4a361b0cb7 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -50,6 +50,7 @@ _CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) USE_UPNP;%(PreprocessorDefinitions) PSAPI_VERSION=1;_M_X86=1;%(PreprocessorDefinitions) + SFML_STATIC;%(PreprocessorDefinitions) _ARCH_64=1;_M_X86_64=1;%(PreprocessorDefinitions) Level3 true