diff --git a/.gitattributes b/.gitattributes
index 3a4c44aedc..baf02f46e3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -30,6 +30,7 @@ indra/tools/vstool/* -text
# Files with Windows line endings
VivoxAUP.txt text eol=crlf
FILES_ARE_UNICODE_UTF-16LE.txt text eol=crlf
+*.nsi text eol=crlf
# Windows Manifest files
*.manifest text eol=crlf
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 0000000000..a110c018ec
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,93 @@
+name: Build
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches: [main, contribute]
+ tags: ["*"]
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ runner: [windows-large]
+ configuration: [ReleaseOS]
+ addrsize: [64]
+ include:
+ - runner: windows-large
+ configuration: ReleaseOS
+ addrsize: 32
+ runs-on: ${{ matrix.runner }}
+ env:
+ AUTOBUILD_CONFIGURATION: ${{ matrix.configuration }}
+ AUTOBUILD_ADDRSIZE: ${{ matrix.addrsize }}
+ AUTOBUILD_INSTALLABLE_CACHE: ${{ github.workspace }}/.autobuild-installables
+ AUTOBUILD_VARIABLES_FILE: ${{ github.workspace }}/.build-variables/variables
+ AUTOBUILD_VSVER: "170" # vs2k22
+ LOGFAIL: debug # Show details when tests fail
+ GIT_REF: ${{ github.head_ref || github.ref }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+ with:
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
+
+ - name: Checkout build variables
+ uses: actions/checkout@v3
+ with:
+ repository: secondlife/build-variables
+ ref: viewer
+ path: .build-variables
+
+ - name: Install autobuild and python dependencies
+ run: pip3 install autobuild llbase
+
+ - name: Cache autobuild packages
+ uses: actions/cache@v3
+ id: cache-installables
+ with:
+ path: .autobuild-installables
+ key: ${{ runner.os }}-${{ matrix.addrsize }}-${{ matrix.configuration }}-${{ hashFiles('autobuild.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-${{ matrix.addrsize }}-${{ matrix.configuration }}-
+ ${{ runner.os }}-${{ matrix.addrsize }}-
+
+ - name: Install windows dependencies
+ if: runner.os == 'Windows'
+ run: choco install nsis-unicode
+
+ - name: Build
+ id: build
+ shell: bash
+ env:
+ RUNNER_OS: ${{ runner.os }}
+ run: |
+ # On windows we need to point the build to the correct python
+ # as neither CMake's FindPython nor our custom Python.cmake module
+ # will resolve the correct interpreter location.
+ if [[ "$RUNNER_OS" == "Windows" ]]; then
+ export PYTHON="$(cygpath -m "$(which python)")"
+ echo "Python location: $PYTHON"
+ fi
+
+ autobuild configure -- -DVIEWER_CHANNEL="Second Life Test ${GIT_REF##*/}"
+ autobuild build --no-configure
+
+ # Find artifacts
+ if [[ "$RUNNER_OS" == "Windows" ]]; then
+ installer_path=$(find ./build-*/newview/ | grep '_Setup\.exe')
+ installer_name="$(basename $installer_path)"
+ elif [[ "$RUNNER_OS" == "macOS" ]]; then
+ installer_path=$(find ./build-*/newview/ | grep '\.dmg')
+ installer_name="$(basename $installer_path)"
+ fi
+
+ echo "installer_path=$installer_path" >> $GITHUB_OUTPUT
+ echo "installer_name=$installer_name" >> $GITHUB_OUTPUT
+
+ - name: Upload installer
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ steps.build.outputs.installer_name }}
+ path: ${{ steps.build.outputs.installer_path }}
diff --git a/.github/workflows/build_viewer.yml b/.github/workflows/build_viewer.yml
index 8adc9171c1..d85167e867 100644
--- a/.github/workflows/build_viewer.yml
+++ b/.github/workflows/build_viewer.yml
@@ -2,8 +2,9 @@ name: Build viewer
on:
push:
branches:
- - "*release"
- - master
+ - "Firestorm*.*.*"
+ tags:
+ - "preview"
schedule:
- cron: '00 03 * * *' # Run every day at 3am UTC
env:
@@ -74,14 +75,14 @@ jobs:
- name: find channel from Branch name
run: |
- if [[ "${{ github.ref_name }}" == *Release* ]]; then
+ if [[ "${{ github.ref_name }}" == Firestorm* ]]; then
FS_RELEASE_TYPE=Release
+ elif [[ "${{ github.ref_name }}" == *review* ]]; then
+ FS_RELEASE_TYPE=Beta
+ elif [[ "${{ github.event_name }}" == 'schedule' ]]; then
+ FS_RELEASE_TYPE=Nightly
else
- if [[ "${{github.event_name}}" == 'schedule' ]]; then
- FS_RELEASE_TYPE=Nightly
- else
- FS_RELEASE_TYPE=Beta
- fi
+ FS_RELEASE_TYPE=Unknown
fi
if [[ "${{ matrix.addrsize }}" == "64" ]]; then
FS_RELEASE_CHAN="${FS_RELEASE_TYPE}x64"
@@ -118,7 +119,11 @@ jobs:
shell: bash
- name: rclone the private 3p packages for this platform (both 64 & 32)
- run: 'rclone copy fs_bundles: --include "*${{ env.fallback_platform }}*bz2" .'
+ run: 'rclone copy fs_bundles: --filter "- Alpha/*" --filter "+ *${{ env.fallback_platform }}*bz2" .'
+
+ - name: rclone any extra private 3p packages for Alpha (allows library updates not in the main repo)
+ if: env.FS_BUILD_TYPE == 'Alpha'
+ run: 'rclone copy fs_bundles:Alpha --include "*${{ env.fallback_platform }}*bz2" .'
- name: set VSVER for Windows builds
if: runner.os == 'Windows'
@@ -255,17 +260,17 @@ jobs:
- name: find channel and webhook from Branch name
run: |
- if [[ "${{ github.ref_name }}" == *Release* ]]; then
+ if [[ "${{ github.ref_name }}" == Firestorm* ]]; then
FS_RELEASE_FOLDER=release
FS_BUILD_WEBHOOK_URL=${{ secrets.RELEASE_WEBHOOK_URL }}
- else
- if [[ "${{github.event_name}}" == 'schedule' ]]; then
- FS_RELEASE_FOLDER=nightly
- FS_BUILD_WEBHOOK_URL=${{ secrets.NIGHTLY_WEBHOOK_URL }}
- else
+ elif [[ "${{ github.ref_name }}" == *review* ]]; then
FS_RELEASE_FOLDER=preview
FS_BUILD_WEBHOOK_URL=${{ secrets.BETA_WEBHOOK_URL }}
- fi
+ elif [[ "${{ github.event_name }}" == 'schedule' ]]; then
+ FS_RELEASE_FOLDER=nightly
+ FS_BUILD_WEBHOOK_URL=${{ secrets.NIGHTLY_WEBHOOK_URL }}
+ else
+ FS_RELEASE_TYPE=Unknown
fi
echo "FS_RELEASE_FOLDER=${FS_RELEASE_FOLDER}" >> $GITHUB_ENV
echo "FS_BUILD_WEBHOOK_URL=${FS_BUILD_WEBHOOK_URL}" >> $GITHUB_ENV
diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml
new file mode 100644
index 0000000000..17c0ace02f
--- /dev/null
+++ b/.github/workflows/pre-commit.yaml
@@ -0,0 +1,18 @@
+name: pre-commit
+
+on:
+ pull_request:
+ push:
+ branches: [main, contribute]
+ tags: [v*]
+
+
+jobs:
+ pre-commit:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ with:
+ python-version: 3.x
+ - uses: pre-commit/action@v3.0.0
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
index 82a9a968b9..35ac41420c 100644
--- a/.github/workflows/stale.yaml
+++ b/.github/workflows/stale.yaml
@@ -15,8 +15,8 @@ jobs:
- uses: actions/stale@v6
id: stale
with:
- stale-pr-message: This pull request is stale because it has been open 60 days with no activity. Remove stale label or comment or it will be closed in 7 days
- days-before-stale: 60
+ stale-pr-message: This pull request is stale because it has been open 30 days with no activity. Remove stale label or comment or it will be closed in 7 days
+ days-before-stale: 30
days-before-close: 7
exempt-pr-labels: blocked,must,should,keep
stale-pr-label: stale
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 6d296d7a24..fe7dfbac7a 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,9 +1,8 @@
repos:
- - repo: https://bitbucket.org/lindenlab/git-hooks.git
- rev: v1.0.0-beta2
+ - repo: https://github.com/secondlife/git-hooks.git
+ rev: v1.0.0
hooks:
- id: opensource-license
- - id: jira-issue
- id: llsd
- id: no-trigraphs
- id: copyright
@@ -11,7 +10,7 @@ repos:
files: \.(cpp|c|h|py|glsl|cmake|txt)$
exclude: language.txt
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v2.5.0
+ rev: v4.4.0
hooks:
- id: check-xml
- id: mixed-line-ending
diff --git a/autobuild.xml b/autobuild.xml
index bcb8f8f17e..f7a237b31b 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -3430,9 +3430,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
darwin64
@@ -3442,24 +3444,28 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
name
linux64
- windows
+ windows64
source
@@ -3467,7 +3473,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
source_type
hg
version
- 3.0.577252
+ 3.0-bd3aec2
vlc-bin
@@ -4404,7 +4410,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
/t:Build
/p:useenv=true
/verbosity:minimal
- /toolsversion:4.0
/p:VCBuildAdditionalOptions= /incremental
@@ -4478,7 +4483,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
/t:Build
/p:useenv=true
/verbosity:minimal
- /toolsversion:4.0
/p:VCBuildAdditionalOptions= /incremental
diff --git a/doc/contributions.txt b/doc/contributions.txt
index e304bb6cef..a419cda3e0 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -600,6 +600,7 @@ Henri Beauchamp
VWR-4157
SL-15175
SL-19110
+ SL-19159
herina Bode
Hikkoshi Sakai
VWR-429
@@ -940,6 +941,8 @@ Lexi Frua
Lillie Cordeaux
Lilly Zenovka
Lizzy Macarthur
+Logue Takacs
+ INTL-490
Luban Yiyuan
Luc Starsider
Luminous Luminos
@@ -1196,6 +1199,7 @@ PanteraPolnocy
SL-18891
SL-18904
SL-18937
+ SL-19207
SL-19681
Parvati Silverweb
Patric Mills
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index ad3aca25fc..f32c941b18 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -77,11 +77,9 @@ if (WINDOWS)
# CP changed to only append the flag for 32bit builds - on 64bit builds,
# locally at least, the build output is spammed with 1000s of 'D9002'
# warnings about this switch being ignored.
- # Remove this, it's no option to cl.exe and causes a massive amount of warnings.
- #if( ADDRESS_SIZE EQUAL 32 )
- #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
- #endif()
-
+ if(ADDRESS_SIZE EQUAL 32 AND DEFINED ENV{"TEAMCITY_PROJECT_NAME"})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
+ endif()
# zlib has assembly-language object files incompatible with SAFESEH
add_link_options(/LARGEADDRESSAWARE
/SAFESEH:NO
@@ -216,6 +214,10 @@ if (DARWIN)
set(ENABLE_SIGNING TRUE)
set(SIGNING_IDENTITY "Developer ID Application: The Phoenix Firestorm Project, Inc." )
+
+ # required for clang-15/xcode-15 since our boost package still uses deprecated std::unary_function/binary_function
+ # see https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#C++-Standard-Library
+ add_compile_definitions(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION)
endif (DARWIN)
if (LINUX OR DARWIN)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 8431c04066..1f954c8f65 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -2,7 +2,11 @@
set(PYTHONINTERP_FOUND)
-if (WINDOWS)
+if (DEFINED ENV{PYTHON})
+ # Allow python executable to be explicitly set
+ set(python "$ENV{PYTHON}")
+ set(PYTHONINTERP_FOUND ON)
+elseif (WINDOWS)
# On Windows, explicitly avoid Cygwin Python.
if (DEFINED ENV{VIRTUAL_ENV})
@@ -53,7 +57,7 @@ else()
if (python)
set(PYTHONINTERP_FOUND ON)
endif (python)
-endif (WINDOWS)
+endif (DEFINED ENV{PYTHON})
if (NOT python)
message(FATAL_ERROR "No Python interpreter found")
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
index a63b38361b..e2b8a7068c 100644
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -32,7 +32,7 @@
#include "llsaleinfo.h"
#include "llwearabletype.h"
-class LLMD5;
+class LLMD5; // [Legacy Bake]
class LLVisualParam;
class LLTexGlobalColorInfo;
class LLTexGlobalColor;
@@ -131,6 +131,7 @@ public:
// Something happened that requires the wearable to be updated (e.g. worn/unworn).
virtual void setUpdated() const = 0;
+ // [Legacy Bake]
// Update the baked texture hash.
virtual void addToBakedTextureHash(LLMD5& hash) const = 0;
diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
index 5d23d3a876..bc3d83ee1e 100644
--- a/indra/llappearance/llwearabledata.cpp
+++ b/indra/llappearance/llwearabledata.cpp
@@ -31,7 +31,7 @@
#include "llavatarappearance.h"
#include "llavatarappearancedefines.h"
#include "lldriverparam.h"
-#include "llmd5.h"
+#include "llmd5.h" // [Legacy Bake]
LLWearableData::LLWearableData() :
mAvatarAppearance(NULL)
@@ -355,6 +355,7 @@ U32 LLWearableData::getWearableCount(const U32 tex_index) const
return getWearableCount(wearable_type);
}
+// [Legacy Bake]
LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index,
BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache
{
@@ -391,5 +392,6 @@ LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBaked
return hash_id;
}
+// [Legacy Bake]
diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h
index cb274ca524..8ecf29a7a0 100644
--- a/indra/llappearance/llwearabledata.h
+++ b/indra/llappearance/llwearabledata.h
@@ -85,6 +85,7 @@ protected:
private:
void pullCrossWearableValues(const LLWearableType::EType type);
+// [Legacy Bake]
//--------------------------------------------------------------------
// Server Communication
//--------------------------------------------------------------------
@@ -93,6 +94,7 @@ public:
BOOL generate_valid_hash = TRUE);
protected:
virtual void invalidateBakedTextureHash(LLMD5& hash) const {}
+// [Legacy Bake]
//--------------------------------------------------------------------
// Member variables
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
index 8f61654de6..2c4a57675e 100644
--- a/indra/llaudio/llaudioengine.cpp
+++ b/indra/llaudio/llaudioengine.cpp
@@ -217,7 +217,8 @@ std::string LLAudioEngine::getInternetStreamURL()
{
if (mStreamingAudioImpl)
return mStreamingAudioImpl->getURL();
- else return std::string();
+
+ return std::string();
}
@@ -358,42 +359,43 @@ void LLAudioEngine::idle()
}
continue;
}
- else
+
+ // Check to see if the current sound is done playing.
+ if (!channelp->isPlaying())
{
- // Check to see if the current sound is done playing, or looped.
- if (!channelp->isPlaying())
+ sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+ sourcep->mQueuedDatap = NULL;
+
+ // Reset the timer so the source doesn't die.
+ sourcep->mAgeTimer.reset();
+
+ // Make sure we have the buffer set up if we just decoded the data
+ if (sourcep->mCurrentDatap)
+ {
+ updateBufferForData(sourcep->mCurrentDatap);
+ }
+
+ // Actually play the associated data.
+ sourcep->setupChannel();
+ channelp->updateBuffer();
+ sourcep->getChannel()->play();
+ continue;
+ }
+
+ // Check to see if the current sound is looped.
+ if (sourcep->isLoop())
+ {
+ // It's a loop, we need to check and see if we're done with it.
+ if (channelp->mLoopedThisFrame)
{
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
sourcep->mQueuedDatap = NULL;
- // Reset the timer so the source doesn't die.
- sourcep->mAgeTimer.reset();
-
- // Make sure we have the buffer set up if we just decoded the data
- if (sourcep->mCurrentDatap)
- {
- updateBufferForData(sourcep->mCurrentDatap);
- }
-
- // Actually play the associated data.
+ // Actually, should do a time sync so if we're a loop master/slave
+ // we don't drift away.
sourcep->setupChannel();
- channelp->updateBuffer();
sourcep->getChannel()->play();
}
- else if (sourcep->isLoop())
- {
- // It's a loop, we need to check and see if we're done with it.
- if (channelp->mLoopedThisFrame)
- {
- sourcep->mCurrentDatap = sourcep->mQueuedDatap;
- sourcep->mQueuedDatap = NULL;
-
- // Actually, should do a time sync so if we're a loop master/slave
- // we don't drift away.
- sourcep->setupChannel();
- sourcep->getChannel()->play();
- }
- }
}
}
@@ -409,18 +411,11 @@ void LLAudioEngine::idle()
for (source_map::value_type& src_pair : mAllSources)
{
LLAudioSource *sourcep = src_pair.second;
- if (sourcep->isMuted())
+ if (sourcep->isMuted() && sourcep->isSyncMaster() && sourcep->getPriority() > max_sm_priority)
{
- continue;
- }
- if (sourcep->isSyncMaster())
- {
- if (sourcep->getPriority() > max_sm_priority)
- {
- sync_masterp = sourcep;
- master_channelp = sync_masterp->getChannel();
- max_sm_priority = sourcep->getPriority();
- }
+ sync_masterp = sourcep;
+ master_channelp = sync_masterp->getChannel();
+ max_sm_priority = sourcep->getPriority();
}
}
@@ -755,7 +750,7 @@ F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
}
return (gain);
-}
+}
F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
@@ -996,11 +991,10 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
else
{
LL_DEBUGS("AudioEngine") << "Cleaning up audio sources for "<< asp->getID() <getID() << ")" << LL_ENDL;
- if (sourcep == mCurrentSourcep)
- {
- // Don't reallocate the channel, this will make FMOD goofy.
- //LL_INFOS() << "Calling setSource with same source!" << LL_ENDL;
+ if (sourcep == mCurrentSourcep)
+ {
+ // Don't reallocate the channel, this will make FMOD goofy.
+ //LL_INFOS() << "Calling setSource with same source!" << LL_ENDL;
+ }
+
+ mCurrentSourcep = sourcep;
+
+ updateBuffer();
+ update3DPosition();
}
-
- mCurrentSourcep = sourcep;
-
- updateBuffer();
- update3DPosition();
}
-}
-
bool LLAudioChannel::updateBuffer()
{
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index 74e264377e..ba3a7f32e3 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -95,6 +95,7 @@ public:
// initialization/startup/shutdown
virtual bool init(void *userdata, const std::string &app_title);
virtual std::string getDriverName(bool verbose) = 0;
+ virtual LLStreamingAudioInterface *createDefaultStreamingAudioImpl() const = 0;
virtual void shutdown();
// Used by the mechanics of the engine
@@ -526,13 +527,13 @@ struct SoundData
const LLUUID& owner_id,
const F32 gain,
const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
- const LLVector3d &pos_global = LLVector3d::zero)
+ const LLVector3d &pos_global = LLVector3d::zero) :
+ audio_uuid(audio_uuid),
+ owner_id(owner_id),
+ gain(gain),
+ type(type),
+ pos_global(pos_global)
{
- this->audio_uuid = audio_uuid;
- this->owner_id = owner_id;
- this->gain = gain;
- this->type = type;
- this->pos_global = pos_global;
}
};
diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp
index 9b215337e9..838b91c66f 100644
--- a/indra/llaudio/llaudioengine_fmodstudio.cpp
+++ b/indra/llaudio/llaudioengine_fmodstudio.cpp
@@ -308,10 +308,6 @@ bool LLAudioEngine_FMODSTUDIO::init(void* userdata, const std::string &app_title
Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup");
}
- // set up our favourite FMOD-native streaming audio implementation if none has already been added
- if (!getStreamingAudioImpl()) // no existing implementation added
- setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem));
-
LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL;
FMOD_ADVANCEDSETTINGS settings_dump = { };
@@ -395,6 +391,13 @@ std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose)
}
+// create our favourite FMOD-native streaming audio implementation
+LLStreamingAudioInterface *LLAudioEngine_FMODSTUDIO::createDefaultStreamingAudioImpl() const
+{
+ return new LLStreamingAudio_FMODSTUDIO(mSystem);
+}
+
+
void LLAudioEngine_FMODSTUDIO::allocateListener(void)
{
try
diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h
index 0c9b4d186f..e8cc03083b 100644
--- a/indra/llaudio/llaudioengine_fmodstudio.h
+++ b/indra/llaudio/llaudioengine_fmodstudio.h
@@ -59,6 +59,7 @@ public:
// initialization/startup/shutdown
virtual bool init(void *user_data, const std::string &app_title);
virtual std::string getDriverName(bool verbose);
+ virtual LLStreamingAudioInterface* createDefaultStreamingAudioImpl() const;
virtual void allocateListener();
virtual void shutdown();
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index d09310a3c4..84df81e048 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -500,13 +500,20 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
// request asset
mAssetStatus = ASSET_FETCHED;
- LL_DEBUGS("Animation") << "Requesting data fetch for: " << mID << LL_ENDL;
- character_id = new LLUUID(mCharacter->getID());
- gAssetStorage->getAssetData(mID,
- LLAssetType::AT_ANIMATION,
- onLoadComplete,
- (void *)character_id,
- FALSE);
+ if (mID.notNull())
+ {
+ LL_DEBUGS("Animation") << "Requesting data fetch for: " << mID << LL_ENDL;
+ character_id = new LLUUID(mCharacter->getID());
+ gAssetStorage->getAssetData(mID,
+ LLAssetType::AT_ANIMATION,
+ onLoadComplete,
+ (void*)character_id,
+ FALSE);
+ }
+ else
+ {
+ LL_INFOS("Animation") << "Attempted to fetch animation " << mName << " with null id for character " << mCharacter->getID() << LL_ENDL;
+ }
return STATUS_HOLD;
case ASSET_FETCHED:
diff --git a/indra/llcommon/hbxxh.h b/indra/llcommon/hbxxh.h
index 236716722a..9c0e9cf172 100644
--- a/indra/llcommon/hbxxh.h
+++ b/indra/llcommon/hbxxh.h
@@ -96,6 +96,15 @@ public:
}
}
+ // Make this class no-copy (it would be possible, with custom copy
+ // operators, but it is not trivially copyable, because of the mState
+ // pointer): it does not really make sense to allow copying it anyway,
+ // since all we care about is the resulting digest (so you should only
+ // need and care about storing/copying the digest and not a class
+ // instance).
+ HBXXH64(const HBXXH64&) noexcept = delete;
+ HBXXH64& operator=(const HBXXH64&) noexcept = delete;
+
~HBXXH64();
void update(const void* buffer, size_t len);
@@ -199,6 +208,15 @@ public:
}
}
+ // Make this class no-copy (it would be possible, with custom copy
+ // operators, but it is not trivially copyable, because of the mState
+ // pointer): it does not really make sense to allow copying it anyway,
+ // since all we care about is the resulting digest (so you should only
+ // need and care about storing/copying the digest and not a class
+ // instance).
+ HBXXH128(const HBXXH128&) noexcept = delete;
+ HBXXH128& operator=(const HBXXH128&) noexcept = delete;
+
~HBXXH128();
void update(const void* buffer, size_t len);
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 937f1a5501..ead46bfa5f 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -349,6 +349,7 @@ const U8 CLICK_ACTION_PLAY = 5;
const U8 CLICK_ACTION_OPEN_MEDIA = 6;
const U8 CLICK_ACTION_ZOOM = 7;
const U8 CLICK_ACTION_DISABLED = 8;
+const U8 CLICK_ACTION_IGNORE = 9;
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 284bfb2afa..e3bb661c63 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -828,11 +828,11 @@ bool unix_post_minidump_callback(const char *dump_dir,
auto dirPathLength = strlen(dump_dir);
auto idLength = strlen(minidump_id);
- // The path must not be truncated.
- llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
+ // The path must not be truncated, and we need to have room left for a terminating zero.
+ llassert((dirPathLength + idLength + 5) < LLApp::MAX_MINDUMP_PATH_LENGTH); // Buffer overrun avoidance (from Aleric Inglewood)
char * path = LLApp::instance()->getMiniDumpFilename();
- auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
+ auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - 1; // Buffer overrun avoidance (from Aleric Inglewood
strncpy(path, dump_dir, remaining);
remaining -= dirPathLength;
path += dirPathLength;
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 5c46f6a796..4e25001fff 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -167,48 +167,34 @@ const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luc
//
// defined for U16, U32, U64, S16, S32, S64, :
// llclampb(a) // clamps a to [0 .. 255]
-//
+//
-template
-inline auto llmax(T1 d1, T2 d2)
+// recursion tail
+template
+inline auto llmax(T data)
{
- return (d1 > d2) ? d1 : d2;
+ return data;
}
-template
-inline auto llmax(T1 d1, T2 d2, T3 d3)
+template
+inline auto llmax(T0 d0, T1 d1, Ts... rest)
{
- auto r = llmax(d1,d2);
- return llmax(r, d3);
+ auto maxrest = llmax(d1, rest...);
+ return (d0 > maxrest)? d0 : maxrest;
}
-template
-inline auto llmax(T1 d1, T2 d2, T3 d3, T4 d4)
+// recursion tail
+template
+inline auto llmin(T data)
{
- auto r1 = llmax(d1,d2);
- auto r2 = llmax(d3,d4);
- return llmax(r1, r2);
+ return data;
}
-template
-inline auto llmin(T1 d1, T2 d2)
+template
+inline auto llmin(T0 d0, T1 d1, Ts... rest)
{
- return (d1 < d2) ? d1 : d2;
-}
-
-template
-inline auto llmin(T1 d1, T2 d2, T3 d3)
-{
- auto r = llmin(d1,d2);
- return (r < d3 ? r : d3);
-}
-
-template
-inline auto llmin(T1 d1, T2 d2, T3 d3, T4 d4)
-{
- auto r1 = llmin(d1,d2);
- auto r2 = llmin(d3,d4);
- return llmin(r1, r2);
+ auto minrest = llmin(d1, rest...);
+ return (d0 < minrest) ? d0 : minrest;
}
template
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index c87c0758fe..259f5bc505 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -204,30 +204,35 @@ public:
LLSD packet(LLSDMap("pump", pump)("data", data));
std::ostringstream buffer;
- buffer << LLSDNotationStreamer(packet);
+ // SL-18330: for large data blocks, it's much faster to parse binary
+ // LLSD than notation LLSD. Use serialize(LLSD_BINARY) rather than
+ // directly calling LLSDBinaryFormatter because, unlike the latter,
+ // serialize() prepends the relevant header, needed by a general-
+ // purpose LLSD parser to distinguish binary from notation.
+ LLSDSerialize::serialize(packet, buffer, LLSDSerialize::LLSD_BINARY,
+ LLSDFormatter::OPTIONS_NONE);
/*==========================================================================*|
// DEBUGGING ONLY: don't copy str() if we can avoid it.
std::string strdata(buffer.str());
if (std::size_t(buffer.tellp()) != strdata.length())
{
- LL_ERRS("LLLeap") << "tellp() -> " << buffer.tellp() << " != "
+ LL_ERRS("LLLeap") << "tellp() -> " << static_cast(buffer.tellp()) << " != "
<< "str().length() -> " << strdata.length() << LL_ENDL;
}
// DEBUGGING ONLY: reading back is terribly inefficient.
std::istringstream readback(strdata);
LLSD echo;
- LLPointer parser(new LLSDNotationParser());
- S32 parse_status(parser->parse(readback, echo, strdata.length()));
- if (parse_status == LLSDParser::PARSE_FAILURE)
+ bool parse_status(LLSDSerialize::deserialize(echo, readback, strdata.length()));
+ if (! parse_status)
{
- LL_ERRS("LLLeap") << "LLSDNotationParser() cannot parse output of "
- << "LLSDNotationStreamer()" << LL_ENDL;
+ LL_ERRS("LLLeap") << "LLSDSerialize::deserialize() cannot parse output of "
+ << "LLSDSerialize::serialize(LLSD_BINARY)" << LL_ENDL;
}
if (! llsd_equals(echo, packet))
{
- LL_ERRS("LLLeap") << "LLSDNotationParser() produced different LLSD "
- << "than passed to LLSDNotationStreamer()" << LL_ENDL;
+ LL_ERRS("LLLeap") << "LLSDSerialize::deserialize() returned different LLSD "
+ << "than passed to LLSDSerialize::serialize()" << LL_ENDL;
}
|*==========================================================================*/
@@ -314,9 +319,17 @@ public:
LL_DEBUGS("LLLeap") << "needed " << mExpect << " bytes, got "
<< childout.size() << ", parsing LLSD" << LL_ENDL;
LLSD data;
+#if 1
+ // specifically require notation LLSD from child
LLPointer parser(new LLSDNotationParser());
S32 parse_status(parser->parse(childout.get_istream(), data, mExpect));
if (parse_status == LLSDParser::PARSE_FAILURE)
+#else
+ // SL-18330: accept any valid LLSD serialization format from child
+ // Unfortunately this runs into trouble we have not yet debugged.
+ bool parse_status(LLSDSerialize::deserialize(data, childout.get_istream(), mExpect));
+ if (! parse_status)
+#endif
{
bad_protocol("unparseable LLSD data");
}
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index 9b2a2bab60..0abe817f1d 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -96,7 +96,7 @@ LLMD5::LLMD5()
// operation, processing another message block, and updating the
// context.
-void LLMD5::update (const uint1 *input, const size_t input_length) {
+void LLMD5::update (const uint8_t *input, const size_t input_length) {
size_t input_index, buffer_index;
size_t buffer_space; // how much space is left in buffer
@@ -189,7 +189,7 @@ void LLMD5::finalize (){
unsigned char bits[8]; /* Flawfinder: ignore */
size_t index, padLen;
- static uint1 PADDING[64]={
+ static uint8_t PADDING[64]={
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -201,8 +201,8 @@ void LLMD5::finalize (){
}
// Save number of bits.
- // Treat count, a uint64_t, as uint4[2].
- encode (bits, reinterpret_cast(&count), 8);
+ // Treat count, a uint64_t, as uint32_t[2].
+ encode (bits, reinterpret_cast(&count), 8);
// Pad out to 56 mod 64.
index = size_t((count >> 3) & 0x3f);
@@ -412,7 +412,7 @@ Rotation is separate from addition to prevent recomputation.
// LLMD5 basic transformation. Transforms state based on block.
void LLMD5::transform (const U8 block[64]){
- uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+ uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode (x, block, 64);
@@ -496,38 +496,38 @@ void LLMD5::transform (const U8 block[64]){
state[3] += d;
// Zeroize sensitive information.
- memset ( (uint1 *) x, 0, sizeof(x));
+ memset ( (uint8_t *) x, 0, sizeof(x));
}
-// Encodes input (UINT4) into output (unsigned char). Assumes len is
+// Encodes input (uint32_t) into output (unsigned char). Assumes len is
// a multiple of 4.
-void LLMD5::encode (uint1 *output, const uint4 *input, const size_t len) {
+void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) {
size_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (uint1) (input[i] & 0xff);
- output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
- output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
- output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
+ output[j] = (uint8_t) (input[i] & 0xff);
+ output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff);
+ output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff);
+ output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff);
}
}
-// Decodes input (unsigned char) into output (UINT4). Assumes len is
+// Decodes input (unsigned char) into output (uint32_t). Assumes len is
// a multiple of 4.
-void LLMD5::decode (uint4 *output, const uint1 *input, const size_t len){
+void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){
size_t i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
- (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
+ output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
+ (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
}
diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h
index 8530dc0389..7d6373c20c 100644
--- a/indra/llcommon/llmd5.h
+++ b/indra/llcommon/llmd5.h
@@ -67,6 +67,8 @@ documentation and/or software.
*/
+#include // uint32_t et al.
+
// use for the raw digest output
const int MD5RAW_BYTES = 16;
@@ -75,18 +77,13 @@ const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null
const int MD5HEX_STR_BYTES = 32; // message system fixed size
class LL_COMMON_API LLMD5 {
-// first, some types:
- typedef unsigned int uint4; // assumes integer is 4 words long
- typedef unsigned short int uint2; // assumes short integer is 2 words long
- typedef unsigned char uint1; // assumes char is 1 word long
-
// how many bytes to grab at a time when checking files
static const int BLOCK_LEN;
public:
// methods for controlled operation:
LLMD5 (); // simple initializer
- void update (const uint1 *input, const size_t input_length);
+ void update (const uint8_t *input, const size_t input_length);
void update (std::istream& stream);
void update (FILE *file);
void update (const std::string& str);
@@ -109,19 +106,19 @@ private:
// next, the private data:
- uint4 state[4];
+ uint32_t state[4];
uint64_t count; // number of *bits*, mod 2^64
- uint1 buffer[64]; // input buffer
- uint1 digest[16];
- uint1 finalized;
+ uint8_t buffer[64]; // input buffer
+ uint8_t digest[16];
+ uint8_t finalized;
// last, the private methods, mostly static:
void init (); // called by all constructors
- void transform (const uint1 *buffer); // does the real update work. Note
+ void transform (const uint8_t *buffer); // does the real update work. Note
// that length is implied to be 64.
- static void encode (uint1 *dest, const uint4 *src, const size_t length);
- static void decode (uint4 *dest, const uint1 *src, const size_t length);
+ static void encode (uint8_t *dest, const uint32_t *src, const size_t length);
+ static void decode (uint32_t *dest, const uint8_t *src, const size_t length);
};
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index bdbb9e85b1..3810aa676c 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -48,6 +48,7 @@
#endif
#include "lldate.h"
+#include "llmemorystream.h"
#include "llsd.h"
#include "llstring.h"
#include "lluri.h"
@@ -64,6 +65,23 @@ const std::string LLSD_NOTATION_HEADER("llsd/notation");
#define windowBits 15
#define ENABLE_ZLIB_GZIP 32
+// If we published this in llsdserialize.h, we could use it in the
+// implementation of LLSDOStreamer's operator<<().
+template
+void format_using(const LLSD& data, std::ostream& ostr,
+ LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY)
+{
+ LLPointer f{ new Formatter };
+ f->format(data, ostr, options);
+}
+
+template
+S32 parse_using(std::istream& istr, LLSD& data, size_t max_bytes, S32 max_depth=-1)
+{
+ LLPointer p{ new Parser };
+ return p->parse(istr, data, max_bytes, max_depth);
+}
+
/**
* LLSDSerialize
*/
@@ -86,10 +104,10 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
f = new LLSDXMLFormatter;
break;
- case LLSD_NOTATION:
- str << " " << LLSD_NOTATION_HEADER << " ?>\n";
- f = new LLSDNotationFormatter;
- break;
+ case LLSD_NOTATION:
+ str << " " << LLSD_NOTATION_HEADER << " ?>\n";
+ f = new LLSDNotationFormatter;
+ break;
default:
LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
@@ -104,18 +122,37 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
// static
bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
{
- LLPointer p = NULL;
char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
- int i;
- int inbuf = 0;
- bool legacy_no_header = false;
bool fail_if_not_legacy = false;
- std::string header;
- /*
- * Get the first line before anything.
- */
- str.get(hdr_buf, MAX_HDR_LEN, '\n');
+ /*
+ * Get the first line before anything. Don't read more than max_bytes:
+ * this get() overload reads no more than (count-1) bytes into the
+ * specified buffer. In the usual case when max_bytes exceeds
+ * sizeof(hdr_buf), get() will read no more than sizeof(hdr_buf)-2.
+ */
+ llssize max_hdr_read = MAX_HDR_LEN;
+ if (max_bytes != LLSDSerialize::SIZE_UNLIMITED)
+ {
+ max_hdr_read = llmin(max_bytes + 1, max_hdr_read);
+ }
+ str.get(hdr_buf, max_hdr_read, '\n');
+ auto inbuf = str.gcount();
+
+ // https://en.cppreference.com/w/cpp/io/basic_istream/get
+ // When the get() above sees the specified delimiter '\n', it stops there
+ // without pulling it from the stream. If it turns out that the stream
+ // does NOT contain a header, and the content includes meaningful '\n',
+ // it's important to pull that into hdr_buf too.
+ if (inbuf < max_bytes && str.get(hdr_buf[inbuf]))
+ {
+ // got the delimiting '\n'
+ ++inbuf;
+ // None of the following requires that hdr_buf contain a final '\0'
+ // byte. We could store one if needed, since even the incremented
+ // inbuf won't exceed sizeof(hdr_buf)-1, but there's no need.
+ }
+ std::string header{ hdr_buf, static_cast(inbuf) };
if (str.fail())
{
str.clear();
@@ -123,79 +160,97 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
}
if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
- {
- legacy_no_header = true;
- inbuf = (int)str.gcount();
+ { // Create a LLSD XML parser, and parse the first chunk read above.
+ LLSDXMLParser x;
+ x.parsePart(hdr_buf, inbuf); // Parse the first part that was already read
+ auto parsed = x.parse(str, sd, max_bytes - inbuf); // Parse the rest of it
+ // Formally we should probably check (parsed != PARSE_FAILURE &&
+ // parsed > 0), but since PARSE_FAILURE is -1, this suffices.
+ return (parsed > 0);
}
- else
+
+ if (fail_if_not_legacy)
{
- if (fail_if_not_legacy)
- goto fail;
- /*
- * Remove the newline chars
- */
- for (i = 0; i < MAX_HDR_LEN; i++)
- {
- if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
- hdr_buf[i] == '\n')
- {
- hdr_buf[i] = 0;
- break;
- }
- }
- header = hdr_buf;
+ LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
+ return false;
+ }
- std::string::size_type start = std::string::npos;
- std::string::size_type end = std::string::npos;
- start = header.find_first_not_of(" ");
- if (start != std::string::npos)
- {
- end = header.find_first_of(" ?", start);
- }
- if ((start == std::string::npos) || (end == std::string::npos))
- goto fail;
+ /*
+ * Remove the newline chars
+ */
+ std::string::size_type lastchar = header.find_last_not_of("\r\n");
+ if (lastchar != std::string::npos)
+ {
+ // It's important that find_last_not_of() returns size_type, which is
+ // why lastchar explicitly declares the type above. erase(size_type)
+ // erases from that offset to the end of the string, whereas
+ // erase(iterator) erases only a single character.
+ header.erase(lastchar+1);
+ }
- header = header.substr(start, end - start);
- ws(str);
+ // trim off the ... ?> header syntax
+ auto start = header.find_first_not_of(" ");
+ if (start != std::string::npos)
+ {
+ auto end = header.find_first_of(" ?", start);
+ if (end != std::string::npos)
+ {
+ header = header.substr(start, end - start);
+ ws(str);
+ }
}
/*
* Create the parser as appropriate
*/
- if (legacy_no_header)
- { // Create a LLSD XML parser, and parse the first chunk read above
- LLSDXMLParser* x = new LLSDXMLParser();
- x->parsePart(hdr_buf, inbuf); // Parse the first part that was already read
- x->parseLines(str, sd); // Parse the rest of it
- delete x;
- return true;
- }
-
- if (header == LLSD_BINARY_HEADER)
+ if (0 == LLStringUtil::compareInsensitive(header, LLSD_BINARY_HEADER))
{
- p = new LLSDBinaryParser;
+ return (parse_using(str, sd, max_bytes-inbuf) > 0);
}
- else if (header == LLSD_XML_HEADER)
+ else if (0 == LLStringUtil::compareInsensitive(header, LLSD_XML_HEADER))
{
- p = new LLSDXMLParser;
+ return (parse_using(str, sd, max_bytes-inbuf) > 0);
}
- else if (header == LLSD_NOTATION_HEADER)
+ else if (0 == LLStringUtil::compareInsensitive(header, LLSD_NOTATION_HEADER))
{
- p = new LLSDNotationParser;
+ return (parse_using(str, sd, max_bytes-inbuf) > 0);
}
- else
+ else // no header we recognize
{
- LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
+ LLPointer p;
+ if (inbuf && hdr_buf[0] == '<')
+ {
+ // looks like XML
+ LL_DEBUGS() << "deserialize request with no header, assuming XML" << LL_ENDL;
+ p = new LLSDXMLParser;
+ }
+ else
+ {
+ // assume notation
+ LL_DEBUGS() << "deserialize request with no header, assuming notation" << LL_ENDL;
+ p = new LLSDNotationParser;
+ }
+ // Since we've already read 'inbuf' bytes into 'hdr_buf', prepend that
+ // data to whatever remains in 'str'.
+ LLMemoryStreamBuf already(reinterpret_cast(hdr_buf), inbuf);
+ cat_streambuf prebuff(&already, str.rdbuf());
+ std::istream prepend(&prebuff);
+#if 1
+ return (p->parse(prepend, sd, max_bytes) > 0);
+#else
+ // debugging the reconstituted 'prepend' stream
+ // allocate a buffer that we hope is big enough for the whole thing
+ std::vector wholemsg((max_bytes == size_t(SIZE_UNLIMITED))? 1024 : max_bytes);
+ prepend.read(wholemsg.data(), std::min(max_bytes, wholemsg.size()));
+ LLMemoryStream replay(reinterpret_cast(wholemsg.data()), prepend.gcount());
+ auto success{ p->parse(replay, sd, prepend.gcount()) > 0 };
+ {
+ LL_DEBUGS() << (success? "parsed: $$" : "failed: '")
+ << std::string(wholemsg.data(), llmin(prepend.gcount(), 100)) << "$$"
+ << LL_ENDL;
+ }
+ return success;
+#endif
}
-
- if (p.notNull())
- {
- p->parse(str, sd, max_bytes);
- return true;
- }
-
-fail:
- LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
- return false;
}
/**
@@ -2195,7 +2250,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
U8* result = NULL;
llssize cur_size = 0;
z_stream strm;
-
+
constexpr U32 CHUNK = 1024 * 512;
static thread_local std::unique_ptr out;
@@ -2399,7 +2454,7 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size
return result;
}
-char* strip_deprecated_header(char* in, llssize& cur_size, U32* header_size)
+char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size)
{
const char* deprecated_header = " LLSD/Binary ?>";
constexpr size_t deprecated_header_size = 17;
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 5ddf0ff552..676b7bfd6a 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -873,5 +873,5 @@ LL_COMMON_API std::string zip_llsd(LLSD& data);
LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, size_t& outsize,std::istream& is, S32 size);
// returns a pointer to the array or past the array if the deprecated header exists
-LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, U32* header_size = nullptr);
+LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size = nullptr);
#endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp
index 1ff15fcf89..bc32b6fd9e 100644
--- a/indra/llcommon/llstreamtools.cpp
+++ b/indra/llcommon/llstreamtools.cpp
@@ -513,3 +513,29 @@ std::istream& operator>>(std::istream& str, const char *tocheck)
}
return str;
}
+
+int cat_streambuf::underflow()
+{
+ if (gptr() == egptr())
+ {
+ // here because our buffer is empty
+ std::streamsize size = 0;
+ // Until we've run out of mInputs, try reading the first of them
+ // into mBuffer. If that fetches some characters, break the loop.
+ while (! mInputs.empty()
+ && ! (size = mInputs.front()->sgetn(mBuffer.data(), mBuffer.size())))
+ {
+ // We tried to read mInputs.front() but got zero characters.
+ // Discard the first streambuf and try the next one.
+ mInputs.pop_front();
+ }
+ // Either we ran out of mInputs or we succeeded in reading some
+ // characters, that is, size != 0. Tell base class what we have.
+ setg(mBuffer.data(), mBuffer.data(), mBuffer.data() + size);
+ }
+ // If we fell out of the above loop with mBuffer still empty, return
+ // eof(), otherwise return the next character.
+ return (gptr() == egptr())
+ ? std::char_traits::eof()
+ : std::char_traits::to_int_type(*gptr());
+}
diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h
index 1b04bf91d7..bb7bc20327 100644
--- a/indra/llcommon/llstreamtools.h
+++ b/indra/llcommon/llstreamtools.h
@@ -27,8 +27,10 @@
#ifndef LL_STREAM_TOOLS_H
#define LL_STREAM_TOOLS_H
+#include
#include
#include
+#include
// unless specifed otherwise these all return input_stream.good()
@@ -113,6 +115,27 @@ LL_COMMON_API std::streamsize fullread(
LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);
+/**
+ * cat_streambuf is a std::streambuf subclass that accepts a variadic number
+ * of std::streambuf* (e.g. some_istream.rdbuf()) and virtually concatenates
+ * their contents.
+ */
+// derived from https://stackoverflow.com/a/49441066/5533635
+class cat_streambuf: public std::streambuf
+{
+private:
+ std::deque mInputs;
+ std::vector mBuffer;
+
+public:
+ // only valid for std::streambuf* arguments
+ template
+ cat_streambuf(Inputs... inputs):
+ mInputs{inputs...},
+ mBuffer(1024)
+ {}
+
+ int underflow() override;
+};
+
#endif
-
-
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index a8dcc5226a..bb3d667a42 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -577,10 +577,12 @@ S32 Recording::getSampleCount( const StatType& stat )
// PeriodicRecording
///////////////////////////////////////////////////////////////////////
-PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state)
+PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
: mAutoResize(num_periods == 0),
mCurPeriod(0),
mNumRecordedPeriods(0),
+ // This guarantee that mRecordingPeriods cannot be empty is essential for
+ // code in several methods.
mRecordingPeriods(num_periods ? num_periods : 1)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
@@ -596,18 +598,19 @@ PeriodicRecording::~PeriodicRecording()
void PeriodicRecording::nextPeriod()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
if (mAutoResize)
{
mRecordingPeriods.push_back(Recording());
}
Recording& old_recording = getCurRecording();
- mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
+ inci(mCurPeriod);
old_recording.splitTo(getCurRecording());
- mNumRecordedPeriods = mRecordingPeriods.empty()? 0 :
- llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
+ // Since mRecordingPeriods always has at least one entry, we can always
+ // safely subtract 1 from its size().
+ mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
}
void PeriodicRecording::appendRecording(Recording& recording)
@@ -620,31 +623,29 @@ void PeriodicRecording::appendRecording(Recording& recording)
void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
if (other.mRecordingPeriods.empty()) return;
getCurRecording().update();
other.getCurRecording().update();
-
- const auto other_recording_slots = other.mRecordingPeriods.size();
+
const auto other_num_recordings = other.getNumRecordedPeriods();
const auto other_current_recording_index = other.mCurPeriod;
- const auto other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots;
+ const auto other_oldest_recording_index = other.previ(other_current_recording_index, other_num_recordings);
// append first recording into our current slot
getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
// from now on, add new recordings for everything after the first
- auto other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+ auto other_index = other.nexti(other_oldest_recording_index);
if (mAutoResize)
{
// push back recordings for everything in the middle
- auto other_index = (other_oldest_recording_index + 1) % other_recording_slots;
while (other_index != other_current_recording_index)
{
mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
- other_index = (other_index + 1) % other_recording_slots;
+ other.inci(other_index);
}
// add final recording, if it wasn't already added as the first
@@ -653,36 +654,25 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
}
- mCurPeriod = mRecordingPeriods.empty()? 0 : mRecordingPeriods.size() - 1;
+ // mRecordingPeriods is never empty()
+ mCurPeriod = mRecordingPeriods.size() - 1;
mNumRecordedPeriods = mCurPeriod;
}
else
{
- S32 num_to_copy = llmin((S32)mRecordingPeriods.size(), (S32)other_num_recordings);
-
- std::vector::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
- std::vector::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod;
-
+ auto num_to_copy = llmin(mRecordingPeriods.size(), other_num_recordings);
// already consumed the first recording from other, so start counting at 1
- for(S32 i = 1; i < num_to_copy; i++)
+ for (size_t n = 1, srci = other_index, dsti = mCurPeriod;
+ n < num_to_copy;
+ ++n, other.inci(srci), inci(dsti))
{
- *dest_it = *src_it;
-
- if (++src_it == other.mRecordingPeriods.end())
- {
- src_it = other.mRecordingPeriods.begin();
- }
-
- if (++dest_it == mRecordingPeriods.end())
- {
- dest_it = mRecordingPeriods.begin();
- }
+ mRecordingPeriods[dsti] = other.mRecordingPeriods[srci];
}
-
+
// want argument to % to be positive, otherwise result could be negative and thus out of bounds
llassert(num_to_copy >= 1);
// advance to last recording period copied, and make that our current period
- mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
+ inci(mCurPeriod, num_to_copy - 1);
mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
}
@@ -694,13 +684,11 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
F64Seconds PeriodicRecording::getDuration() const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
F64Seconds duration;
- auto num_periods = mRecordingPeriods.size();
- for (size_t i = 1; i <= num_periods; i++)
+ for (size_t n = 0; n < mRecordingPeriods.size(); ++n)
{
- auto index = (mCurPeriod + num_periods - i) % num_periods;
- duration += mRecordingPeriods[index].getDuration();
+ duration += mRecordingPeriods[nexti(mCurPeriod, n)].getDuration();
}
return duration;
}
@@ -737,16 +725,14 @@ const Recording& PeriodicRecording::getCurRecording() const
Recording& PeriodicRecording::getPrevRecording( size_t offset )
{
- auto num_periods = mRecordingPeriods.size();
- offset = llclamp(offset, 0, num_periods - 1);
- return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
+ // reuse const implementation, but return non-const reference
+ return const_cast(
+ const_cast(this)->getPrevRecording(offset));
}
const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const
{
- auto num_periods = mRecordingPeriods.size();
- offset = llclamp(offset, 0, num_periods - 1);
- return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
+ return mRecordingPeriods[previ(mCurPeriod, offset)];
}
void PeriodicRecording::handleStart()
@@ -789,14 +775,14 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
getCurRecording().splitTo(other.getCurRecording());
}
-F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 min_val = std::numeric_limits::max();
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -811,14 +797,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType& stat, siz
: NaN;
}
-F64 PeriodicRecording::getPeriodMax( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMax( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 max_val = std::numeric_limits::min();
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -834,7 +820,7 @@ F64 PeriodicRecording::getPeriodMax( const StatType& stat, siz
}
// calculates means using aggregates per period
-F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -842,7 +828,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, si
F64 mean = 0;
S32 valid_period_count = 0;
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -857,7 +843,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, si
: NaN;
}
-F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -866,7 +852,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 min_val = std::numeric_limits::max();
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -904,14 +890,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType& stat, si
: NaN;
}
-F64 PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= S32_MAX*/)
+F64 PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 max_val = std::numeric_limits::min();
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -927,7 +913,7 @@ F64 PeriodicRecording::getPeriodMax(const StatType& stat, siz
}
-F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -935,7 +921,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, s
S32 valid_period_count = 0;
F64 mean = 0;
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -950,13 +936,13 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, s
: NaN;
}
-F64 PeriodicRecording::getPeriodMedian( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMedian( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
std::vector buf;
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.getDuration() > (F32Seconds)0.f)
@@ -976,7 +962,7 @@ F64 PeriodicRecording::getPeriodMedian( const StatType& stat,
return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
}
-F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -985,7 +971,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes min_val(std::numeric_limits::max());
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
min_val = llmin(min_val, recording.getMin(stat));
@@ -1022,13 +1008,13 @@ F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t n
return getPeriodMin(static_cast&>(stat), num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= S32_MAX*/)
+F64Kilobytes PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes max_val(0.0);
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
max_val = llmax(max_val, recording.getMax(stat));
@@ -1042,14 +1028,14 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t n
return getPeriodMax(static_cast&>(stat), num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes mean(0);
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
mean += recording.getMean(stat);
@@ -1063,7 +1049,7 @@ F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t
return getPeriodMean(static_cast&>(stat), num_periods);
}
-F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -1072,7 +1058,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType
class LLStopWatchControlsMixinCommon
{
@@ -330,7 +331,7 @@ namespace LLTrace
: public LLStopWatchControlsMixin
{
public:
- PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
+ PeriodicRecording(size_t num_periods, EPlayState state = STOPPED);
~PeriodicRecording();
void nextPeriod();
@@ -353,7 +354,7 @@ namespace LLTrace
Recording snapshotCurRecording() const;
template
- auto getSampleCount(const StatType& stat, size_t num_periods = S32_MAX)
+ auto getSampleCount(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@@ -373,14 +374,14 @@ namespace LLTrace
// catch all for stats that have a defined sum
template
- typename T::value_t getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX)
+ typename T::value_t getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
typename T::value_t min_val(std::numeric_limits::max());
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -396,39 +397,39 @@ namespace LLTrace
}
template
- T getPeriodMin(const CountStatHandle& stat, size_t num_periods = S32_MAX)
+ T getPeriodMin(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast&>(stat), num_periods));
}
- F64 getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX);
+ F64 getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max());
template
- T getPeriodMin(const SampleStatHandle& stat, size_t num_periods = S32_MAX)
+ T getPeriodMin(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast&>(stat), num_periods));
}
- F64 getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX);
+ F64 getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max());
template
- T getPeriodMin(const EventStatHandle& stat, size_t num_periods = S32_MAX)
+ T getPeriodMin(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast&>(stat), num_periods));
}
- F64Kilobytes getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX);
- F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max());
+ F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max());
template
- typename RelatedTypes::fractional_t getPeriodMinPerSec(const StatType& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMinPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes::fractional_t min_val(std::numeric_limits::max());
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
min_val = llmin(min_val, recording.getPerSec(stat));
@@ -437,7 +438,7 @@ namespace LLTrace
}
template
- typename RelatedTypes::fractional_t getPeriodMinPerSec(const CountStatHandle& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMinPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes::fractional_t(getPeriodMinPerSec(static_cast&>(stat), num_periods));
@@ -449,14 +450,14 @@ namespace LLTrace
// catch all for stats that have a defined sum
template
- typename T::value_t getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX)
+ typename T::value_t getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
typename T::value_t max_val(std::numeric_limits::min());
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
@@ -472,39 +473,39 @@ namespace LLTrace
}
template
- T getPeriodMax(const CountStatHandle& stat, size_t num_periods = S32_MAX)
+ T getPeriodMax(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast&>(stat), num_periods));
}
- F64 getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX);
+ F64 getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max());
template
- T getPeriodMax(const SampleStatHandle& stat, size_t num_periods = S32_MAX)
+ T getPeriodMax(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast&>(stat), num_periods));
}
- F64 getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX);
+ F64 getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max());
template
- T getPeriodMax(const EventStatHandle& stat, size_t num_periods = S32_MAX)
+ T getPeriodMax(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast&>(stat), num_periods));
}
- F64Kilobytes getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX);
- F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max());
+ F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max());
template
- typename RelatedTypes::fractional_t getPeriodMaxPerSec(const StatType& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMaxPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 max_val = std::numeric_limits::min();
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
max_val = llmax(max_val, recording.getPerSec(stat));
@@ -513,7 +514,7 @@ namespace LLTrace
}
template
- typename RelatedTypes::fractional_t getPeriodMaxPerSec(const CountStatHandle& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMaxPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes::fractional_t(getPeriodMaxPerSec(static_cast&>(stat), num_periods));
@@ -525,14 +526,14 @@ namespace LLTrace
// catch all for stats that have a defined sum
template
- typename RelatedTypes::fractional_t getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes::fractional_t mean(0);
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.getDuration() > (F32Seconds)0.f)
@@ -546,39 +547,39 @@ namespace LLTrace
}
template
- typename RelatedTypes::fractional_t getPeriodMean(const CountStatHandle& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMean(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods));
}
- F64 getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX);
+ F64 getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max());
template
- typename RelatedTypes::fractional_t getPeriodMean(const SampleStatHandle& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMean(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods));
}
- F64 getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX);
+ F64 getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max());
template
- typename RelatedTypes::fractional_t getPeriodMean(const EventStatHandle& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMean(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods));
}
- F64Kilobytes getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX);
- F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = S32_MAX);
+ F64Kilobytes getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max());
+ F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max());
template
- typename RelatedTypes::fractional_t getPeriodMeanPerSec(const StatType& stat, size_t num_periods = S32_MAX)
+ typename RelatedTypes::fractional_t getPeriodMeanPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes::fractional_t mean = 0;
- for (S32 i = 1; i <= num_periods; i++)
+ for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.getDuration() > (F32Seconds)0.f)
@@ -593,64 +594,64 @@ namespace LLTrace
}
template
- typename RelatedTypes::fractional_t getPeriodMeanPerSec(const CountStatHandle