Browse Source
Merge remote-tracking branch 'upstream/master' into int-flags
remotes/1778439668340191200/nce_cpp
Merge remote-tracking branch 'upstream/master' into int-flags
remotes/1778439668340191200/nce_cpp
912 changed files with 90766 additions and 25145 deletions
-
4.ci/scripts/common/post-upload.sh
-
3.ci/scripts/common/pre-upload.sh
-
44.ci/scripts/linux/docker.sh
-
5.ci/scripts/linux/upload.sh
-
2.ci/scripts/windows/docker.sh
-
4.ci/templates/build-msvc.yml
-
1.ci/yuzu-patreon-step2.yml
-
5.gitmodules
-
10.travis/linux-mingw/docker.sh
-
2.travis/linux/build.sh
-
2.travis/linux/docker.sh
-
3.travis/macos/build.sh
-
134CMakeLists.txt
-
10CMakeModules/CopyYuzuFFmpegDeps.cmake
-
9CMakeModules/CopyYuzuUnicornDeps.cmake
-
1README.md
-
4749dist/languages/de.ts
-
4757dist/languages/es.ts
-
4732dist/languages/fr.ts
-
4724dist/languages/it.ts
-
4752dist/languages/ja_JP.ts
-
4719dist/languages/nl.ts
-
4713dist/languages/pl.ts
-
4757dist/languages/pt_BR.ts
-
4725dist/languages/pt_PT.ts
-
4720dist/languages/ru_RU.ts
-
4747dist/languages/zh_CN.ts
-
14dist/qt_themes/default/style.qss
-
86dist/qt_themes/qdarkstyle/style.qss
-
95dist/qt_themes/qdarkstyle_midnight_blue/style.qss
-
32externals/CMakeLists.txt
-
2externals/cubeb
-
2externals/dynarmic
-
100externals/find-modules/FindFFmpeg.cmake
-
2externals/httplib/README.md
-
4880externals/httplib/httplib.h
-
2externals/inih/inih
-
2externals/libressl
-
8externals/lurlparser/CMakeLists.txt
-
265externals/lurlparser/LUrlParser.cpp
-
78externals/lurlparser/LUrlParser.h
-
19externals/lurlparser/README.md
-
18externals/microprofile/microprofile.h
-
1externals/unicorn
-
16src/CMakeLists.txt
-
18src/audio_core/CMakeLists.txt
-
9src/audio_core/algorithm/filter.cpp
-
4src/audio_core/algorithm/filter.h
-
7src/audio_core/algorithm/interpolate.cpp
-
4src/audio_core/audio_out.cpp
-
3src/audio_core/audio_out.h
-
131src/audio_core/audio_renderer.cpp
-
29src/audio_core/audio_renderer.h
-
6src/audio_core/behavior_info.cpp
-
30src/audio_core/behavior_info.h
-
2src/audio_core/buffer.h
-
5src/audio_core/codec.cpp
-
2src/audio_core/codec.h
-
47src/audio_core/command_generator.cpp
-
23src/audio_core/command_generator.h
-
3src/audio_core/common.h
-
26src/audio_core/cubeb_sink.cpp
-
68src/audio_core/effect_context.cpp
-
53src/audio_core/effect_context.h
-
37src/audio_core/info_updater.cpp
-
4src/audio_core/info_updater.h
-
13src/audio_core/memory_pool.cpp
-
11src/audio_core/memory_pool.h
-
4src/audio_core/mix_context.cpp
-
26src/audio_core/mix_context.h
-
20src/audio_core/sink_context.cpp
-
29src/audio_core/sink_context.h
-
28src/audio_core/splitter_context.cpp
-
20src/audio_core/splitter_context.h
-
31src/audio_core/stream.cpp
-
25src/audio_core/stream.h
-
16src/audio_core/voice_context.cpp
-
10src/audio_core/voice_context.h
-
34src/common/CMakeLists.txt
-
22src/common/bit_cast.h
-
99src/common/bit_set.h
-
4src/common/concepts.h
-
26src/common/div_ceil.h
-
194src/common/fiber.cpp
-
29src/common/fiber.h
-
31src/common/file_util.cpp
-
2src/common/file_util.h
-
10src/common/hex_util.h
-
17src/common/logging/backend.cpp
-
1src/common/logging/log.h
-
8src/common/math_util.h
-
11src/common/memory_hook.cpp
-
47src/common/memory_hook.h
-
15src/common/misc.cpp
-
345src/common/multi_level_queue.h
-
12src/common/page_table.cpp
-
100src/common/page_table.h
-
2src/common/scope_exit.h
-
8src/common/spin_lock.h
-
47src/common/stream.cpp
@ -1,14 +1,54 @@ |
|||||
#!/bin/bash -ex |
#!/bin/bash -ex |
||||
|
|
||||
|
# Exit on error, rather than continuing with the rest of the script. |
||||
|
set -e |
||||
|
|
||||
cd /yuzu |
cd /yuzu |
||||
|
|
||||
ccache -s |
ccache -s |
||||
|
|
||||
mkdir build || true && cd build |
mkdir build || true && cd build |
||||
cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON |
|
||||
|
cmake .. -DDISPLAY_VERSION=$1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_INSTALL_PREFIX="/usr" |
||||
|
|
||||
ninja |
|
||||
|
make -j$(nproc) |
||||
|
|
||||
ccache -s |
ccache -s |
||||
|
|
||||
ctest -VV -C Release |
ctest -VV -C Release |
||||
|
|
||||
|
make install DESTDIR=AppDir |
||||
|
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester |
||||
|
|
||||
|
# Download tools needed to build an AppImage |
||||
|
wget -nc https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage |
||||
|
wget -nc https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage |
||||
|
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage |
||||
|
wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 |
||||
|
wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so |
||||
|
# Set executable bit |
||||
|
chmod 755 \ |
||||
|
appimagetool-x86_64.AppImage \ |
||||
|
AppRun-patched-x86_64 \ |
||||
|
exec-x86_64.so \ |
||||
|
linuxdeploy-x86_64.AppImage \ |
||||
|
linuxdeploy-plugin-qt-x86_64.AppImage |
||||
|
|
||||
|
# Workaround for https://github.com/AppImage/AppImageKit/issues/828 |
||||
|
export APPIMAGE_EXTRACT_AND_RUN=1 |
||||
|
|
||||
|
mkdir -p AppDir/usr/optional |
||||
|
mkdir -p AppDir/usr/optional/libstdc++ |
||||
|
mkdir -p AppDir/usr/optional/libgcc_s |
||||
|
|
||||
|
# Deploy yuzu's needed dependencies |
||||
|
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt |
||||
|
|
||||
|
# Workaround for building yuzu with GCC 10 but also trying to distribute it to Ubuntu 18.04 et al. |
||||
|
# See https://github.com/darealshinji/AppImageKit-checkrt |
||||
|
cp exec-x86_64.so AppDir/usr/optional/exec.so |
||||
|
cp AppRun-patched-x86_64 AppDir/AppRun |
||||
|
cp --dereference /usr/lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/optional/libstdc++/libstdc++.so.6 |
||||
|
cp --dereference /lib/x86_64-linux-gnu/libgcc_s.so.1 AppDir/usr/optional/libgcc_s/libgcc_s.so.1 |
||||
|
|
||||
|
# Build the AppImage |
||||
|
./appimagetool-x86_64.AppImage AppDir |
||||
@ -1,4 +1,4 @@ |
|||||
#!/bin/bash -ex |
#!/bin/bash -ex |
||||
|
|
||||
mkdir -p "$HOME/.ccache" |
mkdir -p "$HOME/.ccache" |
||||
docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.travis/linux/docker.sh |
|
||||
|
docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/home/yuzu/.ccache yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.travis/linux/docker.sh |
||||
@ -0,0 +1,10 @@ |
|||||
|
function(copy_yuzu_FFmpeg_deps target_dir) |
||||
|
include(WindowsCopyFiles) |
||||
|
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") |
||||
|
windows_copy_files(${target_dir} ${FFMPEG_DLL_DIR} ${DLL_DEST} |
||||
|
avcodec-58.dll |
||||
|
avutil-56.dll |
||||
|
swresample-3.dll |
||||
|
swscale-5.dll |
||||
|
) |
||||
|
endfunction(copy_yuzu_FFmpeg_deps) |
||||
@ -1,9 +0,0 @@ |
|||||
function(copy_yuzu_unicorn_deps target_dir) |
|
||||
include(WindowsCopyFiles) |
|
||||
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") |
|
||||
windows_copy_files(${target_dir} ${UNICORN_DLL_DIR} ${DLL_DEST} |
|
||||
libgcc_s_seh-1.dll |
|
||||
libwinpthread-1.dll |
|
||||
unicorn.dll |
|
||||
) |
|
||||
endfunction(copy_yuzu_unicorn_deps) |
|
||||
4749
dist/languages/de.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4757
dist/languages/es.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4732
dist/languages/fr.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4724
dist/languages/it.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4752
dist/languages/ja_JP.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4719
dist/languages/nl.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4713
dist/languages/pl.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4757
dist/languages/pt_BR.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4725
dist/languages/pt_PT.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4720
dist/languages/ru_RU.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4747
dist/languages/zh_CN.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1 +1 @@ |
|||||
Subproject commit 616d773441b5355800ce64197a699e6cd6b36172 |
|
||||
|
Subproject commit 1d66483ad2b93f0e00e175f9480c771af90003a7 |
||||
@ -1 +1 @@ |
|||||
Subproject commit 0e1112b7df77ae55a62a51622940d5c8f9e8c84c |
|
||||
|
Subproject commit 3806284cbefc4115436dcdc687776a45ec313093 |
||||
@ -0,0 +1,100 @@ |
|||||
|
# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil) |
||||
|
# Once done this will define |
||||
|
# |
||||
|
# FFMPEG_FOUND - system has ffmpeg or libav |
||||
|
# FFMPEG_INCLUDE_DIR - the ffmpeg include directory |
||||
|
# FFMPEG_LIBRARIES - Link these to use ffmpeg |
||||
|
# FFMPEG_LIBAVCODEC |
||||
|
# FFMPEG_LIBAVFORMAT |
||||
|
# FFMPEG_LIBAVUTIL |
||||
|
# |
||||
|
# Copyright (c) 2008 Andreas Schneider <mail@cynapses.org> |
||||
|
# Modified for other libraries by Lasse Kärkkäinen <tronic> |
||||
|
# Modified for Hedgewars by Stepik777 |
||||
|
# Modified for FFmpeg-example Tuukka Pasanen 2018 |
||||
|
# Modified for yuzu toastUnlimted 2020 |
||||
|
# |
||||
|
# Redistribution and use is allowed according to the terms of the New |
||||
|
# BSD license. |
||||
|
# |
||||
|
|
||||
|
include(FindPackageHandleStandardArgs) |
||||
|
|
||||
|
find_package_handle_standard_args(FFMPEG |
||||
|
FOUND_VAR FFMPEG_FOUND |
||||
|
REQUIRED_VARS |
||||
|
FFMPEG_LIBRARY |
||||
|
FFMPEG_INCLUDE_DIR |
||||
|
VERSION_VAR FFMPEG_VERSION |
||||
|
) |
||||
|
|
||||
|
if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) |
||||
|
# in cache already |
||||
|
set(FFMPEG_FOUND TRUE) |
||||
|
else() |
||||
|
# use pkg-config to get the directories and then use these values |
||||
|
# in the FIND_PATH() and FIND_LIBRARY() calls |
||||
|
find_package(PkgConfig) |
||||
|
if(PKG_CONFIG_FOUND) |
||||
|
pkg_check_modules(_FFMPEG_AVCODEC libavcodec) |
||||
|
pkg_check_modules(_FFMPEG_AVUTIL libavutil) |
||||
|
pkg_check_modules(_FFMPEG_SWSCALE libswscale) |
||||
|
endif() |
||||
|
|
||||
|
find_path(FFMPEG_AVCODEC_INCLUDE_DIR |
||||
|
NAMES libavcodec/avcodec.h |
||||
|
PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} |
||||
|
/usr/include |
||||
|
/usr/local/include |
||||
|
/opt/local/include |
||||
|
/sw/include |
||||
|
PATH_SUFFIXES ffmpeg libav) |
||||
|
|
||||
|
find_library(FFMPEG_LIBAVCODEC |
||||
|
NAMES avcodec |
||||
|
PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} |
||||
|
/usr/lib |
||||
|
/usr/local/lib |
||||
|
/opt/local/lib |
||||
|
/sw/lib) |
||||
|
|
||||
|
find_library(FFMPEG_LIBAVUTIL |
||||
|
NAMES avutil |
||||
|
PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} |
||||
|
/usr/lib |
||||
|
/usr/local/lib |
||||
|
/opt/local/lib |
||||
|
/sw/lib) |
||||
|
|
||||
|
find_library(FFMPEG_LIBSWSCALE |
||||
|
NAMES swscale |
||||
|
PATHS ${_FFMPEG_SWSCALE_LIBRARY_DIRS} |
||||
|
/usr/lib |
||||
|
/usr/local/lib |
||||
|
/opt/local/lib |
||||
|
/sw/lib) |
||||
|
|
||||
|
if(FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVUTIL AND FFMPEG_LIBSWSCALE) |
||||
|
set(FFMPEG_FOUND TRUE) |
||||
|
endif() |
||||
|
|
||||
|
if(FFMPEG_FOUND) |
||||
|
set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) |
||||
|
set(FFMPEG_LIBRARIES |
||||
|
${FFMPEG_LIBAVCODEC} |
||||
|
${FFMPEG_LIBAVUTIL} |
||||
|
${FFMPEG_LIBSWSCALE}) |
||||
|
endif() |
||||
|
|
||||
|
if(FFMPEG_FOUND) |
||||
|
if(NOT FFMPEG_FIND_QUIETLY) |
||||
|
message(STATUS |
||||
|
"Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") |
||||
|
endif() |
||||
|
else() |
||||
|
if(FFMPEG_FIND_REQUIRED) |
||||
|
message(FATAL_ERROR |
||||
|
"Could not find libavcodec or libavutil or libswscale") |
||||
|
endif() |
||||
|
endif() |
||||
|
endif() |
||||
4880
externals/httplib/httplib.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1 +1 @@ |
|||||
Subproject commit 603729dec89aaca42d7bd08f08bc333165b7d5d1 |
|
||||
|
Subproject commit 1e80a47dffbda813604f0913e2ad68c7054c14e4 |
||||
@ -1 +1 @@ |
|||||
Subproject commit 7d01cb01cb1a926ecb4c9c98b107ef3c26f59dfb |
|
||||
|
Subproject commit 8289d0d07de6553bf4b900bf60e808ea3f7f59da |
||||
@ -1,8 +0,0 @@ |
|||||
add_library(lurlparser |
|
||||
LUrlParser.cpp |
|
||||
LUrlParser.h |
|
||||
) |
|
||||
|
|
||||
create_target_directory_groups(lurlparser) |
|
||||
|
|
||||
target_include_directories(lurlparser INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) |
|
||||
@ -1,265 +0,0 @@ |
|||||
/*
|
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986) |
|
||||
* https://github.com/corporateshark/LUrlParser
|
|
||||
* |
|
||||
* The MIT License (MIT) |
|
||||
* |
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) |
|
||||
* |
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
* of this software and associated documentation files (the "Software"), to deal |
|
||||
* in the Software without restriction, including without limitation the rights |
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
* copies of the Software, and to permit persons to whom the Software is |
|
||||
* furnished to do so, subject to the following conditions: |
|
||||
* |
|
||||
* The above copyright notice and this permission notice shall be included in all |
|
||||
* copies or substantial portions of the Software. |
|
||||
* |
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
||||
* SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
#include "LUrlParser.h"
|
|
||||
|
|
||||
#include <algorithm>
|
|
||||
#include <cstring>
|
|
||||
#include <stdlib.h>
|
|
||||
|
|
||||
// check if the scheme name is valid
|
|
||||
static bool IsSchemeValid( const std::string& SchemeName ) |
|
||||
{ |
|
||||
for ( auto c : SchemeName ) |
|
||||
{ |
|
||||
if ( !isalpha( c ) && c != '+' && c != '-' && c != '.' ) return false; |
|
||||
} |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
bool LUrlParser::clParseURL::GetPort( int* OutPort ) const |
|
||||
{ |
|
||||
if ( !IsValid() ) { return false; } |
|
||||
|
|
||||
int Port = atoi( m_Port.c_str() ); |
|
||||
|
|
||||
if ( Port <= 0 || Port > 65535 ) { return false; } |
|
||||
|
|
||||
if ( OutPort ) { *OutPort = Port; } |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// based on RFC 1738 and RFC 3986
|
|
||||
LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL ) |
|
||||
{ |
|
||||
LUrlParser::clParseURL Result; |
|
||||
|
|
||||
const char* CurrentString = URL.c_str(); |
|
||||
|
|
||||
/*
|
|
||||
* <scheme>:<scheme-specific-part> |
|
||||
* <scheme> := [a-z\+\-\.]+ |
|
||||
* For resiliency, programs interpreting URLs should treat upper case letters as equivalent to lower case in scheme names |
|
||||
*/ |
|
||||
|
|
||||
// try to read scheme
|
|
||||
{ |
|
||||
const char* LocalString = strchr( CurrentString, ':' ); |
|
||||
|
|
||||
if ( !LocalString ) |
|
||||
{ |
|
||||
return clParseURL( LUrlParserError_NoUrlCharacter ); |
|
||||
} |
|
||||
|
|
||||
// save the scheme name
|
|
||||
Result.m_Scheme = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
if ( !IsSchemeValid( Result.m_Scheme ) ) |
|
||||
{ |
|
||||
return clParseURL( LUrlParserError_InvalidSchemeName ); |
|
||||
} |
|
||||
|
|
||||
// scheme should be lowercase
|
|
||||
std::transform( Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower ); |
|
||||
|
|
||||
// skip ':'
|
|
||||
CurrentString = LocalString+1; |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
* //<user>:<password>@<host>:<port>/<url-path>
|
|
||||
* any ":", "@" and "/" must be normalized |
|
||||
*/ |
|
||||
|
|
||||
// skip "//"
|
|
||||
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash ); |
|
||||
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash ); |
|
||||
|
|
||||
// check if the user name and password are specified
|
|
||||
bool bHasUserName = false; |
|
||||
|
|
||||
const char* LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString ) |
|
||||
{ |
|
||||
if ( *LocalString == '@' ) |
|
||||
{ |
|
||||
// user name and password are specified
|
|
||||
bHasUserName = true; |
|
||||
break; |
|
||||
} |
|
||||
else if ( *LocalString == '/' ) |
|
||||
{ |
|
||||
// end of <host>:<port> specification
|
|
||||
bHasUserName = false; |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
LocalString++; |
|
||||
} |
|
||||
|
|
||||
// user name and password
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
if ( bHasUserName ) |
|
||||
{ |
|
||||
// read user name
|
|
||||
while ( *LocalString && *LocalString != ':' && *LocalString != '@' ) LocalString++; |
|
||||
|
|
||||
Result.m_UserName = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
// proceed with the current pointer
|
|
||||
CurrentString = LocalString; |
|
||||
|
|
||||
if ( *CurrentString == ':' ) |
|
||||
{ |
|
||||
// skip ':'
|
|
||||
CurrentString++; |
|
||||
|
|
||||
// read password
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString && *LocalString != '@' ) LocalString++; |
|
||||
|
|
||||
Result.m_Password = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
CurrentString = LocalString; |
|
||||
} |
|
||||
|
|
||||
// skip '@'
|
|
||||
if ( *CurrentString != '@' ) |
|
||||
{ |
|
||||
return clParseURL( LUrlParserError_NoAtSign ); |
|
||||
} |
|
||||
|
|
||||
CurrentString++; |
|
||||
} |
|
||||
|
|
||||
bool bHasBracket = ( *CurrentString == '[' ); |
|
||||
|
|
||||
// go ahead, read the host name
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString ) |
|
||||
{ |
|
||||
if ( bHasBracket && *LocalString == ']' ) |
|
||||
{ |
|
||||
// end of IPv6 address
|
|
||||
LocalString++; |
|
||||
break; |
|
||||
} |
|
||||
else if ( !bHasBracket && ( *LocalString == ':' || *LocalString == '/' ) ) |
|
||||
{ |
|
||||
// port number is specified
|
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
LocalString++; |
|
||||
} |
|
||||
|
|
||||
Result.m_Host = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
CurrentString = LocalString; |
|
||||
|
|
||||
// is port number specified?
|
|
||||
if ( *CurrentString == ':' ) |
|
||||
{ |
|
||||
CurrentString++; |
|
||||
|
|
||||
// read port number
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString && *LocalString != '/' ) LocalString++; |
|
||||
|
|
||||
Result.m_Port = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
CurrentString = LocalString; |
|
||||
} |
|
||||
|
|
||||
// end of string
|
|
||||
if ( !*CurrentString ) |
|
||||
{ |
|
||||
Result.m_ErrorCode = LUrlParserError_Ok; |
|
||||
|
|
||||
return Result; |
|
||||
} |
|
||||
|
|
||||
// skip '/'
|
|
||||
if ( *CurrentString != '/' ) |
|
||||
{ |
|
||||
return clParseURL( LUrlParserError_NoSlash ); |
|
||||
} |
|
||||
|
|
||||
CurrentString++; |
|
||||
|
|
||||
// parse the path
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString && *LocalString != '#' && *LocalString != '?' ) LocalString++; |
|
||||
|
|
||||
Result.m_Path = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
CurrentString = LocalString; |
|
||||
|
|
||||
// check for query
|
|
||||
if ( *CurrentString == '?' ) |
|
||||
{ |
|
||||
// skip '?'
|
|
||||
CurrentString++; |
|
||||
|
|
||||
// read query
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString && *LocalString != '#' ) LocalString++; |
|
||||
|
|
||||
Result.m_Query = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
CurrentString = LocalString; |
|
||||
} |
|
||||
|
|
||||
// check for fragment
|
|
||||
if ( *CurrentString == '#' ) |
|
||||
{ |
|
||||
// skip '#'
|
|
||||
CurrentString++; |
|
||||
|
|
||||
// read fragment
|
|
||||
LocalString = CurrentString; |
|
||||
|
|
||||
while ( *LocalString ) LocalString++; |
|
||||
|
|
||||
Result.m_Fragment = std::string( CurrentString, LocalString - CurrentString ); |
|
||||
|
|
||||
CurrentString = LocalString; |
|
||||
} |
|
||||
|
|
||||
Result.m_ErrorCode = LUrlParserError_Ok; |
|
||||
|
|
||||
return Result; |
|
||||
} |
|
||||
@ -1,78 +0,0 @@ |
|||||
/* |
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986) |
|
||||
* https://github.com/corporateshark/LUrlParser |
|
||||
* |
|
||||
* The MIT License (MIT) |
|
||||
* |
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com) |
|
||||
* |
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
* of this software and associated documentation files (the "Software"), to deal |
|
||||
* in the Software without restriction, including without limitation the rights |
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
* copies of the Software, and to permit persons to whom the Software is |
|
||||
* furnished to do so, subject to the following conditions: |
|
||||
* |
|
||||
* The above copyright notice and this permission notice shall be included in all |
|
||||
* copies or substantial portions of the Software. |
|
||||
* |
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
||||
* SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <string> |
|
||||
|
|
||||
namespace LUrlParser |
|
||||
{ |
|
||||
enum LUrlParserError |
|
||||
{ |
|
||||
LUrlParserError_Ok = 0, |
|
||||
LUrlParserError_Uninitialized = 1, |
|
||||
LUrlParserError_NoUrlCharacter = 2, |
|
||||
LUrlParserError_InvalidSchemeName = 3, |
|
||||
LUrlParserError_NoDoubleSlash = 4, |
|
||||
LUrlParserError_NoAtSign = 5, |
|
||||
LUrlParserError_UnexpectedEndOfLine = 6, |
|
||||
LUrlParserError_NoSlash = 7, |
|
||||
}; |
|
||||
|
|
||||
class clParseURL |
|
||||
{ |
|
||||
public: |
|
||||
LUrlParserError m_ErrorCode; |
|
||||
std::string m_Scheme; |
|
||||
std::string m_Host; |
|
||||
std::string m_Port; |
|
||||
std::string m_Path; |
|
||||
std::string m_Query; |
|
||||
std::string m_Fragment; |
|
||||
std::string m_UserName; |
|
||||
std::string m_Password; |
|
||||
|
|
||||
clParseURL() |
|
||||
: m_ErrorCode( LUrlParserError_Uninitialized ) |
|
||||
{} |
|
||||
|
|
||||
/// return 'true' if the parsing was successful |
|
||||
bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; } |
|
||||
|
|
||||
/// helper to convert the port number to int, return 'true' if the port is valid (within the 0..65535 range) |
|
||||
bool GetPort( int* OutPort ) const; |
|
||||
|
|
||||
/// parse the URL |
|
||||
static clParseURL ParseURL( const std::string& URL ); |
|
||||
|
|
||||
private: |
|
||||
explicit clParseURL( LUrlParserError ErrorCode ) |
|
||||
: m_ErrorCode( ErrorCode ) |
|
||||
{} |
|
||||
}; |
|
||||
|
|
||||
} // namespace LUrlParser |
|
||||
@ -1,19 +0,0 @@ |
|||||
From https://github.com/corporateshark/LUrlParser/commit/455d5e2d27e3946f11ad0328fee9ee2628e6a8e2 |
|
||||
|
|
||||
MIT License |
|
||||
|
|
||||
=== |
|
||||
|
|
||||
Lightweight URL & URI parser (RFC 1738, RFC 3986) |
|
||||
|
|
||||
(C) Sergey Kosarevsky, 2015 |
|
||||
|
|
||||
@corporateshark sk@linderdaum.com |
|
||||
|
|
||||
http://www.linderdaum.com |
|
||||
|
|
||||
http://blog.linderdaum.com |
|
||||
|
|
||||
============================= |
|
||||
|
|
||||
A tiny and lightweight URL & URI parser (RFC 1738, RFC 3986) written in C++. |
|
||||
@ -0,0 +1,22 @@ |
|||||
|
// Copyright 2020 yuzu emulator team |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <cstring> |
||||
|
#include <type_traits> |
||||
|
|
||||
|
namespace Common { |
||||
|
|
||||
|
template <typename To, typename From> |
||||
|
[[nodiscard]] std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> && |
||||
|
std::is_trivially_copyable_v<To>, |
||||
|
To> |
||||
|
BitCast(const From& src) noexcept { |
||||
|
To dst; |
||||
|
std::memcpy(&dst, &src, sizeof(To)); |
||||
|
return dst; |
||||
|
} |
||||
|
|
||||
|
} // namespace Common |
||||
@ -0,0 +1,99 @@ |
|||||
|
/* |
||||
|
* Copyright (c) 2018-2020 Atmosphère-NX |
||||
|
* |
||||
|
* This program is free software; you can redistribute it and/or modify it |
||||
|
* under the terms and conditions of the GNU General Public License, |
||||
|
* version 2, as published by the Free Software Foundation. |
||||
|
* |
||||
|
* This program is distributed in the hope it will be useful, but WITHOUT |
||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
||||
|
* more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU General Public License |
||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <array> |
||||
|
#include <bit> |
||||
|
|
||||
|
#include "common/alignment.h" |
||||
|
#include "common/bit_util.h" |
||||
|
#include "common/common_types.h" |
||||
|
|
||||
|
namespace Common { |
||||
|
|
||||
|
namespace impl { |
||||
|
|
||||
|
template <typename Storage, size_t N> |
||||
|
class BitSet { |
||||
|
|
||||
|
public: |
||||
|
constexpr BitSet() = default; |
||||
|
|
||||
|
constexpr void SetBit(size_t i) { |
||||
|
this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord); |
||||
|
} |
||||
|
|
||||
|
constexpr void ClearBit(size_t i) { |
||||
|
this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord); |
||||
|
} |
||||
|
|
||||
|
constexpr size_t CountLeadingZero() const { |
||||
|
for (size_t i = 0; i < NumWords; i++) { |
||||
|
if (this->words[i]) { |
||||
|
return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]); |
||||
|
} |
||||
|
} |
||||
|
return FlagsPerWord * NumWords; |
||||
|
} |
||||
|
|
||||
|
constexpr size_t GetNextSet(size_t n) const { |
||||
|
for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) { |
||||
|
Storage word = this->words[i]; |
||||
|
if (!IsAligned(n + 1, FlagsPerWord)) { |
||||
|
word &= GetBitMask(n % FlagsPerWord) - 1; |
||||
|
} |
||||
|
if (word) { |
||||
|
return FlagsPerWord * i + CountLeadingZeroImpl(word); |
||||
|
} |
||||
|
} |
||||
|
return FlagsPerWord * NumWords; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
static_assert(std::is_unsigned_v<Storage>); |
||||
|
static_assert(sizeof(Storage) <= sizeof(u64)); |
||||
|
|
||||
|
static constexpr size_t FlagsPerWord = BitSize<Storage>(); |
||||
|
static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord; |
||||
|
|
||||
|
static constexpr auto CountLeadingZeroImpl(Storage word) { |
||||
|
return std::countl_zero(static_cast<unsigned long long>(word)) - |
||||
|
(BitSize<unsigned long long>() - FlagsPerWord); |
||||
|
} |
||||
|
|
||||
|
static constexpr Storage GetBitMask(size_t bit) { |
||||
|
return Storage(1) << (FlagsPerWord - 1 - bit); |
||||
|
} |
||||
|
|
||||
|
std::array<Storage, NumWords> words{}; |
||||
|
}; |
||||
|
|
||||
|
} // namespace impl |
||||
|
|
||||
|
template <size_t N> |
||||
|
using BitSet8 = impl::BitSet<u8, N>; |
||||
|
|
||||
|
template <size_t N> |
||||
|
using BitSet16 = impl::BitSet<u16, N>; |
||||
|
|
||||
|
template <size_t N> |
||||
|
using BitSet32 = impl::BitSet<u32, N>; |
||||
|
|
||||
|
template <size_t N> |
||||
|
using BitSet64 = impl::BitSet<u64, N>; |
||||
|
|
||||
|
} // namespace Common |
||||
@ -0,0 +1,26 @@ |
|||||
|
// Copyright 2020 yuzu emulator team |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <cstddef> |
||||
|
#include <type_traits> |
||||
|
|
||||
|
namespace Common { |
||||
|
|
||||
|
/// Ceiled integer division. |
||||
|
template <typename N, typename D> |
||||
|
requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeil(N number, |
||||
|
D divisor) { |
||||
|
return static_cast<N>((static_cast<D>(number) + divisor - 1) / divisor); |
||||
|
} |
||||
|
|
||||
|
/// Ceiled integer division with logarithmic divisor in base 2 |
||||
|
template <typename N, typename D> |
||||
|
requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeilLog2( |
||||
|
N value, D alignment_log2) { |
||||
|
return static_cast<N>((static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2); |
||||
|
} |
||||
|
|
||||
|
} // namespace Common |
||||
@ -1,11 +0,0 @@ |
|||||
// Copyright 2018 Citra Emulator Project
|
|
||||
// Licensed under GPLv2 or any later version
|
|
||||
// Refer to the license.txt file included.
|
|
||||
|
|
||||
#include "common/memory_hook.h"
|
|
||||
|
|
||||
namespace Common { |
|
||||
|
|
||||
MemoryHook::~MemoryHook() = default; |
|
||||
|
|
||||
} // namespace Common
|
|
||||
@ -1,47 +0,0 @@ |
|||||
// Copyright 2016 Citra Emulator Project |
|
||||
// Licensed under GPLv2 or any later version |
|
||||
// Refer to the license.txt file included. |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <memory> |
|
||||
#include <optional> |
|
||||
|
|
||||
#include "common/common_types.h" |
|
||||
|
|
||||
namespace Common { |
|
||||
|
|
||||
/** |
|
||||
* Memory hooks have two purposes: |
|
||||
* 1. To allow reads and writes to a region of memory to be intercepted. This is used to implement |
|
||||
* texture forwarding and memory breakpoints for debugging. |
|
||||
* 2. To allow for the implementation of MMIO devices. |
|
||||
* |
|
||||
* A hook may be mapped to multiple regions of memory. |
|
||||
* |
|
||||
* If a std::nullopt or false is returned from a function, the read/write request is passed through |
|
||||
* to the underlying memory region. |
|
||||
*/ |
|
||||
class MemoryHook { |
|
||||
public: |
|
||||
virtual ~MemoryHook(); |
|
||||
|
|
||||
virtual std::optional<bool> IsValidAddress(VAddr addr) = 0; |
|
||||
|
|
||||
virtual std::optional<u8> Read8(VAddr addr) = 0; |
|
||||
virtual std::optional<u16> Read16(VAddr addr) = 0; |
|
||||
virtual std::optional<u32> Read32(VAddr addr) = 0; |
|
||||
virtual std::optional<u64> Read64(VAddr addr) = 0; |
|
||||
|
|
||||
virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) = 0; |
|
||||
|
|
||||
virtual bool Write8(VAddr addr, u8 data) = 0; |
|
||||
virtual bool Write16(VAddr addr, u16 data) = 0; |
|
||||
virtual bool Write32(VAddr addr, u32 data) = 0; |
|
||||
virtual bool Write64(VAddr addr, u64 data) = 0; |
|
||||
|
|
||||
virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size) = 0; |
|
||||
}; |
|
||||
|
|
||||
using MemoryHookPointer = std::shared_ptr<MemoryHook>; |
|
||||
} // namespace Common |
|
||||
@ -1,345 +0,0 @@ |
|||||
// Copyright 2019 TuxSH |
|
||||
// Licensed under GPLv2 or any later version |
|
||||
// Refer to the license.txt file included. |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <array> |
|
||||
#include <iterator> |
|
||||
#include <list> |
|
||||
#include <utility> |
|
||||
|
|
||||
#include "common/bit_util.h" |
|
||||
#include "common/common_types.h" |
|
||||
|
|
||||
namespace Common { |
|
||||
|
|
||||
/** |
|
||||
* A MultiLevelQueue is a type of priority queue which has the following characteristics: |
|
||||
* - iteratable through each of its elements. |
|
||||
* - back can be obtained. |
|
||||
* - O(1) add, lookup (both front and back) |
|
||||
* - discrete priorities and a max of 64 priorities (limited domain) |
|
||||
* This type of priority queue is normaly used for managing threads within an scheduler |
|
||||
*/ |
|
||||
template <typename T, std::size_t Depth> |
|
||||
class MultiLevelQueue { |
|
||||
public: |
|
||||
using value_type = T; |
|
||||
using reference = value_type&; |
|
||||
using const_reference = const value_type&; |
|
||||
using pointer = value_type*; |
|
||||
using const_pointer = const value_type*; |
|
||||
|
|
||||
using difference_type = typename std::pointer_traits<pointer>::difference_type; |
|
||||
using size_type = std::size_t; |
|
||||
|
|
||||
template <bool is_constant> |
|
||||
class iterator_impl { |
|
||||
public: |
|
||||
using iterator_category = std::bidirectional_iterator_tag; |
|
||||
using value_type = T; |
|
||||
using pointer = std::conditional_t<is_constant, T*, const T*>; |
|
||||
using reference = std::conditional_t<is_constant, const T&, T&>; |
|
||||
using difference_type = typename std::pointer_traits<pointer>::difference_type; |
|
||||
|
|
||||
friend bool operator==(const iterator_impl& lhs, const iterator_impl& rhs) { |
|
||||
if (lhs.IsEnd() && rhs.IsEnd()) |
|
||||
return true; |
|
||||
return std::tie(lhs.current_priority, lhs.it) == std::tie(rhs.current_priority, rhs.it); |
|
||||
} |
|
||||
|
|
||||
friend bool operator!=(const iterator_impl& lhs, const iterator_impl& rhs) { |
|
||||
return !operator==(lhs, rhs); |
|
||||
} |
|
||||
|
|
||||
reference operator*() const { |
|
||||
return *it; |
|
||||
} |
|
||||
|
|
||||
pointer operator->() const { |
|
||||
return it.operator->(); |
|
||||
} |
|
||||
|
|
||||
iterator_impl& operator++() { |
|
||||
if (IsEnd()) { |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
++it; |
|
||||
|
|
||||
if (it == GetEndItForPrio()) { |
|
||||
u64 prios = mlq.used_priorities; |
|
||||
prios &= ~((1ULL << (current_priority + 1)) - 1); |
|
||||
if (prios == 0) { |
|
||||
current_priority = static_cast<u32>(mlq.depth()); |
|
||||
} else { |
|
||||
current_priority = CountTrailingZeroes64(prios); |
|
||||
it = GetBeginItForPrio(); |
|
||||
} |
|
||||
} |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
iterator_impl& operator--() { |
|
||||
if (IsEnd()) { |
|
||||
if (mlq.used_priorities != 0) { |
|
||||
current_priority = 63 - CountLeadingZeroes64(mlq.used_priorities); |
|
||||
it = GetEndItForPrio(); |
|
||||
--it; |
|
||||
} |
|
||||
} else if (it == GetBeginItForPrio()) { |
|
||||
u64 prios = mlq.used_priorities; |
|
||||
prios &= (1ULL << current_priority) - 1; |
|
||||
if (prios != 0) { |
|
||||
current_priority = CountTrailingZeroes64(prios); |
|
||||
it = GetEndItForPrio(); |
|
||||
--it; |
|
||||
} |
|
||||
} else { |
|
||||
--it; |
|
||||
} |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
iterator_impl operator++(int) { |
|
||||
const iterator_impl v{*this}; |
|
||||
++(*this); |
|
||||
return v; |
|
||||
} |
|
||||
|
|
||||
iterator_impl operator--(int) { |
|
||||
const iterator_impl v{*this}; |
|
||||
--(*this); |
|
||||
return v; |
|
||||
} |
|
||||
|
|
||||
// allow implicit const->non-const |
|
||||
iterator_impl(const iterator_impl<false>& other) |
|
||||
: mlq(other.mlq), it(other.it), current_priority(other.current_priority) {} |
|
||||
|
|
||||
iterator_impl(const iterator_impl<true>& other) |
|
||||
: mlq(other.mlq), it(other.it), current_priority(other.current_priority) {} |
|
||||
|
|
||||
iterator_impl& operator=(const iterator_impl<false>& other) { |
|
||||
mlq = other.mlq; |
|
||||
it = other.it; |
|
||||
current_priority = other.current_priority; |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
friend class iterator_impl<true>; |
|
||||
iterator_impl() = default; |
|
||||
|
|
||||
private: |
|
||||
friend class MultiLevelQueue; |
|
||||
using container_ref = |
|
||||
std::conditional_t<is_constant, const MultiLevelQueue&, MultiLevelQueue&>; |
|
||||
using list_iterator = std::conditional_t<is_constant, typename std::list<T>::const_iterator, |
|
||||
typename std::list<T>::iterator>; |
|
||||
|
|
||||
explicit iterator_impl(container_ref mlq, list_iterator it, u32 current_priority) |
|
||||
: mlq(mlq), it(it), current_priority(current_priority) {} |
|
||||
explicit iterator_impl(container_ref mlq, u32 current_priority) |
|
||||
: mlq(mlq), it(), current_priority(current_priority) {} |
|
||||
|
|
||||
bool IsEnd() const { |
|
||||
return current_priority == mlq.depth(); |
|
||||
} |
|
||||
|
|
||||
list_iterator GetBeginItForPrio() const { |
|
||||
return mlq.levels[current_priority].begin(); |
|
||||
} |
|
||||
|
|
||||
list_iterator GetEndItForPrio() const { |
|
||||
return mlq.levels[current_priority].end(); |
|
||||
} |
|
||||
|
|
||||
container_ref mlq; |
|
||||
list_iterator it; |
|
||||
u32 current_priority; |
|
||||
}; |
|
||||
|
|
||||
using iterator = iterator_impl<false>; |
|
||||
using const_iterator = iterator_impl<true>; |
|
||||
|
|
||||
void add(const T& element, u32 priority, bool send_back = true) { |
|
||||
if (send_back) |
|
||||
levels[priority].push_back(element); |
|
||||
else |
|
||||
levels[priority].push_front(element); |
|
||||
used_priorities |= 1ULL << priority; |
|
||||
} |
|
||||
|
|
||||
void remove(const T& element, u32 priority) { |
|
||||
auto it = ListIterateTo(levels[priority], element); |
|
||||
if (it == levels[priority].end()) |
|
||||
return; |
|
||||
levels[priority].erase(it); |
|
||||
if (levels[priority].empty()) { |
|
||||
used_priorities &= ~(1ULL << priority); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void adjust(const T& element, u32 old_priority, u32 new_priority, bool adjust_front = false) { |
|
||||
remove(element, old_priority); |
|
||||
add(element, new_priority, !adjust_front); |
|
||||
} |
|
||||
void adjust(const_iterator it, u32 old_priority, u32 new_priority, bool adjust_front = false) { |
|
||||
adjust(*it, old_priority, new_priority, adjust_front); |
|
||||
} |
|
||||
|
|
||||
void transfer_to_front(const T& element, u32 priority, MultiLevelQueue& other) { |
|
||||
ListSplice(other.levels[priority], other.levels[priority].begin(), levels[priority], |
|
||||
ListIterateTo(levels[priority], element)); |
|
||||
|
|
||||
other.used_priorities |= 1ULL << priority; |
|
||||
|
|
||||
if (levels[priority].empty()) { |
|
||||
used_priorities &= ~(1ULL << priority); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void transfer_to_front(const_iterator it, u32 priority, MultiLevelQueue& other) { |
|
||||
transfer_to_front(*it, priority, other); |
|
||||
} |
|
||||
|
|
||||
void transfer_to_back(const T& element, u32 priority, MultiLevelQueue& other) { |
|
||||
ListSplice(other.levels[priority], other.levels[priority].end(), levels[priority], |
|
||||
ListIterateTo(levels[priority], element)); |
|
||||
|
|
||||
other.used_priorities |= 1ULL << priority; |
|
||||
|
|
||||
if (levels[priority].empty()) { |
|
||||
used_priorities &= ~(1ULL << priority); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void transfer_to_back(const_iterator it, u32 priority, MultiLevelQueue& other) { |
|
||||
transfer_to_back(*it, priority, other); |
|
||||
} |
|
||||
|
|
||||
void yield(u32 priority, std::size_t n = 1) { |
|
||||
ListShiftForward(levels[priority], n); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] std::size_t depth() const { |
|
||||
return Depth; |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] std::size_t size(u32 priority) const { |
|
||||
return levels[priority].size(); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] std::size_t size() const { |
|
||||
u64 priorities = used_priorities; |
|
||||
std::size_t size = 0; |
|
||||
while (priorities != 0) { |
|
||||
const u64 current_priority = CountTrailingZeroes64(priorities); |
|
||||
size += levels[current_priority].size(); |
|
||||
priorities &= ~(1ULL << current_priority); |
|
||||
} |
|
||||
return size; |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] bool empty() const { |
|
||||
return used_priorities == 0; |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] bool empty(u32 priority) const { |
|
||||
return (used_priorities & (1ULL << priority)) == 0; |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] u32 highest_priority_set(u32 max_priority = 0) const { |
|
||||
const u64 priorities = |
|
||||
max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1)); |
|
||||
return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities)); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] u32 lowest_priority_set(u32 min_priority = Depth - 1) const { |
|
||||
const u64 priorities = min_priority >= Depth - 1 |
|
||||
? used_priorities |
|
||||
: (used_priorities & ((1ULL << (min_priority + 1)) - 1)); |
|
||||
return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] const_iterator cbegin(u32 max_prio = 0) const { |
|
||||
const u32 priority = highest_priority_set(max_prio); |
|
||||
return priority == Depth ? cend() |
|
||||
: const_iterator{*this, levels[priority].cbegin(), priority}; |
|
||||
} |
|
||||
[[nodiscard]] const_iterator begin(u32 max_prio = 0) const { |
|
||||
return cbegin(max_prio); |
|
||||
} |
|
||||
[[nodiscard]] iterator begin(u32 max_prio = 0) { |
|
||||
const u32 priority = highest_priority_set(max_prio); |
|
||||
return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority}; |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] const_iterator cend(u32 min_prio = Depth - 1) const { |
|
||||
return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1); |
|
||||
} |
|
||||
[[nodiscard]] const_iterator end(u32 min_prio = Depth - 1) const { |
|
||||
return cend(min_prio); |
|
||||
} |
|
||||
[[nodiscard]] iterator end(u32 min_prio = Depth - 1) { |
|
||||
return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] T& front(u32 max_priority = 0) { |
|
||||
const u32 priority = highest_priority_set(max_priority); |
|
||||
return levels[priority == Depth ? 0 : priority].front(); |
|
||||
} |
|
||||
[[nodiscard]] const T& front(u32 max_priority = 0) const { |
|
||||
const u32 priority = highest_priority_set(max_priority); |
|
||||
return levels[priority == Depth ? 0 : priority].front(); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] T& back(u32 min_priority = Depth - 1) { |
|
||||
const u32 priority = lowest_priority_set(min_priority); // intended |
|
||||
return levels[priority == Depth ? 63 : priority].back(); |
|
||||
} |
|
||||
[[nodiscard]] const T& back(u32 min_priority = Depth - 1) const { |
|
||||
const u32 priority = lowest_priority_set(min_priority); // intended |
|
||||
return levels[priority == Depth ? 63 : priority].back(); |
|
||||
} |
|
||||
|
|
||||
void clear() { |
|
||||
used_priorities = 0; |
|
||||
for (std::size_t i = 0; i < Depth; i++) { |
|
||||
levels[i].clear(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
using const_list_iterator = typename std::list<T>::const_iterator; |
|
||||
|
|
||||
static void ListShiftForward(std::list<T>& list, const std::size_t shift = 1) { |
|
||||
if (shift >= list.size()) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
const auto begin_range = list.begin(); |
|
||||
const auto end_range = std::next(begin_range, shift); |
|
||||
list.splice(list.end(), list, begin_range, end_range); |
|
||||
} |
|
||||
|
|
||||
static void ListSplice(std::list<T>& in_list, const_list_iterator position, |
|
||||
std::list<T>& out_list, const_list_iterator element) { |
|
||||
in_list.splice(position, out_list, element); |
|
||||
} |
|
||||
|
|
||||
[[nodiscard]] static const_list_iterator ListIterateTo(const std::list<T>& list, |
|
||||
const T& element) { |
|
||||
auto it = list.cbegin(); |
|
||||
while (it != list.cend() && *it != element) { |
|
||||
++it; |
|
||||
} |
|
||||
return it; |
|
||||
} |
|
||||
|
|
||||
std::array<std::list<T>, Depth> levels; |
|
||||
u64 used_priorities = 0; |
|
||||
}; |
|
||||
|
|
||||
} // namespace Common |
|
||||
@ -0,0 +1,47 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <stdexcept>
|
||||
|
#include "common/common_types.h"
|
||||
|
#include "common/stream.h"
|
||||
|
|
||||
|
namespace Common { |
||||
|
|
||||
|
Stream::Stream() = default; |
||||
|
Stream::~Stream() = default; |
||||
|
|
||||
|
void Stream::Seek(s32 offset, SeekOrigin origin) { |
||||
|
if (origin == SeekOrigin::SetOrigin) { |
||||
|
if (offset < 0) { |
||||
|
position = 0; |
||||
|
} else if (position >= buffer.size()) { |
||||
|
position = buffer.size(); |
||||
|
} else { |
||||
|
position = offset; |
||||
|
} |
||||
|
} else if (origin == SeekOrigin::FromCurrentPos) { |
||||
|
Seek(static_cast<s32>(position) + offset, SeekOrigin::SetOrigin); |
||||
|
} else if (origin == SeekOrigin::FromEnd) { |
||||
|
Seek(static_cast<s32>(buffer.size()) - offset, SeekOrigin::SetOrigin); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
u8 Stream::ReadByte() { |
||||
|
if (position < buffer.size()) { |
||||
|
return buffer[position++]; |
||||
|
} else { |
||||
|
throw std::out_of_range("Attempting to read a byte not within the buffer range"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Stream::WriteByte(u8 byte) { |
||||
|
if (position == buffer.size()) { |
||||
|
buffer.push_back(byte); |
||||
|
position++; |
||||
|
} else { |
||||
|
buffer.insert(buffer.begin() + position, byte); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // namespace Common
|
||||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue