Compare commits

...

343 commits
2503 ... master

Author SHA1 Message Date
Tilka
8ee64a84c7
Merge pull request #13590 from tygyh/UCodes-Remove-redundant-qualifiers
UCodes: Remove redundant qualifiers
2025-04-26 16:23:27 +01:00
JosJuice
741ffc3114
Merge pull request #13514 from LillyJadeKatrin/retroachievements-failed-load-bug
Call AchievementManager CloseGame on load failures
2025-04-26 10:36:09 +02:00
JosJuice
3e5286c1a4
Merge pull request #13593 from Dentomologist/mainwindow_fix_use_after_free_during_dolphin_shutdown
MainWindow: Fix use-after-free during Dolphin shutdown
2025-04-26 09:06:06 +02:00
Dentomologist
3a883f28d6 Config: Add [[nodiscard]] to AddConfigChangedCallback
Require callers of Config::AddConfigChangedCallback and
CPUThreadConfigCallback::AddConfigChangedCallback to handle the returned
ConfigChangedCallbackIDs to hopefully prevent future issues with
callbacks getting called after their associated objects have been
destroyed.
2025-04-25 16:04:12 -07:00
Dentomologist
45b9def42c VideoConfig: Remove ConfigChangedCallback on shutdown 2025-04-25 16:00:43 -07:00
Dentomologist
d0dc8ae5e1 FreeLook: Remove ConfigChangedCallback on shutdown 2025-04-25 16:00:43 -07:00
Dentomologist
9db4067957 UICommon: Merge ConfigChangedCallbacks
Use a single lambda as a callback which calls InitCustomPaths and
RefreshConfig instead of having separate callbacks for each of them.

This fixes the callback for InitCustomPaths not being removed on
shutdown; the callback for the lambda (previously for RefreshConfig) is
already removed in Shutdown().
2025-04-25 16:00:43 -07:00
Dentomologist
8724daf44e Settings: Remove ConfigChangedCallback on shutdown 2025-04-25 16:00:19 -07:00
Dentomologist
9c40a7976b AchievementManager: Remove ConfigChangedCallback on shutdown
Prevent SetHardcoreMode from being called after m_client is set to
nullptr. rc_client_set_hardcore_enabled() checks for nullptr so this
didn't cause any problems, but better not to rely on that.

Also prevents multiple SetHardcoreMode callbacks from piling up when
repeatedly toggling Config::RA_ENABLED.
2025-04-25 15:29:29 -07:00
Dentomologist
e37a195192 MainWindow: Fix use-after-free during shutdown
Remove ConfigChangedCallback in MainWindow's destructor to prevent the
callback from accessing the destroyed MainWindow afterward.

After MainWindow is destroyed UICommon::Shutdown calls
LogManager::Shutdown which ultimately triggers any remaining callbacks.
This resulted in calling MainWindow::OnHardcoreChanged, which crashed in
debug builds and didn't have any obvious effect in release builds.
2025-04-25 15:29:29 -07:00
Dr. Dystopia
9868138c22 UCodes: Remove redundant qualifiers 2025-04-25 13:18:56 +02:00
Tilka
805307f432
Merge pull request #13451 from vyuuui/numeric_labels
Add numeric label support to assembler
2025-04-25 01:56:43 +01:00
Tilka
fe307a06c6
Merge pull request #13476 from jordan-woyak/sdl-header
InputCommon: Move SDL Device class into its own cpp/h files.
2025-04-25 01:49:52 +01:00
Tilka
a95779add0
Merge pull request #13506 from JosJuice/android-time-played
Android: Show time played in game details
2025-04-25 01:43:53 +01:00
Tilka
5523b9a01b
Merge pull request #13487 from Dentomologist/performancemetrics_fix_window_arrangement
PerformanceMetrics: Fix window arrangement
2025-04-25 01:40:58 +01:00
Tilka
50026ab795
Merge pull request #13497 from hoogmin/modernize_fs_path
Core/Common/FileUtil.cpp: Use std path utility for automatic path separator handling.
2025-04-25 01:38:35 +01:00
JosJuice
908094714b Translation resources sync with Transifex 2025-04-24 23:38:09 +02:00
JMC47
8fa725d5e4
Merge pull request #13573 from tygyh/DolphinTool-Make-parameter-constant
DolphinTool: Make parameter constant
2025-04-24 00:49:10 -04:00
JMC47
fc0aafca3b
Merge pull request #13577 from tygyh/UCodes-Make-functions-static
UCodes: Make functions static
2025-04-24 00:48:46 -04:00
JMC47
f675048768
Merge pull request #13578 from tygyh/Core/HW-Remove-redundant-empty-lambda-parameter-lists
Core/HW: Remove redundant empty lambda parameter lists
2025-04-24 00:48:28 -04:00
Jordan Woyak
1cea31c75a
Merge pull request #13580 from LillyJadeKatrin/retroachievements-de-bug-debug
Fix debugger disabled bug
2025-04-23 23:28:19 -05:00
Jordan Woyak
3025cd472c
Merge pull request #13491 from JosJuice/oh0-removed-opened
IOS: Remove from m_opened_devices in OH0::OnDeviceChange
2025-04-23 23:25:34 -05:00
LillyJadeKatrin
022bc3bf8d Fix debugger disabled bug
Fixing an oversight: this was causing the debugger to be disabled if achievements were disabled but hardcore mode was still enabled in the .ini. This fix properly checks for hardcore state via AchievementManager which takes both settings into account.
2025-04-23 22:57:35 -04:00
Admiral H. Curtiss
879a8889aa
Merge pull request #13431 from jordan-woyak/spsc-waiting
Common: SPSCQueue cleanups and improvements.
2025-04-23 22:19:15 +02:00
Dr. Dystopia
564e7c3320 UCodes: Make functions static 2025-04-23 21:36:13 +02:00
Dr. Dystopia
467a568f60 Core/HW: Remove redundant empty lambda parameter lists 2025-04-23 21:32:09 +02:00
Jordan Woyak
6c751fb722
Merge pull request #13570 from SuperSamus/advanced-panel-unused
DolphinQt: Remove unused variables from `AdvancedPane.h`
2025-04-23 13:30:39 -05:00
JosJuice
bda1f379b7 IOS: Remove from m_opened_devices in OH0::OnDeviceChange
I've been playing Rock Band 3 recently and have experienced a bug where
sometimes if you disconnect and reconnect a USB microphone, the game
won't pick up on it connecting, not even it you disconnect and reconnect
it again. An investigation into what's going on inside Dolphin shows
that when the game triggers a call to OH0::DeviceOpen after the device
has been reinserted, Dolphin doesn't open the device because it's
already present in m_opened_devices.

Removing the device from m_opened_devices after calling OH0::TriggerHook
in OH0::OnDeviceChange resolves this specific issue in my testing. Doing
this matches us removing the device from m_opened_devices after calling
OH0::TriggerHook in OH0::DeviceClose, but I haven't looked at exactly
what real IOS does.

I have been able to reproduce a much rarer issue that has the same
symptoms on the surface but where OH0::DeviceOpen gets past its
m_opened_devices check. I'm currently not sure what the cause of this
remaining issue is.
2025-04-23 17:19:14 +02:00
JosJuice
c44418a4d9
Merge pull request #13561 from JosJuice/android-renumbered-platforms
Android: Update platform enum values
2025-04-23 17:08:50 +02:00
Dr. Dystopia
fe657b9759 DolphinTool: Make parameter constant 2025-04-23 15:55:48 +02:00
Martino Fontana
e751235574 DolphinQt: Remove unused variables from AdvancedPane.h
Small oversight from #13422.
2025-04-23 12:32:12 +02:00
JMC47
8f3483fdd4
Merge pull request #13565 from LillyJadeKatrin/retroachievements-end-of-memory-bug
Fix memory bounds error in achievements dev
2025-04-23 01:01:47 -04:00
Jordan Woyak
af960651e8 Common: SPSCQueue cleanups and improvements. 2025-04-22 23:49:32 -05:00
OatmealDome
d04e9e79a6
Merge pull request #13566 from OatmealDome/macos-11-fix
BuildMacOSUniversalBinary: Explicitly specify CMAKE_OSX_DEPLOYMENT_TARGET in CMake flags
2025-04-23 00:46:58 -04:00
OatmealDome
968b0cff44 BuildMacOSUniversalBinary: Explicitly specify CMAKE_OSX_DEPLOYMENT_TARGET in CMake flags
If the build folder is created from an older commit and this flag is not set, the last value set for this flag will be used instead.
This is currently happening on our macOS build machine, causing macOS 10.15 to still be used as the deployment target.
2025-04-22 23:40:37 -04:00
Jordan Woyak
116bd3a031
Merge pull request #13382 from JoshuaVandaele/btadapterchoice
Add a GUI option to select a bluetooth device
2025-04-22 22:05:30 -05:00
LillyJadeKatrin
8b610101bc Fix memory bounds error in achievements dev
This particular out of bounds error was causing every memory read at the far end of memory to return all zeroes.
2025-04-22 22:49:55 -04:00
Tilka
c4f65febf3
Merge pull request #13563 from Tilka/rcheevos
Fix building with USE_RETRO_ACHIEVEMENTS=OFF
2025-04-23 03:27:15 +01:00
Tilka
871073eee2
Merge pull request #13564 from jordan-woyak/triforce_ipl-warning
Core/Boot: Fix unused variable warning.
2025-04-23 03:26:48 +01:00
Jordan Woyak
31a3de819d
Merge pull request #13540 from tygyh/DiscIO-Remove-redundant-qualifiers
DiscIO: Remove redundant qualifiers
2025-04-22 20:00:03 -05:00
Jordan Woyak
0fd090ce19
Merge pull request #13550 from Tilka/top_warnings
IOS/Network: fix some warnings
2025-04-22 19:45:47 -05:00
Joshua Vandaële
4773a6f323
Add a GUI option to select a bluetooth device 2025-04-23 02:19:28 +02:00
JMC47
826625c7be
Merge pull request #13422 from jordan-woyak/adv-tooltips
DolphinQt: Use tooltips on Advanced tab.
2025-04-22 19:27:21 -04:00
Jordan Woyak
00544e4dff Core/Boot: Fix unused variable warning. 2025-04-22 18:19:32 -05:00
Tillmann Karras
609165b62b Fix building with USE_RETRO_ACHIEVEMENTS=OFF 2025-04-22 23:45:40 +01:00
Tillmann Karras
f6d3f448d9 IOS/Network: fix -Wmissing-braces warnings 2025-04-22 23:36:01 +01:00
Jordan Woyak
ac76deaef0
Merge pull request #13529 from jordan-woyak/StateBuffer
Core/State: Avoid unnecessarily value-initializing large buffers.
2025-04-22 16:30:51 -05:00
OatmealDome
da84a9f605
Merge pull request #13477 from OatmealDome/macos-11
CMakeLists: Bump minimum macOS to 11.0
2025-04-22 17:27:12 -04:00
Jordan Woyak
afee9a56e9
Merge pull request #13474 from JosJuice/rock-band-playstation
IOS: Disguise Rock Band PlayStation USB devices as Wii equivalents
2025-04-22 16:02:16 -05:00
Jordan Woyak
9254a53397
Merge pull request #13490 from JosJuice/one-usb-scanner
IOS: Only have one USB scanning thread
2025-04-22 16:01:18 -05:00
JosJuice
25fdde4204 Android: Update platform enum values
71f654c added a new platform in the middle of the C++ platform enum
without updating the corresponding Android code, making the Android code
incorrectly treat Wii discs as WAD files, WAD files as DOL/ELF files,
and so on. This commit fixes the problem.

To be able to add the new Triforce entry into the Platform enum without
it leading to the UI getting an additional tab, I'm splitting the enum
into Platform and PlatformTab. Platform now exactly matches the C++
enum (previously it excluded ELFOrDOL), and PlatformTab has the same
content as the old Platform.
2025-04-22 20:07:15 +02:00
JMC47
fd8ce3ce80
Merge pull request #13555 from jordan-woyak/cubeb-default
AudioCommon: Make cubeb sound backend default on Linux.
2025-04-22 12:07:43 -04:00
JosJuice
12010ebf78
Merge pull request #13557 from LillyJadeKatrin/pause-bugfix
AchievementManager: Always allow pausing if game not loaded
2025-04-22 17:55:23 +02:00
Dr. Dystopia
ecafd8058f DiscIO: Remove redundant qualifiers 2025-04-22 13:54:10 +02:00
Jordan Woyak
89873d6238
Merge pull request #13472 from tygyh/Use-values-function
Core/NetPlayServer: Use std::views::values and std::views::keys functions
2025-04-22 02:25:46 -05:00
LillyJadeKatrin
d670c21c8e Always allow pausing if game not loaded
RetroAchievements disables pausing too frequently when running but there's no sense of doing this if RetroAchievements does not currently have a game running.
2025-04-21 22:38:09 -04:00
JMC47
0f30b59aef
Merge pull request #13556 from jordan-woyak/dvd-interface-crash-fix
DVDInterface: Fix crash when playing wiiware.
2025-04-21 22:15:12 -04:00
Jordan Woyak
1e8b668793 DVDInterface: Fix crash when playing wiiware. 2025-04-21 18:38:33 -05:00
Jordan Woyak
1fc6be7f80 AudioCommon: Make cubeb sound backend default on Linux. 2025-04-21 16:25:40 -05:00
OatmealDome
de2826d995 Merge branch 'release-prep-2503a' 2025-04-21 17:03:52 -04:00
JosJuice
e468e2359a IOS: Only have one USBScanner
Some games open two USB interfaces, e.g. /dev/usb/oh0 and /dev/usb/hid.
This was causing us to run two scanning threads at once, using up more
CPU time for scanning than we need to.
2025-04-21 21:57:49 +02:00
LillyJadeKatrin
8f12512d0d Call AchievementManager CloseGame on load failures
We have identified that a failed RetroAchievements game load (most easily done when closing a game before the server can finish responding) can leave data behind that causes problems. As such, refactored CloseGame to always delete data even if there wasn't a game loaded when it was called, and call it on the failure paths of LoadGameCallback.
2025-04-21 15:53:31 -04:00
JosJuice
920a44aec2 IOS: Diff device lists in USBHost instead of USBScanner
Instead of having USBScanner create "hooks" as it scans for devices,
let's have USBScanner present a list of devices to USBHost and have
USBHost diff the new device list with its old device list to create the
hook calls instead. This gets rid of some complex edge cases that the
next commit otherwise would have to deal with, in particular regarding
toggling determinism and adding new USBHosts to a USBScanner.
2025-04-21 21:25:36 +02:00
JosJuice
24fdcc1a0e IOS: Add missing locking for USBHost::m_devices
Note: After adding the missing locking of m_devices_mutex, I had to move
the locking of m_hooks_mutex to avoid a random deadlock between the CPU
thread and USB scanning thread. (Either that or I would have to lock
m_devices_mutex before m_hooks_mutex.)
2025-04-21 21:25:35 +02:00
JosJuice
50a8ae9d90 IOS: Keep copy of m_devices in USBHost
This gets rid of the ugly direct access to USBScanner::m_devices that
was introduced by the previous commit.

This also fixes a potential thread safety issue.
USB_HIDv4::TriggerDeviceChangeReply loops through m_devices and calls
GetDeviceEntry for each device. If USB_HIDv4::TriggerDeviceChangeReply
is called after a new device is added to m_devices but before hooks are
dispatched, GetDeviceEntry crashes, because the hook that's supposed to
update m_device_ids hasn't run yet. With this commit, this issue can no
longer happen, because USBHost::m_devices_mutex doesn't get unlocked in
between updating m_devices and dispatching the hooks.
2025-04-21 21:25:35 +02:00
JosJuice
427e9c5ad2 IOS: Move USB scanning thread to new class USBScanner 2025-04-21 21:25:35 +02:00
JosJuice
c0c180bdc2
Merge pull request #13467 from JosJuice/profiler-thread-safety
Common: Make Profiler thread safe
2025-04-21 20:19:47 +02:00
JMC47
258fc1b209
Merge pull request #12949 from LillyJadeKatrin/retroachievements-new-dev-branch
RetroAchievements - Dev Branch Refactor
2025-04-21 14:08:40 -04:00
JMC47
0b2338a5ee
Merge pull request #10084 from Zopolis4/master
Identify Triforce games in gamelist
2025-04-21 13:57:57 -04:00
Zopolis4
89fdc0b9e0
Fix Triforce GameINIs 2025-04-21 22:05:26 +10:00
Zopolis4
2238967d93
Add Triforce IPL hash 2025-04-21 22:05:25 +10:00
Zopolis4
660232a12c
Preliminary implementation of the Triforce Baseboard 2025-04-21 22:05:25 +10:00
Zopolis4
2baa09d5b4
Implement endian swapping and lazy decryption of Triforce DI commands 2025-04-21 22:05:25 +10:00
Zopolis4
8d94d25203
Implement Triforce ID parsing 2025-04-21 22:05:25 +10:00
Zopolis4
71f654cdc4
Add Triforce platform and preliminary boot.id parsing 2025-04-21 22:05:25 +10:00
Zopolis4
494e2c05c2
Adding support for detecting .bin images 2025-04-21 22:05:24 +10:00
OatmealDome
0827d9f06d MemArenaDarwin: Initialize all address variables passed to vm_map 2025-04-21 00:40:01 -04:00
Jordan Woyak
0109c27ad7 SI: Fix GBA link by having a separate response for "error" and "no data". 2025-04-21 00:39:07 -04:00
OatmealDome
e40c9b674c ScmRevGen: Bump version to 2503a 2025-04-21 00:38:22 -04:00
OatmealDome
ec9fb08dab MTLUtil: Remove availability check for iOS 13
My personal fork requires minimum iOS 14, so this is not required.
2025-04-21 00:24:58 -04:00
OatmealDome
65f42ee2d2 MTLUtil: Always use MSL 2.3
The minimum macOS (and minimum iOS on my personal fork) are enough to allow MSL 2.3 usage without availability checks.
2025-04-21 00:24:58 -04:00
OatmealDome
53b66be47d MTLUtil: Remove availability checks for macOS 10.15 and iOS 13 2025-04-21 00:24:58 -04:00
OatmealDome
0bc33fb6df MTLUtil: Remove availability check for macOS 10.15 2025-04-21 00:24:58 -04:00
OatmealDome
dc8865718e MTLUtil: Remove availability check for macOS 11 2025-04-21 00:24:58 -04:00
OatmealDome
7213cdd439 MemoryUtil: Remove availability checks for macOS 11 2025-04-21 00:24:58 -04:00
OatmealDome
ad79a62d22 README: Update minimum macOS version to 11.0 2025-04-21 00:24:57 -04:00
OatmealDome
82ee77e4e1 BuildMacOSUniversalBinary: Remove architecture-specific macOS deployment target flags
I can't see any situation in the foreseeable future where we need to target different macOS versions for each architecture.
2025-04-21 00:24:57 -04:00
OatmealDome
39e535d4aa CMakeLists: Bump minimum macOS to 11.0 2025-04-21 00:24:57 -04:00
OatmealDome
bc3c3eb79a
Merge pull request #13524 from jordan-woyak/fix-gba-link
SI: Fix GBA link by having a separate response for "error" and "no data".
2025-04-20 22:29:38 -04:00
JMC47
41408076e3
Merge pull request #13520 from shuffle2/android-start
Prevent android generating duplicate analytics events
2025-04-20 20:17:30 -04:00
Tilka
7e7b75c1e6
Merge pull request #13537 from tygyh/DiscIO-Make-variables-constexpr
DiscIO: Make variables constexpr
2025-04-21 00:52:18 +01:00
Tilka
9504916f72
Merge pull request #13538 from tygyh/DiscIO-Use-default-to-define-a-trivial-destructor
DiscIO: Use `= default` to define a trivial destructor
2025-04-20 22:32:12 +01:00
Tilka
0a52140145
Merge pull request #13549 from shuffle2/ucrtpatch
remove ucrt compat patches
2025-04-20 22:24:57 +01:00
Tilka
45ed4b2be9
Merge pull request #13541 from tygyh/DiscIO-Remove-redundant-zero-initializers-in-aggregate-initializations
DiscIO: Remove redundant zero initializers in aggregate initializations
2025-04-20 22:07:58 +01:00
Tilka
2adf3449f3
Merge pull request #13548 from shuffle2/http
HttpRequest: remove some legacy code for windows < 8.1
2025-04-20 22:07:32 +01:00
Jordan Woyak
8d7d026da6
Merge pull request #13533 from tygyh/DiscIO-Make-classes-final
DiscIO: Make classes final
2025-04-20 16:06:07 -05:00
Shawn Hoffman
2d1161150b remove ucrt compat patches
Dolphin has not supported a version of windows where
these binaries exist for a while.
2025-04-20 12:50:10 -07:00
Shawn Hoffman
5dd896a7d9 HttpRequest: remove some legacy code for windows < 8.1 2025-04-20 11:46:09 -07:00
Shawn Hoffman
a1691a4031 Prevent android generating duplicate analytics events
dolphin-start event was being generated twice for the normal
end-user case, as can be seen in analytics data for some years.
The problem occured when:
* Android reaped the process hosting the dolphin activity
  (e.g. for power/memory saving).
and
* Dolphin activity was in "stopped" state for > 6 hours before
  being switched back to.

Under above conditions, both calls to ReportStartToAnalytics
would be performed, as dolphin thought it was being launched anew,
and also thought it had been asleep for > 6 hours.

fixes https://bugs.dolphin-emu.org/issues/13675
2025-04-19 22:16:01 -07:00
Jordan Woyak
ac3dbe2294 Core/State: Use UniqueBuffer instead of make_unique and std::vector for save state buffers. 2025-04-19 17:29:56 -05:00
Jordan Woyak
12dcd6c285 Common: Add UniqueBuffer and SharedBuffer templates. 2025-04-19 17:13:40 -05:00
Jordan Woyak
f78fa2e9f1 LinearDiskCache: Use make_unique_for_overwrite. 2025-04-19 17:13:40 -05:00
Dr. Dystopia
77b4270981 DiscIO: Remove redundant zero initializers in aggregate initializations 2025-04-19 22:04:50 +02:00
Dr. Dystopia
7123fcd19b DiscIO: Use = default to define a trivial destructor 2025-04-19 17:43:18 +02:00
Dr. Dystopia
f6ba69f99a DiscIO: Make variables constexpr 2025-04-19 17:17:02 +02:00
JosJuice
1ae0b23265
Merge pull request #13528 from jordan-woyak/win-cmake-fix
Common/Timer: Change HANDLE to void* to avoid including Windows.h to fix cmake build.
2025-04-19 16:41:51 +02:00
JosJuice
b8e70df413 Android: Show time played in game details
Unlike in DolphinQt, there isn't much space to show playtimes directly in
the game list, so I've put it in the game details dialog instead.
2025-04-19 14:34:49 +02:00
JosJuice
3eee52cb6b Android: Create toggle for enabling/disabling time tracking 2025-04-19 14:29:49 +02:00
JosJuice
49ebdaaae3
Merge pull request #13507 from JosJuice/time-played-game-id
Core: Don't store game ID inside TimePlayed
2025-04-19 14:28:02 +02:00
Jordan Woyak
fda8afaf5c SI: Fix GBA link by having a separate response for "error" and "no data". 2025-04-19 03:28:57 -05:00
Dr. Dystopia
301cc5ee63 DiscIO: Make classes final 2025-04-19 09:05:22 +02:00
Jordan Woyak
cb20959679 Common/Timer: Change HANDLE to void* to avoid including Windows.h to fix cmake build. 2025-04-18 21:50:15 -05:00
Jordan Woyak
056b0339be
Merge pull request #13496 from TryTwo/PR_GameSettings_Fix
Game config settings: Show global value when no game setting exists.
2025-04-18 15:56:59 -05:00
LillyJadeKatrin
c55624702c Allow RA Dev Tools for Unidentified Games
Due to requests from RA Devs, updating the AchievementManager LoadGameCallback to still set MemoryPeeker (and set m_system) if the load game response is NO_GAME_LOADED, so that the memory inspector et al continue function properly on unidentified hashes. Without this, no memory is loaded and the memory inspector will show all zeroes.
2025-04-16 23:59:16 -04:00
LillyJadeKatrin
a96c935c1c Added modified achievements confirmation
Added a line to the close game confirmation dialog to tell the dev if there are unsaved modifications to the achievement assets.
2025-04-16 17:01:22 -04:00
LillyJadeKatrin
b9a93794ff Added game title estimate for achievement development
If the development system is started for a game with an unrecognized hash, RA_Integration opens a dialog for connecting the hash with a title. That dialog is prepopulated by the results of GameTitleEstimateHandler.
2025-04-16 17:01:22 -04:00
LillyJadeKatrin
ef612912a2 Handle local achievements
Displays an additional message when an achievement unlocks that isn't on the site yet (either hasn't yet been uploaded or modified from remote) i.e. achievements the "player" is actively developing.
2025-04-16 17:01:21 -04:00
LillyJadeKatrin
fa782de15c Add MemoryPoker for RAIntegration 2025-04-16 17:00:58 -04:00
Jordan Woyak
f8bf35e6f0
Merge pull request #13518 from tygyh/Fix-Partition-struct-comparison-operators
DiscIO/Volume: Fix Partition struct comparison operators
2025-04-16 00:20:28 -05:00
Jordan Woyak
8bfde300f4
Merge pull request #13519 from tygyh/Replace-definitions-with-constant-expressions
Replace definitions with constant expressions - Core/HW/EXI/BBA/TAP_Win32
2025-04-16 00:19:40 -05:00
Jordan Woyak
5af315ec17
Merge pull request #13521 from OatmealDome/darwin-memarena-ub
MemArenaDarwin: Initialize all address variables passed to vm_map
2025-04-16 00:12:50 -05:00
OatmealDome
2af276d27e MemArenaDarwin: Initialize all address variables passed to vm_map 2025-04-16 00:50:54 -04:00
Dr. Dystopia
c4f906bcd9 Replace definitions with constant expressions - Core/HW/EXI/BBA/TAP_Win32 2025-04-15 12:26:16 +02:00
Dr. Dystopia
3bb925c1c7 DiscIO/Volume: Fix Partition struct comparison operators 2025-04-15 12:18:23 +02:00
LillyJadeKatrin
90a4be4b36 Add RAIntegration event handler
Some refactoring done to hardcore toggling so that it's more readily available for the toggle hardcore event.
2025-04-13 13:36:15 -04:00
LillyJadeKatrin
9caa02493d Add RetroAchievements development menu
When the menu exists, it replaces the Achievements action in the Tools menu.
2025-04-13 08:06:00 -04:00
LillyJadeKatrin
36c7e7f3c7 Load RA_Integration.DLL at init if present 2025-04-13 08:05:59 -04:00
LillyJadeKatrin
cab5bc5680 Update rcheevos submodule to newest master 2025-04-13 08:05:59 -04:00
LillyJadeKatrin
6ad267017c Refactor AchievementBox to const pointer
Not sure when or why this became necessary but it works.
2025-04-13 08:05:59 -04:00
JosJuice
4f210df86a
Merge pull request #13489 from AdmiralCurtiss/translate-audio-backend
DolphinQt/AudioPane: Fix Audio backend dropdown not using translated names
2025-04-12 17:59:42 +02:00
JMC47
bcddd78a89
Merge pull request #13500 from jordan-woyak/accel-gyro-any-mapping
InputCommon: Activate IMU Accelerometer and Gyroscope mappings when any direction has a bound input.
2025-04-12 11:47:38 -04:00
JosJuice
d194e69bbd Core: Don't store game ID inside TimePlayed
When you use TimePlayed, you have to provide a game ID either when
creating the object or when calling GetTimePlayed on it. If you don't
provide a game ID when creating the object, function calls that don't
take a game ID will silently fail, except for Reload. This isn't very
obvious, and there's no strong benefit to storing the game ID inside
TimePlayed anyway (it just lets TimePlayed skip calling EscapeFileName),
so this commit removes the TimePlayed constructor that takes a game ID
and instead makes the functions that need game IDs always take a game ID
argument.
2025-04-12 15:20:49 +02:00
JMC47
5285b1168a
Merge pull request #13503 from sepalani/ip-top-perf
IP/Top: Fix performance regression in GetInterfaceOpt
2025-04-11 18:56:35 -04:00
Sepalani
03451f2bc9 IP/Top: Fix performance regression in GetInterfaceOpt 2025-04-12 01:38:00 +04:00
Jordan Woyak
87beb7d67b InputCommon: Activate IMU Accelerometer and Gyroscope when any direction has a bound input. 2025-04-10 15:55:49 -05:00
JMC47
fc0179c1ea
Merge pull request #13498 from jordan-woyak/immxfb-dualcore-todo
BPStructs: Add TODO for unsafe usage of GetTicks.
2025-04-09 23:20:35 -04:00
Jordan Woyak
4aa056dd4d BPStructs: Add TODO for unsafe usage of GetTicks. 2025-04-08 19:58:31 -05:00
Javier Martinez
7ca8dc3767 Use std path utility for automatic path seperator handling.
It was being done manually, which a TODO comment advised against.
Using generic_string() from std::filesystem::path solves this.

Fix encoding issue using generic_wstring instead.
2025-04-08 16:54:11 -04:00
JMC47
01363572cb
Merge pull request #13483 from Sam-Belliveau/fixed_playback_speed
Use Doubles for Sample Rate Conversion
2025-04-08 13:45:12 -04:00
TryTwo
91380258a1 GameConfig Settings: If no game setting exists for a certain option, then show the global setting value. Previously showed the default value if the game setting didn't exist. 2025-04-07 20:41:46 -07:00
JMC47
ee27f03a43
Merge pull request #13439 from jordan-woyak/perf-marker
Core: Move CountPerformanceMarker to VideoInterface to eliminate a Throttle call. PerformanceMetrics: Fixes/Cleanups.
2025-04-07 17:57:56 -04:00
Admiral H. Curtiss
b306d00d5d
DolphinQt/AudioPane: Fix Audio backend dropdown not using translated names 2025-04-06 05:09:23 +02:00
JMC47
f59507c856
Merge pull request #13488 from TryTwo/PR_MonsterHT_ini_bloom
Game setting fix: Monster Hunter Tri bloom
2025-04-05 21:38:11 -04:00
TryTwo
69bdb0535c Gamesetting fix: Monster Hunter Tri. set EFBAccessEnable = True to fix over-bloom issues.
Was broken due to the default for this setting being switched.
2025-04-05 17:40:32 -07:00
Dentomologist
ec49ea5be3 PerformanceMetrics: Fix window arrangement
Fix overlays stacking on top of each other or not moving to the edge of
the screen when enabling or disabling overlays while emulation is
active.

This change only applies when Config::GFX_MOVABLE_PERFORMANCE_METRICS is
False.
2025-04-05 14:22:17 -07:00
Sam Belliveau
74e752ed9c Mixer: Use Doubles for Sample Rate Conversion. 2025-04-05 13:46:37 -05:00
JosJuice
2d1671a863
Merge pull request #13485 from jordan-woyak/timer-dualcore-fix
CoreTiming: Fix Precision Frame Timing in Dual Core mode on Windows.
2025-04-05 08:52:32 +02:00
Jordan Woyak
06afa0036a CoreTiming: Fix Precision Frame Timing in Dual Core mode on Windows. 2025-04-04 19:13:53 -05:00
JosJuice
edb1db7400 Translation resources sync with Transifex 2025-04-04 21:45:46 +02:00
JMC47
bee7035322
Merge pull request #13426 from jordan-woyak/sleepy-windows
Common/CoreTiming: Create a PrecisionTimer class for better frame pacing.
2025-04-04 15:34:00 -04:00
Jordan Woyak
e0e53f3235 Common/Timer: Use YieldProcessor on Windows. 2025-04-03 15:48:51 -05:00
Jordan Woyak
7dc27753e2 CoreTiming: Add a setting to use Common::PrecisionTimer. 2025-04-03 15:48:51 -05:00
Jordan Woyak
e5c8935acc Common: Create a PrecisionTimer class. 2025-04-03 15:48:51 -05:00
Admiral H. Curtiss
dadbd2f9fb
Merge pull request #13479 from iwubcode/mali_draw_fix
VideoCommon: fix a mali draw bug that causes crashes in some games
2025-04-03 21:55:41 +02:00
Jordan Woyak
af1f07207f VideoInterface: Throttle for VBlank only when necessary. 2025-04-02 23:24:03 -05:00
Jordan Woyak
c42dab6388 Core: Move CountPerformanceMarker to VideoInterface to eliminate a Throttle call. PerformanceMetrics: Fixes/Cleanups. 2025-04-02 23:23:51 -05:00
JMC47
61ab662733
Merge pull request #13424 from Sam-Belliveau/granule-performance-improvements
AudioCommon: Increased Granule Synthesis Performance
2025-04-02 22:44:14 -04:00
Dr. Dystopia
ebc9c8492d Use std::views::values and std::views::keys functions - NetPlayServer 2025-04-02 20:06:10 +02:00
Tilka
c705e366f0
Merge pull request #13478 from jordan-woyak/metal-af
VideoBackends/Metal: Fix anisotropic filtering handling.
2025-04-02 09:07:44 +01:00
iwubcode
ec36fce7c6 VideoCommon: fix a mali bug by moving the perf queries back to being close to the draw call, having them apart seems to cause errors on some devices 2025-04-01 18:32:42 -05:00
Sam Belliveau
877864c23a Improve Performance of Granular Buffering + User Adjustable Buffer Size 2025-04-01 18:17:21 -04:00
Jordan Woyak
33a7283d3b VideoBackends/Metal: Fix anisotropic filtering handling. 2025-04-01 15:09:21 -05:00
JosJuice
01a7732d50 IOS: Disguise Rock Band PlayStation USB devices as Wii equivalents
This lets you use PS3 Rock Band controllers with Wii Rock Band and
Guitar Hero games.

A normal user will probably never have any reason to disable this
behavior, but I figured maybe there's some person out there who would
like to disable it. (For instance, I know there's a mod for RB3 that's
trying to implement the same kind of cross-console controller
compatibility, and that can only be tested if the behavior I'm adding is
disabled.) So the behavior is controlled by an INI-only setting.
2025-03-31 21:24:25 +02:00
Jordan Woyak
17c994df2a InputCommon: Move SDL Device class into its own cpp/h files. 2025-03-30 23:23:06 -05:00
Admiral H. Curtiss
1b85da9b85
Merge pull request #13471 from Nitch2024/CTRL+G
[Debugger] CTRL+G support in code and memory view
2025-03-30 15:39:54 +02:00
Nitch2024
1b87ea83e6 [Debugger] CTRL+G support in code and memory view 2025-03-29 12:43:15 -07:00
JosJuice
957265ba52 Common: Make Profiler thread safe 2025-03-29 15:05:02 +01:00
JMC47
9819d66a47
Merge pull request #13221 from mitaclaw/nrvo-fails-1
GCC: Remedy NRVO Fails
2025-03-29 03:26:46 -04:00
JMC47
f00b7d39f0
Merge pull request #13465 from TryTwo/PR_Bugfix
AudioPanel Bugfix
2025-03-28 19:56:36 -04:00
TryTwo
efd993f382 AudioPanel bugfix: Forgot to wrap an optional slider in a conditional. 2025-03-28 15:50:24 -07:00
JMC47
4c727a84c5
Merge pull request #13456 from jordan-woyak/mapping-window-blank-square-fix
DolphinQt: Fix blank square in MappingWindow's top-left corner.
2025-03-28 18:44:32 -04:00
JMC47
932b4abdcf
Merge pull request #13457 from jordan-woyak/efb-access-fix
VideoCommon: Fix out-of-bounds and disabled EFB access.
2025-03-28 18:43:57 -04:00
JMC47
7d794897c4
Merge pull request #13434 from JosJuice/android-non-blocking-input-detection
Android: Don't use separate thread for MotionAlertDialog
2025-03-28 18:25:04 -04:00
JMC47
e0032b3e2c
Merge pull request #13122 from TryTwo/PR_Audio_Configs
AudioPanel: Refactor to use Config system.
2025-03-28 14:52:54 -04:00
JosJuice
c7ede8a6b7
Merge pull request #13461 from JoshuaVandaele/warningsbegone
Fix shadowed variable warnings and missing declarations
2025-03-28 18:43:09 +01:00
JosJuice
ee22cf9b22
Merge pull request #13462 from jordan-woyak/android-wm-mapping-fix
Android/Input: Fix crash when mapping wii remote extensions.
2025-03-28 18:35:15 +01:00
Jordan Woyak
0a3feb3e42 Android/Input: Fix a crash when mapping wii remote extensions. 2025-03-27 18:29:02 -05:00
Joshua Vandaële
3a1a60d4f8
Fix shadowed variable warnings and missing declarations
- PPCSymbolDB:  Resolve shadowed variable warnings
- PerformanceMetrics:  Resolve shadowed variable warnings
- SWEfbInterface: Add missing declarations
2025-03-27 21:48:08 +01:00
Tilka
662cfa38c2
Merge pull request #13460 from jordan-woyak/play-time-tracker-thread-name
Core: Name the play time tracker thread.
2025-03-27 17:02:36 +00:00
JMC47
cb24821dcc
Merge pull request #13217 from cristian64/extract_gecko_creator_name
DolphinQt: Extract creator name from code name in Gecko codes.
2025-03-27 12:26:47 -04:00
Jordan Woyak
ebd879cb30 Core: Name the play time tracker thread. 2025-03-27 01:38:55 -05:00
TryTwo
e5608c6ca5 ConfigControl fix: Add invalid index check to ConfigComplexChoice. Resolve with a default index that can be set.
If more control is needed,  it could be changed to allow multiple states to point to the same index.
2025-03-26 13:15:57 -07:00
TryTwo
896b4bb1fa AudioPanel: Refactor to use Config system. Some options were changed to a different format, for easier compatibility.
Removed VolumeChanged signal, as ConfigChanged will trigger what is needed.

Only applies UpdateSoundStream to things that can change during emulation.

Settings::SetVolume might no longer be used, but left it in.
2025-03-26 12:26:01 -07:00
Jordan Woyak
e351f03cdf VideoCommon: Fix out-of-bounds and disabled EFB access. 2025-03-26 01:23:16 -05:00
Jordan Woyak
849d8b7dae DolphinQt: Fix blank square in MappingWindow's top-left corner. 2025-03-25 20:52:29 -05:00
JMC47
1981f22228
Merge pull request #13433 from iwubcode/update_min_win10
Update our minimum windows 10 version to 1903 and reinstate code that depends on it
2025-03-25 18:30:15 -04:00
JMC47
eb84b0fb9b
Merge pull request #13442 from TryTwo/PR_CodeWidget_Layout_Tweak
Debugger CodeWidget: Small layout tweak
2025-03-25 13:19:02 -04:00
vyuuui
e34907025d Add numeric label support to assembler 2025-03-24 18:59:32 -07:00
JMC47
5d4b884e64
Merge pull request #13450 from Tilka/daring_game
GameSettings: fix startup crash in "The Daring Game for Girls"
2025-03-24 00:22:39 -04:00
Tillmann Karras
5a708f0f24 GameSettings: fix startup crash in "The Daring Game for Girls" 2025-03-23 23:28:22 +00:00
cristian64
6d8ba94e4c DolphinQt: Extract creator name from code name in Gecko codes.
Gecko codes in Dolphin feature a dedicated field for the creator of the
cheat code. When saved into the INI file, the code name and the creator
name are concatenated, and then inserted in the `[Gecko]` section:

```ini
[Gecko]
$<cheat code name> [<creator>]
<code line 1>
<code line 2>
<code line 3>
<...>
$<other cheat code name> [<creator>]
<code line 1>
<code line 2>
<code line 3>
<...>
```

On the other hand, enabled codes are listed under the `[Gecko_Enabled]`
section, but in this case the creator name is omitted from the line:

```ini
[Gecko_Enabled]
$<cheat code name>
$<other cheat code name>
```

Having the creator name in the `[Gecko]` section but not in the
`[Gecko_Enabled]` section is arguably not ideal, but this is legacy
behavior in Dolphin.

The **Cheat Code Editor** dialog is not acknowledging this subtle
behavior in Dolphin: the cheat code name and the creator name *can* be
both inserted in the name field. This issue manifests as an inconsistent
state where a Gecko code that *appears* to be enabled has no effect when
the game is launched.

As part of this fix, the creator name (if present) is now moved into the
dedicated creator field before the code is stored internally.

Test plan:

- Right-click on any game and open the **Properties** dialog.
- Switch to the **Gecko Codes** tab.
- Press the **Add New Code...** button.
- In the **Cheat Code Editor** dialog:
  - Enter `This is a test [Jane Doe]` in the **Name:** field.
  - Enter `01234567 00000000` in the **Code:** field.
  - Press **Save**.
- Observe that the newly added code is now in the list, and *appears* to
  be enabled.
- Close the **Properties** dialog.
- Right-click on the same game and open the **Properties** dialog again.

**Without** the fix, the newly added code, while still on the list, has
been inadvertently disabled (it was never really enabled!).

**With** the fix, the newly added code is the list and remains enabled.

This fixes https://bugs.dolphin-emu.org/issues/13695.
2025-03-23 21:37:23 +00:00
JosJuice
9e9faf3be1 Android: Show message when trying to map disconnected device
Having the MotionAlertDialog immediately close is confusing for users.
Let's show a message to tell them what went wrong.
2025-03-23 21:39:08 +01:00
JosJuice
516c1314d2 Android: Don't use separate thread for MotionAlertDialog
This is an Android continuation of bc95c00. We now call
InputDetector::Update immediately after receiving an input event from
Android instead of periodically calling it in a sleep loop. This
improves detection of very short inputs, which are especially likely to
occur for volume buttons on phones (or at least on my phone) if you
don't intentionally keep them held down.
2025-03-23 21:39:04 +01:00
JMC47
ad3650abfc
Merge pull request #13093 from mitaclaw/ranges-modernization-4-projection
Ranges Algorithms Modernization - Projection
2025-03-23 15:56:13 -04:00
JMC47
1515cf6ccd
Merge pull request #13447 from JosJuice/bba-panic-tr
EXI: Make HLE BBA panic alerts translatable
2025-03-23 15:22:11 -04:00
JMC47
cef4d8fb76
Merge pull request #13432 from iwubcode/custom_pixel_fragment
VideoCommon: move to a 'process_fragment()' function to simplify custom shaders
2025-03-23 15:21:48 -04:00
JMC47
f50d2ee86c
Merge pull request #13425 from jordan-woyak/after-present-cleanup
Fix performance statistics when Skip Duplicate Frames is turned off.
2025-03-23 15:21:31 -04:00
JMC47
28f1beeca8
Merge pull request #13398 from jordan-woyak/perf-tracker
PerformanceTracker: Eliminate mutex. General cleanups.
2025-03-23 15:21:11 -04:00
JMC47
178462e10f
Merge pull request #13385 from Tilka/sp2_ad16
Fix AD16 and make SP2 configurable
2025-03-23 15:20:45 -04:00
JMC47
9b0471532c
Merge pull request #13368 from jordan-woyak/anisotropic-filtering
Use Game Requested Anisotropic Filtering
2025-03-23 15:17:24 -04:00
JMC47
2da255d8cd
Merge pull request #13311 from iwubcode/dynamic_input_textures_reduce_image_writes
Core / DolphinQt / InputCommon: reduce the number disk writes when using DynamicInputTextures
2025-03-23 15:12:28 -04:00
JMC47
e93f0de8a4
Merge pull request #13295 from jordan-woyak/controller-emu-cleanup
InputCommon/ControllerEmu: Break out functionality of EmulatedController to eliminate redundant members.
2025-03-23 15:12:06 -04:00
JosJuice
c1990bc687 EXI: Make HLE BBA panic alerts translatable
Also rewording the messages to make them clearer and fix typos.
2025-03-23 15:43:16 +01:00
iwubcode
8e253518e6 VideoCommon: move to a 'process_fragment()' function to simplify custom shaders and provide a direct override of the tev stage logic 2025-03-22 15:22:00 -05:00
iwubcode
e18d98d4fc Core: properly distinguish between ES title switches (Wii titles) and normal loading (GC, also called for Wii..); update config for ES title change, generate textures for both situations 2025-03-22 14:55:20 -05:00
iwubcode
d03f9032c1 Core / DolphinQt / InputCommon: reduce the number disk writes when using DynamicInputTextures 2025-03-22 14:53:02 -05:00
TryTwo
b0867c1602 CodeWidget: Layout tweak. Give left-side widgets more vertical space by moving the address bar out of the way. Align things better. 2025-03-21 09:55:52 -07:00
JMC47
18979129f3
Merge pull request #13441 from jordan-woyak/wm-speaker-cleanup
WiimoteEmu: Eliminate dynamic memory allocation in speaker data decoding.
2025-03-18 16:23:50 -04:00
Jordan Woyak
3bf2de369a WiimoteEmu: Eliminate dynamic memory allocation in speaker data decoding. 2025-03-18 03:12:50 -05:00
Jordan Woyak
561aee7707 Config: Expose Default and 1x Anisotropic Filtering setting. 2025-03-17 20:46:24 -05:00
Jordan Woyak
4b711e1e0a DolphinQt: Allow ConfigComplexChoice to handle DefaultState values. 2025-03-17 20:46:24 -05:00
Jordan Woyak
ba1bf6959e Config: Allow passing a DefaultState object to Set functions to delete keys. 2025-03-17 20:46:24 -05:00
Jordan Woyak
137d1375d4 Enable game-requested anisotropic filtering in Metal backend. 2025-03-17 20:46:24 -05:00
Pokechu22
79a1e480ca Enable anisotropic filtering when the game requests it 2025-03-17 20:46:19 -05:00
Jordan Woyak
a7d1cac8ad Core: Call PerformanceMetrics::CountFrame regardless of PresentReason. 2025-03-17 17:24:08 -05:00
JosJuice
0299540209
Merge pull request #13397 from jordan-woyak/perf-metrics
PerformanceMetrics: Eliminated a mutex. Code cleanups.
2025-03-17 23:20:41 +01:00
Tilka
3b8384acf6
Merge pull request #13438 from Tilka/heads/refs/warning
Fix -Wunused-lambda-capture warning
2025-03-17 22:16:46 +00:00
Tillmann Karras
6a90affa38 Fix -Wunused-lambda-capture warning 2025-03-17 20:08:19 +00:00
OatmealDome
0afbeae70c
Merge pull request #13430 from jordan-woyak/tatacon-desired-state
WiimoteEmu: Make TaTaCon DesiredState use only one byte of space.
2025-03-16 15:04:21 -04:00
OatmealDome
dc4cb7874a
Merge pull request #13428 from rsgnz/Contributing.md-changes
Contributing.md: Replace egrep with grep -E in clang-format command.
2025-03-16 14:59:49 -04:00
OatmealDome
49bee36e6a
Merge pull request #13435 from iwubcode/uninitialized_directx
VideoCommon: initialize uninitialized state value in pixel ubershader
2025-03-16 14:56:44 -04:00
OatmealDome
9720b1f5f5
Merge pull request #13411 from jordan-woyak/gui-vconfig
DolphinQt/GeneralWidget: Eliminate unnecessary g_Config usage.
2025-03-16 14:54:24 -04:00
OatmealDome
9e513d93e1
Merge pull request #13414 from jordan-woyak/vconfig-framedump
VideoConfig: Eliminate frame dumping members.
2025-03-16 14:53:47 -04:00
OatmealDome
07cec796f4
Merge pull request #13417 from luzpaz/typo-source-core-common
Core/Common: Fix typos
2025-03-16 14:53:02 -04:00
iwubcode
c5f89f2de9 VideoCommon: initialize uninitialized state value in pixel ubershader to prevent error on directx in some games 2025-03-16 11:35:56 -05:00
Jordan Woyak
48b2f7d200 VideoConfig: Eliminate frame dumping members. 2025-03-16 04:30:06 -05:00
iwubcode
c1dea828ab Common: use std::chrono for GetLocalTimeSinceJan1970 on Windows
Co-authored-by: Shawn Hoffman <godisgovernment@gmail.com>
2025-03-16 00:59:45 -05:00
iwubcode
452cd1c261 Core: use more recent api in ComputeDefaultCountryCode on Windows
Co-authored-by: Shawn Hoffman <godisgovernment@gmail.com>
2025-03-16 00:59:45 -05:00
iwubcode
373a1a5dc0 Update min win10 version from 1703/15063 to 1903/18362
Co-authored-by: Shawn Hoffman <godisgovernment@gmail.com>
2025-03-16 00:59:45 -05:00
JMC47
f4c37aeb14
Merge pull request #13423 from jordan-woyak/async-request-cleanup-1
AsyncRequests Cleanups.
2025-03-15 18:17:29 -04:00
Tillmann Karras
90b6f0d16d Config: make SP2 configurable 2025-03-15 22:03:17 +00:00
Tillmann Karras
951a84833a EXI: fix AD16
The GameCube IPL is now able to detect this device. However, this
triggers some memory clearing code that trips up Dolphin's I$.
2025-03-15 22:03:16 +00:00
Jordan Woyak
6aff82eda3 WiimoteEmu: Make TaTaCon DesiredState use only one byte of space. 2025-03-15 16:48:05 -05:00
JMC47
99cde4e269
Merge pull request #13395 from jordan-woyak/vi-HORIZONTAL_BEAM_POSITION-ticks
VideoInterface: Update m_ticks_last_line_start from the event's ticks value.
2025-03-15 17:27:07 -04:00
JMC47
1bd3e79fda
Merge pull request #13378 from jordan-woyak/desired-ext-state
WiimoteEmu: Clean up variant handling in DesiredExtensionState.
2025-03-15 17:26:49 -04:00
JMC47
e3deb14156
Merge pull request #13347 from iwubcode/custom_shader_overhaul_lighting
VideoCommon: move lighting shader logic to callable functions
2025-03-15 17:26:32 -04:00
Jordan Woyak
46e0952e97 PerformanceTracker: Use SPSCQueue and atomic to eliminate need for a mutex. Clean up some math. 2025-03-15 14:40:00 -05:00
Jordan Woyak
c763961112 PerformanceTracker: Use std::deque instead of hand-rolled circular
queue.
2025-03-15 14:40:00 -05:00
Jordan Woyak
b2ce3fbefc PerformanceTracker: Pass chrono values instead of us s64. 2025-03-15 14:40:00 -05:00
Jordan Woyak
ddb82a5e8c InputCommon/ControllerEmu: Break out functionality of EmulatedController
to eliminate redundant unused members in Wii Remote extension objects.
2025-03-15 14:30:43 -05:00
JMC47
225039f742
Merge pull request #13427 from LillyJadeKatrin/retroachievements-code-approval-fix
Fixed Multi Config Code Approvals
2025-03-15 13:57:48 -04:00
JosJuice
049e52ce1c
Merge pull request #13429 from JosJuice/fix-broken-merge
Fix broken merge of PR #13181
2025-03-15 17:53:11 +01:00
JosJuice
f2d1918714 Fix broken merge of PR #13181
This undoes one of the changes of PR #13181. I'm guessing the relevant
code changed between when the PR was last pushed to and when it was
merged.
2025-03-15 17:23:39 +01:00
JosJuice
e637a05707
Merge pull request #12866 from JosJuice/android-log-types-sorting
Android: Replace log type names map with array
2025-03-15 16:01:33 +01:00
JosJuice
1f087473aa
Merge pull request #12809 from JosJuice/jitarm64-cmp-sp
JitArm64: Replace a comparison to SP
2025-03-15 16:00:15 +01:00
JosJuice
b2f8dac739
Merge pull request #13271 from dreamsyntax/gradle-wrapper
Android: Upgrade AGP & Gradle
2025-03-15 15:59:21 +01:00
JosJuice
541344ef9b
Merge pull request #13240 from thalesmg/20241225-m-known-bt-addresses-config-only
feat(linux): allow configuring real wiimotes with known bluetooth addresses
2025-03-15 15:34:49 +01:00
JosJuice
8c7ab286f5
Merge pull request #13181 from tygyh/Replace-'reinterpret_cast'
Replace 'reinterpret_cast' with 'static_cast'
2025-03-15 15:31:38 +01:00
JosJuice
3fb4084e25
Merge pull request #13345 from Tilka/unswap_depth
Fix depth texture being incorrectly affected by swap table
2025-03-15 14:30:19 +01:00
JosJuice
fd2c6918fa
Merge pull request #13388 from jordan-woyak/vsync-not-recommended
DolphinQt: Don't recommend v-sync for optimal frame pacing in tool-tip.
2025-03-15 14:24:29 +01:00
LillyJadeKatrin
0615ade725 Fixed Multi Config Code Approvals
Refactors the AR/Gecko/Patch code approval process to verify from every possible game ini, not just the base game ID. This fixes codes on specific revisions or codes general to any region.
2025-03-15 07:57:16 -04:00
rsgnz
01978cfcf7 Contributing.md: Replace egrep with grep -E in clang-format command. 2025-03-15 10:02:53 +00:00
Jordan Woyak
2690a62949 Core: Remove unused GetActualEmulationSpeed function and related variables/functions. 2025-03-14 03:10:13 -05:00
Jordan Woyak
e1745f682f PerformanceMetrics: Eliminated a mutex. Code cleanups. 2025-03-14 03:10:13 -05:00
JMC47
4d3f247cc3
Merge pull request #13352 from Sam-Belliveau/granular_synthesis
AudioCommon: Granule Synthesis Audio System
2025-03-14 03:57:09 -04:00
Sam Belliveau
f09ba10daa AudioCommon: Added Granular Synthesis 2025-03-14 01:22:35 -05:00
OatmealDome
e82f03b825
Merge pull request #13408 from infirit/flatpakscreensaver
Update the flatpak with the changes how screensavers are handled
2025-03-14 02:19:05 -04:00
Jordan Woyak
6c158ed590 VideoCommon: Create AsyncRequests directly in MMU code to eliminate EFB-related functions in VideoBackendBase. 2025-03-14 01:14:51 -05:00
Jordan Woyak
63b848ca93 VideoCommon: Eliminate EFBAccessType enum. Eliminate union and switch statement handler in AsyncRequests. 2025-03-14 00:59:41 -05:00
iwubcode
15372dc835 VideoCommon: move lighting shader logic to callable functions 2025-03-13 23:56:04 -05:00
JMC47
ca9b34a6d1
Merge pull request #13394 from jordan-woyak/odd-even-pacing
VideoInterface: Adjust even-field to match odd-field pacing when PSB values differ.
2025-03-13 21:56:36 -04:00
JMC47
0e2785a562
Merge pull request #13387 from jordan-woyak/frame-pacing
CoreTiming: Improve frame pacing
2025-03-13 14:23:18 -04:00
JMC47
a421d6859f
Merge pull request #13418 from jordan-woyak/efb-interface
VideoCommon: Rename Renderer to EFBInterface.
2025-03-13 14:20:34 -04:00
Jordan Woyak
fdf00050a6 DolphinQt: Use tooltips on Advanced tab. 2025-03-13 05:32:16 -05:00
Jordan Woyak
5b36c13bfb VideoCommon: Rename Renderer to EFBInterface. 2025-03-12 21:09:16 -05:00
Luz Paz
1b47dbf519 Core/Common: Fix typos
Found via `codespell -q 3 -S "./Externals,./Data/Sys/wiitdb-??.txt,*.po,*.pot" -L andf,asnd,bootup,brocken,bufferin,clen,collet,datas,delt,diety,extint,fpr,inout,inport,interm,nd,nin,ontop,pixelx,re-use,re-used,sav,stateman,strat,transer,wil`
2025-03-11 19:48:45 -04:00
JMC47
de997d616f
Merge pull request #13416 from jordan-woyak/unused-viewport-correction
VertexShaderManager: Eliminate unnecessary m_viewport_correction member.
2025-03-11 19:00:55 -04:00
JMC47
b7bd0a0836
Merge pull request #13413 from jordan-woyak/vconfig-progressive
VideoConfig: Eliminate bForceProgressive.
2025-03-11 18:59:28 -04:00
JMC47
67c8d5640f
Merge pull request #13412 from jordan-woyak/netplay-vconfig
VideoConfig: Eliminate NetPlay related members.
2025-03-11 18:59:02 -04:00
JMC47
1698daef66
Merge pull request #13410 from jordan-woyak/movie-vconfig
Movie: Eliminate MovieManager::SetGraphicsConfig.
2025-03-11 18:58:45 -04:00
JMC47
a80062f1b1
Merge pull request #13400 from jordan-woyak/async-request-no-poke-merge
VideoCommon: Don't merge EFBPoke AsyncRequests.
2025-03-11 18:58:27 -04:00
Jordan Woyak
9b2ab6e259
Merge pull request #13407 from luzpaz/typo-data
Data: fix various typos
2025-03-11 15:37:59 -05:00
Jordan Woyak
c191ed5321 VertexShaderManager: Eliminate unnecessary m_viewport_correction member. 2025-03-11 03:55:57 -05:00
Jordan Woyak
5b88c0b90e DolphinQt/GeneralWidget: Eliminate unnecessary g_Config usage. 2025-03-10 20:19:45 -05:00
Jordan Woyak
de01a790e1 VideoConfig: Eliminate bForceProgressive. 2025-03-10 19:02:43 -05:00
Jordan Woyak
7f3d8a1ad4 VideoConfig: Eliminate NetPlay related members. 2025-03-10 18:53:44 -05:00
Jordan Woyak
44423a3656 Movie: Eliminate MovieManager::SetGraphicsConfig. 2025-03-10 18:16:49 -05:00
Jordan Woyak
7222188cde Core/VideoCommon: Push presentation time calculated from CPU thread to GPU thread. 2025-03-10 16:40:46 -05:00
Jordan Woyak
c4bd98c626 VideoInterface: Throttle before VBlank statistics counting. 2025-03-10 16:40:46 -05:00
Jordan Woyak
9ac9813492 SystemTimers: Throttle prior to performance marker. 2025-03-10 16:40:46 -05:00
Jordan Woyak
aa624d8ba8 BTEmu: Throttle prior to wii remote input update. 2025-03-10 16:40:46 -05:00
Jordan Woyak
9675c90890 VideoInterface: Throttle prior to SI poll. 2025-03-10 16:40:46 -05:00
Jordan Woyak
81e842e2aa CoreTiming: Don't Throttle in event queue processing. 2025-03-10 16:39:13 -05:00
Jordan Woyak
fe2d247acb VideoCommon: Don't merge EFBPoke AsyncRequests. 2025-03-10 16:37:24 -05:00
Luz Paz
cf1541a511 Data: fix various typos
Found via `codespell -q 3 -S "./Externals,./Data/Sys/wiitdb-??.txt,*.po,*.pot" -L andf,asnd,bootup,brocken,bufferin,clen,collet,datas,delt,diety,extint,fpr,inout,inport,interm,nd,nin,ontop,pixelx,re-use,re-used,sav,stateman,strat,transer,wil`
2025-03-10 16:54:34 -04:00
Sander Sweers
3705c73d55
xdg-screensaver was replaced by calling dbus interfaces 2025-03-10 21:44:58 +01:00
Sander Sweers
ae11ffadf6
Allow flatpak to talk to inhibit/screensaver dbus interfaces 2025-03-10 21:44:58 +01:00
mitaclaw
433c6ce0f2 GCC: Remedy NRVO Fails
Using the `-Wnrvo` flag introduced by GCC 14, I identified a few places where NRVO was clearly intended, but is fumbled.
2025-03-10 12:38:03 -07:00
JMC47
5ed8b7bc9d
Merge pull request #13403 from jordan-woyak/backend_info
VideoCommon: Move backend_info out of VideoConfig struct.
2025-03-10 15:06:19 -04:00
JMC47
d45e6c6729
Merge pull request #13401 from jordan-woyak/exit-gpu-loop
Core/VideoBackendBase: Call ExitGpuLoop from Core to eliminate Video_ExitLoop.
2025-03-10 15:05:30 -04:00
JMC47
203454a97a
Merge pull request #13396 from jordan-woyak/vi-odd-even
VideoInterface: Cleanup and minor fix in Update.
2025-03-10 15:05:12 -04:00
JMC47
ff4486ee23
Merge pull request #13340 from Dentomologist/state_show_decompressing_osd_longer
State: Show "Decompressing State..." OnScreenDisplay message for longer
2025-03-10 15:04:50 -04:00
JMC47
189d09011b
Merge pull request #13363 from JoshuaVandaele/nowarnings
Fix multiple minor warnings
2025-03-10 15:04:14 -04:00
JMC47
3f73a39dbd
Merge pull request #13286 from JoshuaVandaele/xcb
Enforce XCB within code
2025-03-10 15:03:54 -04:00
JMC47
9f43f59c9b
Merge pull request #13276 from JoshuaVandaele/sfml-3.0.0
Migrate to SFML 3.0.0
2025-03-10 15:03:36 -04:00
JosJuice
13d966760d
Merge pull request #13362 from MackdannyTwitch/dolphin-RA-approved-cheats-
Added widescreen code for Tomb Raider: Legend GL8.ini
2025-03-10 19:13:34 +01:00
OatmealDome
9e23a0a506 Merge branch 'release-prep-2503' 2025-03-10 12:34:02 -04:00
MackdannyTwitch
ba40e4abad Added widescreen code for Tomb Raider: Legend GL8.ini
As the PS2 version is the only one with proper 16:9 widescreen, this cheat brings widescreen to the Gamecube version. This cheat has been tested on the NTSC version, but is stated to be region free.
2025-03-10 01:41:25 -05:00
JosJuice
1cc6b6c5d8
Merge pull request #13384 from MackdannyTwitch/TR-has-graphical-issues
Fix graphical corruption bug in Tomb Raider: Legend
2025-03-09 23:59:45 +01:00
Tilka
f4e6878384
Merge pull request #13406 from Tilka/snow
GameSettings: fix shadows in Triple Crown Championship Snowboarding
2025-03-09 22:48:47 +00:00
Tillmann Karras
cbd71f06ba GameSettings: fix shadows in Triple Crown Championship Snowboarding 2025-03-09 20:50:22 +00:00
mitaclaw
e4efe011d7 Modernize std::max_element with ranges and projections 2025-03-09 13:26:39 -07:00
mitaclaw
258ec4f9cd Modernize std::lower_bound/upper_bound with ranges and projections 2025-03-09 13:26:38 -07:00
mitaclaw
c9f589faa5 Modernize std::stable_sort with ranges and projections 2025-03-09 13:26:38 -07:00
mitaclaw
8b9f92a0af Modernize std::sort with ranges and projections
In PPCTables.cpp, the code is currently unused so I was unable to test it.

In CustomPipeline.cpp, a pointer to member function cannot be used due to 16.4.5.2.1 of the C++ Standard regarding "addressable functions". https://eel.is/c++draft/namespace.std#6

In Fs.cpp and DirectoryBlob.cpp, these examples used projections in a previous iteration of this commit, but no longer do. Still, they remain in this commit because the PR they would actually belong to is already merged.
2025-03-09 13:26:38 -07:00
mitaclaw
9f972db4b8 Modernize std::none_of with ranges and projections 2025-03-09 13:26:37 -07:00
mitaclaw
00e147c722 Simplify std::count_if with std::ranges::count and projections 2025-03-09 13:26:37 -07:00
mitaclaw
62b2b939b5 Simplify std::find_if with std::ranges::find and projections
In LabelMap.cpp, the code is currently unused so I was unable to test it.

In WiiUtils.cpp, the magic value `1u` was replaced by the constant value `DiscIO::PARTITION_UPDATE`.
2025-03-09 13:26:35 -07:00
mitaclaw
1e5e9219cd Common: Create Range Projections For std::pair 2025-03-09 13:19:41 -07:00
JosJuice
87496205aa
Merge pull request #13404 from luzpaz/typo-source-core-windupdater
Core/WinUpdater: fix typo
2025-03-09 12:03:56 +01:00
JosJuice
e974e48e1f
Merge pull request #13405 from luzpaz/typo-source-core-core
Core/Core: fix typos
2025-03-09 12:03:34 +01:00
Jordan Woyak
c18c039089 VideoCommon: Move backend_info out of VideoConfig struct. 2025-03-09 01:42:45 -06:00
Luz Paz
fb6c625fed Core/Core: fix typos
Found via `codespell -q 3 -S "./Externals,./Data/Sys/wiitdb-??.txt,*.po,*.pot" -L andf,asnd,bootup,bufferin,clen,collet,datas,delt,fpr,inout,inport,interm,pixelx,re-use,re-used,sav,stateman,strat,wil`
2025-03-08 15:41:53 -05:00
Luz Paz
9b7d494bd4 Core/WinUpdater: fix typo 2025-03-08 09:58:50 -05:00
JosJuice
d2b4e12f9e
Merge pull request #13399 from luzpaz/typos-macOS
CMake: fix various typos
2025-03-08 12:23:13 +01:00
Jordan Woyak
7925240107 Core/VideoBackendBase: Call ExitGpuLoop from Core to eliminate Video_ExitLoop. 2025-03-07 17:30:33 -06:00
Luz Paz
325c1a24b9 CMake: fix various typos
Also includes a fix for BuildMacOSUniversalBinary.py
2025-03-05 20:57:52 -05:00
Admiral H. Curtiss
99e686de34
Merge pull request #13393 from luzpaz/dbz
GraphicMods: Fix typo in DBZ Budokai Tenkaichi 3/metadata.json
2025-03-06 00:02:32 +01:00
Jordan Woyak
5ff2af9b6a VideoInterface: Cleanup and minor fix in Update. 2025-03-04 20:39:14 -06:00
dreamsyntax
5beb136992 Android: Upgrade AGP & Gradle
AGP 8.2.0 -> 8.9.0
Gradle and wrapper to 8.11.1
Baseline Profile plugin to 1.3.3
2025-03-04 18:28:01 -07:00
Jordan Woyak
16d75eadb5 VideoInterface: Update m_ticks_last_line_start from the event's ticks
value rather than the potentially "cycles late" value.
2025-03-04 15:33:51 -06:00
Jordan Woyak
b28dcf3687 VideoInterface: Adjust even-field to match odd-field pacing when PSB values differ. 2025-03-04 04:52:24 -06:00
Luz Paz
38099f282d GraphicMods: Fix typo in DBZ Budokai Tenkaichi 3/metadata.json 2025-03-04 04:35:10 -05:00
Admiral H. Curtiss
3c5da38177
Merge pull request #13390 from jordan-woyak/ciface-clock
InputCommon: Use Clock from CommonTypes.
2025-03-03 22:29:25 +01:00
Tilka
ecb0a3e5c7
Merge pull request #13389 from iwubcode/static_texcoords_vertex_shadergen
VideoCommon: mark 'WriteTexCoordTransforms' as 'static'
2025-03-03 02:45:52 +00:00
Jordan Woyak
e217d6c939 InputCommon: Use Clock from CommonTypes. 2025-03-02 15:42:26 -06:00
iwubcode
6dedf11c96 VideoCommon: mark 'WriteTexCoordTransforms' as 'static' 2025-03-02 11:27:54 -06:00
Jordan Woyak
5d16c51963 DolphinQt: Don't recommend v-sync for optimal frame pacing in tool-tip. 2025-03-02 05:43:00 -06:00
MackdannyTwitch
5dd10b9644 Fix graphical corruption bug in Tomb Raider: Legend
Tomb Raider: Legend has a graphical bug, as documented in the issue report here https://bugs.dolphin-emu.org/issues/13749?next_issue_id=13748

This .ini entry fixes the issue.
2025-03-01 03:07:12 -07:00
Jordan Woyak
3f92f86de1 WiimoteEmu: Add a static_assert in DesiredExtensionState to keep variant alternative order consistent. 2025-02-25 17:22:59 -06:00
Jordan Woyak
0d0734e083 WiimoteEmu: Clean up variant handling in DesiredExtensionState. 2025-02-25 17:22:59 -06:00
Jordan Woyak
1d481a395a VariantUtil: Introduce WithVariantAlternative to dynamically construct and visit a variant alternative. 2025-02-25 17:22:59 -06:00
Tillmann Karras
4e460a7968 UberShaderPixel: use unswapped texture samples for depth 2025-02-25 18:45:01 +00:00
Tillmann Karras
359fb51d64 PixelShaderGen: use unswapped texture samples for depth 2025-02-25 18:45:01 +00:00
Tillmann Karras
7abb9e7974 Sofware/Tev: use unswapped texture samples for depth 2025-02-25 18:45:01 +00:00
Joshua Vandaële
0a83783fae
Migrate to SFML>=3.0.0 2025-02-25 06:42:13 +01:00
Thales MG
97bc28aac4 feat(linux): allow configuring real wiimotes with known bluetooth addresses
This adds the option to configure real Wiimotes by specifying their Bluetooth addresses in
the configuration file.  This allows off-brand Wiimotes to work without using the
Bluetooth Passthrough option, if you know their Bluetooth addresses beforehand.

Despite correctly setting the LAP to `0x9e8b00` in `WiimoteScannerLinux::FindWiimotes`
while scanning, which is indeed enough to make off-brand / knock-off Wiimotes respond to a
Bluetooth Inquiry, some (several? all?) bluetooth adapters seem to override and ignore
this given LAP value when performing the Inquiry, and actually use the `0x9e8b33` value as
if a null pointer have been given to `hci_inquiry`, as inspection of USB/Bluetooth packets
by Wireshark indicate.  Off-brand Wiimotes don't respond to inquiries with this LAP.

If one happens to know the Bluetooth address of their Wiimote (for example, by checking
`BluetoothPassthrough.LinkKeys` after using Bluetooth Passthrough, or other means such as
directly using `libusb` to force the adapter to use the correct LAP in the Inquiry), then
it's enough to add those addresses to the vector of found Wiimotes.

Since this a niche use case and I only happen to know and have tested in Linux, this
change only affects the `WiimoteScannerLinux` backend.  It's likely that it could be added
to other backends, but I'm unfamiliar with these.

If no addresses are given or this config section does not exist, behavior is completely
unchanged.
2025-02-23 18:27:48 -03:00
Joshua Vandaële
5b4d4ca5eb
Fix multiple minor warnings
- ExpressionParser.cpp: `-Wmissing-declarations`
- AchievementManager.cpp: `-Wsign-compare`
- SI.cpp: `-Warray-bounds=`
- NetPlayClient.cpp: `-Wdangling-reference`
2025-02-21 19:17:29 +01:00
Dentomologist
363155b597 State: Increase Decompressing OSD message duration
Show the "Decompressing State..." message for 2 seconds, instead of the
half-second duration that caused it to be halfway faded out immediately.
2025-02-06 17:17:18 -08:00
Joshua Vandaële
a3b06b0572
Enforce XCB within code 2025-01-20 11:57:21 +01:00
Dr. Dystopia
6d44afc7dd Replace 'reinterpret_cast' with 'static_cast' 2024-11-08 07:26:47 +01:00
JosJuice
ea7928b3cd Android: Replace log type names map with array
Storing the log type names in a map results in them getting re-sorted by
their keys, which doesn't quite give us the sorting we want. In
particular, the Achievements category ended up being sorted at R (for
RetroAchivements) instead of at A. Every use of the map is just
iterating through it, so there's no real reason why it has to be a map
anyway.
2024-06-15 20:06:34 +02:00
JosJuice
dc6e5e7ff6 JitArm64: Replace a comparison to SP
Comparing with an immediate 0 has the same effect but is much easier to
read.
2024-05-26 08:47:20 +02:00
663 changed files with 49501 additions and 62308 deletions

3
.gitmodules vendored
View file

@ -84,3 +84,6 @@
[submodule "Externals/Vulkan-Headers"]
path = Externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "Externals/SFML/SFML"]
path = Externals/SFML/SFML
url = https://github.com/SFML/SFML.git

View file

@ -57,13 +57,9 @@ DEFAULT_CONFIG = {
# SHA checksum to verify the integrity of the app. This doesn't
# protect against malicious actors, but it does protect against
# running corrupted binaries and allows for access to the extended
# permisions needed for ARM builds
# permissions needed for ARM builds
"codesign_identity": "-",
# Minimum macOS version for each architecture slice
"arm64_mac_os_deployment_target": "11.0.0",
"x86_64_mac_os_deployment_target": "10.15.0",
# CMake Generator to use for building
"generator": "Unix Makefiles",
"build_type": "Release",
@ -77,7 +73,7 @@ DEFAULT_CONFIG = {
"distributor": "None"
}
# Architectures to build for. This is explicity left out of the command line
# Architectures to build for. This is explicitly left out of the command line
# config options for several reasons:
# 1) Adding new architectures will generally require more code changes
# 2) Single architecture builds should utilize the normal generated cmake
@ -146,11 +142,6 @@ def parse_args(conf=DEFAULT_CONFIG):
help=f"Install path for {arch} qt5 libraries",
default=conf[arch+"_qt5_path"])
parser.add_argument(
f"--{arch}_mac_os_deployment_target",
help=f"Deployment architecture for {arch} slice",
default=conf[arch+"_mac_os_deployment_target"])
return vars(parser.parse_args())
@ -297,8 +288,7 @@ def build(config):
"-DCMAKE_PREFIX_PATH="+prefix_path,
"-DCMAKE_SYSTEM_PROCESSOR="+arch,
"-DCMAKE_IGNORE_PATH="+ignore_path,
"-DCMAKE_OSX_DEPLOYMENT_TARGET="
+ config[arch+"_mac_os_deployment_target"],
"-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0.0",
"-DMACOS_CODE_SIGNING_IDENTITY="
+ config["codesign_identity"],
'-DMACOS_CODE_SIGNING="ON"',

View file

@ -11,7 +11,7 @@
# FFmpeg_LIBRARIES: aggregate all the paths to the libraries
# FFmpeg_FOUND: True if all components have been found
#
# This module defines the following targets, which are prefered over variables:
# This module defines the following targets, which are preferred over variables:
#
# FFmpeg::<component>: Target to use <component> directly, with include path,
# library and dependencies set up. If you are using a static build, you are

View file

@ -87,9 +87,10 @@ if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp")
endif()
FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS)
STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX MATCH "#define SFML_VERSION_MAJOR[ \t]+([0-9]+)" SFML_VERSION_MAJOR_MATCH "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX MATCH "#define SFML_VERSION_MINOR[ \t]+([0-9]+)" SFML_VERSION_MINOR_MATCH "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX REPLACE "#define SFML_VERSION_MAJOR[ \t]+([0-9]+)" "\\1" SFML_VERSION_MAJOR "${SFML_VERSION_MAJOR_MATCH}")
STRING(REGEX REPLACE "#define SFML_VERSION_MINOR[ \t]+([0-9]+)" "\\1" SFML_VERSION_MINOR "${SFML_VERSION_MINOR_MATCH}")
math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10 + ${SFML_FIND_VERSION_MINOR}")
# if we could extract them, compare with the requested version number
@ -102,10 +103,14 @@ if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
set(SFML_VERSION_OK FALSE)
endif()
else()
# SFML version is < 2.0
if (SFML_REQUESTED_VERSION GREATER 19)
# SFML version is < 3.0
if (SFML_REQUESTED_VERSION GREATER 29)
set(SFML_VERSION_OK FALSE)
if (SFML_REQUESTED_VERSION GREATER 19)
set(SFML_VERSION_MAJOR 1)
else()
set(SFML_VERSION_MAJOR 2)
endif()
set(SFML_VERSION_MINOR x)
endif()
endif()

View file

@ -34,7 +34,7 @@ string(TIMESTAMP DOLPHIN_WC_BUILD_DATE "%Y-%m-%d" UTC)
# version number
set(DOLPHIN_VERSION_MAJOR "2503")
set(DOLPHIN_VERSION_MINOR "0")
set(DOLPHIN_VERSION_MINOR "1")
set(DOLPHIN_VERSION_PATCH ${DOLPHIN_WC_REVISION})
# If Dolphin is not built from a Git repository, default the version info to

View file

@ -24,7 +24,7 @@ endif()
# Minimum OS X version.
# This is inserted into the Info.plist as well.
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15.0" CACHE STRING "")
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0.0" CACHE STRING "")
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FlagsOverride.cmake")
@ -44,7 +44,7 @@ endif()
set(COMPILER ${CMAKE_CXX_COMPILER_ID})
if (COMPILER STREQUAL "GNU")
set(COMPILER "GCC") # perfer printing GCC instead of GNU
set(COMPILER "GCC") # prefer printing GCC instead of GNU
endif()
# Enforce minimum compiler versions that support the c++20 features we use
@ -124,6 +124,11 @@ option(OPROFILING "Enable profiling" OFF)
# TODO: Add DSPSpy
option(DSPTOOL "Build dsptool" OFF)
# RetroAchievements developer tools require Windows hooks
if(WIN32)
option(RC_CLIENT_SUPPORTS_RAINTEGRATION "Enables RetroAchievements developer tools" ON)
endif()
# Enable SDL by default on operating systems that aren't Android.
if(NOT ANDROID)
option(ENABLE_SDL "Enables SDL as a generic controller backend" ON)
@ -144,6 +149,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
option(ENABLE_VTUNE "Enable Intel VTune integration for JIT code." OFF)
if(NOT ANDROID)
option(ENABLE_HWDB "Enables the udev hardware database" ON)
option(ENABLE_EVDEV "Enables the evdev controller backend" ON)
endif()
endif()
@ -407,7 +413,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0)
# Workaround: the llvm libc++ and versions of clang eariler than 14 have a bug with consteval
# Workaround: the llvm libc++ and versions of clang earlier than 14 have a bug with consteval
# so we define FMT_CONSTEVAL to blank to just disable consteval in fmt
add_definitions(-DFMT_CONSTEVAL=)
endif()
@ -566,6 +572,16 @@ if(OPROFILING)
endif()
endif()
if(ENABLE_HWDB)
find_package(LIBUDEV REQUIRED)
if(LIBUDEV_FOUND)
message(STATUS "libudev found, enabling hardware database")
add_definitions(-DHAVE_LIBUDEV=1)
else()
message(FATAL_ERROR "Couldn't find libudev. Can't build hardware database.\nDisable ENABLE_HWDB if you wish to build without hardware database support")
endif()
endif()
if(ENABLE_EVDEV)
find_package(LIBUDEV REQUIRED)
find_package(LIBEVDEV REQUIRED)
@ -696,11 +712,6 @@ if (APPLE OR WIN32)
include_directories(Externals/ed25519)
endif()
# Using static soundtouch from Externals
# Unable to use system soundtouch library: We require shorts, not floats.
add_subdirectory(Externals/soundtouch)
include_directories(Externals/soundtouch)
if(ENABLE_CUBEB)
dolphin_find_optional_system_library(CUBEB Externals/cubeb)
add_definitions(-DHAVE_CUBEB)
@ -713,7 +724,7 @@ if(NOT ANDROID)
add_definitions(-D__LIBUSB__)
endif()
dolphin_find_optional_system_library(SFML Externals/SFML 2.1 COMPONENTS network system)
dolphin_find_optional_system_library(SFML Externals/SFML 3.0 COMPONENTS Network System)
if(USE_UPNP)
dolphin_find_optional_system_library(MINIUPNPC Externals/miniupnpc 1.6)

View file

@ -49,7 +49,7 @@ In most cases, clang-format can and **should** be used to automatically reformat
- To run clang-format on all staged files:
```
git diff --cached --name-only | egrep '[.](cpp|h|mm)$' | xargs clang-format -i
git diff --cached --name-only | grep -E '[.](cpp|h|mm)$' | xargs -I {} clang-format -i {}
```
- Formatting issues can be checked for before committing with a lint script that is included with the codebase. To enable it as a pre-commit hook (assuming you are in the repository root):

View file

@ -932,10 +932,6 @@
"title": "Region Select",
"AD12237401ABE9FE4A545AADB5C5AE10355E2076": "RSAPatch"
},
"RELJAB": {
"title": "SegaBoot",
"130F3594CAB57B85616F95C7126F4748AAC5867D": "DI Seed Blanker"
},
"RGQE70": {
"title": "Ghostbusters",
"5F4CF8D4DA19A0FF74FF9EB925AC0236069BFD59": "crashfix"

View file

@ -9,9 +9,9 @@ SafeTextureCacheColorSamples = 0
[Video_Hacks]
# Some very early NES releases use a version of the NES emulator that doesn't require EFB2Ram.
# All US releases before Feburary 2007 use this version (with all remaining US releases requiring EFB2Ram).
# All US releases before February 2007 use this version (with all remaining US releases requiring EFB2Ram).
# But in the PAL region the same games don't necessarily have the same emulator version and
# only a few of the pre-Feburary 2007 releases don't require EFB2Ram.
# only a few of the pre-February 2007 releases don't require EFB2Ram.
#
# Because of this, Inifiles that override this setting should only be created for the explicit region
# that was tested and they should not be merged.

View file

@ -1,5 +1,5 @@
# FAAE01 - Donkey Kong
[Video_Hacks]
# All US NES VC titles released before Feburary 2007 don't need EFB2ram
# All US NES VC titles released before February 2007 don't need EFB2ram
EFBToTextureEnable =

View file

@ -1,5 +1,5 @@
# FAGE01 - Super Mario Bros.
[Video_Hacks]
# All US NES VC titles released before Feburary 2007 don't need EFB2ram
# All US NES VC titles released before February 2007 don't need EFB2ram
EFBToTextureEnable =

View file

@ -11,3 +11,9 @@
[Video_Hacks]
EFBToTextureEnable = False
DeferEFBCopies = False
[Gecko]
$Widescreen 16:9 (Region Free)
04007B7C 38600001
*Renders the game in Widescreen 16:9

View file

@ -968,7 +968,7 @@ $Minigame: Memory Lane - No Trail [Airsola]
204d6a0f 00000000
044d699f 0000003f
e2000002 80008000
*Shy Guy will no longer leave a trail durning the demo in the minigame Memory Lane.
*Shy Guy will no longer leave a trail during the demo in the minigame Memory Lane.
$Minigame: Mole It All Moles are Worth 3 Points [gamemasterplc]
204D57F0 A8A10008

View file

@ -1164,7 +1164,7 @@ $Mechanics - Use Multiple Orbs in the Same Turn [Ralf]
041E3764 3860FFFF
*Does not work with CPUs
$Mechanics - Vaccum Orb Always Steals 5 Coins
$Mechanics - Vacuum Orb Always Steals 5 Coins
041c8a34 38600005
$Minigame: Balloonatic - 25 Second Timer [Airsola]

View file

@ -1,4 +1,5 @@
# GVSE8P, GVSP8P - Virtua Striker 3 ver. 2002
# GVSP8P, GVSE8P, GVSJ8P - Virtua Striker 2002 (GC)
# GVSJ8P - Virtua Striker 2002 (Triforce), Virtua Striker 4, Virtua Striker 4 ver. 2006
[Core]
# Values set here will override the main Dolphin settings.
@ -10,3 +11,7 @@ FPRF = True
[ActionReplay]
# Add action replay cheats here.
[Video]
# Add memory patches to be applied every frame here.
[Video_Settings]

View file

@ -1,18 +0,0 @@
# GVS46E, GVS46J - Virtua Striker 4 ver. 2006
# Because Triforce games have weird IDs, properties are inherited from GVS.ini (Virtua Striker 3 ver. 2002)!
[Core]
# Values set here will override the main Dolphin settings.
FPRF = True
[OnFrame]
# Add memory patches to be applied every frame here.
[ActionReplay]
# Add action replay cheats here.
[Video]
# Add memory patches to be applied every frame here.
[Video_Settings]

View file

@ -1,18 +0,0 @@
# GVS46E, GVS46J - Virtua Striker 4 ver. 2006
# Because Triforce games have weird IDs, properties are inherited from GVS.ini (Virtua Striker 3 ver. 2002)!
[Core]
# Values set here will override the main Dolphin settings.
FPRF = True
[OnFrame]
# Add memory patches to be applied every frame here.
[ActionReplay]
# Add action replay cheats here.
[Video]
# Add memory patches to be applied every frame here.
[Video_Settings]

View file

@ -362,7 +362,7 @@ $Can Walk Ontop of Deep Snow (Twilight Spectre)
$Run Normal Speed With Iron Boots On (brkirch)
040BB53C 38600000
040B2D18 4800004C
$Alywas Preform Dive When Jumping (brkirch)
$Always Perform Dive When Jumping (brkirch)
040B6618 60000000
$Can Always Flourish Sword (brkirch)
040B9B68 60000000
@ -514,7 +514,7 @@ $Mute BG Music (Twilight Spectre)
043DC3D0 00000000
$BG music muted v2 (Twilight Spectre)
044507F4 00000000
$Enviornment muted (Twilight Spectre)
$Environment muted (Twilight Spectre)
04450814 00000000
$Link makes no noise (Twilight Spectre)
044507FC 00000000

View file

@ -7,7 +7,7 @@
# Add action replay cheats here.
$==========The Legend of Zelda==========
001D73B0 000000FB
$Max/Infinte Health
$Max/Infinite Health
001D73AF 000000FF
001D73B0 000000FB
$Max/Infinite Rupees

View file

@ -1,18 +0,0 @@
# RELJAB - SegaBoot
[Core]
# Values set here will override the main Dolphin settings.
[OnFrame]
# Add memory patches to be applied every frame here.
$DI Seed Blanker
0x80000000:dword:0x00000000
0x80000004:dword:0x00000000
0x80000008:dword:0x00000000
[Patches_RetroAchievements_Verified]
$DI Seed Blanker
[ActionReplay]
# Add action replay cheats here.

View file

@ -1,5 +1,5 @@
# RLIE64, RLIP64 - Lego Indiana Jones: The Original Adventures
[Video_Hacks]
# Fixes the alpha value of glpyh puzzles; see https://bugs.dolphin-emu.org/issues/12987
# Fixes the alpha value of glyph puzzles; see https://bugs.dolphin-emu.org/issues/12987
MissingColorValue = 0xFFFFFF82

View file

@ -542,7 +542,7 @@ de000000 80008180
30012d2c 2c000000
14012d54 38030000
e0000000 80008000
*Carry Infinite Boosts instad of 3 in the minigame Cosmic Slalom
*Carry Infinite Boosts instead of 3 in the minigame Cosmic Slalom
$Minigame - Lob to Rob: All Targets Worth 30 Points [gamemasterplc]
48000000 800030c8

View file

@ -11,3 +11,4 @@
[Video_Hacks]
ImmediateXFBEnable = False
EFBAccessEnable = True

View file

@ -0,0 +1,5 @@
# S3CENR - Triple Crown Championship Snowboarding
[Video_Hacks]
# Fixes shadows.
EFBToTextureEnable = False

View file

@ -0,0 +1,35 @@
# SDAE5G - The Daring Game for Girls
[OnFrame]
# The game registers an AX callback function that uses a pointer which is only
# initialized afterwards. The race condition depends on AID interrupt timing.
# This patch moves the pointer initialization from 0x801C9E5C to 0x801C9DFC,
# shifting the instructions in-between down.
$Fix startup crash
0x801C9DFC:dword:0x93EDBAB0
0x801C9E00:dword:0x48030721
0x801C9E04:dword:0x48032B8D
0x801C9E08:dword:0x48063A89
0x801C9E0C:dword:0x5460063F
0x801C9E10:dword:0x41820018
0x801C9E14:dword:0x2C000001
0x801C9E18:dword:0x41820024
0x801C9E1C:dword:0x2C000002
0x801C9E20:dword:0x41820030
0x801C9E24:dword:0x4800003C
0x801C9E28:dword:0x38600000
0x801C9E2C:dword:0x4802FF85
0x801C9E30:dword:0x38600000
0x801C9E34:dword:0x48032C9D
0x801C9E38:dword:0x48000028
0x801C9E3C:dword:0x38600000
0x801C9E40:dword:0x4802FF71
0x801C9E44:dword:0x38600001
0x801C9E48:dword:0x48032C89
0x801C9E4C:dword:0x48000014
0x801C9E50:dword:0x38600001
0x801C9E54:dword:0x4802FF5D
0x801C9E58:dword:0x38600002
0x801C9E5C:dword:0x48032C75
[OnFrame_Enabled]
$Fix startup crash

View file

@ -165,7 +165,7 @@
{
"type": "draw_started",
"prettyname": "Buttom Prompt Y",
"prettyname": "Button Prompt Y",
"texture_filename": "tex1_32x32_15f350b2b7f46481_66860824280a89bf_8"
},
{
@ -180,7 +180,7 @@
},
{
"type": "draw_started",
"prettyname": "Buttom Prompt B",
"prettyname": "Button Prompt B",
"texture_filename": "tex1_32x32_ce62786fc1170192_70b585e07941e91c_8"
},
{
@ -195,7 +195,7 @@
},
{
"type": "draw_started",
"prettyname": "Buttom Prompt X",
"prettyname": "Button Prompt X",
"texture_filename": "tex1_32x32_b52817e68be0e2d7_d1b283ce04ce1c7c_8"
},
{
@ -205,7 +205,7 @@
},
{
"type": "draw_started",
"prettyname": "Buttom Prompt A",
"prettyname": "Button Prompt A",
"texture_filename": "tex1_32x32_630cfa888a9d005a_d95570935377e345_8"
},
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

@ -106,14 +106,14 @@ void main()
// scaling while also being able to use the luminance channel.
float4 ictcp_color = LinearRGBToICtCP(color);
// Scale the color in perceptual space depending on the percieved luminance.
// Scale the color in perceptual space depending on the perceived luminance.
//
// At low luminances, ~0.0, pow(AMPLIFICATION, ~0.0) ~= 1.0, so the
// color will appear to be unchanged. This is important as we don't want to
// over expose dark colors which would not have otherwise been seen.
//
// At high luminances, ~1.0, pow(AMPLIFICATION, ~1.0) ~= AMPLIFICATION,
// which is equivilant to scaling the color by AMPLIFICATION. This is
// which is equivalent to scaling the color by AMPLIFICATION. This is
// important as we want to get the most out of the display, and we want to
// get bright colors to hit their target brightness.
//

View file

@ -391,7 +391,7 @@ bool supportsSIMD(uint simd_width)
#endif
}
// "Error: The AsciiArt shader requires the missing GPU extention KHR_shader_subgroup."
// "Error: The AsciiArt shader requires the missing GPU extension KHR_shader_subgroup."
const uint missing_subgroup_warning_len = 82;
const uint missing_subgroup_warning[missing_subgroup_warning_len] = {
37, 82, 82, 79, 82, 26, 95, 52, 72, 69, 95, 33, 83, 67, 73, 73, 33, 82, 84, 95, 83,

View file

@ -353,7 +353,7 @@ void main()
// Doing linear sampling in "gamma space" on linear texture formats isn't correct.
// If the source and target resolutions don't match, the GPU will return a color
// that is the average of 4 gamma space colors, but gamma space colors can't be blended together,
// gamma neeeds to be de-applied first. This makes a big difference if colors change
// gamma needs to be de-applied first. This makes a big difference if colors change
// drastically between two pixels.
color = LinearGammaCorrectedSample(game_gamma);

View file

@ -40,7 +40,7 @@ void main()
/*****inline square root routines*****/
// bit of a performance bottleneck.
// neccessary to make the darkened area rounded
// necessary to make the darkened area rounded
// instead of rhombus-shaped.
float sqrt = x / 10.0;

View file

@ -50,7 +50,7 @@ void main()
//****inline square root routines*****/
// bit of a performance bottleneck.
// neccessary to make the darkened area rounded
// necessary to make the darkened area rounded
// instead of rhombus-shaped.
float sqrt = x / 10.0;
while ((sqrt*sqrt) < x)

View file

@ -0,0 +1,10 @@
TITLES = (type: Triforce language: EN version: 20210908)
S000 = Triforce Firmware Update For Compact Flash Box (4.01)
SBEY = Virtua Striker 2002
SBFX = The Key Of Avalon
SBGG = F-Zero AX
SBHZ = Virtua Striker 4 (Asia)
SBJA = Virtua Striker 4 (Export)
SBJN = The Key Of Avalon 2.5: War of the Key
SBLK = Virtua Striker 4 Ver.2006 (Japan)
SBLL = Virtua Striker 4 Ver.2006 (Export)

View file

@ -1,7 +1,7 @@
[Desktop Entry]
Version=1.0
Icon=dolphin-emu
Exec=env QT_QPA_PLATFORM=xcb dolphin-emu
Exec=dolphin-emu
Terminal=false
Type=Application
Categories=Game;Emulator;

View file

@ -1,31 +1,34 @@
set(SRC_NETWORK
src/SFML/Network/Http.cpp
src/SFML/Network/IPAddress.cpp
src/SFML/Network/Packet.cpp
src/SFML/Network/Socket.cpp
src/SFML/Network/SocketSelector.cpp
src/SFML/Network/TcpListener.cpp
src/SFML/Network/TcpSocket.cpp
src/SFML/Network/UdpSocket.cpp
SFML/src/SFML/Network/Http.cpp
SFML/src/SFML/Network/IpAddress.cpp
SFML/src/SFML/Network/Packet.cpp
SFML/src/SFML/Network/Socket.cpp
SFML/src/SFML/Network/SocketSelector.cpp
SFML/src/SFML/Network/TcpListener.cpp
SFML/src/SFML/Network/TcpSocket.cpp
SFML/src/SFML/Network/UdpSocket.cpp
)
if(WIN32)
list(APPEND SRC_NETWORK src/SFML/Network/Win32/SocketImpl.cpp)
list(APPEND SRC_NETWORK SFML/src/SFML/Network/Win32/SocketImpl.cpp)
else()
list(APPEND SRC_NETWORK src/SFML/Network/Unix/SocketImpl.cpp)
list(APPEND SRC_NETWORK SFML/src/SFML/Network/Unix/SocketImpl.cpp)
endif()
set(SRC_SYSTEM
src/SFML/System/Err.cpp
src/SFML/System/String.cpp
src/SFML/System/Time.cpp
SFML/src/SFML/System/Err.cpp
SFML/include/SFML/System/String.hpp
SFML/src/SFML/System/String.cpp
SFML/src/SFML/System/Utils.cpp
)
add_library(sfml-network STATIC ${SRC_NETWORK})
add_library(sfml-system STATIC ${SRC_SYSTEM})
target_compile_features(sfml-network PUBLIC cxx_std_17)
target_compile_features(sfml-system PUBLIC cxx_std_17)
target_compile_definitions(sfml-system PUBLIC SFML_STATIC)
target_include_directories(sfml-system PUBLIC include PRIVATE src)
target_include_directories(sfml-network PUBLIC include PRIVATE src)
target_include_directories(sfml-system PUBLIC SFML/include PRIVATE SFML/src)
target_include_directories(sfml-network PUBLIC SFML/include PRIVATE SFML/src)
target_link_libraries(sfml-network PUBLIC sfml-system)
dolphin_disable_warnings(sfml-network)
dolphin_disable_warnings(sfml-system)

1
Externals/SFML/SFML vendored Submodule

@ -0,0 +1 @@
Subproject commit 7f1162dfea4969bc17417563ac55d93b72e84c1e

67
Externals/SFML/SFML.vcxproj vendored Normal file
View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Project="..\..\Source\VSProps\Base.Macros.props" />
<Import Project="$(VSPropsDir)Base.Targets.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{93D73454-2512-424E-9CDA-4BB357FE13DD}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
<Import Project="$(VSPropsDir)Base.props" />
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>SFML\include;SFML\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="SFML\src\SFML\Network\Http.cpp" />
<ClCompile Include="SFML\src\SFML\Network\IpAddress.cpp" />
<ClCompile Include="SFML\src\SFML\Network\Packet.cpp" />
<ClCompile Include="SFML\src\SFML\Network\Socket.cpp" />
<ClCompile Include="SFML\src\SFML\Network\SocketSelector.cpp" />
<ClCompile Include="SFML\src\SFML\Network\TcpListener.cpp" />
<ClCompile Include="SFML\src\SFML\Network\TcpSocket.cpp" />
<ClCompile Include="SFML\src\SFML\Network\UdpSocket.cpp" />
<ClCompile Include="SFML\src\SFML\Network\Win32\SocketImpl.cpp" />
<ClCompile Include="SFML\src\SFML\System\Err.cpp" />
<ClCompile Include="SFML\src\SFML\System\String.cpp" />
<ClCompile Include="SFML\src\SFML\System\Utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="SFML\include\SFML\Config.hpp" />
<ClInclude Include="SFML\include\SFML\Network.hpp" />
<ClInclude Include="SFML\include\SFML\Network\Export.hpp" />
<ClInclude Include="SFML\include\SFML\Network\Http.hpp" />
<ClInclude Include="SFML\include\SFML\Network\IPAddress.hpp" />
<ClInclude Include="SFML\include\SFML\Network\Packet.hpp" />
<ClInclude Include="SFML\include\SFML\Network\Socket.hpp" />
<ClInclude Include="SFML\include\SFML\Network\SocketHandle.hpp" />
<ClInclude Include="SFML\include\SFML\Network\SocketSelector.hpp" />
<ClInclude Include="SFML\include\SFML\Network\TcpListener.hpp" />
<ClInclude Include="SFML\include\SFML\Network\TcpSocket.hpp" />
<ClInclude Include="SFML\include\SFML\Network\UdpSocket.hpp" />
<ClInclude Include="SFML\include\SFML\System.hpp" />
<ClInclude Include="SFML\include\SFML\System\Err.hpp" />
<ClInclude Include="SFML\include\SFML\System\Export.hpp" />
<ClInclude Include="SFML\include\SFML\System\NonCopyable.hpp" />
<ClInclude Include="SFML\include\SFML\System\String.hpp" />
<ClInclude Include="SFML\include\SFML\System\String.inl" />
<ClInclude Include="SFML\include\SFML\System\Utf.hpp" />
<ClInclude Include="SFML\include\SFML\System\Utf.inl" />
<ClInclude Include="SFML\src\SFML\Network\SocketImpl.hpp" />
<ClInclude Include="SFML\src\SFML\Network\Win32\SocketImpl.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Project="..\..\..\..\Source\VSProps\Base.Macros.props" />
<Import Project="$(VSPropsDir)Base.Targets.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{93D73454-2512-424E-9CDA-4BB357FE13DD}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VSPropsDir)Base.props" />
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\..\include;..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\SFML\Network\Http.cpp" />
<ClCompile Include="..\..\src\SFML\Network\IPAddress.cpp" />
<ClCompile Include="..\..\src\SFML\Network\Packet.cpp" />
<ClCompile Include="..\..\src\SFML\Network\Socket.cpp" />
<ClCompile Include="..\..\src\SFML\Network\SocketSelector.cpp" />
<ClCompile Include="..\..\src\SFML\Network\TcpListener.cpp" />
<ClCompile Include="..\..\src\SFML\Network\TcpSocket.cpp" />
<ClCompile Include="..\..\src\SFML\Network\UdpSocket.cpp" />
<ClCompile Include="..\..\src\SFML\Network\Win32\SocketImpl.cpp" />
<ClCompile Include="..\..\src\SFML\System\Err.cpp" />
<ClCompile Include="..\..\src\SFML\System\String.cpp" />
<ClCompile Include="..\..\src\SFML\System\Time.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\SFML\Config.hpp" />
<ClInclude Include="..\..\include\SFML\Network.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Export.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Http.hpp" />
<ClInclude Include="..\..\include\SFML\Network\IPAddress.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Packet.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Socket.hpp" />
<ClInclude Include="..\..\include\SFML\Network\SocketHandle.hpp" />
<ClInclude Include="..\..\include\SFML\Network\SocketSelector.hpp" />
<ClInclude Include="..\..\include\SFML\Network\TcpListener.hpp" />
<ClInclude Include="..\..\include\SFML\Network\TcpSocket.hpp" />
<ClInclude Include="..\..\include\SFML\Network\UdpSocket.hpp" />
<ClInclude Include="..\..\include\SFML\System.hpp" />
<ClInclude Include="..\..\include\SFML\System\Err.hpp" />
<ClInclude Include="..\..\include\SFML\System\Export.hpp" />
<ClInclude Include="..\..\include\SFML\System\NonCopyable.hpp" />
<ClInclude Include="..\..\include\SFML\System\String.hpp" />
<ClInclude Include="..\..\include\SFML\System\String.inl" />
<ClInclude Include="..\..\include\SFML\System\Time.hpp" />
<ClInclude Include="..\..\include\SFML\System\Utf.hpp" />
<ClInclude Include="..\..\include\SFML\System\Utf.inl" />
<ClInclude Include="..\..\src\SFML\Network\SocketImpl.hpp" />
<ClInclude Include="..\..\src\SFML\Network\Win32\SocketImpl.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemGroup>
<ClCompile Include="..\..\src\SFML\Network\Http.cpp" />
<ClCompile Include="..\..\src\SFML\Network\IPAddress.cpp" />
<ClCompile Include="..\..\src\SFML\Network\Packet.cpp" />
<ClCompile Include="..\..\src\SFML\Network\Socket.cpp" />
<ClCompile Include="..\..\src\SFML\Network\SocketSelector.cpp" />
<ClCompile Include="..\..\src\SFML\Network\TcpListener.cpp" />
<ClCompile Include="..\..\src\SFML\Network\TcpSocket.cpp" />
<ClCompile Include="..\..\src\SFML\Network\UdpSocket.cpp" />
<ClCompile Include="..\..\src\SFML\Network\Win32\SocketImpl.cpp">
<Filter>Win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\SFML\System\Err.cpp" />
<ClCompile Include="..\..\src\SFML\System\String.cpp" />
<ClCompile Include="..\..\src\SFML\System\Time.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\SFML\Config.hpp" />
<ClInclude Include="..\..\include\SFML\Network.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Export.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Http.hpp" />
<ClInclude Include="..\..\include\SFML\Network\IPAddress.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Packet.hpp" />
<ClInclude Include="..\..\include\SFML\Network\Socket.hpp" />
<ClInclude Include="..\..\include\SFML\Network\SocketHandle.hpp" />
<ClInclude Include="..\..\include\SFML\Network\SocketSelector.hpp" />
<ClInclude Include="..\..\include\SFML\Network\TcpListener.hpp" />
<ClInclude Include="..\..\include\SFML\Network\TcpSocket.hpp" />
<ClInclude Include="..\..\include\SFML\Network\UdpSocket.hpp" />
<ClInclude Include="..\..\include\SFML\System.hpp" />
<ClInclude Include="..\..\include\SFML\System\Err.hpp" />
<ClInclude Include="..\..\include\SFML\System\Export.hpp" />
<ClInclude Include="..\..\include\SFML\System\NonCopyable.hpp" />
<ClInclude Include="..\..\include\SFML\System\String.hpp" />
<ClInclude Include="..\..\include\SFML\System\String.inl" />
<ClInclude Include="..\..\include\SFML\System\Time.hpp" />
<ClInclude Include="..\..\include\SFML\System\Utf.hpp" />
<ClInclude Include="..\..\include\SFML\System\Utf.inl" />
<ClInclude Include="..\..\src\SFML\Network\SocketImpl.hpp" />
<ClInclude Include="..\..\src\SFML\Network\Win32\SocketImpl.hpp">
<Filter>Win32</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Win32">
<UniqueIdentifier>{8280ecca-24fc-48a2-b7f5-6aca41826b66}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View file

@ -2,12 +2,12 @@
<Project>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(ExternalsDir)SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)SFML\SFML\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(ExternalsDir)SFML\build\vc2010\SFML_Network.vcxproj">
<ProjectReference Include="$(ExternalsDir)SFML\SFML.vcxproj">
<Project>{93d73454-2512-424e-9cda-4bb357fe13dd}</Project>
</ProjectReference>
</ItemGroup>

View file

@ -1,236 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_CONFIG_HPP
#define SFML_CONFIG_HPP
////////////////////////////////////////////////////////////
// Define the SFML version
////////////////////////////////////////////////////////////
#define SFML_VERSION_MAJOR 2
#define SFML_VERSION_MINOR 5
#define SFML_VERSION_PATCH 0
////////////////////////////////////////////////////////////
// Identify the operating system
// see http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
////////////////////////////////////////////////////////////
#if defined(_WIN32)
// Windows
#define SFML_SYSTEM_WINDOWS
#ifndef NOMINMAX
#define NOMINMAX
#endif
#elif defined(__APPLE__) && defined(__MACH__)
// Apple platform, see which one it is
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
// iOS
#define SFML_SYSTEM_IOS
#elif TARGET_OS_MAC
// MacOS
#define SFML_SYSTEM_MACOS
#else
// Unsupported Apple system
#error This Apple operating system is not supported by SFML library
#endif
#elif defined(__unix__)
// UNIX system, see which one it is
#if defined(__ANDROID__)
// Android
#define SFML_SYSTEM_ANDROID
#elif defined(__linux__)
// Linux
#define SFML_SYSTEM_LINUX
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
// FreeBSD
#define SFML_SYSTEM_FREEBSD
#elif defined(__OpenBSD__)
// OpenBSD
#define SFML_SYSTEM_OPENBSD
#else
// Unsupported UNIX system
#error This UNIX operating system is not supported by SFML library
#endif
#else
// Unsupported system
#error This operating system is not supported by SFML library
#endif
////////////////////////////////////////////////////////////
// Define a portable debug macro
////////////////////////////////////////////////////////////
#if !defined(NDEBUG)
#define SFML_DEBUG
#endif
////////////////////////////////////////////////////////////
// Define helpers to create portable import / export macros for each module
////////////////////////////////////////////////////////////
#if !defined(SFML_STATIC)
#if defined(SFML_SYSTEM_WINDOWS)
// Windows compilers need specific (and different) keywords for export and import
#define SFML_API_EXPORT __declspec(dllexport)
#define SFML_API_IMPORT __declspec(dllimport)
// For Visual C++ compilers, we also need to turn off this annoying C4251 warning
#ifdef _MSC_VER
#pragma warning(disable: 4251)
#endif
#else // Linux, FreeBSD, Mac OS X
#if __GNUC__ >= 4
// GCC 4 has special keywords for showing/hidding symbols,
// the same keyword is used for both importing and exporting
#define SFML_API_EXPORT __attribute__ ((__visibility__ ("default")))
#define SFML_API_IMPORT __attribute__ ((__visibility__ ("default")))
#else
// GCC < 4 has no mechanism to explicitely hide symbols, everything's exported
#define SFML_API_EXPORT
#define SFML_API_IMPORT
#endif
#endif
#else
// Static build doesn't need import/export macros
#define SFML_API_EXPORT
#define SFML_API_IMPORT
#endif
////////////////////////////////////////////////////////////
// Cross-platform warning for deprecated functions and classes
//
// Usage:
// class SFML_DEPRECATED MyClass
// {
// SFML_DEPRECATED void memberFunc();
// };
//
// SFML_DEPRECATED void globalFunc();
////////////////////////////////////////////////////////////
#if defined(SFML_NO_DEPRECATED_WARNINGS)
// User explicitly requests to disable deprecation warnings
#define SFML_DEPRECATED
#elif defined(_MSC_VER)
// Microsoft C++ compiler
// Note: On newer MSVC versions, using deprecated functions causes a compiler error. In order to
// trigger a warning instead of an error, the compiler flag /sdl- (instead of /sdl) must be specified.
#define SFML_DEPRECATED __declspec(deprecated)
#elif defined(__GNUC__)
// g++ and Clang
#define SFML_DEPRECATED __attribute__ ((deprecated))
#else
// Other compilers are not supported, leave class or function as-is.
// With a bit of luck, the #pragma directive works, otherwise users get a warning (no error!) for unrecognized #pragma.
#pragma message("SFML_DEPRECATED is not supported for your compiler, please contact the SFML team")
#define SFML_DEPRECATED
#endif
////////////////////////////////////////////////////////////
// Define portable fixed-size types
////////////////////////////////////////////////////////////
namespace sf
{
// All "common" platforms use the same size for char, short and int
// (basically there are 3 types for 3 sizes, so no other match is possible),
// we can use them without doing any kind of check
// 8 bits integer types
typedef signed char Int8;
typedef unsigned char Uint8;
// 16 bits integer types
typedef signed short Int16;
typedef unsigned short Uint16;
// 32 bits integer types
typedef signed int Int32;
typedef unsigned int Uint32;
// 64 bits integer types
#if defined(_MSC_VER)
typedef signed __int64 Int64;
typedef unsigned __int64 Uint64;
#else
typedef signed long long Int64;
typedef unsigned long long Uint64;
#endif
} // namespace sf
#endif // SFML_CONFIG_HPP

View file

@ -1,55 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_NETWORK_HPP
#define SFML_NETWORK_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System.hpp>
//#include <SFML/Network/Ftp.hpp>
#include <SFML/Network/Http.hpp>
// This file is "IpAddress.hpp" upstream
#include <SFML/Network/IPAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/SocketHandle.hpp>
#include <SFML/Network/SocketSelector.hpp>
#include <SFML/Network/TcpListener.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/Network/UdpSocket.hpp>
#endif // SFML_NETWORK_HPP
////////////////////////////////////////////////////////////
/// \defgroup network Network module
///
/// Socket-based communication, utilities and higher-level
/// network protocols (HTTP, FTP).
///
////////////////////////////////////////////////////////////

View file

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_NETWORK_EXPORT_HPP
#define SFML_NETWORK_EXPORT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
// Define portable import / export macros
////////////////////////////////////////////////////////////
#if defined(SFML_NETWORK_EXPORTS)
#define SFML_NETWORK_API SFML_API_EXPORT
#else
#define SFML_NETWORK_API SFML_API_IMPORT
#endif
#endif // SFML_NETWORK_EXPORT_HPP

View file

@ -1,482 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_HTTP_HPP
#define SFML_HTTP_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/IPAddress.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Time.hpp>
#include <map>
#include <string>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief A HTTP client
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Http : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Define a HTTP request
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Request
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumerate the available HTTP methods for a request
///
////////////////////////////////////////////////////////////
enum Method
{
Get, ///< Request in get mode, standard method to retrieve a page
Post, ///< Request in post mode, usually to send data to a page
Head, ///< Request a page's header only
Put, ///< Request in put mode, useful for a REST API
Delete ///< Request in delete mode, useful for a REST API
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates a GET request, with the root
/// URI ("/") and an empty body.
///
/// \param uri Target URI
/// \param method Method to use for the request
/// \param body Content of the request's body
///
////////////////////////////////////////////////////////////
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "");
////////////////////////////////////////////////////////////
/// \brief Set the value of a field
///
/// The field is created if it doesn't exist. The name of
/// the field is case-insensitive.
/// By default, a request doesn't contain any field (but the
/// mandatory fields are added later by the HTTP client when
/// sending the request).
///
/// \param field Name of the field to set
/// \param value Value of the field
///
////////////////////////////////////////////////////////////
void setField(const std::string& field, const std::string& value);
////////////////////////////////////////////////////////////
/// \brief Set the request method
///
/// See the Method enumeration for a complete list of all
/// the availale methods.
/// The method is Http::Request::Get by default.
///
/// \param method Method to use for the request
///
////////////////////////////////////////////////////////////
void setMethod(Method method);
////////////////////////////////////////////////////////////
/// \brief Set the requested URI
///
/// The URI is the resource (usually a web page or a file)
/// that you want to get or post.
/// The URI is "/" (the root page) by default.
///
/// \param uri URI to request, relative to the host
///
////////////////////////////////////////////////////////////
void setUri(const std::string& uri);
////////////////////////////////////////////////////////////
/// \brief Set the HTTP version for the request
///
/// The HTTP version is 1.0 by default.
///
/// \param major Major HTTP version number
/// \param minor Minor HTTP version number
///
////////////////////////////////////////////////////////////
void setHttpVersion(unsigned int major, unsigned int minor);
////////////////////////////////////////////////////////////
/// \brief Set the body of the request
///
/// The body of a request is optional and only makes sense
/// for POST requests. It is ignored for all other methods.
/// The body is empty by default.
///
/// \param body Content of the body
///
////////////////////////////////////////////////////////////
void setBody(const std::string& body);
private:
friend class Http;
////////////////////////////////////////////////////////////
/// \brief Prepare the final request to send to the server
///
/// This is used internally by Http before sending the
/// request to the web server.
///
/// \return String containing the request, ready to be sent
///
////////////////////////////////////////////////////////////
std::string prepare() const;
////////////////////////////////////////////////////////////
/// \brief Check if the request defines a field
///
/// This function uses case-insensitive comparisons.
///
/// \param field Name of the field to test
///
/// \return True if the field exists, false otherwise
///
////////////////////////////////////////////////////////////
bool hasField(const std::string& field) const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::map<std::string, std::string> FieldTable;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FieldTable m_fields; ///< Fields of the header associated to their value
Method m_method; ///< Method to use for the request
std::string m_uri; ///< Target URI of the request
unsigned int m_majorVersion; ///< Major HTTP version
unsigned int m_minorVersion; ///< Minor HTTP version
std::string m_body; ///< Body of the request
};
////////////////////////////////////////////////////////////
/// \brief Define a HTTP response
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Response
{
public:
////////////////////////////////////////////////////////////
/// \brief Enumerate all the valid status codes for a response
///
////////////////////////////////////////////////////////////
enum Status
{
// 2xx: success
Ok = 200, ///< Most common code returned when operation was successful
Created = 201, ///< The resource has successfully been created
Accepted = 202, ///< The request has been accepted, but will be processed later by the server
NoContent = 204, ///< The server didn't send any data in return
ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent
PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request
// 3xx: redirection
MultipleChoices = 300, ///< The requested page can be accessed from several locations
MovedPermanently = 301, ///< The requested page has permanently moved to a new location
MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location
NotModified = 304, ///< For conditional requests, means the requested page hasn't changed and doesn't need to be refreshed
// 4xx: client error
BadRequest = 400, ///< The server couldn't understand the request (syntax error)
Unauthorized = 401, ///< The requested page needs an authentication to be accessed
Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentication
NotFound = 404, ///< The requested page doesn't exist
RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field)
// 5xx: server error
InternalServerError = 500, ///< The server encountered an unexpected error
NotImplemented = 501, ///< The server doesn't implement a requested feature
BadGateway = 502, ///< The gateway server has received an error from the source server
ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...)
GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server
VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version
// 10xx: SFML custom codes
InvalidResponse = 1000, ///< Response is not a valid HTTP one
ConnectionFailed = 1001 ///< Connection with server failed
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructs an empty response.
///
////////////////////////////////////////////////////////////
Response();
////////////////////////////////////////////////////////////
/// \brief Get the value of a field
///
/// If the field \a field is not found in the response header,
/// the empty string is returned. This function uses
/// case-insensitive comparisons.
///
/// \param field Name of the field to get
///
/// \return Value of the field, or empty string if not found
///
////////////////////////////////////////////////////////////
const std::string& getField(const std::string& field) const;
////////////////////////////////////////////////////////////
/// \brief Get the response status code
///
/// The status code should be the first thing to be checked
/// after receiving a response, it defines whether it is a
/// success, a failure or anything else (see the Status
/// enumeration).
///
/// \return Status code of the response
///
////////////////////////////////////////////////////////////
Status getStatus() const;
////////////////////////////////////////////////////////////
/// \brief Get the major HTTP version number of the response
///
/// \return Major HTTP version number
///
/// \see getMinorHttpVersion
///
////////////////////////////////////////////////////////////
unsigned int getMajorHttpVersion() const;
////////////////////////////////////////////////////////////
/// \brief Get the minor HTTP version number of the response
///
/// \return Minor HTTP version number
///
/// \see getMajorHttpVersion
///
////////////////////////////////////////////////////////////
unsigned int getMinorHttpVersion() const;
////////////////////////////////////////////////////////////
/// \brief Get the body of the response
///
/// The body of a response may contain:
/// \li the requested page (for GET requests)
/// \li a response from the server (for POST requests)
/// \li nothing (for HEAD requests)
/// \li an error message (in case of an error)
///
/// \return The response body
///
////////////////////////////////////////////////////////////
const std::string& getBody() const;
private:
friend class Http;
////////////////////////////////////////////////////////////
/// \brief Construct the header from a response string
///
/// This function is used by Http to build the response
/// of a request.
///
/// \param data Content of the response to parse
///
////////////////////////////////////////////////////////////
void parse(const std::string& data);
////////////////////////////////////////////////////////////
/// \brief Read values passed in the answer header
///
/// This function is used by Http to extract values passed
/// in the response.
///
/// \param in String stream containing the header values
///
////////////////////////////////////////////////////////////
void parseFields(std::istream &in);
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::map<std::string, std::string> FieldTable;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FieldTable m_fields; ///< Fields of the header
Status m_status; ///< Status code
unsigned int m_majorVersion; ///< Major HTTP version
unsigned int m_minorVersion; ///< Minor HTTP version
std::string m_body; ///< Body of the response
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Http();
////////////////////////////////////////////////////////////
/// \brief Construct the HTTP client with the target host
///
/// This is equivalent to calling setHost(host, port).
/// The port has a default value of 0, which means that the
/// HTTP client will use the right port according to the
/// protocol used (80 for HTTP). You should leave it like
/// this unless you really need a port other than the
/// standard one, or use an unknown protocol.
///
/// \param host Web server to connect to
/// \param port Port to use for connection
///
////////////////////////////////////////////////////////////
Http(const std::string& host, unsigned short port = 0);
////////////////////////////////////////////////////////////
/// \brief Set the target host
///
/// This function just stores the host address and port, it
/// doesn't actually connect to it until you send a request.
/// The port has a default value of 0, which means that the
/// HTTP client will use the right port according to the
/// protocol used (80 for HTTP). You should leave it like
/// this unless you really need a port other than the
/// standard one, or use an unknown protocol.
///
/// \param host Web server to connect to
/// \param port Port to use for connection
///
////////////////////////////////////////////////////////////
void setHost(const std::string& host, unsigned short port = 0);
////////////////////////////////////////////////////////////
/// \brief Send a HTTP request and return the server's response.
///
/// You must have a valid host before sending a request (see setHost).
/// Any missing mandatory header field in the request will be added
/// with an appropriate value.
/// Warning: this function waits for the server's response and may
/// not return instantly; use a thread if you don't want to block your
/// application, or use a timeout to limit the time to wait. A value
/// of Time::Zero means that the client will use the system default timeout
/// (which is usually pretty long).
///
/// \param request Request to send
/// \param timeout Maximum time to wait
///
/// \return Server's response
///
////////////////////////////////////////////////////////////
Response sendRequest(const Request& request, Time timeout = Time::Zero);
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
TcpSocket m_connection; ///< Connection to the host
IpAddress m_host; ///< Web host address
std::string m_hostName; ///< Web host name
unsigned short m_port; ///< Port used for connection with host
};
} // namespace sf
#endif // SFML_HTTP_HPP
////////////////////////////////////////////////////////////
/// \class sf::Http
/// \ingroup network
///
/// sf::Http is a very simple HTTP client that allows you
/// to communicate with a web server. You can retrieve
/// web pages, send data to an interactive resource,
/// download a remote file, etc. The HTTPS protocol is
/// not supported.
///
/// The HTTP client is split into 3 classes:
/// \li sf::Http::Request
/// \li sf::Http::Response
/// \li sf::Http
///
/// sf::Http::Request builds the request that will be
/// sent to the server. A request is made of:
/// \li a method (what you want to do)
/// \li a target URI (usually the name of the web page or file)
/// \li one or more header fields (options that you can pass to the server)
/// \li an optional body (for POST requests)
///
/// sf::Http::Response parse the response from the web server
/// and provides getters to read them. The response contains:
/// \li a status code
/// \li header fields (that may be answers to the ones that you requested)
/// \li a body, which contains the contents of the requested resource
///
/// sf::Http provides a simple function, SendRequest, to send a
/// sf::Http::Request and return the corresponding sf::Http::Response
/// from the server.
///
/// Usage example:
/// \code
/// // Create a new HTTP client
/// sf::Http http;
///
/// // We'll work on http://www.sfml-dev.org
/// http.setHost("http://www.sfml-dev.org");
///
/// // Prepare a request to get the 'features.php' page
/// sf::Http::Request request("features.php");
///
/// // Send the request
/// sf::Http::Response response = http.sendRequest(request);
///
/// // Check the status code and display the result
/// sf::Http::Response::Status status = response.getStatus();
/// if (status == sf::Http::Response::Ok)
/// {
/// std::cout << response.getBody() << std::endl;
/// }
/// else
/// {
/// std::cout << "Error " << status << std::endl;
/// }
/// \endcode
///
////////////////////////////////////////////////////////////

View file

@ -1,328 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_IPADDRESS_HPP
#define SFML_IPADDRESS_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/System/Time.hpp>
#include <istream>
#include <ostream>
#include <string>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Encapsulate an IPv4 network address
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API IpAddress
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates an empty (invalid) address
///
////////////////////////////////////////////////////////////
IpAddress();
////////////////////////////////////////////////////////////
/// \brief Construct the address from a string
///
/// Here \a address can be either a decimal address
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
///
/// \param address IP address or network name
///
////////////////////////////////////////////////////////////
IpAddress(const std::string& address);
////////////////////////////////////////////////////////////
/// \brief Construct the address from a string
///
/// Here \a address can be either a decimal address
/// (ex: "192.168.1.56") or a network name (ex: "localhost").
/// This is equivalent to the constructor taking a std::string
/// parameter, it is defined for convenience so that the
/// implicit conversions from literal strings to IpAddress work.
///
/// \param address IP address or network name
///
////////////////////////////////////////////////////////////
IpAddress(const char* address);
////////////////////////////////////////////////////////////
/// \brief Construct the address from 4 bytes
///
/// Calling IpAddress(a, b, c, d) is equivalent to calling
/// IpAddress("a.b.c.d"), but safer as it doesn't have to
/// parse a string to get the address components.
///
/// \param byte0 First byte of the address
/// \param byte1 Second byte of the address
/// \param byte2 Third byte of the address
/// \param byte3 Fourth byte of the address
///
////////////////////////////////////////////////////////////
IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3);
////////////////////////////////////////////////////////////
/// \brief Construct the address from a 32-bits integer
///
/// This constructor uses the internal representation of
/// the address directly. It should be used for optimization
/// purposes, and only if you got that representation from
/// IpAddress::toInteger().
///
/// \param address 4 bytes of the address packed into a 32-bits integer
///
/// \see toInteger
///
////////////////////////////////////////////////////////////
explicit IpAddress(Uint32 address);
////////////////////////////////////////////////////////////
/// \brief Get a string representation of the address
///
/// The returned string is the decimal representation of the
/// IP address (like "192.168.1.56"), even if it was constructed
/// from a host name.
///
/// \return String representation of the address
///
/// \see toInteger
///
////////////////////////////////////////////////////////////
std::string toString() const;
////////////////////////////////////////////////////////////
/// \brief Get an integer representation of the address
///
/// The returned number is the internal representation of the
/// address, and should be used for optimization purposes only
/// (like sending the address through a socket).
/// The integer produced by this function can then be converted
/// back to a sf::IpAddress with the proper constructor.
///
/// \return 32-bits unsigned integer representation of the address
///
/// \see toString
///
////////////////////////////////////////////////////////////
Uint32 toInteger() const;
////////////////////////////////////////////////////////////
/// \brief Get the computer's local address
///
/// The local address is the address of the computer from the
/// LAN point of view, i.e. something like 192.168.1.56. It is
/// meaningful only for communications over the local network.
/// Unlike getPublicAddress, this function is fast and may be
/// used safely anywhere.
///
/// \return Local IP address of the computer
///
/// \see getPublicAddress
///
////////////////////////////////////////////////////////////
static IpAddress getLocalAddress();
////////////////////////////////////////////////////////////
/// \brief Get the computer's public address
///
/// The public address is the address of the computer from the
/// internet point of view, i.e. something like 89.54.1.169.
/// It is necessary for communications over the world wide web.
/// The only way to get a public address is to ask it to a
/// distant website; as a consequence, this function depends on
/// both your network connection and the server, and may be
/// very slow. You should use it as few as possible. Because
/// this function depends on the network connection and on a distant
/// server, you may use a time limit if you don't want your program
/// to be possibly stuck waiting in case there is a problem; this
/// limit is deactivated by default.
///
/// \param timeout Maximum time to wait
///
/// \return Public IP address of the computer
///
/// \see getLocalAddress
///
////////////////////////////////////////////////////////////
static IpAddress getPublicAddress(Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
static const IpAddress None; ///< Value representing an empty/invalid address
static const IpAddress Any; ///< Value representing any address (0.0.0.0)
static const IpAddress LocalHost; ///< The "localhost" address (for connecting a computer to itself locally)
static const IpAddress Broadcast; ///< The "broadcast" address (for sending UDP messages to everyone on a local network)
private:
friend SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Resolve the given address string
///
/// \param address Address string
///
////////////////////////////////////////////////////////////
void resolve(const std::string& address);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Uint32 m_address; ///< Address stored as an unsigned 32 bits integer
bool m_valid; ///< Is the address valid?
};
////////////////////////////////////////////////////////////
/// \brief Overload of == operator to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return True if both addresses are equal
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API bool operator ==(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Overload of != operator to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return True if both addresses are different
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API bool operator !=(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Overload of < operator to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return True if \a left is lesser than \a right
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Overload of > operator to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return True if \a left is greater than \a right
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API bool operator >(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Overload of <= operator to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return True if \a left is lesser or equal than \a right
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API bool operator <=(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Overload of >= operator to compare two IP addresses
///
/// \param left Left operand (a IP address)
/// \param right Right operand (a IP address)
///
/// \return True if \a left is greater or equal than \a right
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API bool operator >=(const IpAddress& left, const IpAddress& right);
////////////////////////////////////////////////////////////
/// \brief Overload of >> operator to extract an IP address from an input stream
///
/// \param stream Input stream
/// \param address IP address to extract
///
/// \return Reference to the input stream
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address);
////////////////////////////////////////////////////////////
/// \brief Overload of << operator to print an IP address to an output stream
///
/// \param stream Output stream
/// \param address IP address to print
///
/// \return Reference to the output stream
///
////////////////////////////////////////////////////////////
SFML_NETWORK_API std::ostream& operator <<(std::ostream& stream, const IpAddress& address);
} // namespace sf
#endif // SFML_IPADDRESS_HPP
////////////////////////////////////////////////////////////
/// \class sf::IpAddress
/// \ingroup network
///
/// sf::IpAddress is a utility class for manipulating network
/// addresses. It provides a set a implicit constructors and
/// conversion functions to easily build or transform an IP
/// address from/to various representations.
///
/// Usage example:
/// \code
/// sf::IpAddress a0; // an invalid address
/// sf::IpAddress a1 = sf::IpAddress::None; // an invalid address (same as a0)
/// sf::IpAddress a2("127.0.0.1"); // the local host address
/// sf::IpAddress a3 = sf::IpAddress::Broadcast; // the broadcast address
/// sf::IpAddress a4(192, 168, 1, 56); // a local address
/// sf::IpAddress a5("my_computer"); // a local address created from a network name
/// sf::IpAddress a6("89.54.1.169"); // a distant address
/// sf::IpAddress a7("www.google.com"); // a distant address created from a network name
/// sf::IpAddress a8 = sf::IpAddress::getLocalAddress(); // my address on the local network
/// sf::IpAddress a9 = sf::IpAddress::getPublicAddress(); // my address on the internet
/// \endcode
///
/// Note that sf::IpAddress currently doesn't support IPv6
/// nor other types of network addresses.
///
////////////////////////////////////////////////////////////

View file

@ -1,532 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_PACKET_HPP
#define SFML_PACKET_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <string>
#include <vector>
namespace sf
{
class String;
class TcpSocket;
class UdpSocket;
////////////////////////////////////////////////////////////
/// \brief Utility class to build blocks of data to transfer
/// over the network
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Packet
{
// A bool-like type that cannot be converted to integer or pointer types
typedef bool (Packet::*BoolType)(std::size_t);
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty packet.
///
////////////////////////////////////////////////////////////
Packet();
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~Packet();
////////////////////////////////////////////////////////////
/// \brief Append data to the end of the packet
///
/// \param data Pointer to the sequence of bytes to append
/// \param sizeInBytes Number of bytes to append
///
/// \see clear
///
////////////////////////////////////////////////////////////
void append(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Clear the packet
///
/// After calling Clear, the packet is empty.
///
/// \see append
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Get a pointer to the data contained in the packet
///
/// Warning: the returned pointer may become invalid after
/// you append data to the packet, therefore it should never
/// be stored.
/// The return pointer is NULL if the packet is empty.
///
/// \return Pointer to the data
///
/// \see getDataSize
///
////////////////////////////////////////////////////////////
const void* getData() const;
////////////////////////////////////////////////////////////
/// \brief Get the size of the data contained in the packet
///
/// This function returns the number of bytes pointed to by
/// what getData returns.
///
/// \return Data size, in bytes
///
/// \see getData
///
////////////////////////////////////////////////////////////
std::size_t getDataSize() const;
////////////////////////////////////////////////////////////
/// \brief Tell if the reading position has reached the
/// end of the packet
///
/// This function is useful to know if there is some data
/// left to be read, without actually reading it.
///
/// \return True if all data was read, false otherwise
///
/// \see operator bool
///
////////////////////////////////////////////////////////////
bool endOfPacket() const;
public:
////////////////////////////////////////////////////////////
/// \brief Test the validity of the packet, for reading
///
/// This operator allows to test the packet as a boolean
/// variable, to check if a reading operation was successful.
///
/// A packet will be in an invalid state if it has no more
/// data to read.
///
/// This behavior is the same as standard C++ streams.
///
/// Usage example:
/// \code
/// float x;
/// packet >> x;
/// if (packet)
/// {
/// // ok, x was extracted successfully
/// }
///
/// // -- or --
///
/// float x;
/// if (packet >> x)
/// {
/// // ok, x was extracted successfully
/// }
/// \endcode
///
/// Don't focus on the return type, it's equivalent to bool but
/// it disallows unwanted implicit conversions to integer or
/// pointer types.
///
/// \return True if last data extraction from packet was successful
///
/// \see endOfPacket
///
////////////////////////////////////////////////////////////
operator BoolType() const;
////////////////////////////////////////////////////////////
/// Overload of operator >> to read data from the packet
///
////////////////////////////////////////////////////////////
Packet& operator >>(bool& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Int8& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Uint8& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Int16& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Uint16& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Int32& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Uint32& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Int64& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(Uint64& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(float& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(double& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(char* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(std::string& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(wchar_t* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(std::wstring& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator >>(String& data);
////////////////////////////////////////////////////////////
/// Overload of operator << to write data into the packet
///
////////////////////////////////////////////////////////////
Packet& operator <<(bool data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Int8 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Uint8 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Int16 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Uint16 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Int32 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Uint32 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Int64 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(Uint64 data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(float data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(double data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(const char* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(const std::string& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(const wchar_t* data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(const std::wstring& data);
////////////////////////////////////////////////////////////
/// \overload
////////////////////////////////////////////////////////////
Packet& operator <<(const String& data);
protected:
friend class TcpSocket;
friend class UdpSocket;
////////////////////////////////////////////////////////////
/// \brief Called before the packet is sent over the network
///
/// This function can be defined by derived classes to
/// transform the data before it is sent; this can be
/// used for compression, encryption, etc.
/// The function must return a pointer to the modified data,
/// as well as the number of bytes pointed.
/// The default implementation provides the packet's data
/// without transforming it.
///
/// \param size Variable to fill with the size of data to send
///
/// \return Pointer to the array of bytes to send
///
/// \see onReceive
///
////////////////////////////////////////////////////////////
virtual const void* onSend(std::size_t& size);
////////////////////////////////////////////////////////////
/// \brief Called after the packet is received over the network
///
/// This function can be defined by derived classes to
/// transform the data after it is received; this can be
/// used for decompression, decryption, etc.
/// The function receives a pointer to the received data,
/// and must fill the packet with the transformed bytes.
/// The default implementation fills the packet directly
/// without transforming the data.
///
/// \param data Pointer to the received bytes
/// \param size Number of bytes
///
/// \see onSend
///
////////////////////////////////////////////////////////////
virtual void onReceive(const void* data, std::size_t size);
private:
////////////////////////////////////////////////////////////
/// Disallow comparisons between packets
///
////////////////////////////////////////////////////////////
bool operator ==(const Packet& right) const;
bool operator !=(const Packet& right) const;
////////////////////////////////////////////////////////////
/// \brief Check if the packet can extract a given number of bytes
///
/// This function updates accordingly the state of the packet.
///
/// \param size Size to check
///
/// \return True if \a size bytes can be read from the packet
///
////////////////////////////////////////////////////////////
bool checkSize(std::size_t size);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<char> m_data; ///< Data stored in the packet
std::size_t m_readPos; ///< Current reading position in the packet
std::size_t m_sendPos; ///< Current send position in the packet (for handling partial sends)
bool m_isValid; ///< Reading state of the packet
};
} // namespace sf
#endif // SFML_PACKET_HPP
////////////////////////////////////////////////////////////
/// \class sf::Packet
/// \ingroup network
///
/// Packets provide a safe and easy way to serialize data,
/// in order to send it over the network using sockets
/// (sf::TcpSocket, sf::UdpSocket).
///
/// Packets solve 2 fundamental problems that arise when
/// transferring data over the network:
/// \li data is interpreted correctly according to the endianness
/// \li the bounds of the packet are preserved (one send == one receive)
///
/// The sf::Packet class provides both input and output modes.
/// It is designed to follow the behavior of standard C++ streams,
/// using operators >> and << to extract and insert data.
///
/// It is recommended to use only fixed-size types (like sf::Int32, etc.),
/// to avoid possible differences between the sender and the receiver.
/// Indeed, the native C++ types may have different sizes on two platforms
/// and your data may be corrupted if that happens.
///
/// Usage example:
/// \code
/// sf::Uint32 x = 24;
/// std::string s = "hello";
/// double d = 5.89;
///
/// // Group the variables to send into a packet
/// sf::Packet packet;
/// packet << x << s << d;
///
/// // Send it over the network (socket is a valid sf::TcpSocket)
/// socket.send(packet);
///
/// -----------------------------------------------------------------
///
/// // Receive the packet at the other end
/// sf::Packet packet;
/// socket.receive(packet);
///
/// // Extract the variables contained in the packet
/// sf::Uint32 x;
/// std::string s;
/// double d;
/// if (packet >> x >> s >> d)
/// {
/// // Data extracted successfully...
/// }
/// \endcode
///
/// Packets have built-in operator >> and << overloads for
/// standard types:
/// \li bool
/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32)
/// \li floating point numbers (float, double)
/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String)
///
/// Like standard streams, it is also possible to define your own
/// overloads of operators >> and << in order to handle your
/// custom types.
///
/// \code
/// struct MyStruct
/// {
/// float number;
/// sf::Int8 integer;
/// std::string str;
/// };
///
/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m)
/// {
/// return packet << m.number << m.integer << m.str;
/// }
///
/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m)
/// {
/// return packet >> m.number >> m.integer >> m.str;
/// }
/// \endcode
///
/// Packets also provide an extra feature that allows to apply
/// custom transformations to the data before it is sent,
/// and after it is received. This is typically used to
/// handle automatic compression or encryption of the data.
/// This is achieved by inheriting from sf::Packet, and overriding
/// the onSend and onReceive functions.
///
/// Here is an example:
/// \code
/// class ZipPacket : public sf::Packet
/// {
/// virtual const void* onSend(std::size_t& size)
/// {
/// const void* srcData = getData();
/// std::size_t srcSize = getDataSize();
///
/// return MySuperZipFunction(srcData, srcSize, &size);
/// }
///
/// virtual void onReceive(const void* data, std::size_t size)
/// {
/// std::size_t dstSize;
/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize);
///
/// append(dstData, dstSize);
/// }
/// };
///
/// // Use like regular packets:
/// ZipPacket packet;
/// packet << x << s << d;
/// ...
/// \endcode
///
/// \see sf::TcpSocket, sf::UdpSocket
///
////////////////////////////////////////////////////////////

View file

@ -1,219 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOCKET_HPP
#define SFML_SOCKET_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/SocketHandle.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <vector>
namespace sf
{
class SocketSelector;
////////////////////////////////////////////////////////////
/// \brief Base class for all the socket types
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API Socket : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Status codes that may be returned by socket functions
///
////////////////////////////////////////////////////////////
enum Status
{
Done, ///< The socket has sent / received the data
NotReady, ///< The socket is not ready to send / receive data yet
Partial, ///< The socket sent a part of the data
Disconnected, ///< The TCP socket has been disconnected
Error ///< An unexpected error happened
};
////////////////////////////////////////////////////////////
/// \brief Some special values used by sockets
///
////////////////////////////////////////////////////////////
enum
{
AnyPort = 0 ///< Special value that tells the system to pick any available port
};
public:
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~Socket();
////////////////////////////////////////////////////////////
/// \brief Set the blocking state of the socket
///
/// In blocking mode, calls will not return until they have
/// completed their task. For example, a call to Receive in
/// blocking mode won't return until some data was actually
/// received.
/// In non-blocking mode, calls will always return immediately,
/// using the return code to signal whether there was data
/// available or not.
/// By default, all sockets are blocking.
///
/// \param blocking True to set the socket as blocking, false for non-blocking
///
/// \see isBlocking
///
////////////////////////////////////////////////////////////
void setBlocking(bool blocking);
////////////////////////////////////////////////////////////
/// \brief Tell whether the socket is in blocking or non-blocking mode
///
/// \return True if the socket is blocking, false otherwise
///
/// \see setBlocking
///
////////////////////////////////////////////////////////////
bool isBlocking() const;
protected:
////////////////////////////////////////////////////////////
/// \brief Types of protocols that the socket can use
///
////////////////////////////////////////////////////////////
enum Type
{
Tcp, ///< TCP protocol
Udp ///< UDP protocol
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor can only be accessed by derived classes.
///
/// \param type Type of the socket (TCP or UDP)
///
////////////////////////////////////////////////////////////
Socket(Type type);
////////////////////////////////////////////////////////////
/// \brief Return the internal handle of the socket
///
/// The returned handle may be invalid if the socket
/// was not created yet (or already destroyed).
/// This function can only be accessed by derived classes.
///
/// \return The internal (OS-specific) handle of the socket
///
////////////////////////////////////////////////////////////
SocketHandle getHandle() const;
////////////////////////////////////////////////////////////
/// \brief Create the internal representation of the socket
///
/// This function can only be accessed by derived classes.
///
////////////////////////////////////////////////////////////
void create();
////////////////////////////////////////////////////////////
/// \brief Create the internal representation of the socket
/// from a socket handle
///
/// This function can only be accessed by derived classes.
///
/// \param handle OS-specific handle of the socket to wrap
///
////////////////////////////////////////////////////////////
void create(SocketHandle handle);
////////////////////////////////////////////////////////////
/// \brief Close the socket gracefully
///
/// This function can only be accessed by derived classes.
///
////////////////////////////////////////////////////////////
void close();
private:
friend class SocketSelector;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Type m_type; ///< Type of the socket (TCP or UDP)
SocketHandle m_socket; ///< Socket descriptor
bool m_isBlocking; ///< Current blocking mode of the socket
};
} // namespace sf
#endif // SFML_SOCKET_HPP
////////////////////////////////////////////////////////////
/// \class sf::Socket
/// \ingroup network
///
/// This class mainly defines internal stuff to be used by
/// derived classes.
///
/// The only public features that it defines, and which
/// is therefore common to all the socket classes, is the
/// blocking state. All sockets can be set as blocking or
/// non-blocking.
///
/// In blocking mode, socket functions will hang until
/// the operation completes, which means that the entire
/// program (well, in fact the current thread if you use
/// multiple ones) will be stuck waiting for your socket
/// operation to complete.
///
/// In non-blocking mode, all the socket functions will
/// return immediately. If the socket is not ready to complete
/// the requested operation, the function simply returns
/// the proper status code (Socket::NotReady).
///
/// The default mode, which is blocking, is the one that is
/// generally used, in combination with threads or selectors.
/// The non-blocking mode is rather used in real-time
/// applications that run an endless loop that can poll
/// the socket often enough, and cannot afford blocking
/// this loop.
///
/// \see sf::TcpListener, sf::TcpSocket, sf::UdpSocket
///
////////////////////////////////////////////////////////////

View file

@ -1,57 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOCKETHANDLE_HPP
#define SFML_SOCKETHANDLE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <basetsd.h>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
// Define the low-level socket handle type, specific to
// each platform
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_WINDOWS)
typedef UINT_PTR SocketHandle;
#else
typedef int SocketHandle;
#endif
} // namespace sf
#endif // SFML_SOCKETHANDLE_HPP

View file

@ -1,263 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOCKETSELECTOR_HPP
#define SFML_SOCKETSELECTOR_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/System/Time.hpp>
namespace sf
{
class Socket;
////////////////////////////////////////////////////////////
/// \brief Multiplexer that allows to read from multiple sockets
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API SocketSelector
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SocketSelector();
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
SocketSelector(const SocketSelector& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SocketSelector();
////////////////////////////////////////////////////////////
/// \brief Add a new socket to the selector
///
/// This function keeps a weak reference to the socket,
/// so you have to make sure that the socket is not destroyed
/// while it is stored in the selector.
/// This function does nothing if the socket is not valid.
///
/// \param socket Reference to the socket to add
///
/// \see remove, clear
///
////////////////////////////////////////////////////////////
void add(Socket& socket);
////////////////////////////////////////////////////////////
/// \brief Remove a socket from the selector
///
/// This function doesn't destroy the socket, it simply
/// removes the reference that the selector has to it.
///
/// \param socket Reference to the socket to remove
///
/// \see add, clear
///
////////////////////////////////////////////////////////////
void remove(Socket& socket);
////////////////////////////////////////////////////////////
/// \brief Remove all the sockets stored in the selector
///
/// This function doesn't destroy any instance, it simply
/// removes all the references that the selector has to
/// external sockets.
///
/// \see add, remove
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Wait until one or more sockets are ready to receive
///
/// This function returns as soon as at least one socket has
/// some data available to be received. To know which sockets are
/// ready, use the isReady function.
/// If you use a timeout and no socket is ready before the timeout
/// is over, the function returns false.
///
/// \param timeout Maximum time to wait, (use Time::Zero for infinity)
///
/// \return True if there are sockets ready, false otherwise
///
/// \see isReady
///
////////////////////////////////////////////////////////////
bool wait(Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
/// \brief Test a socket to know if it is ready to receive data
///
/// This function must be used after a call to Wait, to know
/// which sockets are ready to receive data. If a socket is
/// ready, a call to receive will never block because we know
/// that there is data available to read.
/// Note that if this function returns true for a TcpListener,
/// this means that it is ready to accept a new connection.
///
/// \param socket Socket to test
///
/// \return True if the socket is ready to read, false otherwise
///
/// \see isReady
///
////////////////////////////////////////////////////////////
bool isReady(Socket& socket) const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
SocketSelector& operator =(const SocketSelector& right);
private:
struct SocketSelectorImpl;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
SocketSelectorImpl* m_impl; ///< Opaque pointer to the implementation (which requires OS-specific types)
};
} // namespace sf
#endif // SFML_SOCKETSELECTOR_HPP
////////////////////////////////////////////////////////////
/// \class sf::SocketSelector
/// \ingroup network
///
/// Socket selectors provide a way to wait until some data is
/// available on a set of sockets, instead of just one. This
/// is convenient when you have multiple sockets that may
/// possibly receive data, but you don't know which one will
/// be ready first. In particular, it avoids to use a thread
/// for each socket; with selectors, a single thread can handle
/// all the sockets.
///
/// All types of sockets can be used in a selector:
/// \li sf::TcpListener
/// \li sf::TcpSocket
/// \li sf::UdpSocket
///
/// A selector doesn't store its own copies of the sockets
/// (socket classes are not copyable anyway), it simply keeps
/// a reference to the original sockets that you pass to the
/// "add" function. Therefore, you can't use the selector as a
/// socket container, you must store them outside and make sure
/// that they are alive as long as they are used in the selector.
///
/// Using a selector is simple:
/// \li populate the selector with all the sockets that you want to observe
/// \li make it wait until there is data available on any of the sockets
/// \li test each socket to find out which ones are ready
///
/// Usage example:
/// \code
/// // Create a socket to listen to new connections
/// sf::TcpListener listener;
/// listener.listen(55001);
///
/// // Create a list to store the future clients
/// std::list<sf::TcpSocket*> clients;
///
/// // Create a selector
/// sf::SocketSelector selector;
///
/// // Add the listener to the selector
/// selector.add(listener);
///
/// // Endless loop that waits for new connections
/// while (running)
/// {
/// // Make the selector wait for data on any socket
/// if (selector.wait())
/// {
/// // Test the listener
/// if (selector.isReady(listener))
/// {
/// // The listener is ready: there is a pending connection
/// sf::TcpSocket* client = new sf::TcpSocket;
/// if (listener.accept(*client) == sf::Socket::Done)
/// {
/// // Add the new client to the clients list
/// clients.push_back(client);
///
/// // Add the new client to the selector so that we will
/// // be notified when he sends something
/// selector.add(*client);
/// }
/// else
/// {
/// // Error, we won't get a new connection, delete the socket
/// delete client;
/// }
/// }
/// else
/// {
/// // The listener socket is not ready, test all other sockets (the clients)
/// for (std::list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it)
/// {
/// sf::TcpSocket& client = **it;
/// if (selector.isReady(client))
/// {
/// // The client has sent some data, we can receive it
/// sf::Packet packet;
/// if (client.receive(packet) == sf::Socket::Done)
/// {
/// ...
/// }
/// }
/// }
/// }
/// }
/// }
/// \endcode
///
/// \see sf::Socket
///
////////////////////////////////////////////////////////////

View file

@ -1,166 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_TCPLISTENER_HPP
#define SFML_TCPLISTENER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/IPAddress.hpp>
namespace sf
{
class TcpSocket;
////////////////////////////////////////////////////////////
/// \brief Socket that listens to new TCP connections
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API TcpListener : public Socket
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
TcpListener();
////////////////////////////////////////////////////////////
/// \brief Get the port to which the socket is bound locally
///
/// If the socket is not listening to a port, this function
/// returns 0.
///
/// \return Port to which the socket is bound
///
/// \see listen
///
////////////////////////////////////////////////////////////
unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
/// \brief Start listening for incoming connection attempts
///
/// This function makes the socket start listening on the
/// specified port, waiting for incoming connection attempts.
///
/// If the socket is already listening on a port when this
/// function is called, it will stop listening on the old
/// port before starting to listen on the new port.
///
/// \param port Port to listen on for incoming connection attempts
/// \param address Address of the interface to listen on
///
/// \return Status code
///
/// \see accept, close
///
////////////////////////////////////////////////////////////
Status listen(unsigned short port, const IpAddress& address = IpAddress::Any);
////////////////////////////////////////////////////////////
/// \brief Stop listening and close the socket
///
/// This function gracefully stops the listener. If the
/// socket is not listening, this function has no effect.
///
/// \see listen
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
/// \brief Accept a new connection
///
/// If the socket is in blocking mode, this function will
/// not return until a connection is actually received.
///
/// \param socket Socket that will hold the new connection
///
/// \return Status code
///
/// \see listen
///
////////////////////////////////////////////////////////////
Status accept(TcpSocket& socket);
};
} // namespace sf
#endif // SFML_TCPLISTENER_HPP
////////////////////////////////////////////////////////////
/// \class sf::TcpListener
/// \ingroup network
///
/// A listener socket is a special type of socket that listens to
/// a given port and waits for connections on that port.
/// This is all it can do.
///
/// When a new connection is received, you must call accept and
/// the listener returns a new instance of sf::TcpSocket that
/// is properly initialized and can be used to communicate with
/// the new client.
///
/// Listener sockets are specific to the TCP protocol,
/// UDP sockets are connectionless and can therefore communicate
/// directly. As a consequence, a listener socket will always
/// return the new connections as sf::TcpSocket instances.
///
/// A listener is automatically closed on destruction, like all
/// other types of socket. However if you want to stop listening
/// before the socket is destroyed, you can call its close()
/// function.
///
/// Usage example:
/// \code
/// // Create a listener socket and make it wait for new
/// // connections on port 55001
/// sf::TcpListener listener;
/// listener.listen(55001);
///
/// // Endless loop that waits for new connections
/// while (running)
/// {
/// sf::TcpSocket client;
/// if (listener.accept(client) == sf::Socket::Done)
/// {
/// // A new client just connected!
/// std::cout << "New connection received from " << client.getRemoteAddress() << std::endl;
/// doSomethingWith(client);
/// }
/// }
/// \endcode
///
/// \see sf::TcpSocket, sf::Socket
///
////////////////////////////////////////////////////////////

View file

@ -1,316 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_TCPSOCKET_HPP
#define SFML_TCPSOCKET_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/System/Time.hpp>
namespace sf
{
class TcpListener;
class IpAddress;
class Packet;
////////////////////////////////////////////////////////////
/// \brief Specialized socket using the TCP protocol
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API TcpSocket : public Socket
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
TcpSocket();
////////////////////////////////////////////////////////////
/// \brief Get the port to which the socket is bound locally
///
/// If the socket is not connected, this function returns 0.
///
/// \return Port to which the socket is bound
///
/// \see connect, getRemotePort
///
////////////////////////////////////////////////////////////
unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
/// \brief Get the address of the connected peer
///
/// It the socket is not connected, this function returns
/// sf::IpAddress::None.
///
/// \return Address of the remote peer
///
/// \see getRemotePort
///
////////////////////////////////////////////////////////////
IpAddress getRemoteAddress() const;
////////////////////////////////////////////////////////////
/// \brief Get the port of the connected peer to which
/// the socket is connected
///
/// If the socket is not connected, this function returns 0.
///
/// \return Remote port to which the socket is connected
///
/// \see getRemoteAddress
///
////////////////////////////////////////////////////////////
unsigned short getRemotePort() const;
////////////////////////////////////////////////////////////
/// \brief Connect the socket to a remote peer
///
/// In blocking mode, this function may take a while, especially
/// if the remote peer is not reachable. The last parameter allows
/// you to stop trying to connect after a given timeout.
/// If the socket is already connected, the connection is
/// forcibly disconnected before attempting to connect again.
///
/// \param remoteAddress Address of the remote peer
/// \param remotePort Port of the remote peer
/// \param timeout Optional maximum time to wait
///
/// \return Status code
///
/// \see disconnect
///
////////////////////////////////////////////////////////////
Status connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero);
////////////////////////////////////////////////////////////
/// \brief Disconnect the socket from its remote peer
///
/// This function gracefully closes the connection. If the
/// socket is not connected, this function has no effect.
///
/// \see connect
///
////////////////////////////////////////////////////////////
void disconnect();
////////////////////////////////////////////////////////////
/// \brief Send raw data to the remote peer
///
/// To be able to handle partial sends over non-blocking
/// sockets, use the send(const void*, std::size_t, std::size_t&)
/// overload instead.
/// This function will fail if the socket is not connected.
///
/// \param data Pointer to the sequence of bytes to send
/// \param size Number of bytes to send
///
/// \return Status code
///
/// \see receive
///
////////////////////////////////////////////////////////////
Status send(const void* data, std::size_t size);
////////////////////////////////////////////////////////////
/// \brief Send raw data to the remote peer
///
/// This function will fail if the socket is not connected.
///
/// \param data Pointer to the sequence of bytes to send
/// \param size Number of bytes to send
/// \param sent The number of bytes sent will be written here
///
/// \return Status code
///
/// \see receive
///
////////////////////////////////////////////////////////////
Status send(const void* data, std::size_t size, std::size_t& sent);
////////////////////////////////////////////////////////////
/// \brief Receive raw data from the remote peer
///
/// In blocking mode, this function will wait until some
/// bytes are actually received.
/// This function will fail if the socket is not connected.
///
/// \param data Pointer to the array to fill with the received bytes
/// \param size Maximum number of bytes that can be received
/// \param received This variable is filled with the actual number of bytes received
///
/// \return Status code
///
/// \see send
///
////////////////////////////////////////////////////////////
Status receive(void* data, std::size_t size, std::size_t& received);
////////////////////////////////////////////////////////////
/// \brief Send a formatted packet of data to the remote peer
///
/// In non-blocking mode, if this function returns sf::Socket::Partial,
/// you \em must retry sending the same unmodified packet before sending
/// anything else in order to guarantee the packet arrives at the remote
/// peer uncorrupted.
/// This function will fail if the socket is not connected.
///
/// \param packet Packet to send
///
/// \return Status code
///
/// \see receive
///
////////////////////////////////////////////////////////////
Status send(Packet& packet);
////////////////////////////////////////////////////////////
/// \brief Receive a formatted packet of data from the remote peer
///
/// In blocking mode, this function will wait until the whole packet
/// has been received.
/// This function will fail if the socket is not connected.
///
/// \param packet Packet to fill with the received data
///
/// \return Status code
///
/// \see send
///
////////////////////////////////////////////////////////////
Status receive(Packet& packet);
private:
friend class TcpListener;
////////////////////////////////////////////////////////////
/// \brief Structure holding the data of a pending packet
///
////////////////////////////////////////////////////////////
struct PendingPacket
{
PendingPacket();
Uint32 Size; ///< Data of packet size
std::size_t SizeReceived; ///< Number of size bytes received so far
std::vector<char> Data; ///< Data of the packet
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
PendingPacket m_pendingPacket; ///< Temporary data of the packet currently being received
};
} // namespace sf
#endif // SFML_TCPSOCKET_HPP
////////////////////////////////////////////////////////////
/// \class sf::TcpSocket
/// \ingroup network
///
/// TCP is a connected protocol, which means that a TCP
/// socket can only communicate with the host it is connected
/// to. It can't send or receive anything if it is not connected.
///
/// The TCP protocol is reliable but adds a slight overhead.
/// It ensures that your data will always be received in order
/// and without errors (no data corrupted, lost or duplicated).
///
/// When a socket is connected to a remote host, you can
/// retrieve informations about this host with the
/// getRemoteAddress and getRemotePort functions. You can
/// also get the local port to which the socket is bound
/// (which is automatically chosen when the socket is connected),
/// with the getLocalPort function.
///
/// Sending and receiving data can use either the low-level
/// or the high-level functions. The low-level functions
/// process a raw sequence of bytes, and cannot ensure that
/// one call to Send will exactly match one call to Receive
/// at the other end of the socket.
///
/// The high-level interface uses packets (see sf::Packet),
/// which are easier to use and provide more safety regarding
/// the data that is exchanged. You can look at the sf::Packet
/// class to get more details about how they work.
///
/// The socket is automatically disconnected when it is destroyed,
/// but if you want to explicitly close the connection while
/// the socket instance is still alive, you can call disconnect.
///
/// Usage example:
/// \code
/// // ----- The client -----
///
/// // Create a socket and connect it to 192.168.1.50 on port 55001
/// sf::TcpSocket socket;
/// socket.connect("192.168.1.50", 55001);
///
/// // Send a message to the connected host
/// std::string message = "Hi, I am a client";
/// socket.send(message.c_str(), message.size() + 1);
///
/// // Receive an answer from the server
/// char buffer[1024];
/// std::size_t received = 0;
/// socket.receive(buffer, sizeof(buffer), received);
/// std::cout << "The server said: " << buffer << std::endl;
///
/// // ----- The server -----
///
/// // Create a listener to wait for incoming connections on port 55001
/// sf::TcpListener listener;
/// listener.listen(55001);
///
/// // Wait for a connection
/// sf::TcpSocket socket;
/// listener.accept(socket);
/// std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
///
/// // Receive a message from the client
/// char buffer[1024];
/// std::size_t received = 0;
/// socket.receive(buffer, sizeof(buffer), received);
/// std::cout << "The client said: " << buffer << std::endl;
///
/// // Send an answer
/// std::string message = "Welcome, client";
/// socket.send(message.c_str(), message.size() + 1);
/// \endcode
///
/// \see sf::Socket, sf::UdpSocket, sf::Packet
///
////////////////////////////////////////////////////////////

View file

@ -1,291 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_UDPSOCKET_HPP
#define SFML_UDPSOCKET_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/IPAddress.hpp>
#include <vector>
namespace sf
{
class Packet;
////////////////////////////////////////////////////////////
/// \brief Specialized socket using the UDP protocol
///
////////////////////////////////////////////////////////////
class SFML_NETWORK_API UdpSocket : public Socket
{
public:
////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////
enum
{
MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
UdpSocket();
////////////////////////////////////////////////////////////
/// \brief Get the port to which the socket is bound locally
///
/// If the socket is not bound to a port, this function
/// returns 0.
///
/// \return Port to which the socket is bound
///
/// \see bind
///
////////////////////////////////////////////////////////////
unsigned short getLocalPort() const;
////////////////////////////////////////////////////////////
/// \brief Bind the socket to a specific port
///
/// Binding the socket to a port is necessary for being
/// able to receive data on that port.
/// You can use the special value Socket::AnyPort to tell the
/// system to automatically pick an available port, and then
/// call getLocalPort to retrieve the chosen port.
///
/// Since the socket can only be bound to a single port at
/// any given moment, if it is already bound when this
/// function is called, it will be unbound from the previous
/// port before being bound to the new one.
///
/// \param port Port to bind the socket to
/// \param address Address of the interface to bind to
///
/// \return Status code
///
/// \see unbind, getLocalPort
///
////////////////////////////////////////////////////////////
Status bind(unsigned short port, const IpAddress& address = IpAddress::Any);
////////////////////////////////////////////////////////////
/// \brief Unbind the socket from the local port to which it is bound
///
/// The port that the socket was previously bound to is immediately
/// made available to the operating system after this function is called.
/// This means that a subsequent call to bind() will be able to re-bind
/// the port if no other process has done so in the mean time.
/// If the socket is not bound to a port, this function has no effect.
///
/// \see bind
///
////////////////////////////////////////////////////////////
void unbind();
////////////////////////////////////////////////////////////
/// \brief Send raw data to a remote peer
///
/// Make sure that \a size is not greater than
/// UdpSocket::MaxDatagramSize, otherwise this function will
/// fail and no data will be sent.
///
/// \param data Pointer to the sequence of bytes to send
/// \param size Number of bytes to send
/// \param remoteAddress Address of the receiver
/// \param remotePort Port of the receiver to send the data to
///
/// \return Status code
///
/// \see receive
///
////////////////////////////////////////////////////////////
Status send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort);
////////////////////////////////////////////////////////////
/// \brief Receive raw data from a remote peer
///
/// In blocking mode, this function will wait until some
/// bytes are actually received.
/// Be careful to use a buffer which is large enough for
/// the data that you intend to receive, if it is too small
/// then an error will be returned and *all* the data will
/// be lost.
///
/// \param data Pointer to the array to fill with the received bytes
/// \param size Maximum number of bytes that can be received
/// \param received This variable is filled with the actual number of bytes received
/// \param remoteAddress Address of the peer that sent the data
/// \param remotePort Port of the peer that sent the data
///
/// \return Status code
///
/// \see send
///
////////////////////////////////////////////////////////////
Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort);
////////////////////////////////////////////////////////////
/// \brief Send a formatted packet of data to a remote peer
///
/// Make sure that the packet size is not greater than
/// UdpSocket::MaxDatagramSize, otherwise this function will
/// fail and no data will be sent.
///
/// \param packet Packet to send
/// \param remoteAddress Address of the receiver
/// \param remotePort Port of the receiver to send the data to
///
/// \return Status code
///
/// \see receive
///
////////////////////////////////////////////////////////////
Status send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort);
////////////////////////////////////////////////////////////
/// \brief Receive a formatted packet of data from a remote peer
///
/// In blocking mode, this function will wait until the whole packet
/// has been received.
///
/// \param packet Packet to fill with the received data
/// \param remoteAddress Address of the peer that sent the data
/// \param remotePort Port of the peer that sent the data
///
/// \return Status code
///
/// \see send
///
////////////////////////////////////////////////////////////
Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort);
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<char> m_buffer; ///< Temporary buffer holding the received data in Receive(Packet)
};
} // namespace sf
#endif // SFML_UDPSOCKET_HPP
////////////////////////////////////////////////////////////
/// \class sf::UdpSocket
/// \ingroup network
///
/// A UDP socket is a connectionless socket. Instead of
/// connecting once to a remote host, like TCP sockets,
/// it can send to and receive from any host at any time.
///
/// It is a datagram protocol: bounded blocks of data (datagrams)
/// are transfered over the network rather than a continuous
/// stream of data (TCP). Therefore, one call to send will always
/// match one call to receive (if the datagram is not lost),
/// with the same data that was sent.
///
/// The UDP protocol is lightweight but unreliable. Unreliable
/// means that datagrams may be duplicated, be lost or
/// arrive reordered. However, if a datagram arrives, its
/// data is guaranteed to be valid.
///
/// UDP is generally used for real-time communication
/// (audio or video streaming, real-time games, etc.) where
/// speed is crucial and lost data doesn't matter much.
///
/// Sending and receiving data can use either the low-level
/// or the high-level functions. The low-level functions
/// process a raw sequence of bytes, whereas the high-level
/// interface uses packets (see sf::Packet), which are easier
/// to use and provide more safety regarding the data that is
/// exchanged. You can look at the sf::Packet class to get
/// more details about how they work.
///
/// It is important to note that UdpSocket is unable to send
/// datagrams bigger than MaxDatagramSize. In this case, it
/// returns an error and doesn't send anything. This applies
/// to both raw data and packets. Indeed, even packets are
/// unable to split and recompose data, due to the unreliability
/// of the protocol (dropped, mixed or duplicated datagrams may
/// lead to a big mess when trying to recompose a packet).
///
/// If the socket is bound to a port, it is automatically
/// unbound from it when the socket is destroyed. However,
/// you can unbind the socket explicitly with the Unbind
/// function if necessary, to stop receiving messages or
/// make the port available for other sockets.
///
/// Usage example:
/// \code
/// // ----- The client -----
///
/// // Create a socket and bind it to the port 55001
/// sf::UdpSocket socket;
/// socket.bind(55001);
///
/// // Send a message to 192.168.1.50 on port 55002
/// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString();
/// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002);
///
/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else)
/// char buffer[1024];
/// std::size_t received = 0;
/// sf::IpAddress sender;
/// unsigned short port;
/// socket.receive(buffer, sizeof(buffer), received, sender, port);
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
///
/// // ----- The server -----
///
/// // Create a socket and bind it to the port 55002
/// sf::UdpSocket socket;
/// socket.bind(55002);
///
/// // Receive a message from anyone
/// char buffer[1024];
/// std::size_t received = 0;
/// sf::IpAddress sender;
/// unsigned short port;
/// socket.receive(buffer, sizeof(buffer), received, sender, port);
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
///
/// // Send an answer
/// std::string message = "Welcome " + sender.toString();
/// socket.send(message.c_str(), message.size() + 1, sender, port);
/// \endcode
///
/// \see sf::Socket, sf::TcpSocket, sf::Packet
///
////////////////////////////////////////////////////////////

View file

@ -1,58 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SYSTEM_HPP
#define SFML_SYSTEM_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
//#include <SFML/System/Clock.hpp>
#include <SFML/System/Err.hpp>
//#include <SFML/System/InputStream.hpp>
//#include <SFML/System/Lock.hpp>
//#include <SFML/System/Mutex.hpp>
//#include <SFML/System/Sleep.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/String.hpp>
//#include <SFML/System/Thread.hpp>
//#include <SFML/System/ThreadLocal.hpp>
//#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Utf.hpp>
//#include <SFML/System/Vector2.hpp>
//#include <SFML/System/Vector3.hpp>
#endif // SFML_SYSTEM_HPP
////////////////////////////////////////////////////////////
/// \defgroup system System module
///
/// Base module of SFML, defining various utilities. It provides
/// vector classes, Unicode strings and conversion functions,
/// threads and mutexes, timing classes.
///
////////////////////////////////////////////////////////////

View file

@ -1,80 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_ERR_HPP
#define SFML_ERR_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <ostream>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Standard stream used by SFML to output warnings and errors
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API std::ostream& err();
} // namespace sf
#endif // SFML_ERR_HPP
////////////////////////////////////////////////////////////
/// \fn sf::err
/// \ingroup system
///
/// By default, sf::err() outputs to the same location as std::cerr,
/// (-> the stderr descriptor) which is the console if there's
/// one available.
///
/// It is a standard std::ostream instance, so it supports all the
/// insertion operations defined by the STL
/// (operator <<, manipulators, etc.).
///
/// sf::err() can be redirected to write to another output, independently
/// of std::cerr, by using the rdbuf() function provided by the
/// std::ostream class.
///
/// Example:
/// \code
/// // Redirect to a file
/// std::ofstream file("sfml-log.txt");
/// std::streambuf* previous = sf::err().rdbuf(file.rdbuf());
///
/// // Redirect to nothing
/// sf::err().rdbuf(NULL);
///
/// // Restore the original output
/// sf::err().rdbuf(previous);
/// \endcode
///
/// \return Reference to std::ostream representing the SFML error stream
///
////////////////////////////////////////////////////////////

View file

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SYSTEM_EXPORT_HPP
#define SFML_SYSTEM_EXPORT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
////////////////////////////////////////////////////////////
// Define portable import / export macros
////////////////////////////////////////////////////////////
#if defined(SFML_SYSTEM_EXPORTS)
#define SFML_SYSTEM_API SFML_API_EXPORT
#else
#define SFML_SYSTEM_API SFML_API_IMPORT
#endif
#endif // SFML_SYSTEM_EXPORT_HPP

View file

@ -1,129 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_NONCOPYABLE_HPP
#define SFML_NONCOPYABLE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Utility class that makes any derived
/// class non-copyable
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API NonCopyable
{
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Because this class has a copy constructor, the compiler
/// will not automatically generate the default constructor.
/// That's why we must define it explicitly.
///
////////////////////////////////////////////////////////////
NonCopyable() {}
////////////////////////////////////////////////////////////
/// \brief Default destructor
///
/// By declaring a protected destructor it's impossible to
/// call delete on a pointer of sf::NonCopyable, thus
/// preventing possible resource leaks.
///
////////////////////////////////////////////////////////////
~NonCopyable() {}
private:
////////////////////////////////////////////////////////////
/// \brief Disabled copy constructor
///
/// By making the copy constructor private, the compiler will
/// trigger an error if anyone outside tries to use it.
/// To prevent NonCopyable or friend classes from using it,
/// we also give no definition, so that the linker will
/// produce an error if the first protection was inefficient.
///
////////////////////////////////////////////////////////////
NonCopyable(const NonCopyable&);
////////////////////////////////////////////////////////////
/// \brief Disabled assignment operator
///
/// By making the assignment operator private, the compiler will
/// trigger an error if anyone outside tries to use it.
/// To prevent NonCopyable or friend classes from using it,
/// we also give no definition, so that the linker will
/// produce an error if the first protection was inefficient.
///
////////////////////////////////////////////////////////////
NonCopyable& operator =(const NonCopyable&);
};
} // namespace sf
#endif // SFML_NONCOPYABLE_HPP
////////////////////////////////////////////////////////////
/// \class sf::NonCopyable
/// \ingroup system
///
/// This class makes its instances non-copyable, by explicitly
/// disabling its copy constructor and its assignment operator.
///
/// To create a non-copyable class, simply inherit from
/// sf::NonCopyable.
///
/// The type of inheritance (public or private) doesn't matter,
/// the copy constructor and assignment operator are declared private
/// in sf::NonCopyable so they will end up being inaccessible in both
/// cases. Thus you can use a shorter syntax for inheriting from it
/// (see below).
///
/// Usage example:
/// \code
/// class MyNonCopyableClass : sf::NonCopyable
/// {
/// ...
/// };
/// \endcode
///
/// Deciding whether the instances of a class can be copied
/// or not is a very important design choice. You are strongly
/// encouraged to think about it before writing a class,
/// and to use sf::NonCopyable when necessary to prevent
/// many potential future errors when using it. This is also
/// a very important indication to users of your class.
///
////////////////////////////////////////////////////////////

View file

@ -1,669 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_STRING_HPP
#define SFML_STRING_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
#include <SFML/System/Utf.hpp>
#include <iterator>
#include <locale>
#include <string>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Utility string class that automatically handles
/// conversions between types and encodings
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API String
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::basic_string<Uint32>::iterator Iterator; ///< Iterator type
typedef std::basic_string<Uint32>::const_iterator ConstIterator; ///< Read-only iterator type
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
static const std::size_t InvalidPos; ///< Represents an invalid position in the string
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates an empty string.
///
////////////////////////////////////////////////////////////
String();
////////////////////////////////////////////////////////////
/// \brief Construct from a single ANSI character and a locale
///
/// The source character is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiChar ANSI character to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
String(char ansiChar, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Construct from single wide character
///
/// \param wideChar Wide character to convert
///
////////////////////////////////////////////////////////////
String(wchar_t wideChar);
////////////////////////////////////////////////////////////
/// \brief Construct from single UTF-32 character
///
/// \param utf32Char UTF-32 character to convert
///
////////////////////////////////////////////////////////////
String(Uint32 utf32Char);
////////////////////////////////////////////////////////////
/// \brief Construct from a null-terminated C-style ANSI string and a locale
///
/// The source string is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiString ANSI string to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
String(const char* ansiString, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Construct from an ANSI string and a locale
///
/// The source string is converted to UTF-32 according
/// to the given locale.
///
/// \param ansiString ANSI string to convert
/// \param locale Locale to use for conversion
///
////////////////////////////////////////////////////////////
String(const std::string& ansiString, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Construct from null-terminated C-style wide string
///
/// \param wideString Wide string to convert
///
////////////////////////////////////////////////////////////
String(const wchar_t* wideString);
////////////////////////////////////////////////////////////
/// \brief Construct from a wide string
///
/// \param wideString Wide string to convert
///
////////////////////////////////////////////////////////////
String(const std::wstring& wideString);
////////////////////////////////////////////////////////////
/// \brief Construct from a null-terminated C-style UTF-32 string
///
/// \param utf32String UTF-32 string to assign
///
////////////////////////////////////////////////////////////
String(const Uint32* utf32String);
////////////////////////////////////////////////////////////
/// \brief Construct from an UTF-32 string
///
/// \param utf32String UTF-32 string to assign
///
////////////////////////////////////////////////////////////
String(const std::basic_string<Uint32>& utf32String);
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
String(const String& copy);
////////////////////////////////////////////////////////////
/// \brief Create a new sf::String from a UTF-8 encoded string
///
/// \param begin Forward iterator to the beginning of the UTF-8 sequence
/// \param end Forward iterator to the end of the UTF-8 sequence
///
/// \return A sf::String containing the source string
///
/// \see fromUtf16, fromUtf32
///
////////////////////////////////////////////////////////////
template <typename T>
static String fromUtf8(T begin, T end);
////////////////////////////////////////////////////////////
/// \brief Create a new sf::String from a UTF-16 encoded string
///
/// \param begin Forward iterator to the beginning of the UTF-16 sequence
/// \param end Forward iterator to the end of the UTF-16 sequence
///
/// \return A sf::String containing the source string
///
/// \see fromUtf8, fromUtf32
///
////////////////////////////////////////////////////////////
template <typename T>
static String fromUtf16(T begin, T end);
////////////////////////////////////////////////////////////
/// \brief Create a new sf::String from a UTF-32 encoded string
///
/// This function is provided for consistency, it is equivalent to
/// using the constructors that takes a const sf::Uint32* or
/// a std::basic_string<sf::Uint32>.
///
/// \param begin Forward iterator to the beginning of the UTF-32 sequence
/// \param end Forward iterator to the end of the UTF-32 sequence
///
/// \return A sf::String containing the source string
///
/// \see fromUtf8, fromUtf16
///
////////////////////////////////////////////////////////////
template <typename T>
static String fromUtf32(T begin, T end);
////////////////////////////////////////////////////////////
/// \brief Implicit conversion operator to std::string (ANSI string)
///
/// The current global locale is used for conversion. If you
/// want to explicitly specify a locale, see toAnsiString.
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
/// This operator is defined for convenience, and is equivalent
/// to calling toAnsiString().
///
/// \return Converted ANSI string
///
/// \see toAnsiString, operator std::wstring
///
////////////////////////////////////////////////////////////
operator std::string() const;
////////////////////////////////////////////////////////////
/// \brief Implicit conversion operator to std::wstring (wide string)
///
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
/// This operator is defined for convenience, and is equivalent
/// to calling toWideString().
///
/// \return Converted wide string
///
/// \see toWideString, operator std::string
///
////////////////////////////////////////////////////////////
operator std::wstring() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to an ANSI string
///
/// The UTF-32 string is converted to an ANSI string in
/// the encoding defined by \a locale.
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
///
/// \param locale Locale to use for conversion
///
/// \return Converted ANSI string
///
/// \see toWideString, operator std::string
///
////////////////////////////////////////////////////////////
std::string toAnsiString(const std::locale& locale = std::locale()) const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a wide string
///
/// Characters that do not fit in the target encoding are
/// discarded from the returned string.
///
/// \return Converted wide string
///
/// \see toAnsiString, operator std::wstring
///
////////////////////////////////////////////////////////////
std::wstring toWideString() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-8 string
///
/// \return Converted UTF-8 string
///
/// \see toUtf16, toUtf32
///
////////////////////////////////////////////////////////////
std::basic_string<Uint8> toUtf8() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-16 string
///
/// \return Converted UTF-16 string
///
/// \see toUtf8, toUtf32
///
////////////////////////////////////////////////////////////
std::basic_string<Uint16> toUtf16() const;
////////////////////////////////////////////////////////////
/// \brief Convert the Unicode string to a UTF-32 string
///
/// This function doesn't perform any conversion, since the
/// string is already stored as UTF-32 internally.
///
/// \return Converted UTF-32 string
///
/// \see toUtf8, toUtf16
///
////////////////////////////////////////////////////////////
std::basic_string<Uint32> toUtf32() const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
String& operator =(const String& right);
////////////////////////////////////////////////////////////
/// \brief Overload of += operator to append an UTF-32 string
///
/// \param right String to append
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
String& operator +=(const String& right);
////////////////////////////////////////////////////////////
/// \brief Overload of [] operator to access a character by its position
///
/// This function provides read-only access to characters.
/// Note: the behavior is undefined if \a index is out of range.
///
/// \param index Index of the character to get
///
/// \return Character at position \a index
///
////////////////////////////////////////////////////////////
Uint32 operator [](std::size_t index) const;
////////////////////////////////////////////////////////////
/// \brief Overload of [] operator to access a character by its position
///
/// This function provides read and write access to characters.
/// Note: the behavior is undefined if \a index is out of range.
///
/// \param index Index of the character to get
///
/// \return Reference to the character at position \a index
///
////////////////////////////////////////////////////////////
Uint32& operator [](std::size_t index);
////////////////////////////////////////////////////////////
/// \brief Clear the string
///
/// This function removes all the characters from the string.
///
/// \see isEmpty, erase
///
////////////////////////////////////////////////////////////
void clear();
////////////////////////////////////////////////////////////
/// \brief Get the size of the string
///
/// \return Number of characters in the string
///
/// \see isEmpty
///
////////////////////////////////////////////////////////////
std::size_t getSize() const;
////////////////////////////////////////////////////////////
/// \brief Check whether the string is empty or not
///
/// \return True if the string is empty (i.e. contains no character)
///
/// \see clear, getSize
///
////////////////////////////////////////////////////////////
bool isEmpty() const;
////////////////////////////////////////////////////////////
/// \brief Erase one or more characters from the string
///
/// This function removes a sequence of \a count characters
/// starting from \a position.
///
/// \param position Position of the first character to erase
/// \param count Number of characters to erase
///
////////////////////////////////////////////////////////////
void erase(std::size_t position, std::size_t count = 1);
////////////////////////////////////////////////////////////
/// \brief Insert one or more characters into the string
///
/// This function inserts the characters of \a str
/// into the string, starting from \a position.
///
/// \param position Position of insertion
/// \param str Characters to insert
///
////////////////////////////////////////////////////////////
void insert(std::size_t position, const String& str);
////////////////////////////////////////////////////////////
/// \brief Find a sequence of one or more characters in the string
///
/// This function searches for the characters of \a str
/// in the string, starting from \a start.
///
/// \param str Characters to find
/// \param start Where to begin searching
///
/// \return Position of \a str in the string, or String::InvalidPos if not found
///
////////////////////////////////////////////////////////////
std::size_t find(const String& str, std::size_t start = 0) const;
////////////////////////////////////////////////////////////
/// \brief Replace a substring with another string
///
/// This function replaces the substring that starts at index \a position
/// and spans \a length characters with the string \a replaceWith.
///
/// \param position Index of the first character to be replaced
/// \param length Number of characters to replace. You can pass InvalidPos to
/// replace all characters until the end of the string.
/// \param replaceWith String that replaces the given substring.
///
////////////////////////////////////////////////////////////
void replace(std::size_t position, std::size_t length, const String& replaceWith);
////////////////////////////////////////////////////////////
/// \brief Replace all occurrences of a substring with a replacement string
///
/// This function replaces all occurrences of \a searchFor in this string
/// with the string \a replaceWith.
///
/// \param searchFor The value being searched for
/// \param replaceWith The value that replaces found \a searchFor values
///
////////////////////////////////////////////////////////////
void replace(const String& searchFor, const String& replaceWith);
////////////////////////////////////////////////////////////
/// \brief Return a part of the string
///
/// This function returns the substring that starts at index \a position
/// and spans \a length characters.
///
/// \param position Index of the first character
/// \param length Number of characters to include in the substring (if
/// the string is shorter, as many characters as possible
/// are included). \ref InvalidPos can be used to include all
/// characters until the end of the string.
///
/// \return String object containing a substring of this object
///
////////////////////////////////////////////////////////////
String substring(std::size_t position, std::size_t length = InvalidPos) const;
////////////////////////////////////////////////////////////
/// \brief Get a pointer to the C-style array of characters
///
/// This functions provides a read-only access to a
/// null-terminated C-style representation of the string.
/// The returned pointer is temporary and is meant only for
/// immediate use, thus it is not recommended to store it.
///
/// \return Read-only pointer to the array of characters
///
////////////////////////////////////////////////////////////
const Uint32* getData() const;
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the beginning of the string
///
/// \return Read-write iterator to the beginning of the string characters
///
/// \see end
///
////////////////////////////////////////////////////////////
Iterator begin();
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the beginning of the string
///
/// \return Read-only iterator to the beginning of the string characters
///
/// \see end
///
////////////////////////////////////////////////////////////
ConstIterator begin() const;
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the end of the string
///
/// The end iterator refers to 1 position past the last character;
/// thus it represents an invalid character and should never be
/// accessed.
///
/// \return Read-write iterator to the end of the string characters
///
/// \see begin
///
////////////////////////////////////////////////////////////
Iterator end();
////////////////////////////////////////////////////////////
/// \brief Return an iterator to the end of the string
///
/// The end iterator refers to 1 position past the last character;
/// thus it represents an invalid character and should never be
/// accessed.
///
/// \return Read-only iterator to the end of the string characters
///
/// \see begin
///
////////////////////////////////////////////////////////////
ConstIterator end() const;
private:
friend SFML_SYSTEM_API bool operator ==(const String& left, const String& right);
friend SFML_SYSTEM_API bool operator <(const String& left, const String& right);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::basic_string<Uint32> m_string; ///< Internal string of UTF-32 characters
};
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of == operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if both strings are equal
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator ==(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of != operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if both strings are different
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator !=(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of < operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically before \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator <(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of > operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically after \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator >(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of <= operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically before or equivalent to \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator <=(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of >= operator to compare two UTF-32 strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return True if \a left is lexicographically after or equivalent to \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator >=(const String& left, const String& right);
////////////////////////////////////////////////////////////
/// \relates String
/// \brief Overload of binary + operator to concatenate two strings
///
/// \param left Left operand (a string)
/// \param right Right operand (a string)
///
/// \return Concatenated string
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API String operator +(const String& left, const String& right);
#include <SFML/System/String.inl>
} // namespace sf
#endif // SFML_STRING_HPP
////////////////////////////////////////////////////////////
/// \class sf::String
/// \ingroup system
///
/// sf::String is a utility string class defined mainly for
/// convenience. It is a Unicode string (implemented using
/// UTF-32), thus it can store any character in the world
/// (European, Chinese, Arabic, Hebrew, etc.).
///
/// It automatically handles conversions from/to ANSI and
/// wide strings, so that you can work with standard string
/// classes and still be compatible with functions taking a
/// sf::String.
///
/// \code
/// sf::String s;
///
/// std::string s1 = s; // automatically converted to ANSI string
/// std::wstring s2 = s; // automatically converted to wide string
/// s = "hello"; // automatically converted from ANSI string
/// s = L"hello"; // automatically converted from wide string
/// s += 'a'; // automatically converted from ANSI string
/// s += L'a'; // automatically converted from wide string
/// \endcode
///
/// Conversions involving ANSI strings use the default user locale. However
/// it is possible to use a custom locale if necessary:
/// \code
/// std::locale locale;
/// sf::String s;
/// ...
/// std::string s1 = s.toAnsiString(locale);
/// s = sf::String("hello", locale);
/// \endcode
///
/// sf::String defines the most important functions of the
/// standard std::string class: removing, random access, iterating,
/// appending, comparing, etc. However it is a simple class
/// provided for convenience, and you may have to consider using
/// a more optimized class if your program requires complex string
/// handling. The automatic conversion functions will then take
/// care of converting your string to sf::String whenever SFML
/// requires it.
///
/// Please note that SFML also defines a low-level, generic
/// interface for Unicode handling, see the sf::Utf classes.
///
////////////////////////////////////////////////////////////

View file

@ -1,53 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
template <typename T>
String String::fromUtf8(T begin, T end)
{
String string;
Utf8::toUtf32(begin, end, std::back_inserter(string.m_string));
return string;
}
////////////////////////////////////////////////////////////
template <typename T>
String String::fromUtf16(T begin, T end)
{
String string;
Utf16::toUtf32(begin, end, std::back_inserter(string.m_string));
return string;
}
////////////////////////////////////////////////////////////
template <typename T>
String String::fromUtf32(T begin, T end)
{
String string;
string.m_string.assign(begin, end);
return string;
}

View file

@ -1,488 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_TIME_HPP
#define SFML_TIME_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Export.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Represents a time value
///
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API Time
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Sets the time value to zero.
///
////////////////////////////////////////////////////////////
Time();
////////////////////////////////////////////////////////////
/// \brief Return the time value as a number of seconds
///
/// \return Time in seconds
///
/// \see asMilliseconds, asMicroseconds
///
////////////////////////////////////////////////////////////
float asSeconds() const;
////////////////////////////////////////////////////////////
/// \brief Return the time value as a number of milliseconds
///
/// \return Time in milliseconds
///
/// \see asSeconds, asMicroseconds
///
////////////////////////////////////////////////////////////
Int32 asMilliseconds() const;
////////////////////////////////////////////////////////////
/// \brief Return the time value as a number of microseconds
///
/// \return Time in microseconds
///
/// \see asSeconds, asMilliseconds
///
////////////////////////////////////////////////////////////
Int64 asMicroseconds() const;
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
static const Time Zero; ///< Predefined "zero" time value
private:
friend SFML_SYSTEM_API Time seconds(float);
friend SFML_SYSTEM_API Time milliseconds(Int32);
friend SFML_SYSTEM_API Time microseconds(Int64);
////////////////////////////////////////////////////////////
/// \brief Construct from a number of microseconds
///
/// This function is internal. To construct time values,
/// use sf::seconds, sf::milliseconds or sf::microseconds instead.
///
/// \param microseconds Number of microseconds
///
////////////////////////////////////////////////////////////
explicit Time(Int64 microseconds);
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Int64 m_microseconds; ///< Time value stored as microseconds
};
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Construct a time value from a number of seconds
///
/// \param amount Number of seconds
///
/// \return Time value constructed from the amount of seconds
///
/// \see milliseconds, microseconds
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time seconds(float amount);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Construct a time value from a number of milliseconds
///
/// \param amount Number of milliseconds
///
/// \return Time value constructed from the amount of milliseconds
///
/// \see seconds, microseconds
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time milliseconds(Int32 amount);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Construct a time value from a number of microseconds
///
/// \param amount Number of microseconds
///
/// \return Time value constructed from the amount of microseconds
///
/// \see seconds, milliseconds
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time microseconds(Int64 amount);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of == operator to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return True if both time values are equal
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator ==(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of != operator to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return True if both time values are different
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator !=(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of < operator to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return True if \a left is lesser than \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator <(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of > operator to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return True if \a left is greater than \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator >(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of <= operator to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return True if \a left is lesser or equal than \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator <=(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of >= operator to compare two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return True if \a left is greater or equal than \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API bool operator >=(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of unary - operator to negate a time value
///
/// \param right Right operand (a time)
///
/// \return Opposite of the time value
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator -(Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary + operator to add two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Sum of the two times values
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator +(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary += operator to add/assign two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Sum of the two times values
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator +=(Time& left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary - operator to subtract two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Difference of the two times values
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator -(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary -= operator to subtract/assign two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return Difference of the two times values
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator -=(Time& left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary * operator to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left multiplied by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator *(Time left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary * operator to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left multiplied by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator *(Time left, Int64 right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary * operator to scale a time value
///
/// \param left Left operand (a number)
/// \param right Right operand (a time)
///
/// \return \a left multiplied by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator *(float left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary * operator to scale a time value
///
/// \param left Left operand (a number)
/// \param right Right operand (a time)
///
/// \return \a left multiplied by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator *(Int64 left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary *= operator to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left multiplied by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator *=(Time& left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary *= operator to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left multiplied by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator *=(Time& left, Int64 right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary / operator to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left divided by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator /(Time left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary / operator to scale a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left divided by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator /(Time left, Int64 right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary /= operator to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left divided by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator /=(Time& left, float right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary /= operator to scale/assign a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a number)
///
/// \return \a left divided by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator /=(Time& left, Int64 right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary / operator to compute the ratio of two time values
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return \a left divided by \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API float operator /(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary % operator to compute remainder of a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return \a left modulo \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time operator %(Time left, Time right);
////////////////////////////////////////////////////////////
/// \relates Time
/// \brief Overload of binary %= operator to compute/assign remainder of a time value
///
/// \param left Left operand (a time)
/// \param right Right operand (a time)
///
/// \return \a left modulo \a right
///
////////////////////////////////////////////////////////////
SFML_SYSTEM_API Time& operator %=(Time& left, Time right);
} // namespace sf
#endif // SFML_TIME_HPP
////////////////////////////////////////////////////////////
/// \class sf::Time
/// \ingroup system
///
/// sf::Time encapsulates a time value in a flexible way.
/// It allows to define a time value either as a number of
/// seconds, milliseconds or microseconds. It also works the
/// other way round: you can read a time value as either
/// a number of seconds, milliseconds or microseconds.
///
/// By using such a flexible interface, the API doesn't
/// impose any fixed type or resolution for time values,
/// and let the user choose its own favorite representation.
///
/// Time values support the usual mathematical operations:
/// you can add or subtract two times, multiply or divide
/// a time by a number, compare two times, etc.
///
/// Since they represent a time span and not an absolute time
/// value, times can also be negative.
///
/// Usage example:
/// \code
/// sf::Time t1 = sf::seconds(0.1f);
/// Int32 milli = t1.asMilliseconds(); // 100
///
/// sf::Time t2 = sf::milliseconds(30);
/// Int64 micro = t2.asMicroseconds(); // 30000
///
/// sf::Time t3 = sf::microseconds(-800000);
/// float sec = t3.asSeconds(); // -0.8
/// \endcode
///
/// \code
/// void update(sf::Time elapsed)
/// {
/// position += speed * elapsed.asSeconds();
/// }
///
/// update(sf::milliseconds(100));
/// \endcode
///
/// \see sf::Clock
///
////////////////////////////////////////////////////////////

View file

@ -1,763 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_UTF_HPP
#define SFML_UTF_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <algorithm>
#include <locale>
#include <string>
#include <cstdlib>
namespace sf
{
template <unsigned int N>
class Utf;
////////////////////////////////////////////////////////////
/// \brief Specialization of the Utf template for UTF-8
///
////////////////////////////////////////////////////////////
template <>
class Utf<8>
{
public:
////////////////////////////////////////////////////////////
/// \brief Decode a single UTF-8 character
///
/// Decoding a character means finding its unique 32-bits
/// code (called the codepoint) in the Unicode standard.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Codepoint of the decoded UTF-8 character
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-8 character
///
/// Encoding a character means converting a unique 32-bits
/// code (called the codepoint) in the target encoding, UTF-8.
///
/// \param input Codepoint to encode as UTF-8
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encode(Uint32 input, Out output, Uint8 replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Advance to the next UTF-8 character
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In next(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Count the number of characters of a UTF-8 sequence
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element, thus the
/// total size can be different from (begin - end).
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static std::size_t count(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Convert an ANSI characters range to UTF-8
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the \a locale parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Convert a wide characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromWide(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromLatin1(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-8 characters range to ANSI characters
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the \a locale parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-8 characters range to wide characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-8 characters range to UTF-8
///
/// This functions does nothing more than a direct copy;
/// it is defined only to provide the same interface as other
/// specializations of the sf::Utf<> template, and allow
/// generic code to be written on top of it.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf8(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-8 characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf16(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-8 characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf32(In begin, In end, Out output);
};
////////////////////////////////////////////////////////////
/// \brief Specialization of the Utf template for UTF-16
///
////////////////////////////////////////////////////////////
template <>
class Utf<16>
{
public:
////////////////////////////////////////////////////////////
/// \brief Decode a single UTF-16 character
///
/// Decoding a character means finding its unique 32-bits
/// code (called the codepoint) in the Unicode standard.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Codepoint of the decoded UTF-16 character
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-16 character
///
/// Encoding a character means converting a unique 32-bits
/// code (called the codepoint) in the target encoding, UTF-16.
///
/// \param input Codepoint to encode as UTF-16
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encode(Uint32 input, Out output, Uint16 replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Advance to the next UTF-16 character
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In next(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Count the number of characters of a UTF-16 sequence
///
/// This function is necessary for multi-elements encodings, as
/// a single character may use more than 1 storage element, thus the
/// total size can be different from (begin - end).
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static std::size_t count(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Convert an ANSI characters range to UTF-16
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the \a locale parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Convert a wide characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromWide(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromLatin1(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to ANSI characters
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the \a locale parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to wide characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-16 characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf8(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-16 characters range to UTF-16
///
/// This functions does nothing more than a direct copy;
/// it is defined only to provide the same interface as other
/// specializations of the sf::Utf<> template, and allow
/// generic code to be written on top of it.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf16(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-16 characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf32(In begin, In end, Out output);
};
////////////////////////////////////////////////////////////
/// \brief Specialization of the Utf template for UTF-32
///
////////////////////////////////////////////////////////////
template <>
class Utf<32>
{
public:
////////////////////////////////////////////////////////////
/// \brief Decode a single UTF-32 character
///
/// Decoding a character means finding its unique 32-bits
/// code (called the codepoint) in the Unicode standard.
/// For UTF-32, the character value is the same as the codepoint.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Codepoint of the decoded UTF-32 character
/// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-32 character
///
/// Encoding a character means converting a unique 32-bits
/// code (called the codepoint) in the target encoding, UTF-32.
/// For UTF-32, the codepoint is the same as the character value.
///
/// \param input Codepoint to encode as UTF-32
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encode(Uint32 input, Out output, Uint32 replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Advance to the next UTF-32 character
///
/// This function is trivial for UTF-32, which can store
/// every character in a single storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static In next(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Count the number of characters of a UTF-32 sequence
///
/// This function is trivial for UTF-32, which can store
/// every character in a single storage element.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
///
/// \return Iterator pointing to one past the last read element of the input sequence
///
////////////////////////////////////////////////////////////
template <typename In>
static std::size_t count(In begin, In end);
////////////////////////////////////////////////////////////
/// \brief Convert an ANSI characters range to UTF-32
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the \a locale parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Convert a wide characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromWide(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out fromLatin1(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-32 characters range to ANSI characters
///
/// The current global locale will be used by default, unless you
/// pass a custom one in the \a locale parameter.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-32 characters range to wide characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toWide(In begin, In end, Out output, wchar_t replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toLatin1(In begin, In end, Out output, char replacement = 0);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-32 characters range to UTF-8
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf8(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-32 characters range to UTF-16
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf16(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Convert a UTF-32 characters range to UTF-32
///
/// This functions does nothing more than a direct copy;
/// it is defined only to provide the same interface as other
/// specializations of the sf::Utf<> template, and allow
/// generic code to be written on top of it.
///
/// \param begin Iterator pointing to the beginning of the input sequence
/// \param end Iterator pointing to the end of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename In, typename Out>
static Out toUtf32(In begin, In end, Out output);
////////////////////////////////////////////////////////////
/// \brief Decode a single ANSI character to UTF-32
///
/// This function does not exist in other specializations
/// of sf::Utf<>, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param input Input ANSI character
/// \param locale Locale to use for conversion
///
/// \return Converted character
///
////////////////////////////////////////////////////////////
template <typename In>
static Uint32 decodeAnsi(In input, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Decode a single wide character to UTF-32
///
/// This function does not exist in other specializations
/// of sf::Utf<>, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param input Input wide character
///
/// \return Converted character
///
////////////////////////////////////////////////////////////
template <typename In>
static Uint32 decodeWide(In input);
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-32 character to ANSI
///
/// This function does not exist in other specializations
/// of sf::Utf<>, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param codepoint Iterator pointing to the beginning of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it)
/// \param locale Locale to use for conversion
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale());
////////////////////////////////////////////////////////////
/// \brief Encode a single UTF-32 character to wide
///
/// This function does not exist in other specializations
/// of sf::Utf<>, it is defined for convenience (it is used by
/// several other conversion functions).
///
/// \param codepoint Iterator pointing to the beginning of the input sequence
/// \param output Iterator pointing to the beginning of the output sequence
/// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it)
///
/// \return Iterator to the end of the output sequence which has been written
///
////////////////////////////////////////////////////////////
template <typename Out>
static Out encodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0);
};
#include <SFML/System/Utf.inl>
// Make typedefs to get rid of the template syntax
typedef Utf<8> Utf8;
typedef Utf<16> Utf16;
typedef Utf<32> Utf32;
} // namespace sf
#endif // SFML_UTF_HPP
////////////////////////////////////////////////////////////
/// \class sf::Utf
/// \ingroup system
///
/// Utility class providing generic functions for UTF conversions.
///
/// sf::Utf is a low-level, generic interface for counting, iterating,
/// encoding and decoding Unicode characters and strings. It is able
/// to handle ANSI, wide, latin-1, UTF-8, UTF-16 and UTF-32 encodings.
///
/// sf::Utf<X> functions are all static, these classes are not meant to
/// be instantiated. All the functions are template, so that you
/// can use any character / string type for a given encoding.
///
/// It has 3 specializations:
/// \li sf::Utf<8> (typedef'd to sf::Utf8)
/// \li sf::Utf<16> (typedef'd to sf::Utf16)
/// \li sf::Utf<32> (typedef'd to sf::Utf32)
///
////////////////////////////////////////////////////////////

View file

@ -1,752 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// References:
//
// https://www.unicode.org/
// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
// https://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
// https://people.w3.org/rishida/scripts/uniview/conversion
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
template <typename In>
In Utf<8>::decode(In begin, In end, Uint32& output, Uint32 replacement)
{
// Some useful precomputed data
static const int trailing[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
};
static const Uint32 offsets[6] =
{
0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
};
// decode the character
int trailingBytes = trailing[static_cast<Uint8>(*begin)];
if (begin + trailingBytes < end)
{
output = 0;
switch (trailingBytes)
{
case 5: output += static_cast<Uint8>(*begin++); output <<= 6;
case 4: output += static_cast<Uint8>(*begin++); output <<= 6;
case 3: output += static_cast<Uint8>(*begin++); output <<= 6;
case 2: output += static_cast<Uint8>(*begin++); output <<= 6;
case 1: output += static_cast<Uint8>(*begin++); output <<= 6;
case 0: output += static_cast<Uint8>(*begin++);
}
output -= offsets[trailingBytes];
}
else
{
// Incomplete character
begin = end;
output = replacement;
}
return begin;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<8>::encode(Uint32 input, Out output, Uint8 replacement)
{
// Some useful precomputed data
static const Uint8 firstBytes[7] =
{
0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
};
// encode the character
if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
{
// Invalid character
if (replacement)
*output++ = replacement;
}
else
{
// Valid character
// Get the number of bytes to write
std::size_t bytestoWrite = 1;
if (input < 0x80) bytestoWrite = 1;
else if (input < 0x800) bytestoWrite = 2;
else if (input < 0x10000) bytestoWrite = 3;
else if (input <= 0x0010FFFF) bytestoWrite = 4;
// Extract the bytes to write
Uint8 bytes[4];
switch (bytestoWrite)
{
case 4: bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
case 3: bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
case 2: bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
case 1: bytes[0] = static_cast<Uint8> (input | firstBytes[bytestoWrite]);
}
// Add them to the output
output = std::copy(bytes, bytes + bytestoWrite, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<8>::next(In begin, In end)
{
Uint32 codepoint;
return decode(begin, end, codepoint);
}
////////////////////////////////////////////////////////////
template <typename In>
std::size_t Utf<8>::count(In begin, In end)
{
std::size_t length = 0;
while (begin < end)
{
begin = next(begin, end);
++length;
}
return length;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
{
while (begin < end)
{
Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::fromWide(In begin, In end, Out output)
{
while (begin < end)
{
Uint32 codepoint = Utf<32>::decodeWide(*begin++);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::fromLatin1(In begin, In end, Out output)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin < end)
output = encode(*begin++, output);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toWide(In begin, In end, Out output, wchar_t replacement)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeWide(codepoint, output, replacement);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toLatin1(In begin, In end, Out output, char replacement)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
*output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toUtf8(In begin, In end, Out output)
{
return std::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toUtf16(In begin, In end, Out output)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
output = Utf<16>::encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<8>::toUtf32(In begin, In end, Out output)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
*output++ = codepoint;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<16>::decode(In begin, In end, Uint32& output, Uint32 replacement)
{
Uint16 first = *begin++;
// If it's a surrogate pair, first convert to a single UTF-32 character
if ((first >= 0xD800) && (first <= 0xDBFF))
{
if (begin < end)
{
Uint32 second = *begin++;
if ((second >= 0xDC00) && (second <= 0xDFFF))
{
// The second element is valid: convert the two elements to a UTF-32 character
output = static_cast<Uint32>(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000);
}
else
{
// Invalid character
output = replacement;
}
}
else
{
// Invalid character
begin = end;
output = replacement;
}
}
else
{
// We can make a direct copy
output = first;
}
return begin;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<16>::encode(Uint32 input, Out output, Uint16 replacement)
{
if (input <= 0xFFFF)
{
// The character can be copied directly, we just need to check if it's in the valid range
if ((input >= 0xD800) && (input <= 0xDFFF))
{
// Invalid character (this range is reserved)
if (replacement)
*output++ = replacement;
}
else
{
// Valid character directly convertible to a single UTF-16 character
*output++ = static_cast<Uint16>(input);
}
}
else if (input > 0x0010FFFF)
{
// Invalid character (greater than the maximum Unicode value)
if (replacement)
*output++ = replacement;
}
else
{
// The input character will be converted to two UTF-16 elements
input -= 0x0010000;
*output++ = static_cast<Uint16>((input >> 10) + 0xD800);
*output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<16>::next(In begin, In end)
{
Uint32 codepoint;
return decode(begin, end, codepoint);
}
////////////////////////////////////////////////////////////
template <typename In>
std::size_t Utf<16>::count(In begin, In end)
{
std::size_t length = 0;
while (begin < end)
{
begin = next(begin, end);
++length;
}
return length;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
{
while (begin < end)
{
Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::fromWide(In begin, In end, Out output)
{
while (begin < end)
{
Uint32 codepoint = Utf<32>::decodeWide(*begin++);
output = encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::fromLatin1(In begin, In end, Out output)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
return std::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toWide(In begin, In end, Out output, wchar_t replacement)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
output = Utf<32>::encodeWide(codepoint, output, replacement);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toLatin1(In begin, In end, Out output, char replacement)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin < end)
{
*output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
begin++;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toUtf8(In begin, In end, Out output)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
output = Utf<8>::encode(codepoint, output);
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toUtf16(In begin, In end, Out output)
{
return std::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<16>::toUtf32(In begin, In end, Out output)
{
while (begin < end)
{
Uint32 codepoint;
begin = decode(begin, end, codepoint);
*output++ = codepoint;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<32>::decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/)
{
output = *begin++;
return begin;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<32>::encode(Uint32 input, Out output, Uint32 /*replacement*/)
{
*output++ = input;
return output;
}
////////////////////////////////////////////////////////////
template <typename In>
In Utf<32>::next(In begin, In /*end*/)
{
return ++begin;
}
////////////////////////////////////////////////////////////
template <typename In>
std::size_t Utf<32>::count(In begin, In end)
{
return begin - end;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale)
{
while (begin < end)
*output++ = decodeAnsi(*begin++, locale);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::fromWide(In begin, In end, Out output)
{
while (begin < end)
*output++ = decodeWide(*begin++);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::fromLatin1(In begin, In end, Out output)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
return std::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
{
while (begin < end)
output = encodeAnsi(*begin++, output, replacement, locale);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement)
{
while (begin < end)
output = encodeWide(*begin++, output, replacement);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toLatin1(In begin, In end, Out output, char replacement)
{
// Latin-1 is directly compatible with Unicode encodings,
// and can thus be treated as (a sub-range of) UTF-32
while (begin < end)
{
*output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
begin++;
}
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toUtf8(In begin, In end, Out output)
{
while (begin < end)
output = Utf<8>::encode(*begin++, output);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toUtf16(In begin, In end, Out output)
{
while (begin < end)
output = Utf<16>::encode(*begin++, output);
return output;
}
////////////////////////////////////////////////////////////
template <typename In, typename Out>
Out Utf<32>::toUtf32(In begin, In end, Out output)
{
return std::copy(begin, end, output);
}
////////////////////////////////////////////////////////////
template <typename In>
Uint32 Utf<32>::decodeAnsi(In input, const std::locale& locale)
{
// On Windows, GCC's standard library (glibc++) has almost
// no support for Unicode stuff. As a consequence, in this
// context we can only use the default locale and ignore
// the one passed as parameter.
#if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
(defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
!(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
(void)locale; // to avoid warnings
wchar_t character = 0;
mbtowc(&character, &input, 1);
return static_cast<Uint32>(character);
#else
// Get the facet of the locale which deals with character conversion
const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
// Use the facet to convert each character of the input string
return static_cast<Uint32>(facet.widen(input));
#endif
}
////////////////////////////////////////////////////////////
template <typename In>
Uint32 Utf<32>::decodeWide(In input)
{
// The encoding of wide characters is not well defined and is left to the system;
// however we can safely assume that it is UCS-2 on Windows and
// UCS-4 on Unix systems.
// In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4,
// and UCS-4 *is* UTF-32).
return input;
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<32>::encodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale)
{
// On Windows, gcc's standard library (glibc++) has almost
// no support for Unicode stuff. As a consequence, in this
// context we can only use the default locale and ignore
// the one passed as parameter.
#if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \
(defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
!(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
(void)locale; // to avoid warnings
char character = 0;
if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0)
*output++ = character;
else if (replacement)
*output++ = replacement;
return output;
#else
// Get the facet of the locale which deals with character conversion
const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
// Use the facet to convert each character of the input string
*output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement);
return output;
#endif
}
////////////////////////////////////////////////////////////
template <typename Out>
Out Utf<32>::encodeWide(Uint32 codepoint, Out output, wchar_t replacement)
{
// The encoding of wide characters is not well defined and is left to the system;
// however we can safely assume that it is UCS-2 on Windows and
// UCS-4 on Unix systems.
// For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4).
// For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32).
switch (sizeof(wchar_t))
{
case 4:
{
*output++ = static_cast<wchar_t>(codepoint);
break;
}
default:
{
if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF)))
{
*output++ = static_cast<wchar_t>(codepoint);
}
else if (replacement)
{
*output++ = replacement;
}
break;
}
}
return output;
}

View file

@ -1,415 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Http.hpp>
#include <SFML/System/Err.hpp>
#include <cctype>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <limits>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
{
setMethod(method);
setUri(uri);
setHttpVersion(1, 0);
setBody(body);
}
////////////////////////////////////////////////////////////
void Http::Request::setField(const std::string& field, const std::string& value)
{
m_fields[toLower(field)] = value;
}
////////////////////////////////////////////////////////////
void Http::Request::setMethod(Http::Request::Method method)
{
m_method = method;
}
////////////////////////////////////////////////////////////
void Http::Request::setUri(const std::string& uri)
{
m_uri = uri;
// Make sure it starts with a '/'
if (m_uri.empty() || (m_uri[0] != '/'))
m_uri.insert(0, "/");
}
////////////////////////////////////////////////////////////
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
{
m_majorVersion = major;
m_minorVersion = minor;
}
////////////////////////////////////////////////////////////
void Http::Request::setBody(const std::string& body)
{
m_body = body;
}
////////////////////////////////////////////////////////////
std::string Http::Request::prepare() const
{
std::ostringstream out;
// Convert the method to its string representation
std::string method;
switch (m_method)
{
case Get: method = "GET"; break;
case Post: method = "POST"; break;
case Head: method = "HEAD"; break;
case Put: method = "PUT"; break;
case Delete: method = "DELETE"; break;
}
// Write the first line containing the request type
out << method << " " << m_uri << " ";
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
// Write fields
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
{
out << i->first << ": " << i->second << "\r\n";
}
// Use an extra \r\n to separate the header from the body
out << "\r\n";
// Add the body
out << m_body;
return out.str();
}
////////////////////////////////////////////////////////////
bool Http::Request::hasField(const std::string& field) const
{
return m_fields.find(toLower(field)) != m_fields.end();
}
////////////////////////////////////////////////////////////
Http::Response::Response() :
m_status (ConnectionFailed),
m_majorVersion(0),
m_minorVersion(0)
{
}
////////////////////////////////////////////////////////////
const std::string& Http::Response::getField(const std::string& field) const
{
FieldTable::const_iterator it = m_fields.find(toLower(field));
if (it != m_fields.end())
{
return it->second;
}
else
{
static const std::string empty = "";
return empty;
}
}
////////////////////////////////////////////////////////////
Http::Response::Status Http::Response::getStatus() const
{
return m_status;
}
////////////////////////////////////////////////////////////
unsigned int Http::Response::getMajorHttpVersion() const
{
return m_majorVersion;
}
////////////////////////////////////////////////////////////
unsigned int Http::Response::getMinorHttpVersion() const
{
return m_minorVersion;
}
////////////////////////////////////////////////////////////
const std::string& Http::Response::getBody() const
{
return m_body;
}
////////////////////////////////////////////////////////////
void Http::Response::parse(const std::string& data)
{
std::istringstream in(data);
// Extract the HTTP version from the first line
std::string version;
if (in >> version)
{
if ((version.size() >= 8) && (version[6] == '.') &&
(toLower(version.substr(0, 5)) == "http/") &&
isdigit(version[5]) && isdigit(version[7]))
{
m_majorVersion = version[5] - '0';
m_minorVersion = version[7] - '0';
}
else
{
// Invalid HTTP version
m_status = InvalidResponse;
return;
}
}
// Extract the status code from the first line
int status;
if (in >> status)
{
m_status = static_cast<Status>(status);
}
else
{
// Invalid status code
m_status = InvalidResponse;
return;
}
// Ignore the end of the first line
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Parse the other lines, which contain fields, one by one
parseFields(in);
m_body.clear();
// Determine whether the transfer is chunked
if (toLower(getField("transfer-encoding")) != "chunked")
{
// Not chunked - just read everything at once
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
}
else
{
// Chunked - have to read chunk by chunk
std::size_t length;
// Read all chunks, identified by a chunk-size not being 0
while (in >> std::hex >> length)
{
// Drop the rest of the line (chunk-extension)
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Copy the actual content data
std::istreambuf_iterator<char> it(in);
std::istreambuf_iterator<char> itEnd;
for (std::size_t i = 0; ((i < length) && (it != itEnd)); i++)
m_body.push_back(*it++);
}
// Drop the rest of the line (chunk-extension)
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Read all trailers (if present)
parseFields(in);
}
}
////////////////////////////////////////////////////////////
void Http::Response::parseFields(std::istream &in)
{
std::string line;
while (std::getline(in, line) && (line.size() > 2))
{
std::string::size_type pos = line.find(": ");
if (pos != std::string::npos)
{
// Extract the field name and its value
std::string field = line.substr(0, pos);
std::string value = line.substr(pos + 2);
// Remove any trailing \r
if (!value.empty() && (*value.rbegin() == '\r'))
value.erase(value.size() - 1);
// Add the field
m_fields[toLower(field)] = value;
}
}
}
////////////////////////////////////////////////////////////
Http::Http() :
m_host(),
m_port(0)
{
}
////////////////////////////////////////////////////////////
Http::Http(const std::string& host, unsigned short port)
{
setHost(host, port);
}
////////////////////////////////////////////////////////////
void Http::setHost(const std::string& host, unsigned short port)
{
// Check the protocol
if (toLower(host.substr(0, 7)) == "http://")
{
// HTTP protocol
m_hostName = host.substr(7);
m_port = (port != 0 ? port : 80);
}
else if (toLower(host.substr(0, 8)) == "https://")
{
// HTTPS protocol -- unsupported (requires encryption and certificates and stuff...)
err() << "HTTPS protocol is not supported by sf::Http" << std::endl;
m_hostName = "";
m_port = 0;
}
else
{
// Undefined protocol - use HTTP
m_hostName = host;
m_port = (port != 0 ? port : 80);
}
// Remove any trailing '/' from the host name
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
m_hostName.erase(m_hostName.size() - 1);
m_host = IpAddress(m_hostName);
}
////////////////////////////////////////////////////////////
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
{
// First make sure that the request is valid -- add missing mandatory fields
Request toSend(request);
if (!toSend.hasField("From"))
{
toSend.setField("From", "user@sfml-dev.org");
}
if (!toSend.hasField("User-Agent"))
{
toSend.setField("User-Agent", "libsfml-network/2.x");
}
if (!toSend.hasField("Host"))
{
toSend.setField("Host", m_hostName);
}
if (!toSend.hasField("Content-Length"))
{
std::ostringstream out;
out << toSend.m_body.size();
toSend.setField("Content-Length", out.str());
}
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
{
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
}
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
{
toSend.setField("Connection", "close");
}
// Prepare the response
Response received;
// Connect the socket to the host
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
{
// Convert the request to string and send it through the connected socket
std::string requestStr = toSend.prepare();
if (!requestStr.empty())
{
// Send it through the socket
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
{
// Wait for the server's response
std::string receivedStr;
std::size_t size = 0;
char buffer[1024];
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
{
receivedStr.append(buffer, buffer + size);
}
// Build the Response object from the received data
received.parse(receivedStr);
}
}
// Close the connection
m_connection.disconnect();
}
return received;
}
} // namespace sf

View file

@ -1,271 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/IPAddress.hpp>
#include <SFML/Network/Http.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <cstring>
#include <utility>
namespace sf
{
////////////////////////////////////////////////////////////
const IpAddress IpAddress::None;
const IpAddress IpAddress::Any(0, 0, 0, 0);
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
////////////////////////////////////////////////////////////
IpAddress::IpAddress() :
m_address(0),
m_valid (false)
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(const std::string& address) :
m_address(0),
m_valid (false)
{
resolve(address);
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(const char* address) :
m_address(0),
m_valid (false)
{
resolve(address);
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3)),
m_valid (true)
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(Uint32 address) :
m_address(htonl(address)),
m_valid (true)
{
}
////////////////////////////////////////////////////////////
std::string IpAddress::toString() const
{
in_addr address;
address.s_addr = m_address;
return inet_ntoa(address);
}
////////////////////////////////////////////////////////////
Uint32 IpAddress::toInteger() const
{
return ntohl(m_address);
}
////////////////////////////////////////////////////////////
IpAddress IpAddress::getLocalAddress()
{
// The method here is to connect a UDP socket to anyone (here to localhost),
// and get the local socket address with the getsockname function.
// UDP connection will not send anything to the network, so this function won't cause any overhead.
IpAddress localAddress;
// Create the socket
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == priv::SocketImpl::invalidSocket())
return localAddress;
// Connect the socket to localhost on any port
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
priv::SocketImpl::close(sock);
return localAddress;
}
// Get the local address of the socket connection
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
{
priv::SocketImpl::close(sock);
return localAddress;
}
// Close the socket
priv::SocketImpl::close(sock);
// Finally build the IP address
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
return localAddress;
}
////////////////////////////////////////////////////////////
IpAddress IpAddress::getPublicAddress(Time timeout)
{
// The trick here is more complicated, because the only way
// to get our public IP address is to get it from a distant computer.
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
// and parse the result to extract our IP address
// (not very hard: the web page contains only our IP address).
Http server("www.sfml-dev.org");
Http::Request request("/ip-provider.php", Http::Request::Get);
Http::Response page = server.sendRequest(request, timeout);
if (page.getStatus() == Http::Response::Ok)
return IpAddress(page.getBody());
// Something failed: return an invalid address
return IpAddress();
}
////////////////////////////////////////////////////////////
void IpAddress::resolve(const std::string& address)
{
m_address = 0;
m_valid = false;
if (address == "255.255.255.255")
{
// The broadcast address needs to be handled explicitly,
// because it is also the value returned by inet_addr on error
m_address = INADDR_BROADCAST;
m_valid = true;
}
else if (address == "0.0.0.0")
{
m_address = INADDR_ANY;
m_valid = true;
}
else
{
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
Uint32 ip = inet_addr(address.c_str());
if (ip != INADDR_NONE)
{
m_address = ip;
m_valid = true;
}
else
{
// Not a valid address, try to convert it as a host name
addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
addrinfo* result = NULL;
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
{
if (result)
{
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
m_address = ip;
m_valid = true;
}
}
}
}
}
////////////////////////////////////////////////////////////
bool operator ==(const IpAddress& left, const IpAddress& right)
{
return !(left < right) && !(right < left);
}
////////////////////////////////////////////////////////////
bool operator !=(const IpAddress& left, const IpAddress& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const IpAddress& left, const IpAddress& right)
{
return std::make_pair(left.m_valid, left.m_address) < std::make_pair(right.m_valid, right.m_address);
}
////////////////////////////////////////////////////////////
bool operator >(const IpAddress& left, const IpAddress& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const IpAddress& left, const IpAddress& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const IpAddress& left, const IpAddress& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
std::istream& operator >>(std::istream& stream, IpAddress& address)
{
std::string str;
stream >> str;
address = IpAddress(str);
return stream;
}
////////////////////////////////////////////////////////////
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
{
return stream << address.toString();
}
} // namespace sf

View file

@ -1,596 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/String.hpp>
#include <cstring>
#include <cwchar>
namespace sf
{
////////////////////////////////////////////////////////////
Packet::Packet() :
m_readPos(0),
m_sendPos(0),
m_isValid(true)
{
}
////////////////////////////////////////////////////////////
Packet::~Packet()
{
}
////////////////////////////////////////////////////////////
void Packet::append(const void* data, std::size_t sizeInBytes)
{
if (data && (sizeInBytes > 0))
{
std::size_t start = m_data.size();
m_data.resize(start + sizeInBytes);
std::memcpy(&m_data[start], data, sizeInBytes);
}
}
////////////////////////////////////////////////////////////
void Packet::clear()
{
m_data.clear();
m_readPos = 0;
m_isValid = true;
}
////////////////////////////////////////////////////////////
const void* Packet::getData() const
{
return !m_data.empty() ? &m_data[0] : NULL;
}
////////////////////////////////////////////////////////////
std::size_t Packet::getDataSize() const
{
return m_data.size();
}
////////////////////////////////////////////////////////////
bool Packet::endOfPacket() const
{
return m_readPos >= m_data.size();
}
////////////////////////////////////////////////////////////
Packet::operator BoolType() const
{
return m_isValid ? &Packet::checkSize : NULL;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(bool& data)
{
Uint8 value;
if (*this >> value)
data = (value != 0);
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Int8& data)
{
if (checkSize(sizeof(data)))
{
data = *reinterpret_cast<const Int8*>(&m_data[m_readPos]);
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Uint8& data)
{
if (checkSize(sizeof(data)))
{
data = *reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Int16& data)
{
if (checkSize(sizeof(data)))
{
data = ntohs(*reinterpret_cast<const Int16*>(&m_data[m_readPos]));
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Uint16& data)
{
if (checkSize(sizeof(data)))
{
data = ntohs(*reinterpret_cast<const Uint16*>(&m_data[m_readPos]));
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Int32& data)
{
if (checkSize(sizeof(data)))
{
data = ntohl(*reinterpret_cast<const Int32*>(&m_data[m_readPos]));
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Uint32& data)
{
if (checkSize(sizeof(data)))
{
data = ntohl(*reinterpret_cast<const Uint32*>(&m_data[m_readPos]));
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Int64& data)
{
if (checkSize(sizeof(data)))
{
// Since ntohll is not available everywhere, we have to convert
// to network byte order (big endian) manually
const Uint8* bytes = reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
data = (static_cast<Int64>(bytes[0]) << 56) |
(static_cast<Int64>(bytes[1]) << 48) |
(static_cast<Int64>(bytes[2]) << 40) |
(static_cast<Int64>(bytes[3]) << 32) |
(static_cast<Int64>(bytes[4]) << 24) |
(static_cast<Int64>(bytes[5]) << 16) |
(static_cast<Int64>(bytes[6]) << 8) |
(static_cast<Int64>(bytes[7]) );
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(Uint64& data)
{
if (checkSize(sizeof(data)))
{
// Since ntohll is not available everywhere, we have to convert
// to network byte order (big endian) manually
const Uint8* bytes = reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
data = (static_cast<Uint64>(bytes[0]) << 56) |
(static_cast<Uint64>(bytes[1]) << 48) |
(static_cast<Uint64>(bytes[2]) << 40) |
(static_cast<Uint64>(bytes[3]) << 32) |
(static_cast<Uint64>(bytes[4]) << 24) |
(static_cast<Uint64>(bytes[5]) << 16) |
(static_cast<Uint64>(bytes[6]) << 8) |
(static_cast<Uint64>(bytes[7]) );
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(float& data)
{
if (checkSize(sizeof(data)))
{
data = *reinterpret_cast<const float*>(&m_data[m_readPos]);
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(double& data)
{
if (checkSize(sizeof(data)))
{
data = *reinterpret_cast<const double*>(&m_data[m_readPos]);
m_readPos += sizeof(data);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(char* data)
{
// First extract string length
Uint32 length = 0;
*this >> length;
if ((length > 0) && checkSize(length))
{
// Then extract characters
std::memcpy(data, &m_data[m_readPos], length);
data[length] = '\0';
// Update reading position
m_readPos += length;
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(std::string& data)
{
// First extract string length
Uint32 length = 0;
*this >> length;
data.clear();
if ((length > 0) && checkSize(length))
{
// Then extract characters
data.assign(&m_data[m_readPos], length);
// Update reading position
m_readPos += length;
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(wchar_t* data)
{
// First extract string length
Uint32 length = 0;
*this >> length;
if ((length > 0) && checkSize(length * sizeof(Uint32)))
{
// Then extract characters
for (Uint32 i = 0; i < length; ++i)
{
Uint32 character = 0;
*this >> character;
data[i] = static_cast<wchar_t>(character);
}
data[length] = L'\0';
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(std::wstring& data)
{
// First extract string length
Uint32 length = 0;
*this >> length;
data.clear();
if ((length > 0) && checkSize(length * sizeof(Uint32)))
{
// Then extract characters
for (Uint32 i = 0; i < length; ++i)
{
Uint32 character = 0;
*this >> character;
data += static_cast<wchar_t>(character);
}
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator >>(String& data)
{
// First extract the string length
Uint32 length = 0;
*this >> length;
data.clear();
if ((length > 0) && checkSize(length * sizeof(Uint32)))
{
// Then extract characters
for (Uint32 i = 0; i < length; ++i)
{
Uint32 character = 0;
*this >> character;
data += character;
}
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(bool data)
{
*this << static_cast<Uint8>(data);
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Int8 data)
{
append(&data, sizeof(data));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Uint8 data)
{
append(&data, sizeof(data));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Int16 data)
{
Int16 toWrite = htons(data);
append(&toWrite, sizeof(toWrite));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Uint16 data)
{
Uint16 toWrite = htons(data);
append(&toWrite, sizeof(toWrite));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Int32 data)
{
Int32 toWrite = htonl(data);
append(&toWrite, sizeof(toWrite));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Uint32 data)
{
Uint32 toWrite = htonl(data);
append(&toWrite, sizeof(toWrite));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Int64 data)
{
// Since htonll is not available everywhere, we have to convert
// to network byte order (big endian) manually
Uint8 toWrite[] =
{
static_cast<Uint8>((data >> 56) & 0xFF),
static_cast<Uint8>((data >> 48) & 0xFF),
static_cast<Uint8>((data >> 40) & 0xFF),
static_cast<Uint8>((data >> 32) & 0xFF),
static_cast<Uint8>((data >> 24) & 0xFF),
static_cast<Uint8>((data >> 16) & 0xFF),
static_cast<Uint8>((data >> 8) & 0xFF),
static_cast<Uint8>((data ) & 0xFF)
};
append(&toWrite, sizeof(toWrite));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(Uint64 data)
{
// Since htonll is not available everywhere, we have to convert
// to network byte order (big endian) manually
Uint8 toWrite[] =
{
static_cast<Uint8>((data >> 56) & 0xFF),
static_cast<Uint8>((data >> 48) & 0xFF),
static_cast<Uint8>((data >> 40) & 0xFF),
static_cast<Uint8>((data >> 32) & 0xFF),
static_cast<Uint8>((data >> 24) & 0xFF),
static_cast<Uint8>((data >> 16) & 0xFF),
static_cast<Uint8>((data >> 8) & 0xFF),
static_cast<Uint8>((data ) & 0xFF)
};
append(&toWrite, sizeof(toWrite));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(float data)
{
append(&data, sizeof(data));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(double data)
{
append(&data, sizeof(data));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(const char* data)
{
// First insert string length
Uint32 length = static_cast<Uint32>(std::strlen(data));
*this << length;
// Then insert characters
append(data, length * sizeof(char));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(const std::string& data)
{
// First insert string length
Uint32 length = static_cast<Uint32>(data.size());
*this << length;
// Then insert characters
if (length > 0)
append(data.c_str(), length * sizeof(std::string::value_type));
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(const wchar_t* data)
{
// First insert string length
Uint32 length = static_cast<Uint32>(std::wcslen(data));
*this << length;
// Then insert characters
for (const wchar_t* c = data; *c != L'\0'; ++c)
*this << static_cast<Uint32>(*c);
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(const std::wstring& data)
{
// First insert string length
Uint32 length = static_cast<Uint32>(data.size());
*this << length;
// Then insert characters
if (length > 0)
{
for (std::wstring::const_iterator c = data.begin(); c != data.end(); ++c)
*this << static_cast<Uint32>(*c);
}
return *this;
}
////////////////////////////////////////////////////////////
Packet& Packet::operator <<(const String& data)
{
// First insert the string length
Uint32 length = static_cast<Uint32>(data.getSize());
*this << length;
// Then insert characters
if (length > 0)
{
for (String::ConstIterator c = data.begin(); c != data.end(); ++c)
*this << *c;
}
return *this;
}
////////////////////////////////////////////////////////////
bool Packet::checkSize(std::size_t size)
{
m_isValid = m_isValid && (m_readPos + size <= m_data.size());
return m_isValid;
}
////////////////////////////////////////////////////////////
const void* Packet::onSend(std::size_t& size)
{
size = getDataSize();
return getData();
}
////////////////////////////////////////////////////////////
void Packet::onReceive(const void* data, std::size_t size)
{
append(data, size);
}
} // namespace sf

View file

@ -1,151 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Socket::Socket(Type type) :
m_type (type),
m_socket (priv::SocketImpl::invalidSocket()),
m_isBlocking(true)
{
}
////////////////////////////////////////////////////////////
Socket::~Socket()
{
// Close the socket before it gets destructed
close();
}
////////////////////////////////////////////////////////////
void Socket::setBlocking(bool blocking)
{
// Apply if the socket is already created
if (m_socket != priv::SocketImpl::invalidSocket())
priv::SocketImpl::setBlocking(m_socket, blocking);
m_isBlocking = blocking;
}
////////////////////////////////////////////////////////////
bool Socket::isBlocking() const
{
return m_isBlocking;
}
////////////////////////////////////////////////////////////
SocketHandle Socket::getHandle() const
{
return m_socket;
}
////////////////////////////////////////////////////////////
void Socket::create()
{
// Don't create the socket if it already exists
if (m_socket == priv::SocketImpl::invalidSocket())
{
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
if (handle == priv::SocketImpl::invalidSocket())
{
err() << "Failed to create socket" << std::endl;
return;
}
create(handle);
}
}
////////////////////////////////////////////////////////////
void Socket::create(SocketHandle handle)
{
// Don't create the socket if it already exists
if (m_socket == priv::SocketImpl::invalidSocket())
{
// Assign the new handle
m_socket = handle;
// Set the current blocking state
setBlocking(m_isBlocking);
if (m_type == Tcp)
{
// Disable the Nagle algorithm (i.e. removes buffering of TCP packets)
int yes = 1;
if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to set socket option \"TCP_NODELAY\" ; "
<< "all your TCP packets will be buffered" << std::endl;
}
// On Mac OS X, disable the SIGPIPE signal on disconnection
#ifdef SFML_SYSTEM_MACOS
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
}
#endif
}
else
{
// Enable broadcast by default for UDP sockets
int yes = 1;
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to enable broadcast on UDP socket" << std::endl;
}
}
}
}
////////////////////////////////////////////////////////////
void Socket::close()
{
// Close the socket
if (m_socket != priv::SocketImpl::invalidSocket())
{
priv::SocketImpl::close(m_socket);
m_socket = priv::SocketImpl::invalidSocket();
}
}
} // namespace sf

View file

@ -1,39 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Network/Win32/SocketImpl.hpp>
#else
#include <SFML/Network/Unix/SocketImpl.hpp>
#endif

View file

@ -1,205 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/SocketSelector.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <utility>
#ifdef _MSC_VER
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
#endif
namespace sf
{
////////////////////////////////////////////////////////////
struct SocketSelector::SocketSelectorImpl
{
fd_set allSockets; ///< Set containing all the sockets handles
fd_set socketsReady; ///< Set containing handles of the sockets that are ready
int maxSocket; ///< Maximum socket handle
int socketCount; ///< Number of socket handles
};
////////////////////////////////////////////////////////////
SocketSelector::SocketSelector() :
m_impl(new SocketSelectorImpl)
{
clear();
}
////////////////////////////////////////////////////////////
SocketSelector::SocketSelector(const SocketSelector& copy) :
m_impl(new SocketSelectorImpl(*copy.m_impl))
{
}
////////////////////////////////////////////////////////////
SocketSelector::~SocketSelector()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
void SocketSelector::add(Socket& socket)
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if defined(SFML_SYSTEM_WINDOWS)
if (m_impl->socketCount >= FD_SETSIZE)
{
err() << "The socket can't be added to the selector because the "
<< "selector is full. This is a limitation of your operating "
<< "system's FD_SETSIZE setting.";
return;
}
if (FD_ISSET(handle, &m_impl->allSockets))
return;
m_impl->socketCount++;
#else
if (handle >= FD_SETSIZE)
{
err() << "The socket can't be added to the selector because its "
<< "ID is too high. This is a limitation of your operating "
<< "system's FD_SETSIZE setting.";
return;
}
// SocketHandle is an int in POSIX
m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
#endif
FD_SET(handle, &m_impl->allSockets);
}
}
////////////////////////////////////////////////////////////
void SocketSelector::remove(Socket& socket)
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if defined(SFML_SYSTEM_WINDOWS)
if (!FD_ISSET(handle, &m_impl->allSockets))
return;
m_impl->socketCount--;
#else
if (handle >= FD_SETSIZE)
return;
#endif
FD_CLR(handle, &m_impl->allSockets);
FD_CLR(handle, &m_impl->socketsReady);
}
}
////////////////////////////////////////////////////////////
void SocketSelector::clear()
{
FD_ZERO(&m_impl->allSockets);
FD_ZERO(&m_impl->socketsReady);
m_impl->maxSocket = 0;
m_impl->socketCount = 0;
}
////////////////////////////////////////////////////////////
bool SocketSelector::wait(Time timeout)
{
// Setup the timeout
timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
// Initialize the set that will contain the sockets that are ready
m_impl->socketsReady = m_impl->allSockets;
// Wait until one of the sockets is ready for reading, or timeout is reached
// The first parameter is ignored on Windows
int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
return count > 0;
}
////////////////////////////////////////////////////////////
bool SocketSelector::isReady(Socket& socket) const
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if !defined(SFML_SYSTEM_WINDOWS)
if (handle >= FD_SETSIZE)
return false;
#endif
return FD_ISSET(handle, &m_impl->socketsReady) != 0;
}
return false;
}
////////////////////////////////////////////////////////////
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
{
SocketSelector temp(right);
std::swap(m_impl, temp.m_impl);
return *this;
}
} // namespace sf

View file

@ -1,131 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/TcpListener.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
TcpListener::TcpListener() :
Socket(Tcp)
{
}
////////////////////////////////////////////////////////////
unsigned short TcpListener::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address)
{
// Close the socket if it is already bound
close();
// Create the internal socket if it doesn't exist
create();
// Check if the address is valid
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
return Error;
// Bind the socket to the specified port
sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
{
// Not likely to happen, but...
err() << "Failed to bind listener socket to port " << port << std::endl;
return Error;
}
// Listen to the bound port
if (::listen(getHandle(), SOMAXCONN) == -1)
{
// Oops, socket is deaf
err() << "Failed to listen to port " << port << std::endl;
return Error;
}
return Done;
}
////////////////////////////////////////////////////////////
void TcpListener::close()
{
// Simply close the socket
Socket::close();
}
////////////////////////////////////////////////////////////
Socket::Status TcpListener::accept(TcpSocket& socket)
{
// Make sure that we're listening
if (getHandle() == priv::SocketImpl::invalidSocket())
{
err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
return Error;
}
// Accept a new connection
sockaddr_in address;
priv::SocketImpl::AddrLength length = sizeof(address);
SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
// Check for errors
if (remote == priv::SocketImpl::invalidSocket())
return priv::SocketImpl::getErrorStatus();
// Initialize the new connected socket
socket.close();
socket.create(remote);
return Done;
}
} // namespace sf

View file

@ -1,416 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/Network/IPAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <cstring>
#ifdef _MSC_VER
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
#endif
namespace
{
// Define the low-level send/receive flags, which depend on the OS
#ifdef SFML_SYSTEM_LINUX
const int flags = MSG_NOSIGNAL;
#else
const int flags = 0;
#endif
}
namespace sf
{
////////////////////////////////////////////////////////////
TcpSocket::TcpSocket() :
Socket(Tcp)
{
}
////////////////////////////////////////////////////////////
unsigned short TcpSocket::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
IpAddress TcpSocket::getRemoteAddress() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the remote end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return IpAddress(ntohl(address.sin_addr.s_addr));
}
}
// We failed to retrieve the address
return IpAddress::None;
}
////////////////////////////////////////////////////////////
unsigned short TcpSocket::getRemotePort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the remote end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
{
// Disconnect the socket if it is already connected
disconnect();
// Create the internal socket if it doesn't exist
create();
// Create the remote address
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
if (timeout <= Time::Zero)
{
// ----- We're not using a timeout: just try to connect -----
// Connect the socket
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
return priv::SocketImpl::getErrorStatus();
// Connection succeeded
return Done;
}
else
{
// ----- We're using a timeout: we'll need a few tricks to make it work -----
// Save the previous blocking state
bool blocking = isBlocking();
// Switch to non-blocking to enable our connection timeout
if (blocking)
setBlocking(false);
// Try to connect to the remote address
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
{
// We got instantly connected! (it may no happen a lot...)
setBlocking(blocking);
return Done;
}
// Get the error status
Status status = priv::SocketImpl::getErrorStatus();
// If we were in non-blocking mode, return immediately
if (!blocking)
return status;
// Otherwise, wait until something happens to our socket (success, timeout or error)
if (status == Socket::NotReady)
{
// Setup the selector
fd_set selector;
FD_ZERO(&selector);
FD_SET(getHandle(), &selector);
// Setup the timeout
timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
// Wait for something to write on our socket (which means that the connection request has returned)
if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0)
{
// At this point the connection may have been either accepted or refused.
// To know whether it's a success or a failure, we must check the address of the connected peer
if (getRemoteAddress() != IpAddress::None)
{
// Connection accepted
status = Done;
}
else
{
// Connection refused
status = priv::SocketImpl::getErrorStatus();
}
}
else
{
// Failed to connect before timeout is over
status = priv::SocketImpl::getErrorStatus();
}
}
// Switch back to blocking mode
setBlocking(true);
return status;
}
}
////////////////////////////////////////////////////////////
void TcpSocket::disconnect()
{
// Close the socket
close();
// Reset the pending packet data
m_pendingPacket = PendingPacket();
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(const void* data, std::size_t size)
{
if (!isBlocking())
err() << "Warning: Partial sends might not be handled properly." << std::endl;
std::size_t sent;
return send(data, size, sent);
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(const void* data, std::size_t size, std::size_t& sent)
{
// Check the parameters
if (!data || (size == 0))
{
err() << "Cannot send data over the network (no data to send)" << std::endl;
return Error;
}
// Loop until every byte has been sent
int result = 0;
for (sent = 0; sent < size; sent += result)
{
// Send a chunk of data
result = ::send(getHandle(), static_cast<const char*>(data) + sent, size - sent, flags);
// Check for errors
if (result < 0)
{
Status status = priv::SocketImpl::getErrorStatus();
if ((status == NotReady) && sent)
return Partial;
return status;
}
}
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
{
// First clear the variables to fill
received = 0;
// Check the destination buffer
if (!data)
{
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
return Error;
}
// Receive a chunk of bytes
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
// Check the number of bytes received
if (sizeReceived > 0)
{
received = static_cast<std::size_t>(sizeReceived);
return Done;
}
else if (sizeReceived == 0)
{
return Socket::Disconnected;
}
else
{
return priv::SocketImpl::getErrorStatus();
}
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(Packet& packet)
{
// TCP is a stream protocol, it doesn't preserve messages boundaries.
// This means that we have to send the packet size first, so that the
// receiver knows the actual end of the packet in the data stream.
// We allocate an extra memory block so that the size can be sent
// together with the data in a single call. This may seem inefficient,
// but it is actually required to avoid partial send, which could cause
// data corruption on the receiving end.
// Get the data to send from the packet
std::size_t size = 0;
const void* data = packet.onSend(size);
// First convert the packet size to network byte order
Uint32 packetSize = htonl(static_cast<Uint32>(size));
// Allocate memory for the data block to send
std::vector<char> blockToSend(sizeof(packetSize) + size);
// Copy the packet size and data into the block to send
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
if (size > 0)
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
// Send the data block
std::size_t sent;
Status status = send(&blockToSend[0] + packet.m_sendPos, blockToSend.size() - packet.m_sendPos, sent);
// In the case of a partial send, record the location to resume from
if (status == Partial)
{
packet.m_sendPos += sent;
}
else if (status == Done)
{
packet.m_sendPos = 0;
}
return status;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::receive(Packet& packet)
{
// First clear the variables to fill
packet.clear();
// We start by getting the size of the incoming packet
Uint32 packetSize = 0;
std::size_t received = 0;
if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
{
// Loop until we've received the entire size of the packet
// (even a 4 byte variable may be received in more than one call)
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
{
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
m_pendingPacket.SizeReceived += received;
if (status != Done)
return status;
}
// The packet size has been fully received
packetSize = ntohl(m_pendingPacket.Size);
}
else
{
// The packet size has already been received in a previous call
packetSize = ntohl(m_pendingPacket.Size);
}
// Loop until we receive all the packet data
char buffer[1024];
while (m_pendingPacket.Data.size() < packetSize)
{
// Receive a chunk of data
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
Status status = receive(buffer, sizeToGet, received);
if (status != Done)
return status;
// Append it into the packet
if (received > 0)
{
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
std::memcpy(begin, buffer, received);
}
}
// We have received all the packet data: we can copy it to the user packet
if (!m_pendingPacket.Data.empty())
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
// Clear the pending packet data
m_pendingPacket = PendingPacket();
return Done;
}
////////////////////////////////////////////////////////////
TcpSocket::PendingPacket::PendingPacket() :
Size (0),
SizeReceived(0),
Data ()
{
}
} // namespace sf

View file

@ -1,200 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/UdpSocket.hpp>
#include <SFML/Network/IPAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
namespace sf
{
////////////////////////////////////////////////////////////
UdpSocket::UdpSocket() :
Socket (Udp),
m_buffer(MaxDatagramSize)
{
}
////////////////////////////////////////////////////////////
unsigned short UdpSocket::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::bind(unsigned short port, const IpAddress& address)
{
// Close the socket if it is already bound
close();
// Create the internal socket if it doesn't exist
create();
// Check if the address is valid
if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
return Error;
// Bind the socket
sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
{
err() << "Failed to bind socket to port " << port << std::endl;
return Error;
}
return Done;
}
////////////////////////////////////////////////////////////
void UdpSocket::unbind()
{
// Simply close the socket
close();
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
{
// Create the internal socket if it doesn't exist
create();
// Make sure that all the data will fit in one datagram
if (size > MaxDatagramSize)
{
err() << "Cannot send data over the network "
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
return Error;
}
// Build the target address
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
// Send the data (unlike TCP, all the data is always sent in one call)
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
// Check for errors
if (sent < 0)
return priv::SocketImpl::getErrorStatus();
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
{
// First clear the variables to fill
received = 0;
remoteAddress = IpAddress();
remotePort = 0;
// Check the destination buffer
if (!data)
{
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
return Error;
}
// Data that will be filled with the other computer's address
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0);
// Receive a chunk of bytes
priv::SocketImpl::AddrLength addressSize = sizeof(address);
int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
// Check for errors
if (sizeReceived < 0)
return priv::SocketImpl::getErrorStatus();
// Fill the sender informations
received = static_cast<std::size_t>(sizeReceived);
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
remotePort = ntohs(address.sin_port);
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
{
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
// This also removes the overhead associated to packets -- there's no size to send in addition
// to the packet's data.
// Get the data to send from the packet
std::size_t size = 0;
const void* data = packet.onSend(size);
// Send it
return send(data, size, remoteAddress, remotePort);
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
{
// See the detailed comment in send(Packet) above.
// Receive the datagram
std::size_t received = 0;
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
// If we received valid data, we can copy it to the user packet
packet.clear();
if ((status == Done) && (received > 0))
packet.onReceive(&m_buffer[0], received);
return status;
}
} // namespace sf

View file

@ -1,112 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Unix/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <errno.h>
#include <fcntl.h>
#include <cstring>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
#if defined(SFML_SYSTEM_MACOS)
addr.sin_len = sizeof(addr);
#endif
return addr;
}
////////////////////////////////////////////////////////////
SocketHandle SocketImpl::invalidSocket()
{
return -1;
}
////////////////////////////////////////////////////////////
void SocketImpl::close(SocketHandle sock)
{
::close(sock);
}
////////////////////////////////////////////////////////////
void SocketImpl::setBlocking(SocketHandle sock, bool block)
{
int status = fcntl(sock, F_GETFL);
if (block)
{
if (fcntl(sock, F_SETFL, status & ~O_NONBLOCK) == -1)
err() << "Failed to set file status flags: " << errno << std::endl;
}
else
{
if (fcntl(sock, F_SETFL, status | O_NONBLOCK) == -1)
err() << "Failed to set file status flags: " << errno << std::endl;
}
}
////////////////////////////////////////////////////////////
Socket::Status SocketImpl::getErrorStatus()
{
// The followings are sometimes equal to EWOULDBLOCK,
// so we have to make a special case for them in order
// to avoid having double values in the switch case
if ((errno == EAGAIN) || (errno == EINPROGRESS))
return Socket::NotReady;
switch (errno)
{
case EWOULDBLOCK: return Socket::NotReady;
case ECONNABORTED: return Socket::Disconnected;
case ECONNRESET: return Socket::Disconnected;
case ETIMEDOUT: return Socket::Disconnected;
case ENETRESET: return Socket::Disconnected;
case ENOTCONN: return Socket::Disconnected;
case EPIPE: return Socket::Disconnected;
default: return Socket::Error;
}
}
} // namespace priv
} // namespace sf

View file

@ -1,109 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOCKETIMPL_HPP
#define SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Socket.hpp>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Helper class implementing all the non-portable
/// socket stuff; this is the Unix version
///
////////////////////////////////////////////////////////////
class SocketImpl
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef socklen_t AddrLength;
////////////////////////////////////////////////////////////
/// \brief Create an internal sockaddr_in address
///
/// \param address Target address
/// \param port Target port
///
/// \return sockaddr_in ready to be used by socket functions
///
////////////////////////////////////////////////////////////
static sockaddr_in createAddress(Uint32 address, unsigned short port);
////////////////////////////////////////////////////////////
/// \brief Return the value of the invalid socket
///
/// \return Special value of the invalid socket
///
////////////////////////////////////////////////////////////
static SocketHandle invalidSocket();
////////////////////////////////////////////////////////////
/// \brief Close and destroy a socket
///
/// \param sock Handle of the socket to close
///
////////////////////////////////////////////////////////////
static void close(SocketHandle sock);
////////////////////////////////////////////////////////////
/// \brief Set a socket as blocking or non-blocking
///
/// \param sock Handle of the socket
/// \param block New blocking state of the socket
///
////////////////////////////////////////////////////////////
static void setBlocking(SocketHandle sock, bool block);
////////////////////////////////////////////////////////////
/// Get the last socket error status
///
/// \return Status corresponding to the last socket error
///
////////////////////////////////////////////////////////////
static Socket::Status getErrorStatus();
};
} // namespace priv
} // namespace sf
#endif // SFML_SOCKETIMPL_HPP

View file

@ -1,112 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Win32/SocketImpl.hpp>
#include <cstring>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
return addr;
}
////////////////////////////////////////////////////////////
SocketHandle SocketImpl::invalidSocket()
{
return INVALID_SOCKET;
}
////////////////////////////////////////////////////////////
void SocketImpl::close(SocketHandle sock)
{
closesocket(sock);
}
////////////////////////////////////////////////////////////
void SocketImpl::setBlocking(SocketHandle sock, bool block)
{
u_long blocking = block ? 0 : 1;
ioctlsocket(sock, FIONBIO, &blocking);
}
////////////////////////////////////////////////////////////
Socket::Status SocketImpl::getErrorStatus()
{
switch (WSAGetLastError())
{
case WSAEWOULDBLOCK: return Socket::NotReady;
case WSAEALREADY: return Socket::NotReady;
case WSAECONNABORTED: return Socket::Disconnected;
case WSAECONNRESET: return Socket::Disconnected;
case WSAETIMEDOUT: return Socket::Disconnected;
case WSAENETRESET: return Socket::Disconnected;
case WSAENOTCONN: return Socket::Disconnected;
case WSAEISCONN: return Socket::Done; // when connecting a non-blocking socket
default: return Socket::Error;
}
}
////////////////////////////////////////////////////////////
// Windows needs some initialization and cleanup to get
// sockets working properly... so let's create a class that will
// do it automatically
////////////////////////////////////////////////////////////
struct SocketInitializer
{
SocketInitializer()
{
WSADATA init;
WSAStartup(MAKEWORD(2, 2), &init);
}
~SocketInitializer()
{
WSACleanup();
}
};
SocketInitializer globalInitializer;
} // namespace priv
} // namespace sf

View file

@ -1,112 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOCKETIMPL_HPP
#define SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#ifdef _WIN32_WINDOWS
#undef _WIN32_WINDOWS
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINDOWS 0x0501
#define _WIN32_WINNT 0x0501
#include <SFML/Network/Socket.hpp>
#include <winsock2.h>
#include <ws2tcpip.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Helper class implementing all the non-portable
/// socket stuff; this is the Windows version
///
////////////////////////////////////////////////////////////
class SocketImpl
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef int AddrLength;
////////////////////////////////////////////////////////////
/// \brief Create an internal sockaddr_in address
///
/// \param address Target address
/// \param port Target port
///
/// \return sockaddr_in ready to be used by socket functions
///
////////////////////////////////////////////////////////////
static sockaddr_in createAddress(Uint32 address, unsigned short port);
////////////////////////////////////////////////////////////
/// \brief Return the value of the invalid socket
///
/// \return Special value of the invalid socket
///
////////////////////////////////////////////////////////////
static SocketHandle invalidSocket();
////////////////////////////////////////////////////////////
/// \brief Close and destroy a socket
///
/// \param sock Handle of the socket to close
///
////////////////////////////////////////////////////////////
static void close(SocketHandle sock);
////////////////////////////////////////////////////////////
/// \brief Set a socket as blocking or non-blocking
///
/// \param sock Handle of the socket
/// \param block New blocking state of the socket
///
////////////////////////////////////////////////////////////
static void setBlocking(SocketHandle sock, bool block);
////////////////////////////////////////////////////////////
/// Get the last socket error status
///
/// \return Status corresponding to the last socket error
///
////////////////////////////////////////////////////////////
static Socket::Status getErrorStatus();
};
} // namespace priv
} // namespace sf
#endif // SFML_SOCKETIMPL_HPP

View file

@ -1,110 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Err.hpp>
#include <streambuf>
#include <cstdio>
namespace
{
// This class will be used as the default streambuf of sf::Err,
// it outputs to stderr by default (to keep the default behavior)
class DefaultErrStreamBuf : public std::streambuf
{
public:
DefaultErrStreamBuf()
{
// Allocate the write buffer
static const int size = 64;
char* buffer = new char[size];
setp(buffer, buffer + size);
}
~DefaultErrStreamBuf()
{
// Synchronize
sync();
// Delete the write buffer
delete[] pbase();
}
private:
virtual int overflow(int character)
{
if ((character != EOF) && (pptr() != epptr()))
{
// Valid character
return sputc(static_cast<char>(character));
}
else if (character != EOF)
{
// Not enough space in the buffer: synchronize output and try again
sync();
return overflow(character);
}
else
{
// Invalid character: synchronize output
return sync();
}
}
virtual int sync()
{
// Check if there is something into the write buffer
if (pbase() != pptr())
{
// Print the contents of the write buffer into the standard error output
std::size_t size = static_cast<int>(pptr() - pbase());
fwrite(pbase(), 1, size, stderr);
// Reset the pointer position to the beginning of the write buffer
setp(pbase(), epptr());
}
return 0;
}
};
}
namespace sf
{
////////////////////////////////////////////////////////////
std::ostream& err()
{
static DefaultErrStreamBuf buffer;
static std::ostream stream(&buffer);
return stream;
}
} // namespace sf

View file

@ -1,400 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/String.hpp>
#include <SFML/System/Utf.hpp>
#include <iterator>
#include <cstring>
namespace sf
{
////////////////////////////////////////////////////////////
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
////////////////////////////////////////////////////////////
String::String()
{
}
////////////////////////////////////////////////////////////
String::String(char ansiChar, const std::locale& locale)
{
m_string += Utf32::decodeAnsi(ansiChar, locale);
}
////////////////////////////////////////////////////////////
String::String(wchar_t wideChar)
{
m_string += Utf32::decodeWide(wideChar);
}
////////////////////////////////////////////////////////////
String::String(Uint32 utf32Char)
{
m_string += utf32Char;
}
////////////////////////////////////////////////////////////
String::String(const char* ansiString, const std::locale& locale)
{
if (ansiString)
{
std::size_t length = strlen(ansiString);
if (length > 0)
{
m_string.reserve(length + 1);
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::string& ansiString, const std::locale& locale)
{
m_string.reserve(ansiString.length() + 1);
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
}
////////////////////////////////////////////////////////////
String::String(const wchar_t* wideString)
{
if (wideString)
{
std::size_t length = std::wcslen(wideString);
if (length > 0)
{
m_string.reserve(length + 1);
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::wstring& wideString)
{
m_string.reserve(wideString.length() + 1);
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
}
////////////////////////////////////////////////////////////
String::String(const Uint32* utf32String)
{
if (utf32String)
m_string = utf32String;
}
////////////////////////////////////////////////////////////
String::String(const std::basic_string<Uint32>& utf32String) :
m_string(utf32String)
{
}
////////////////////////////////////////////////////////////
String::String(const String& copy) :
m_string(copy.m_string)
{
}
////////////////////////////////////////////////////////////
String::operator std::string() const
{
return toAnsiString();
}
////////////////////////////////////////////////////////////
String::operator std::wstring() const
{
return toWideString();
}
////////////////////////////////////////////////////////////
std::string String::toAnsiString(const std::locale& locale) const
{
// Prepare the output string
std::string output;
output.reserve(m_string.length() + 1);
// Convert
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
return output;
}
////////////////////////////////////////////////////////////
std::wstring String::toWideString() const
{
// Prepare the output string
std::wstring output;
output.reserve(m_string.length() + 1);
// Convert
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint8> String::toUtf8() const
{
// Prepare the output string
std::basic_string<Uint8> output;
output.reserve(m_string.length());
// Convert
Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output));
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint16> String::toUtf16() const
{
// Prepare the output string
std::basic_string<Uint16> output;
output.reserve(m_string.length());
// Convert
Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output));
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint32> String::toUtf32() const
{
return m_string;
}
////////////////////////////////////////////////////////////
String& String::operator =(const String& right)
{
m_string = right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(const String& right)
{
m_string += right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
Uint32 String::operator [](std::size_t index) const
{
return m_string[index];
}
////////////////////////////////////////////////////////////
Uint32& String::operator [](std::size_t index)
{
return m_string[index];
}
////////////////////////////////////////////////////////////
void String::clear()
{
m_string.clear();
}
////////////////////////////////////////////////////////////
std::size_t String::getSize() const
{
return m_string.size();
}
////////////////////////////////////////////////////////////
bool String::isEmpty() const
{
return m_string.empty();
}
////////////////////////////////////////////////////////////
void String::erase(std::size_t position, std::size_t count)
{
m_string.erase(position, count);
}
////////////////////////////////////////////////////////////
void String::insert(std::size_t position, const String& str)
{
m_string.insert(position, str.m_string);
}
////////////////////////////////////////////////////////////
std::size_t String::find(const String& str, std::size_t start) const
{
return m_string.find(str.m_string, start);
}
////////////////////////////////////////////////////////////
void String::replace(std::size_t position, std::size_t length, const String& replaceWith)
{
m_string.replace(position, length, replaceWith.m_string);
}
////////////////////////////////////////////////////////////
void String::replace(const String& searchFor, const String& replaceWith)
{
std::size_t step = replaceWith.getSize();
std::size_t len = searchFor.getSize();
std::size_t pos = find(searchFor);
// Replace each occurrence of search
while (pos != InvalidPos)
{
replace(pos, len, replaceWith);
pos = find(searchFor, pos + step);
}
}
////////////////////////////////////////////////////////////
String String::substring(std::size_t position, std::size_t length) const
{
return m_string.substr(position, length);
}
////////////////////////////////////////////////////////////
const Uint32* String::getData() const
{
return m_string.c_str();
}
////////////////////////////////////////////////////////////
String::Iterator String::begin()
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::begin() const
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
String::Iterator String::end()
{
return m_string.end();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::end() const
{
return m_string.end();
}
////////////////////////////////////////////////////////////
bool operator ==(const String& left, const String& right)
{
return left.m_string == right.m_string;
}
////////////////////////////////////////////////////////////
bool operator !=(const String& left, const String& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const String& left, const String& right)
{
return left.m_string < right.m_string;
}
////////////////////////////////////////////////////////////
bool operator >(const String& left, const String& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const String& left, const String& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const String& left, const String& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
String operator +(const String& left, const String& right)
{
String string = left;
string += right;
return string;
}
} // namespace sf

View file

@ -1,260 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Time.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
const Time Time::Zero;
////////////////////////////////////////////////////////////
Time::Time() :
m_microseconds(0)
{
}
////////////////////////////////////////////////////////////
float Time::asSeconds() const
{
return m_microseconds / 1000000.f;
}
////////////////////////////////////////////////////////////
Int32 Time::asMilliseconds() const
{
return static_cast<Int32>(m_microseconds / 1000);
}
////////////////////////////////////////////////////////////
Int64 Time::asMicroseconds() const
{
return m_microseconds;
}
////////////////////////////////////////////////////////////
Time::Time(Int64 microseconds) :
m_microseconds(microseconds)
{
}
////////////////////////////////////////////////////////////
Time seconds(float amount)
{
return Time(static_cast<Int64>(amount * 1000000));
}
////////////////////////////////////////////////////////////
Time milliseconds(Int32 amount)
{
return Time(static_cast<Int64>(amount) * 1000);
}
////////////////////////////////////////////////////////////
Time microseconds(Int64 amount)
{
return Time(amount);
}
////////////////////////////////////////////////////////////
bool operator ==(Time left, Time right)
{
return left.asMicroseconds() == right.asMicroseconds();
}
////////////////////////////////////////////////////////////
bool operator !=(Time left, Time right)
{
return left.asMicroseconds() != right.asMicroseconds();
}
////////////////////////////////////////////////////////////
bool operator <(Time left, Time right)
{
return left.asMicroseconds() < right.asMicroseconds();
}
////////////////////////////////////////////////////////////
bool operator >(Time left, Time right)
{
return left.asMicroseconds() > right.asMicroseconds();
}
////////////////////////////////////////////////////////////
bool operator <=(Time left, Time right)
{
return left.asMicroseconds() <= right.asMicroseconds();
}
////////////////////////////////////////////////////////////
bool operator >=(Time left, Time right)
{
return left.asMicroseconds() >= right.asMicroseconds();
}
////////////////////////////////////////////////////////////
Time operator -(Time right)
{
return microseconds(-right.asMicroseconds());
}
////////////////////////////////////////////////////////////
Time operator +(Time left, Time right)
{
return microseconds(left.asMicroseconds() + right.asMicroseconds());
}
////////////////////////////////////////////////////////////
Time& operator +=(Time& left, Time right)
{
return left = left + right;
}
////////////////////////////////////////////////////////////
Time operator -(Time left, Time right)
{
return microseconds(left.asMicroseconds() - right.asMicroseconds());
}
////////////////////////////////////////////////////////////
Time& operator -=(Time& left, Time right)
{
return left = left - right;
}
////////////////////////////////////////////////////////////
Time operator *(Time left, float right)
{
return seconds(left.asSeconds() * right);
}
////////////////////////////////////////////////////////////
Time operator *(Time left, Int64 right)
{
return microseconds(left.asMicroseconds() * right);
}
////////////////////////////////////////////////////////////
Time operator *(float left, Time right)
{
return right * left;
}
////////////////////////////////////////////////////////////
Time operator *(Int64 left, Time right)
{
return right * left;
}
////////////////////////////////////////////////////////////
Time& operator *=(Time& left, float right)
{
return left = left * right;
}
////////////////////////////////////////////////////////////
Time& operator *=(Time& left, Int64 right)
{
return left = left * right;
}
////////////////////////////////////////////////////////////
Time operator /(Time left, float right)
{
return seconds(left.asSeconds() / right);
}
////////////////////////////////////////////////////////////
Time operator /(Time left, Int64 right)
{
return microseconds(left.asMicroseconds() / right);
}
////////////////////////////////////////////////////////////
Time& operator /=(Time& left, float right)
{
return left = left / right;
}
////////////////////////////////////////////////////////////
Time& operator /=(Time& left, Int64 right)
{
return left = left / right;
}
////////////////////////////////////////////////////////////
float operator /(Time left, Time right)
{
return left.asSeconds() / right.asSeconds();
}
////////////////////////////////////////////////////////////
Time operator %(Time left, Time right)
{
return microseconds(left.asMicroseconds() % right.asMicroseconds());
}
////////////////////////////////////////////////////////////
Time& operator %=(Time& left, Time right)
{
return left = left % right;
}
} // namespace sf

View file

@ -68,8 +68,6 @@ Dolphin includes or links code of the following third-party software projects:
[zlib license](http://hg.libsdl.org/SDL/file/tip/COPYING.txt)
- [SFML](http://www.sfml-dev.org/):
[zlib license](http://www.sfml-dev.org/license.php)
- [SoundTouch](http://www.surina.net/soundtouch/):
[LGPLv2+](http://www.surina.net/soundtouch/license.html)
- [TAP-Windows](https://openvpn.net/):
header only
- [Windows Implementation Libraries](https://github.com/microsoft/wil):

View file

@ -43,9 +43,12 @@ add_library(rcheevos
rcheevos/src/rhash/hash.c
rcheevos/src/rhash/md5.c
rcheevos/src/rhash/md5.h
rcheevos/src/rhash/rc_hash_internal.h
rcheevos/src/rurl/url.c
rcheevos/src/rc_client.c
rcheevos/src/rc_client_external.c
rcheevos/src/rc_client_external.h
rcheevos/src/rc_client_external_versions.h
rcheevos/src/rc_client_internal.h
rcheevos/src/rc_client_raintegration.c
rcheevos/src/rc_client_raintegration_internal.h
@ -61,6 +64,11 @@ target_include_directories(rcheevos PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/rcheevo
target_include_directories(rcheevos INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
target_compile_definitions(rcheevos PRIVATE "RC_DISABLE_LUA=1" "RCHEEVOS_URL_SSL")
target_compile_definitions(rcheevos PRIVATE "RC_CLIENT_SUPPORTS_HASH")
target_compile_definitions(rcheevos PRIVATE "RC_CLIENT_SUPPORTS_EXTERNAL")
target_compile_definitions(rcheevos PRIVATE "RC_HASH_NO_ENCRYPTED")
target_compile_definitions(rcheevos PRIVATE "RC_HASH_NO_ROM")
target_compile_definitions(rcheevos PRIVATE "RC_HASH_NO_ZIP")
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
target_compile_definitions(rcheevos PRIVATE "RC_CLIENT_SUPPORTS_RAINTEGRATION")
target_compile_definitions(rcheevos PRIVATE "_CRT_SECURE_NO_WARNINGS")
endif()

@ -1 +1 @@
Subproject commit d54cf8f1059cebc90a6f5ecdf03df69259f22054
Subproject commit 022ac70cff6cf60c8957de63d6297998904a6f05

View file

@ -41,6 +41,7 @@
<ClCompile Include="rcheevos\src\rhash\md5.c" />
<ClCompile Include="rcheevos\src\rurl\url.c" />
<ClCompile Include="rcheevos\src\rc_client.c" />
<ClCompile Include="rcheevos\src\rc_client_external.c" />
<ClCompile Include="rcheevos\src\rc_client_raintegration.c" />
<ClCompile Include="rcheevos\src\rc_compat.c" />
<ClCompile Include="rcheevos\src\rc_util.c" />
@ -68,7 +69,9 @@
<ClInclude Include="rcheevos\src\rcheevos\rc_validate.h" />
<ClInclude Include="rcheevos\src\rhash\aes.h" />
<ClInclude Include="rcheevos\src\rhash\md5.h" />
<ClInclude Include="rcheevos\src\rhash\rc_hash_internal.h" />
<ClInclude Include="rcheevos\src\rc_client_external.h" />
<ClInclude Include="rcheevos\src\rc_client_external_versions.h" />
<ClInclude Include="rcheevos\src\rc_client_internal.h" />
<ClInclude Include="rcheevos\src\rc_client_raintegration_internal.h" />
<ClInclude Include="rcheevos\src\rc_compat.h" />
@ -76,7 +79,7 @@
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>RC_DISABLE_LUA;RCHEEVOS_URL_SSL;RC_CLIENT_SUPPORTS_HASH;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>RC_DISABLE_LUA;RCHEEVOS_URL_SSL;RC_CLIENT_SUPPORTS_HASH;RC_CLIENT_SUPPORTS_EXTERNAL;RC_CLIENT_SUPPORTS_RAINTEGRATION;RC_HASH_NO_ENCRYPTED;RC_HASH_NO_ROM;RC_HASH_NO_ZIP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)rcheevos\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>

View file

@ -1,222 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// FIR low-pass (anti-alias) filter with filter coefficient design routine and
/// MMX optimization.
///
/// Anti-alias filter is used to prevent folding of high frequencies when
/// transposing the sample rate with interpolation.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <memory.h>
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include "AAFilter.h"
#include "FIRFilter.h"
using namespace soundtouch;
#define PI 3.14159265358979323846
#define TWOPI (2 * PI)
// define this to save AA filter coefficients to a file
// #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
#ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
#include <stdio.h>
static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
{
FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
if (fptr == nullptr) return;
for (int i = 0; i < len; i ++)
{
double temp = coeffs[i];
fprintf(fptr, "%lf\n", temp);
}
fclose(fptr);
}
#else
#define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
#endif
/*****************************************************************************
*
* Implementation of the class 'AAFilter'
*
*****************************************************************************/
AAFilter::AAFilter(uint len)
{
pFIR = FIRFilter::newInstance();
cutoffFreq = 0.5;
setLength(len);
}
AAFilter::~AAFilter()
{
delete pFIR;
}
// Sets new anti-alias filter cut-off edge frequency, scaled to
// sampling frequency (nyquist frequency = 0.5).
// The filter will cut frequencies higher than the given frequency.
void AAFilter::setCutoffFreq(double newCutoffFreq)
{
cutoffFreq = newCutoffFreq;
calculateCoeffs();
}
// Sets number of FIR filter taps
void AAFilter::setLength(uint newLength)
{
length = newLength;
calculateCoeffs();
}
// Calculates coefficients for a low-pass FIR filter using Hamming window
void AAFilter::calculateCoeffs()
{
uint i;
double cntTemp, temp, tempCoeff,h, w;
double wc;
double scaleCoeff, sum;
double *work;
SAMPLETYPE *coeffs;
assert(length >= 2);
assert(length % 4 == 0);
assert(cutoffFreq >= 0);
assert(cutoffFreq <= 0.5);
work = new double[length];
coeffs = new SAMPLETYPE[length];
wc = 2.0 * PI * cutoffFreq;
tempCoeff = TWOPI / (double)length;
sum = 0;
for (i = 0; i < length; i ++)
{
cntTemp = (double)i - (double)(length / 2);
temp = cntTemp * wc;
if (temp != 0)
{
h = sin(temp) / temp; // sinc function
}
else
{
h = 1.0;
}
w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
temp = w * h;
work[i] = temp;
// calc net sum of coefficients
sum += temp;
}
// ensure the sum of coefficients is larger than zero
assert(sum > 0);
// ensure we've really designed a lowpass filter...
assert(work[length/2] > 0);
assert(work[length/2 + 1] > -1e-6);
assert(work[length/2 - 1] > -1e-6);
// Calculate a scaling coefficient in such a way that the result can be
// divided by 16384
scaleCoeff = 16384.0f / sum;
for (i = 0; i < length; i ++)
{
temp = work[i] * scaleCoeff;
// scale & round to nearest integer
temp += (temp >= 0) ? 0.5 : -0.5;
// ensure no overfloods
assert(temp >= -32768 && temp <= 32767);
coeffs[i] = (SAMPLETYPE)temp;
}
// Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
pFIR->setCoefficients(coeffs, length, 14);
_DEBUG_SAVE_AAFIR_COEFFS(coeffs, length);
delete[] work;
delete[] coeffs;
}
// Applies the filter to the given sequence of samples.
// Note : The amount of outputted samples is by value of 'filter length'
// smaller than the amount of input samples.
uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
{
return pFIR->evaluate(dest, src, numSamples, numChannels);
}
/// Applies the filter to the given src & dest pipes, so that processed amount of
/// samples get removed from src, and produced amount added to dest
/// Note : The amount of outputted samples is by value of 'filter length'
/// smaller than the amount of input samples.
uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
{
SAMPLETYPE *pdest;
const SAMPLETYPE *psrc;
uint numSrcSamples;
uint result;
int numChannels = src.getChannels();
assert(numChannels == dest.getChannels());
numSrcSamples = src.numSamples();
psrc = src.ptrBegin();
pdest = dest.ptrEnd(numSrcSamples);
result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
src.receiveSamples(result);
dest.putSamples(result);
return result;
}
uint AAFilter::getLength() const
{
return pFIR->getLength();
}

View file

@ -1,93 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
/// while maintaining the original pitch by using a time domain WSOLA-like method
/// with several performance-increasing tweaks.
///
/// Anti-alias filter is used to prevent folding of high frequencies when
/// transposing the sample rate with interpolation.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef AAFilter_H
#define AAFilter_H
#include "STTypes.h"
#include "FIFOSampleBuffer.h"
namespace soundtouch
{
class AAFilter
{
protected:
class FIRFilter *pFIR;
/// Low-pass filter cut-off frequency, negative = invalid
double cutoffFreq;
/// num of filter taps
uint length;
/// Calculate the FIR coefficients realizing the given cutoff-frequency
void calculateCoeffs();
public:
AAFilter(uint length);
~AAFilter();
/// Sets new anti-alias filter cut-off edge frequency, scaled to sampling
/// frequency (nyquist frequency = 0.5). The filter will cut off the
/// frequencies than that.
void setCutoffFreq(double newCutoffFreq);
/// Sets number of FIR filter taps, i.e. ~filter complexity
void setLength(uint newLength);
uint getLength() const;
/// Applies the filter to the given sequence of samples.
/// Note : The amount of outputted samples is by value of 'filter length'
/// smaller than the amount of input samples.
uint evaluate(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples,
uint numChannels) const;
/// Applies the filter to the given src & dest pipes, so that processed amount of
/// samples get removed from src, and produced amount added to dest
/// Note : The amount of outputted samples is by value of 'filter length'
/// smaller than the amount of input samples.
uint evaluate(FIFOSampleBuffer &dest,
FIFOSampleBuffer &src) const;
};
}
#endif

View file

@ -1,570 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Beats-per-minute (BPM) detection routine.
///
/// The beat detection algorithm works as follows:
/// - Use function 'inputSamples' to input a chunks of samples to the class for
/// analysis. It's a good idea to enter a large sound file or stream in smallish
/// chunks of around few kilosamples in order not to extinguish too much RAM memory.
/// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden,
/// which is basically ok as low (bass) frequencies mostly determine the beat rate.
/// Simple averaging is used for anti-alias filtering because the resulting signal
/// quality isn't of that high importance.
/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
/// taking absolute value that's smoothed by sliding average. Signal levels that
/// are below a couple of times the general RMS amplitude level are cut away to
/// leave only notable peaks there.
/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
/// autocorrelation function of the enveloped signal.
/// - After whole sound data file has been analyzed as above, the bpm level is
/// detected by function 'getBpm' that finds the highest peak of the autocorrelation
/// function, calculates it's precise location and converts this reading to bpm's.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <cfloat>
#include "FIFOSampleBuffer.h"
#include "PeakFinder.h"
#include "BPMDetect.h"
using namespace soundtouch;
// algorithm input sample block size
static const int INPUT_BLOCK_SIZE = 2048;
// decimated sample block size
static const int DECIMATED_BLOCK_SIZE = 256;
/// Target sample rate after decimation
static const int TARGET_SRATE = 1000;
/// XCorr update sequence size, update in about 200msec chunks
static const int XCORR_UPDATE_SEQUENCE = (int)(TARGET_SRATE / 5);
/// Moving average N size
static const int MOVING_AVERAGE_N = 15;
/// XCorr decay time constant, decay to half in 30 seconds
/// If it's desired to have the system adapt quicker to beat rate
/// changes within a continuing music stream, then the
/// 'xcorr_decay_time_constant' value can be reduced, yet that
/// can increase possibility of glitches in bpm detection.
static const double XCORR_DECAY_TIME_CONSTANT = 30.0;
/// Data overlap factor for beat detection algorithm
static const int OVERLAP_FACTOR = 4;
#define PI 3.14159265358979323846
#define TWOPI (2 * PI)
////////////////////////////////////////////////////////////////////////////////
// Enable following define to create bpm analysis file:
//#define _CREATE_BPM_DEBUG_FILE
#ifdef _CREATE_BPM_DEBUG_FILE
static void _SaveDebugData(const char *name, const float *data, int minpos, int maxpos, double coeff)
{
FILE *fptr = fopen(name, "wt");
int i;
if (fptr)
{
printf("\nWriting BPM debug data into file %s\n", name);
for (i = minpos; i < maxpos; i ++)
{
fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]);
}
fclose(fptr);
}
}
void _SaveDebugBeatPos(const char *name, const std::vector<BEAT> &beats)
{
printf("\nWriting beat detections data into file %s\n", name);
FILE *fptr = fopen(name, "wt");
if (fptr)
{
for (uint i = 0; i < beats.size(); i++)
{
BEAT b = beats[i];
fprintf(fptr, "%lf\t%lf\n", b.pos, b.strength);
}
fclose(fptr);
}
}
#else
#define _SaveDebugData(name, a,b,c,d)
#define _SaveDebugBeatPos(name, b)
#endif
// Hamming window
void hamming(float *w, int N)
{
for (int i = 0; i < N; i++)
{
w[i] = (float)(0.54 - 0.46 * cos(TWOPI * i / (N - 1)));
}
}
////////////////////////////////////////////////////////////////////////////////
//
// IIR2_filter - 2nd order IIR filter
IIR2_filter::IIR2_filter(const double *lpf_coeffs)
{
memcpy(coeffs, lpf_coeffs, 5 * sizeof(double));
memset(prev, 0, sizeof(prev));
}
float IIR2_filter::update(float x)
{
prev[0] = x;
double y = x * coeffs[0];
for (int i = 4; i >= 1; i--)
{
y += coeffs[i] * prev[i];
prev[i] = prev[i - 1];
}
prev[3] = y;
return (float)y;
}
// IIR low-pass filter coefficients, calculated with matlab/octave cheby2(2,40,0.05)
const double _LPF_coeffs[5] = { 0.00996655391939, -0.01944529148401, 0.00996655391939, 1.96867605796247, -0.96916387431724 };
////////////////////////////////////////////////////////////////////////////////
BPMDetect::BPMDetect(int numChannels, int aSampleRate) :
beat_lpf(_LPF_coeffs)
{
beats.reserve(250); // initial reservation to prevent frequent reallocation
this->sampleRate = aSampleRate;
this->channels = numChannels;
decimateSum = 0;
decimateCount = 0;
// choose decimation factor so that result is approx. 1000 Hz
decimateBy = sampleRate / TARGET_SRATE;
if ((decimateBy <= 0) || (decimateBy * DECIMATED_BLOCK_SIZE < INPUT_BLOCK_SIZE))
{
ST_THROW_RT_ERROR("Too small samplerate");
}
// Calculate window length & starting item according to desired min & max bpms
windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM_RANGE);
assert(windowLen > windowStart);
// allocate new working objects
xcorr = new float[windowLen];
memset(xcorr, 0, windowLen * sizeof(float));
pos = 0;
peakPos = 0;
peakVal = 0;
init_scaler = 1;
beatcorr_ringbuffpos = 0;
beatcorr_ringbuff = new float[windowLen];
memset(beatcorr_ringbuff, 0, windowLen * sizeof(float));
// allocate processing buffer
buffer = new FIFOSampleBuffer();
// we do processing in mono mode
buffer->setChannels(1);
buffer->clear();
// calculate hamming windows
hamw = new float[XCORR_UPDATE_SEQUENCE];
hamming(hamw, XCORR_UPDATE_SEQUENCE);
hamw2 = new float[XCORR_UPDATE_SEQUENCE / 2];
hamming(hamw2, XCORR_UPDATE_SEQUENCE / 2);
}
BPMDetect::~BPMDetect()
{
delete[] xcorr;
delete[] beatcorr_ringbuff;
delete[] hamw;
delete[] hamw2;
delete buffer;
}
/// convert to mono, low-pass filter & decimate to about 500 Hz.
/// return number of outputted samples.
///
/// Decimation is used to remove the unnecessary frequencies and thus to reduce
/// the amount of data needed to be processed as calculating autocorrelation
/// function is a very-very heavy operation.
///
/// Anti-alias filtering is done simply by averaging the samples. This is really a
/// poor-man's anti-alias filtering, but it's not so critical in this kind of application
/// (it'd also be difficult to design a high-quality filter with steep cut-off at very
/// narrow band)
int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples)
{
int count, outcount;
LONG_SAMPLETYPE out;
assert(channels > 0);
assert(decimateBy > 0);
outcount = 0;
for (count = 0; count < numsamples; count ++)
{
int j;
// convert to mono and accumulate
for (j = 0; j < channels; j ++)
{
decimateSum += src[j];
}
src += j;
decimateCount ++;
if (decimateCount >= decimateBy)
{
// Store every Nth sample only
out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels));
decimateSum = 0;
decimateCount = 0;
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
// check ranges for sure (shouldn't actually be necessary)
if (out > 32767)
{
out = 32767;
}
else if (out < -32768)
{
out = -32768;
}
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[outcount] = (SAMPLETYPE)out;
outcount ++;
}
}
return outcount;
}
// Calculates autocorrelation function of the sample history buffer
void BPMDetect::updateXCorr(int process_samples)
{
int offs;
SAMPLETYPE *pBuffer;
assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
assert(process_samples == XCORR_UPDATE_SEQUENCE);
pBuffer = buffer->ptrBegin();
// calculate decay factor for xcorr filtering
float xcorr_decay = (float)pow(0.5, 1.0 / (XCORR_DECAY_TIME_CONSTANT * TARGET_SRATE / process_samples));
// prescale pbuffer
float tmp[XCORR_UPDATE_SEQUENCE];
for (int i = 0; i < process_samples; i++)
{
tmp[i] = hamw[i] * hamw[i] * pBuffer[i];
}
#pragma omp parallel for
for (offs = windowStart; offs < windowLen; offs ++)
{
float sum;
int i;
sum = 0;
for (i = 0; i < process_samples; i ++)
{
sum += tmp[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary
}
xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable time constant.
xcorr[offs] += (float)fabs(sum);
}
}
// Detect individual beat positions
void BPMDetect::updateBeatPos(int process_samples)
{
SAMPLETYPE *pBuffer;
assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
pBuffer = buffer->ptrBegin();
assert(process_samples == XCORR_UPDATE_SEQUENCE / 2);
// static double thr = 0.0003;
double posScale = (double)this->decimateBy / (double)this->sampleRate;
int resetDur = (int)(0.12 / posScale + 0.5);
// prescale pbuffer
float tmp[XCORR_UPDATE_SEQUENCE / 2];
for (int i = 0; i < process_samples; i++)
{
tmp[i] = hamw2[i] * hamw2[i] * pBuffer[i];
}
#pragma omp parallel for
for (int offs = windowStart; offs < windowLen; offs++)
{
float sum = 0;
for (int i = 0; i < process_samples; i++)
{
sum += tmp[i] * pBuffer[offs + i];
}
beatcorr_ringbuff[(beatcorr_ringbuffpos + offs) % windowLen] += (float)((sum > 0) ? sum : 0); // accumulate only positive correlations
}
int skipstep = XCORR_UPDATE_SEQUENCE / OVERLAP_FACTOR;
// compensate empty buffer at beginning by scaling coefficient
float scale = (float)windowLen / (float)(skipstep * init_scaler);
if (scale > 1.0f)
{
init_scaler++;
}
else
{
scale = 1.0f;
}
// detect beats
for (int i = 0; i < skipstep; i++)
{
float sum = beatcorr_ringbuff[beatcorr_ringbuffpos];
sum -= beat_lpf.update(sum);
if (sum > peakVal)
{
// found new local largest value
peakVal = sum;
peakPos = pos;
}
if (pos > peakPos + resetDur)
{
// largest value not updated for 200msec => accept as beat
peakPos += skipstep;
if (peakVal > 0)
{
// add detected beat to end of "beats" vector
BEAT temp = { (float)(peakPos * posScale), (float)(peakVal * scale) };
beats.push_back(temp);
}
peakVal = 0;
peakPos = pos;
}
beatcorr_ringbuff[beatcorr_ringbuffpos] = 0;
pos++;
beatcorr_ringbuffpos = (beatcorr_ringbuffpos + 1) % windowLen;
}
}
#define max(x,y) ((x) > (y) ? (x) : (y))
void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
{
SAMPLETYPE decimated[DECIMATED_BLOCK_SIZE];
// iterate so that max INPUT_BLOCK_SAMPLES processed per iteration
while (numSamples > 0)
{
int block;
int decSamples;
block = (numSamples > INPUT_BLOCK_SIZE) ? INPUT_BLOCK_SIZE : numSamples;
// decimate. note that converts to mono at the same time
decSamples = decimate(decimated, samples, block);
samples += block * channels;
numSamples -= block;
buffer->putSamples(decimated, decSamples);
}
// when the buffer has enough samples for processing...
int req = max(windowLen + XCORR_UPDATE_SEQUENCE, 2 * XCORR_UPDATE_SEQUENCE);
while ((int)buffer->numSamples() >= req)
{
// ... update autocorrelations...
updateXCorr(XCORR_UPDATE_SEQUENCE);
// ...update beat position calculation...
updateBeatPos(XCORR_UPDATE_SEQUENCE / 2);
// ... and remove proceessed samples from the buffer
int n = XCORR_UPDATE_SEQUENCE / OVERLAP_FACTOR;
buffer->receiveSamples(n);
}
}
void BPMDetect::removeBias()
{
int i;
// Remove linear bias: calculate linear regression coefficient
// 1. calc mean of 'xcorr' and 'i'
double mean_i = 0;
double mean_x = 0;
for (i = windowStart; i < windowLen; i++)
{
mean_x += xcorr[i];
}
mean_x /= (windowLen - windowStart);
mean_i = 0.5 * (windowLen - 1 + windowStart);
// 2. calculate linear regression coefficient
double b = 0;
double div = 0;
for (i = windowStart; i < windowLen; i++)
{
double xt = xcorr[i] - mean_x;
double xi = i - mean_i;
b += xt * xi;
div += xi * xi;
}
b /= div;
// subtract linear regression and resolve min. value bias
float minval = FLT_MAX; // arbitrary large number
for (i = windowStart; i < windowLen; i ++)
{
xcorr[i] -= (float)(b * i);
if (xcorr[i] < minval)
{
minval = xcorr[i];
}
}
// subtract min.value
for (i = windowStart; i < windowLen; i ++)
{
xcorr[i] -= minval;
}
}
// Calculate N-point moving average for "source" values
void MAFilter(float *dest, const float *source, int start, int end, int N)
{
for (int i = start; i < end; i++)
{
int i1 = i - N / 2;
int i2 = i + N / 2 + 1;
if (i1 < start) i1 = start;
if (i2 > end) i2 = end;
double sum = 0;
for (int j = i1; j < i2; j ++)
{
sum += source[j];
}
dest[i] = (float)(sum / (i2 - i1));
}
}
float BPMDetect::getBpm()
{
double peakPos;
double coeff;
PeakFinder peakFinder;
// remove bias from xcorr data
removeBias();
coeff = 60.0 * ((double)sampleRate / (double)decimateBy);
// save bpm debug data if debug data writing enabled
_SaveDebugData("soundtouch-bpm-xcorr.txt", xcorr, windowStart, windowLen, coeff);
// Smoothen by N-point moving-average
float *data = new float[windowLen];
memset(data, 0, sizeof(float) * windowLen);
MAFilter(data, xcorr, windowStart, windowLen, MOVING_AVERAGE_N);
// find peak position
peakPos = peakFinder.detectPeak(data, windowStart, windowLen);
// save bpm debug data if debug data writing enabled
_SaveDebugData("soundtouch-bpm-smoothed.txt", data, windowStart, windowLen, coeff);
delete[] data;
assert(decimateBy != 0);
if (peakPos < 1e-9) return 0.0; // detection failed.
_SaveDebugBeatPos("soundtouch-detected-beats.txt", beats);
// calculate BPM
float bpm = (float)(coeff / peakPos);
return (bpm >= MIN_BPM && bpm <= MAX_BPM_VALID) ? bpm : 0;
}
/// Get beat position arrays. Note: The array includes also really low beat detection values
/// in absence of clear strong beats. Consumer may wish to filter low values away.
/// - "pos" receive array of beat positions
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
int BPMDetect::getBeats(float *pos, float *values, int max_num)
{
int num = (int)beats.size();
if ((!pos) || (!values)) return num; // pos or values nullptr, return just size
for (int i = 0; (i < num) && (i < max_num); i++)
{
pos[i] = beats[i].pos;
values[i] = beats[i].strength;
}
return num;
}

View file

@ -1,205 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Beats-per-minute (BPM) detection routine.
///
/// The beat detection algorithm works as follows:
/// - Use function 'inputSamples' to input a chunks of samples to the class for
/// analysis. It's a good idea to enter a large sound file or stream in smallish
/// chunks of around few kilosamples in order not to extinguish too much RAM memory.
/// - Input sound data is decimated to approx 500 Hz to reduce calculation burden,
/// which is basically ok as low (bass) frequencies mostly determine the beat rate.
/// Simple averaging is used for anti-alias filtering because the resulting signal
/// quality isn't of that high importance.
/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
/// taking absolute value that's smoothed by sliding average. Signal levels that
/// are below a couple of times the general RMS amplitude level are cut away to
/// leave only notable peaks there.
/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
/// autocorrelation function of the enveloped signal.
/// - After whole sound data file has been analyzed as above, the bpm level is
/// detected by function 'getBpm' that finds the highest peak of the autocorrelation
/// function, calculates it's precise location and converts this reading to bpm's.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef _BPMDetect_H_
#define _BPMDetect_H_
#include <vector>
#include "STTypes.h"
#include "FIFOSampleBuffer.h"
namespace soundtouch
{
/// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
#define MIN_BPM 45
/// Maximum allowed BPM rate range. Used for calculating algorithm parametrs
#define MAX_BPM_RANGE 200
/// Maximum allowed BPM rate range. Used to restrict accepted result below a reasonable limit.
#define MAX_BPM_VALID 190
////////////////////////////////////////////////////////////////////////////////
typedef struct
{
float pos;
float strength;
} BEAT;
class IIR2_filter
{
double coeffs[5];
double prev[5];
public:
IIR2_filter(const double *lpf_coeffs);
float update(float x);
};
/// Class for calculating BPM rate for audio data.
class BPMDetect
{
protected:
/// Auto-correlation accumulator bins.
float *xcorr;
/// Sample average counter.
int decimateCount;
/// Sample average accumulator for FIFO-like decimation.
soundtouch::LONG_SAMPLETYPE decimateSum;
/// Decimate sound by this coefficient to reach approx. 500 Hz.
int decimateBy;
/// Auto-correlation window length
int windowLen;
/// Number of channels (1 = mono, 2 = stereo)
int channels;
/// sample rate
int sampleRate;
/// Beginning of auto-correlation window: Autocorrelation isn't being updated for
/// the first these many correlation bins.
int windowStart;
/// window functions for data preconditioning
float *hamw;
float *hamw2;
// beat detection variables
int pos;
int peakPos;
int beatcorr_ringbuffpos;
int init_scaler;
float peakVal;
float *beatcorr_ringbuff;
/// FIFO-buffer for decimated processing samples.
soundtouch::FIFOSampleBuffer *buffer;
/// Collection of detected beat positions
//BeatCollection beats;
std::vector<BEAT> beats;
// 2nd order low-pass-filter
IIR2_filter beat_lpf;
/// Updates auto-correlation function for given number of decimated samples that
/// are read from the internal 'buffer' pipe (samples aren't removed from the pipe
/// though).
void updateXCorr(int process_samples /// How many samples are processed.
);
/// Decimates samples to approx. 500 Hz.
///
/// \return Number of output samples.
int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer
const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
int numsamples ///< Number of source samples.
);
/// Calculates amplitude envelope for the buffer of samples.
/// Result is output to 'samples'.
void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer
int numsamples ///< Number of samples in buffer
);
/// remove constant bias from xcorr data
void removeBias();
// Detect individual beat positions
void updateBeatPos(int process_samples);
public:
/// Constructor.
BPMDetect(int numChannels, ///< Number of channels in sample data.
int sampleRate ///< Sample rate in Hz.
);
/// Destructor.
virtual ~BPMDetect();
/// Inputs a block of samples for analyzing: Envelopes the samples and then
/// updates the autocorrelation estimation. When whole song data has been input
/// in smaller blocks using this function, read the resulting bpm with 'getBpm'
/// function.
///
/// Notice that data in 'samples' array can be disrupted in processing.
void inputSamples(const soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer
int numSamples ///< Number of samples in buffer
);
/// Analyzes the results and returns the BPM rate. Use this function to read result
/// after whole song data has been input to the class by consecutive calls of
/// 'inputSamples' function.
///
/// \return Beats-per-minute rate, or zero if detection failed.
float getBpm();
/// Get beat position arrays. Note: The array includes also really low beat detection values
/// in absence of clear strong beats. Consumer may wish to filter low values away.
/// - "pos" receive array of beat positions
/// - "values" receive array of beat detection strengths
/// - max_num indicates max.size of "pos" and "values" array.
///
/// You can query a suitable array sized by calling this with nullptr in "pos" & "values".
///
/// \return number of beats in the arrays.
int getBeats(float *pos, float *strength, int max_num);
};
}
#endif // _BPMDetect_H_

View file

@ -1,22 +0,0 @@
# OSX meeds to know
check_and_add_flag(CXX11 -std=c++11)
set(SRCS
AAFilter.cpp
BPMDetect.cpp
cpu_detect_x86.cpp
FIFOSampleBuffer.cpp
FIRFilter.cpp
InterpolateCubic.cpp
InterpolateLinear.cpp
InterpolateShannon.cpp
mmx_optimized.cpp
PeakFinder.cpp
RateTransposer.cpp
SoundTouch.cpp
sse_optimized.cpp
TDStretch.cpp
)
add_library(SoundTouch STATIC ${SRCS})
dolphin_disable_warnings(SoundTouch)

View file

@ -1,275 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// A buffer class for temporarily storaging sound samples, operates as a
/// first-in-first-out pipe.
///
/// Samples are added to the end of the sample buffer with the 'putSamples'
/// function, and are received from the beginning of the buffer by calling
/// the 'receiveSamples' function. The class automatically removes the
/// outputted samples from the buffer, as well as grows the buffer size
/// whenever necessary.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <assert.h>
#include "FIFOSampleBuffer.h"
using namespace soundtouch;
// Constructor
FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
{
assert(numChannels > 0);
sizeInBytes = 0; // reasonable initial value
buffer = nullptr;
bufferUnaligned = nullptr;
samplesInBuffer = 0;
bufferPos = 0;
channels = (uint)numChannels;
ensureCapacity(32); // allocate initial capacity
}
// destructor
FIFOSampleBuffer::~FIFOSampleBuffer()
{
delete[] bufferUnaligned;
bufferUnaligned = nullptr;
buffer = nullptr;
}
// Sets number of channels, 1 = mono, 2 = stereo
void FIFOSampleBuffer::setChannels(int numChannels)
{
uint usedBytes;
if (!verifyNumberOfChannels(numChannels)) return;
usedBytes = channels * samplesInBuffer;
channels = (uint)numChannels;
samplesInBuffer = usedBytes / channels;
}
// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
// zeroes this pointer by copying samples from the 'bufferPos' pointer
// location on to the beginning of the buffer.
void FIFOSampleBuffer::rewind()
{
if (buffer && bufferPos)
{
memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
bufferPos = 0;
}
}
// Adds 'numSamples' pcs of samples from the 'samples' memory position to
// the sample buffer.
void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
{
memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
samplesInBuffer += nSamples;
}
// Increases the number of samples in the buffer without copying any actual
// samples.
//
// This function is used to update the number of samples in the sample buffer
// when accessing the buffer directly with 'ptrEnd' function. Please be
// careful though!
void FIFOSampleBuffer::putSamples(uint nSamples)
{
uint req;
req = samplesInBuffer + nSamples;
ensureCapacity(req);
samplesInBuffer += nSamples;
}
// Returns a pointer to the end of the used part of the sample buffer (i.e.
// where the new samples are to be inserted). This function may be used for
// inserting new samples into the sample buffer directly. Please be careful!
//
// Parameter 'slackCapacity' tells the function how much free capacity (in
// terms of samples) there _at least_ should be, in order to the caller to
// successfully insert all the required samples to the buffer. When necessary,
// the function grows the buffer size to comply with this requirement.
//
// When using this function as means for inserting new samples, also remember
// to increase the sample count afterwards, by calling the
// 'putSamples(numSamples)' function.
SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
{
ensureCapacity(samplesInBuffer + slackCapacity);
return buffer + samplesInBuffer * channels;
}
// Returns a pointer to the beginning of the currently non-outputted samples.
// This function is provided for accessing the output samples directly.
// Please be careful!
//
// When using this function to output samples, also remember to 'remove' the
// outputted samples from the buffer by calling the
// 'receiveSamples(numSamples)' function
SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
{
assert(buffer);
return buffer + bufferPos * channels;
}
// Ensures that the buffer has enough capacity, i.e. space for _at least_
// 'capacityRequirement' number of samples. The buffer is grown in steps of
// 4 kilobytes to eliminate the need for frequently growing up the buffer,
// as well as to round the buffer size up to the virtual memory page size.
void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
{
SAMPLETYPE *tempUnaligned, *temp;
if (capacityRequirement > getCapacity())
{
// enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
assert(sizeInBytes % 2 == 0);
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
if (tempUnaligned == nullptr)
{
ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
}
// Align the buffer to begin at 16byte cache line boundary for optimal performance
temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned);
if (samplesInBuffer)
{
memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
}
delete[] bufferUnaligned;
buffer = temp;
bufferUnaligned = tempUnaligned;
bufferPos = 0;
}
else
{
// simply rewind the buffer (if necessary)
rewind();
}
}
// Returns the current buffer capacity in terms of samples
uint FIFOSampleBuffer::getCapacity() const
{
return sizeInBytes / (channels * sizeof(SAMPLETYPE));
}
// Returns the number of samples currently in the buffer
uint FIFOSampleBuffer::numSamples() const
{
return samplesInBuffer;
}
// Output samples from beginning of the sample buffer. Copies demanded number
// of samples to output and removes them from the sample buffer. If there
// are less than 'numsample' samples in the buffer, returns all available.
//
// Returns number of samples copied.
uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
{
uint num;
num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
return receiveSamples(num);
}
// Removes samples from the beginning of the sample buffer without copying them
// anywhere. Used to reduce the number of samples in the buffer, when accessing
// the sample buffer with the 'ptrBegin' function.
uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
{
if (maxSamples >= samplesInBuffer)
{
uint temp;
temp = samplesInBuffer;
samplesInBuffer = 0;
return temp;
}
samplesInBuffer -= maxSamples;
bufferPos += maxSamples;
return maxSamples;
}
// Returns nonzero if the sample buffer is empty
int FIFOSampleBuffer::isEmpty() const
{
return (samplesInBuffer == 0) ? 1 : 0;
}
// Clears the sample buffer
void FIFOSampleBuffer::clear()
{
samplesInBuffer = 0;
bufferPos = 0;
}
/// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples
uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
{
if (numSamples < samplesInBuffer)
{
samplesInBuffer = numSamples;
}
return samplesInBuffer;
}
/// Add silence to end of buffer
void FIFOSampleBuffer::addSilent(uint nSamples)
{
memset(ptrEnd(nSamples), 0, sizeof(SAMPLETYPE) * nSamples * channels);
samplesInBuffer += nSamples;
}

View file

@ -1,180 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// A buffer class for temporarily storaging sound samples, operates as a
/// first-in-first-out pipe.
///
/// Samples are added to the end of the sample buffer with the 'putSamples'
/// function, and are received from the beginning of the buffer by calling
/// the 'receiveSamples' function. The class automatically removes the
/// output samples from the buffer as well as grows the storage size
/// whenever necessary.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef FIFOSampleBuffer_H
#define FIFOSampleBuffer_H
#include "FIFOSamplePipe.h"
namespace soundtouch
{
/// Sample buffer working in FIFO (first-in-first-out) principle. The class takes
/// care of storage size adjustment and data moving during input/output operations.
///
/// Notice that in case of stereo audio, one sample is considered to consist of
/// both channel data.
class FIFOSampleBuffer : public FIFOSamplePipe
{
private:
/// Sample buffer.
SAMPLETYPE *buffer;
// Raw unaligned buffer memory. 'buffer' is made aligned by pointing it to first
// 16-byte aligned location of this buffer
SAMPLETYPE *bufferUnaligned;
/// Sample buffer size in bytes
uint sizeInBytes;
/// How many samples are currently in buffer.
uint samplesInBuffer;
/// Channels, 1=mono, 2=stereo.
uint channels;
/// Current position pointer to the buffer. This pointer is increased when samples are
/// removed from the pipe so that it's necessary to actually rewind buffer (move data)
/// only new data when is put to the pipe.
uint bufferPos;
/// Rewind the buffer by moving data from position pointed by 'bufferPos' to real
/// beginning of the buffer.
void rewind();
/// Ensures that the buffer has capacity for at least this many samples.
void ensureCapacity(uint capacityRequirement);
/// Returns current capacity.
uint getCapacity() const;
public:
/// Constructor
FIFOSampleBuffer(int numChannels = 2 ///< Number of channels, 1=mono, 2=stereo.
///< Default is stereo.
);
/// destructor
~FIFOSampleBuffer() override;
/// Returns a pointer to the beginning of the output samples.
/// This function is provided for accessing the output samples directly.
/// Please be careful for not to corrupt the book-keeping!
///
/// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin() override;
/// Returns a pointer to the end of the used part of the sample buffer (i.e.
/// where the new samples are to be inserted). This function may be used for
/// inserting new samples into the sample buffer directly. Please be careful
/// not corrupt the book-keeping!
///
/// When using this function as means for inserting new samples, also remember
/// to increase the sample count afterwards, by calling the
/// 'putSamples(numSamples)' function.
SAMPLETYPE *ptrEnd(
uint slackCapacity ///< How much free capacity (in samples) there _at least_
///< should be so that the caller can successfully insert the
///< desired samples to the buffer. If necessary, the function
///< grows the buffer size to comply with this requirement.
);
/// Adds 'numSamples' pcs of samples from the 'samples' memory position to
/// the sample buffer.
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
uint numSamples ///< Number of samples to insert.
) override;
/// Adjusts the book-keeping to increase number of samples in the buffer without
/// copying any actual samples.
///
/// This function is used to update the number of samples in the sample buffer
/// when accessing the buffer directly with 'ptrEnd' function. Please be
/// careful though!
virtual void putSamples(uint numSamples ///< Number of samples been inserted.
);
/// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max.
) override;
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
) override;
/// Returns number of samples currently available.
virtual uint numSamples() const override;
/// Sets number of channels, 1 = mono, 2 = stereo.
void setChannels(int numChannels);
/// Get number of channels
int getChannels()
{
return channels;
}
/// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const override;
/// Clears all the samples.
virtual void clear() override;
/// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples
uint adjustAmountOfSamples(uint numSamples) override;
/// Add silence to end of buffer
void addSilent(uint nSamples);
};
}
#endif

View file

@ -1,230 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// 'FIFOSamplePipe' : An abstract base class for classes that manipulate sound
/// samples by operating like a first-in-first-out pipe: New samples are fed
/// into one end of the pipe with the 'putSamples' function, and the processed
/// samples are received from the other end with the 'receiveSamples' function.
///
/// 'FIFOProcessor' : A base class for classes the do signal processing with
/// the samples while operating like a first-in-first-out pipe. When samples
/// are input with the 'putSamples' function, the class processes them
/// and moves the processed samples to the given 'output' pipe object, which
/// may be either another processing stage, or a fifo sample buffer object.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef FIFOSamplePipe_H
#define FIFOSamplePipe_H
#include <assert.h>
#include <stdlib.h>
#include "STTypes.h"
namespace soundtouch
{
/// Abstract base class for FIFO (first-in-first-out) sample processing classes.
class FIFOSamplePipe
{
protected:
bool verifyNumberOfChannels(int nChannels) const
{
if ((nChannels > 0) && (nChannels <= SOUNDTOUCH_MAX_CHANNELS))
{
return true;
}
ST_THROW_RT_ERROR("Error: Illegal number of channels");
return false;
}
public:
// virtual default destructor
virtual ~FIFOSamplePipe() {}
/// Returns a pointer to the beginning of the output samples.
/// This function is provided for accessing the output samples directly.
/// Please be careful for not to corrupt the book-keeping!
///
/// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin() = 0;
/// Adds 'numSamples' pcs of samples from the 'samples' memory position to
/// the sample buffer.
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
uint numSamples ///< Number of samples to insert.
) = 0;
// Moves samples from the 'other' pipe instance to this instance.
void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data.
)
{
int oNumSamples = other.numSamples();
putSamples(other.ptrBegin(), oNumSamples);
other.receiveSamples(oNumSamples);
};
/// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max.
) = 0;
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
) = 0;
/// Returns number of samples currently available.
virtual uint numSamples() const = 0;
// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const = 0;
/// Clears all the samples.
virtual void clear() = 0;
/// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples
virtual uint adjustAmountOfSamples(uint numSamples) = 0;
};
/// Base-class for sound processing routines working in FIFO principle. With this base
/// class it's easy to implement sound processing stages that can be chained together,
/// so that samples that are fed into beginning of the pipe automatically go through
/// all the processing stages.
///
/// When samples are input to this class, they're first processed and then put to
/// the FIFO pipe that's defined as output of this class. This output pipe can be
/// either other processing stage or a FIFO sample buffer.
class FIFOProcessor :public FIFOSamplePipe
{
protected:
/// Internal pipe where processed samples are put.
FIFOSamplePipe *output;
/// Sets output pipe.
void setOutPipe(FIFOSamplePipe *pOutput)
{
assert(output == nullptr);
assert(pOutput != nullptr);
output = pOutput;
}
/// Constructor. Doesn't define output pipe; it has to be set be
/// 'setOutPipe' function.
FIFOProcessor()
{
output = nullptr;
}
/// Constructor. Configures output pipe.
FIFOProcessor(FIFOSamplePipe *pOutput ///< Output pipe.
)
{
output = pOutput;
}
/// Destructor.
virtual ~FIFOProcessor() override
{
}
/// Returns a pointer to the beginning of the output samples.
/// This function is provided for accessing the output samples directly.
/// Please be careful for not to corrupt the book-keeping!
///
/// When using this function to output samples, also remember to 'remove' the
/// output samples from the buffer by calling the
/// 'receiveSamples(numSamples)' function
virtual SAMPLETYPE *ptrBegin() override
{
return output->ptrBegin();
}
public:
/// Output samples from beginning of the sample buffer. Copies requested samples to
/// output buffer and removes them from the sample buffer. If there are less than
/// 'numsample' samples in the buffer, returns all that available.
///
/// \return Number of samples returned.
virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
uint maxSamples ///< How many samples to receive at max.
) override
{
return output->receiveSamples(outBuffer, maxSamples);
}
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
) override
{
return output->receiveSamples(maxSamples);
}
/// Returns number of samples currently available.
virtual uint numSamples() const override
{
return output->numSamples();
}
/// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const override
{
return output->isEmpty();
}
/// allow trimming (downwards) amount of samples in pipeline.
/// Returns adjusted amount of samples
virtual uint adjustAmountOfSamples(uint numSamples) override
{
return output->adjustAmountOfSamples(numSamples);
}
};
}
#endif

View file

@ -1,314 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// General FIR digital filter routines with MMX optimization.
///
/// Notes : MMX optimized functions reside in a separate, platform-specific file,
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
///
/// This source file contains OpenMP optimizations that allow speeding up the
/// corss-correlation algorithm by executing it in several threads / CPU cores
/// in parallel. See the following article link for more detailed discussion
/// about SoundTouch OpenMP optimizations:
/// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <memory.h>
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include "FIRFilter.h"
#include "cpu_detect.h"
using namespace soundtouch;
/*****************************************************************************
*
* Implementation of the class 'FIRFilter'
*
*****************************************************************************/
FIRFilter::FIRFilter()
{
resultDivFactor = 0;
resultDivider = 0;
length = 0;
lengthDiv8 = 0;
filterCoeffs = nullptr;
filterCoeffsStereo = nullptr;
}
FIRFilter::~FIRFilter()
{
delete[] filterCoeffs;
delete[] filterCoeffsStereo;
}
// Usual C-version of the filter routine for stereo sound
uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{
int j, end;
// hint compiler autovectorization that loop length is divisible by 8
uint ilength = length & -8;
assert((length != 0) && (length == ilength) && (src != nullptr) && (dest != nullptr) && (filterCoeffs != nullptr));
assert(numSamples > ilength);
end = 2 * (numSamples - ilength);
#pragma omp parallel for
for (j = 0; j < end; j += 2)
{
const SAMPLETYPE *ptr;
LONG_SAMPLETYPE suml, sumr;
suml = sumr = 0;
ptr = src + j;
for (uint i = 0; i < ilength; i ++)
{
suml += ptr[2 * i] * filterCoeffsStereo[2 * i];
sumr += ptr[2 * i + 1] * filterCoeffsStereo[2 * i + 1];
}
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
suml >>= resultDivFactor;
sumr >>= resultDivFactor;
// saturate to 16 bit integer limits
suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
// saturate to 16 bit integer limits
sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)suml;
dest[j + 1] = (SAMPLETYPE)sumr;
}
return numSamples - ilength;
}
// Usual C-version of the filter routine for mono sound
uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
{
int j, end;
// hint compiler autovectorization that loop length is divisible by 8
int ilength = length & -8;
assert(ilength != 0);
end = numSamples - ilength;
#pragma omp parallel for
for (j = 0; j < end; j ++)
{
const SAMPLETYPE *pSrc = src + j;
LONG_SAMPLETYPE sum;
int i;
sum = 0;
for (i = 0; i < ilength; i ++)
{
sum += pSrc[i] * filterCoeffs[i];
}
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
sum >>= resultDivFactor;
// saturate to 16 bit integer limits
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j] = (SAMPLETYPE)sum;
}
return end;
}
uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels)
{
int j, end;
assert(length != 0);
assert(src != nullptr);
assert(dest != nullptr);
assert(filterCoeffs != nullptr);
assert(numChannels < 16);
// hint compiler autovectorization that loop length is divisible by 8
int ilength = length & -8;
end = numChannels * (numSamples - ilength);
#pragma omp parallel for
for (j = 0; j < end; j += numChannels)
{
const SAMPLETYPE *ptr;
LONG_SAMPLETYPE sums[16];
uint c;
int i;
for (c = 0; c < numChannels; c ++)
{
sums[c] = 0;
}
ptr = src + j;
for (i = 0; i < ilength; i ++)
{
SAMPLETYPE coef=filterCoeffs[i];
for (c = 0; c < numChannels; c ++)
{
sums[c] += ptr[0] * coef;
ptr ++;
}
}
for (c = 0; c < numChannels; c ++)
{
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
sums[c] >>= resultDivFactor;
#endif // SOUNDTOUCH_INTEGER_SAMPLES
dest[j+c] = (SAMPLETYPE)sums[c];
}
}
return numSamples - ilength;
}
// Set filter coeffiecients and length.
//
// Throws an exception if filter length isn't divisible by 8
void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
{
assert(newLength > 0);
if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
// scale coefficients already here if using floating samples
double scale = 1.0 / resultDivider;
#else
short scale = 1;
#endif
lengthDiv8 = newLength / 8;
length = lengthDiv8 * 8;
assert(length == newLength);
resultDivFactor = uResultDivFactor;
resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
delete[] filterCoeffs;
filterCoeffs = new SAMPLETYPE[length];
delete[] filterCoeffsStereo;
filterCoeffsStereo = new SAMPLETYPE[length*2];
for (uint i = 0; i < length; i ++)
{
filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale);
// create also stereo set of filter coefficients: this allows compiler
// to autovectorize filter evaluation much more efficiently
filterCoeffsStereo[2 * i] = (SAMPLETYPE)(coeffs[i] * scale);
filterCoeffsStereo[2 * i + 1] = (SAMPLETYPE)(coeffs[i] * scale);
}
}
uint FIRFilter::getLength() const
{
return length;
}
// Applies the filter to the given sequence of samples.
//
// Note : The amount of outputted samples is by value of 'filter_length'
// smaller than the amount of input samples.
uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels)
{
assert(length > 0);
assert(lengthDiv8 * 8 == length);
if (numSamples < length) return 0;
#ifndef USE_MULTICH_ALWAYS
if (numChannels == 1)
{
return evaluateFilterMono(dest, src, numSamples);
}
else if (numChannels == 2)
{
return evaluateFilterStereo(dest, src, numSamples);
}
else
#endif // USE_MULTICH_ALWAYS
{
assert(numChannels > 0);
return evaluateFilterMulti(dest, src, numSamples, numChannels);
}
}
// Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX-capable CPU available or not.
void * FIRFilter::operator new(size_t)
{
// Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
return newInstance();
}
FIRFilter * FIRFilter::newInstance()
{
uint uExtensions;
uExtensions = detectCPUextensions();
// Check if MMX/SSE instruction set extensions supported by CPU
#ifdef SOUNDTOUCH_ALLOW_MMX
// MMX routines available only with integer sample types
if (uExtensions & SUPPORT_MMX)
{
return ::new FIRFilterMMX;
}
else
#endif // SOUNDTOUCH_ALLOW_MMX
#ifdef SOUNDTOUCH_ALLOW_SSE
if (uExtensions & SUPPORT_SSE)
{
// SSE support
return ::new FIRFilterSSE;
}
else
#endif // SOUNDTOUCH_ALLOW_SSE
{
// ISA optimizations not supported, use plain C version
return ::new FIRFilter;
}
}

View file

@ -1,140 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// General FIR digital filter routines with MMX optimization.
///
/// Note : MMX optimized functions reside in a separate, platform-specific file,
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef FIRFilter_H
#define FIRFilter_H
#include <stddef.h>
#include "STTypes.h"
namespace soundtouch
{
class FIRFilter
{
protected:
// Number of FIR filter taps
uint length;
// Number of FIR filter taps divided by 8
uint lengthDiv8;
// Result divider factor in 2^k format
uint resultDivFactor;
// Result divider value.
SAMPLETYPE resultDivider;
// Memory for filter coefficients
SAMPLETYPE *filterCoeffs;
SAMPLETYPE *filterCoeffsStereo;
virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) const;
virtual uint evaluateFilterMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) const;
virtual uint evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels);
public:
FIRFilter();
virtual ~FIRFilter();
/// Operator 'new' is overloaded so that it automatically creates a suitable instance
/// depending on if we've a MMX-capable CPU available or not.
static void * operator new(size_t s);
static FIRFilter *newInstance();
/// Applies the filter to the given sequence of samples.
/// Note : The amount of outputted samples is by value of 'filter_length'
/// smaller than the amount of input samples.
///
/// \return Number of samples copied to 'dest'.
uint evaluate(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples,
uint numChannels);
uint getLength() const;
virtual void setCoefficients(const SAMPLETYPE *coeffs,
uint newLength,
uint uResultDivFactor);
};
// Optional subclasses that implement CPU-specific optimizations:
#ifdef SOUNDTOUCH_ALLOW_MMX
/// Class that implements MMX optimized functions exclusive for 16bit integer samples type.
class FIRFilterMMX : public FIRFilter
{
protected:
short *filterCoeffsUnalign;
short *filterCoeffsAlign;
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const override;
public:
FIRFilterMMX();
~FIRFilterMMX();
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor) override;
};
#endif // SOUNDTOUCH_ALLOW_MMX
#ifdef SOUNDTOUCH_ALLOW_SSE
/// Class that implements SSE optimized functions exclusive for floating point samples type.
class FIRFilterSSE : public FIRFilter
{
protected:
float *filterCoeffsUnalign;
float *filterCoeffsAlign;
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const override;
public:
FIRFilterSSE();
~FIRFilterSSE();
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor) override;
};
#endif // SOUNDTOUCH_ALLOW_SSE
}
#endif // FIRFilter_H

View file

@ -1,196 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Cubic interpolation routine.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <stddef.h>
#include <math.h>
#include "InterpolateCubic.h"
#include "STTypes.h"
using namespace soundtouch;
// cubic interpolation coefficients
static const float _coeffs[]=
{ -0.5f, 1.0f, -0.5f, 0.0f,
1.5f, -2.5f, 0.0f, 1.0f,
-1.5f, 2.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f};
InterpolateCubic::InterpolateCubic()
{
fract = 0;
}
void InterpolateCubic::resetRegisters()
{
fract = 0;
}
/// Transpose mono audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateCubic::transposeMono(SAMPLETYPE *pdest,
const SAMPLETYPE *psrc,
int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 4;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
float out;
const float x3 = 1.0f;
const float x2 = (float)fract; // x
const float x1 = x2*x2; // x^2
const float x0 = x1*x2; // x^3
float y0, y1, y2, y3;
assert(fract < 1.0);
y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
out = y0 * psrc[0] + y1 * psrc[1] + y2 * psrc[2] + y3 * psrc[3];
pdest[i] = (SAMPLETYPE)out;
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
psrc += whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}
/// Transpose stereo audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateCubic::transposeStereo(SAMPLETYPE *pdest,
const SAMPLETYPE *psrc,
int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 4;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
const float x3 = 1.0f;
const float x2 = (float)fract; // x
const float x1 = x2*x2; // x^2
const float x0 = x1*x2; // x^3
float y0, y1, y2, y3;
float out0, out1;
assert(fract < 1.0);
y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
out0 = y0 * psrc[0] + y1 * psrc[2] + y2 * psrc[4] + y3 * psrc[6];
out1 = y0 * psrc[1] + y1 * psrc[3] + y2 * psrc[5] + y3 * psrc[7];
pdest[2*i] = (SAMPLETYPE)out0;
pdest[2*i+1] = (SAMPLETYPE)out1;
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
psrc += 2*whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}
/// Transpose multi-channel audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateCubic::transposeMulti(SAMPLETYPE *pdest,
const SAMPLETYPE *psrc,
int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 4;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
const float x3 = 1.0f;
const float x2 = (float)fract; // x
const float x1 = x2*x2; // x^2
const float x0 = x1*x2; // x^3
float y0, y1, y2, y3;
assert(fract < 1.0);
y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
for (int c = 0; c < numChannels; c ++)
{
float out;
out = y0 * psrc[c] + y1 * psrc[c + numChannels] + y2 * psrc[c + 2 * numChannels] + y3 * psrc[c + 3 * numChannels];
pdest[0] = (SAMPLETYPE)out;
pdest ++;
}
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
psrc += numChannels*whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}

View file

@ -1,69 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Cubic interpolation routine.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef _InterpolateCubic_H_
#define _InterpolateCubic_H_
#include "RateTransposer.h"
#include "STTypes.h"
namespace soundtouch
{
class InterpolateCubic : public TransposerBase
{
protected:
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
virtual int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
double fract;
public:
InterpolateCubic();
virtual void resetRegisters() override;
virtual int getLatency() const override
{
return 1;
}
};
}
#endif

View file

@ -1,296 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Linear interpolation algorithm.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <assert.h>
#include <stdlib.h>
#include "InterpolateLinear.h"
using namespace soundtouch;
//////////////////////////////////////////////////////////////////////////////
//
// InterpolateLinearInteger - integer arithmetic implementation
//
/// fixed-point interpolation routine precision
#define SCALE 65536
// Constructor
InterpolateLinearInteger::InterpolateLinearInteger() : TransposerBase()
{
// Notice: use local function calling syntax for sake of clarity,
// to indicate the fact that C++ constructor can't call virtual functions.
resetRegisters();
setRate(1.0f);
}
void InterpolateLinearInteger::resetRegisters()
{
iFract = 0;
}
// Transposes the sample rate of the given samples using linear interpolation.
// 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer
int InterpolateLinearInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 1;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
LONG_SAMPLETYPE temp;
assert(iFract < SCALE);
temp = (SCALE - iFract) * src[0] + iFract * src[1];
dest[i] = (SAMPLETYPE)(temp / SCALE);
i++;
iFract += iRate;
int iWhole = iFract / SCALE;
iFract -= iWhole * SCALE;
srcCount += iWhole;
src += iWhole;
}
srcSamples = srcCount;
return i;
}
// Transposes the sample rate of the given samples using linear interpolation.
// 'Stereo' version of the routine. Returns the number of samples returned in
// the "dest" buffer
int InterpolateLinearInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 1;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
LONG_SAMPLETYPE temp0;
LONG_SAMPLETYPE temp1;
assert(iFract < SCALE);
temp0 = (SCALE - iFract) * src[0] + iFract * src[2];
temp1 = (SCALE - iFract) * src[1] + iFract * src[3];
dest[0] = (SAMPLETYPE)(temp0 / SCALE);
dest[1] = (SAMPLETYPE)(temp1 / SCALE);
dest += 2;
i++;
iFract += iRate;
int iWhole = iFract / SCALE;
iFract -= iWhole * SCALE;
srcCount += iWhole;
src += 2*iWhole;
}
srcSamples = srcCount;
return i;
}
int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 1;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
LONG_SAMPLETYPE temp, vol1;
assert(iFract < SCALE);
vol1 = (LONG_SAMPLETYPE)(SCALE - iFract);
for (int c = 0; c < numChannels; c ++)
{
temp = vol1 * src[c] + iFract * src[c + numChannels];
dest[0] = (SAMPLETYPE)(temp / SCALE);
dest ++;
}
i++;
iFract += iRate;
int iWhole = iFract / SCALE;
iFract -= iWhole * SCALE;
srcCount += iWhole;
src += iWhole * numChannels;
}
srcSamples = srcCount;
return i;
}
// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
// iRate, larger faster iRates.
void InterpolateLinearInteger::setRate(double newRate)
{
iRate = (int)(newRate * SCALE + 0.5);
TransposerBase::setRate(newRate);
}
//////////////////////////////////////////////////////////////////////////////
//
// InterpolateLinearFloat - floating point arithmetic implementation
//
//////////////////////////////////////////////////////////////////////////////
// Constructor
InterpolateLinearFloat::InterpolateLinearFloat() : TransposerBase()
{
// Notice: use local function calling syntax for sake of clarity,
// to indicate the fact that C++ constructor can't call virtual functions.
resetRegisters();
setRate(1.0);
}
void InterpolateLinearFloat::resetRegisters()
{
fract = 0;
}
// Transposes the sample rate of the given samples using linear interpolation.
// 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer
int InterpolateLinearFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 1;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
double out;
assert(fract < 1.0);
out = (1.0 - fract) * src[0] + fract * src[1];
dest[i] = (SAMPLETYPE)out;
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
src += whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}
// Transposes the sample rate of the given samples using linear interpolation.
// 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer
int InterpolateLinearFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 1;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
double out0, out1;
assert(fract < 1.0);
out0 = (1.0 - fract) * src[0] + fract * src[2];
out1 = (1.0 - fract) * src[1] + fract * src[3];
dest[2*i] = (SAMPLETYPE)out0;
dest[2*i+1] = (SAMPLETYPE)out1;
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
src += 2*whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}
int InterpolateLinearFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 1;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
float temp, vol1, fract_float;
vol1 = (float)(1.0 - fract);
fract_float = (float)fract;
for (int c = 0; c < numChannels; c ++)
{
temp = vol1 * src[c] + fract_float * src[c + numChannels];
*dest = (SAMPLETYPE)temp;
dest ++;
}
i++;
fract += rate;
int iWhole = (int)fract;
fract -= iWhole;
srcCount += iWhole;
src += iWhole * numChannels;
}
srcSamples = srcCount;
return i;
}

View file

@ -1,98 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Linear interpolation routine.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef _InterpolateLinear_H_
#define _InterpolateLinear_H_
#include "RateTransposer.h"
#include "STTypes.h"
namespace soundtouch
{
/// Linear transposer class that uses integer arithmetic
class InterpolateLinearInteger : public TransposerBase
{
protected:
int iFract;
int iRate;
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples) override;
public:
InterpolateLinearInteger();
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower
/// rate, larger faster rates.
virtual void setRate(double newRate) override;
virtual void resetRegisters() override;
virtual int getLatency() const override
{
return 0;
}
};
/// Linear transposer class that uses floating point arithmetic
class InterpolateLinearFloat : public TransposerBase
{
protected:
double fract;
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples);
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
public:
InterpolateLinearFloat();
virtual void resetRegisters();
int getLatency() const
{
return 0;
}
};
}
#endif

View file

@ -1,181 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Sample interpolation routine using 8-tap band-limited Shannon interpolation
/// with kaiser window.
///
/// Notice. This algorithm is remarkably much heavier than linear or cubic
/// interpolation, and not remarkably better than cubic algorithm. Thus mostly
/// for experimental purposes
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include "InterpolateShannon.h"
#include "STTypes.h"
using namespace soundtouch;
/// Kaiser window with beta = 2.0
/// Values scaled down by 5% to avoid overflows
static const double _kaiser8[8] =
{
0.41778693317814,
0.64888025049173,
0.83508562409944,
0.93887857733412,
0.93887857733412,
0.83508562409944,
0.64888025049173,
0.41778693317814
};
InterpolateShannon::InterpolateShannon()
{
fract = 0;
}
void InterpolateShannon::resetRegisters()
{
fract = 0;
}
#define PI 3.1415926536
#define sinc(x) (sin(PI * (x)) / (PI * (x)))
/// Transpose mono audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,
const SAMPLETYPE *psrc,
int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 8;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
double out;
assert(fract < 1.0);
out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0];
out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1];
out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2];
if (fract < 1e-6)
{
out += psrc[3] * _kaiser8[3]; // sinc(0) = 1
}
else
{
out += psrc[3] * sinc(- fract) * _kaiser8[3];
}
out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4];
out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5];
out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6];
out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7];
pdest[i] = (SAMPLETYPE)out;
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
psrc += whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}
/// Transpose stereo audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
const SAMPLETYPE *psrc,
int &srcSamples)
{
int i;
int srcSampleEnd = srcSamples - 8;
int srcCount = 0;
i = 0;
while (srcCount < srcSampleEnd)
{
double out0, out1, w;
assert(fract < 1.0);
w = sinc(-3.0 - fract) * _kaiser8[0];
out0 = psrc[0] * w; out1 = psrc[1] * w;
w = sinc(-2.0 - fract) * _kaiser8[1];
out0 += psrc[2] * w; out1 += psrc[3] * w;
w = sinc(-1.0 - fract) * _kaiser8[2];
out0 += psrc[4] * w; out1 += psrc[5] * w;
w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1
out0 += psrc[6] * w; out1 += psrc[7] * w;
w = sinc( 1.0 - fract) * _kaiser8[4];
out0 += psrc[8] * w; out1 += psrc[9] * w;
w = sinc( 2.0 - fract) * _kaiser8[5];
out0 += psrc[10] * w; out1 += psrc[11] * w;
w = sinc( 3.0 - fract) * _kaiser8[6];
out0 += psrc[12] * w; out1 += psrc[13] * w;
w = sinc( 4.0 - fract) * _kaiser8[7];
out0 += psrc[14] * w; out1 += psrc[15] * w;
pdest[2*i] = (SAMPLETYPE)out0;
pdest[2*i+1] = (SAMPLETYPE)out1;
i ++;
// update position fraction
fract += rate;
// update whole positions
int whole = (int)fract;
fract -= whole;
psrc += 2*whole;
srcCount += whole;
}
srcSamples = srcCount;
return i;
}
/// Transpose stereo audio. Returns number of produced output samples, and
/// updates "srcSamples" to amount of consumed source samples
int InterpolateShannon::transposeMulti(SAMPLETYPE *,
const SAMPLETYPE *,
int &)
{
// not implemented
assert(false);
return 0;
}

View file

@ -1,74 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Sample interpolation routine using 8-tap band-limited Shannon interpolation
/// with kaiser window.
///
/// Notice. This algorithm is remarkably much heavier than linear or cubic
/// interpolation, and not remarkably better than cubic algorithm. Thus mostly
/// for experimental purposes
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef _InterpolateShannon_H_
#define _InterpolateShannon_H_
#include "RateTransposer.h"
#include "STTypes.h"
namespace soundtouch
{
class InterpolateShannon : public TransposerBase
{
protected:
int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src,
int &srcSamples) override;
double fract;
public:
InterpolateShannon();
void resetRegisters() override;
virtual int getLatency() const override
{
return 3;
}
};
}
#endif

View file

@ -1,277 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
///
/// Peak detection routine.
///
/// The routine detects highest value on an array of values and calculates the
/// precise peak location as a mass-center of the 'hump' around the peak value.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include <assert.h>
#include "PeakFinder.h"
using namespace soundtouch;
#define max(x, y) (((x) > (y)) ? (x) : (y))
PeakFinder::PeakFinder()
{
minPos = maxPos = 0;
}
// Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
int PeakFinder::findTop(const float *data, int peakpos) const
{
int i;
int start, end;
float refvalue;
refvalue = data[peakpos];
// seek within ±10 points
start = peakpos - 10;
if (start < minPos) start = minPos;
end = peakpos + 10;
if (end > maxPos) end = maxPos;
for (i = start; i <= end; i ++)
{
if (data[i] > refvalue)
{
peakpos = i;
refvalue = data[i];
}
}
// failure if max value is at edges of seek range => it's not peak, it's at slope.
if ((peakpos == start) || (peakpos == end)) return 0;
return peakpos;
}
// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding
// to direction defined by 'direction' until next 'hump' after minimum value will
// begin
int PeakFinder::findGround(const float *data, int peakpos, int direction) const
{
int lowpos;
int pos;
int climb_count;
float refvalue;
float delta;
climb_count = 0;
refvalue = data[peakpos];
lowpos = peakpos;
pos = peakpos;
while ((pos > minPos+1) && (pos < maxPos-1))
{
int prevpos;
prevpos = pos;
pos += direction;
// calculate derivate
delta = data[pos] - data[prevpos];
if (delta <= 0)
{
// going downhill, ok
if (climb_count)
{
climb_count --; // decrease climb count
}
// check if new minimum found
if (data[pos] < refvalue)
{
// new minimum found
lowpos = pos;
refvalue = data[pos];
}
}
else
{
// going uphill, increase climbing counter
climb_count ++;
if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit
}
}
return lowpos;
}
// Find offset where the value crosses the given level, when starting from 'peakpos' and
// proceeds to direction defined in 'direction'
int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const
{
float peaklevel;
int pos;
peaklevel = data[peakpos];
assert(peaklevel >= level);
pos = peakpos;
while ((pos >= minPos) && (pos + direction < maxPos))
{
if (data[pos + direction] < level) return pos; // crossing found
pos += direction;
}
return -1; // not found
}
// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos'
double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const
{
int i;
float sum;
float wsum;
sum = 0;
wsum = 0;
for (i = firstPos; i <= lastPos; i ++)
{
sum += (float)i * data[i];
wsum += data[i];
}
if (wsum < 1e-6) return 0;
return sum / wsum;
}
/// get exact center of peak near given position by calculating local mass of center
double PeakFinder::getPeakCenter(const float *data, int peakpos) const
{
float peakLevel; // peak level
int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level
float cutLevel; // cutting value
float groundLevel; // ground level of the peak
int gp1, gp2; // bottom positions of the peak 'hump'
// find ground positions.
gp1 = findGround(data, peakpos, -1);
gp2 = findGround(data, peakpos, 1);
peakLevel = data[peakpos];
if (gp1 == gp2)
{
// avoid rounding errors when all are equal
assert(gp1 == peakpos);
cutLevel = groundLevel = peakLevel;
} else {
// get average of the ground levels
groundLevel = 0.5f * (data[gp1] + data[gp2]);
// calculate 70%-level of the peak
cutLevel = 0.70f * peakLevel + 0.30f * groundLevel;
}
// find mid-level crossings
crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1);
crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1);
if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak..
// calculate mass center of the peak surroundings
return calcMassCenter(data, crosspos1, crosspos2);
}
double PeakFinder::detectPeak(const float *data, int aminPos, int amaxPos)
{
int i;
int peakpos; // position of peak level
double highPeak, peak;
this->minPos = aminPos;
this->maxPos = amaxPos;
// find absolute peak
peakpos = minPos;
peak = data[minPos];
for (i = minPos + 1; i < maxPos; i ++)
{
if (data[i] > peak)
{
peak = data[i];
peakpos = i;
}
}
// Calculate exact location of the highest peak mass center
highPeak = getPeakCenter(data, peakpos);
peak = highPeak;
// Now check if the highest peak were in fact harmonic of the true base beat peak
// - sometimes the highest peak can be Nth harmonic of the true base peak yet
// just a slightly higher than the true base
for (i = 1; i < 3; i ++)
{
double peaktmp, harmonic;
int i1,i2;
harmonic = (double)pow(2.0, i);
peakpos = (int)(highPeak / harmonic + 0.5f);
if (peakpos < minPos) break;
peakpos = findTop(data, peakpos); // seek true local maximum index
if (peakpos == 0) continue; // no local max here
// calculate mass-center of possible harmonic peak
peaktmp = getPeakCenter(data, peakpos);
// accept harmonic peak if
// (a) it is found
// (b) is within ±4% of the expected harmonic interval
// (c) has at least half x-corr value of the max. peak
double diff = harmonic * peaktmp / highPeak;
if ((diff < 0.96) || (diff > 1.04)) continue; // peak too afar from expected
// now compare to highest detected peak
i1 = (int)(highPeak + 0.5);
i2 = (int)(peaktmp + 0.5);
if (data[i2] >= 0.4*data[i1])
{
// The harmonic is at least half as high primary peak,
// thus use the harmonic peak instead
peak = peaktmp;
}
}
return peak;
}

Some files were not shown because too many files have changed in this diff Show more