SL-18837: Merge branch 'main' into actions

master
Nat Goodspeed 2023-09-07 11:15:56 -04:00
commit b8e6777439
768 changed files with 23922 additions and 12499 deletions

View File

@ -4,7 +4,7 @@ on:
workflow_dispatch:
pull_request:
push:
branches: ["actions*"]
branches: [main, "actions*"]
tags: ["*"]
jobs:
@ -12,11 +12,14 @@ jobs:
strategy:
matrix:
runner: [windows-large, macos-12-xl]
configuration: [Release]
configuration: [Release, ReleaseOS]
python-version: ["3.11"]
include:
- runner: macos-12-xl
developer_dir: "/Applications/Xcode_14.0.1.app/Contents/Developer"
exclude:
- runner: macos-12-xl
configuration: ReleaseOS
runs-on: ${{ matrix.runner }}
outputs:
viewer_channel: ${{ steps.build.outputs.viewer_channel }}
@ -75,7 +78,7 @@ jobs:
repository: secondlife/master-message-template
path: .master-message-template
- name: Install autobuild
- name: Install autobuild and python dependencies
run: pip3 install autobuild llsd
- name: Cache autobuild packages

18
.github/workflows/pre-commit.yaml vendored Normal file
View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
<?xml version="1.0" ?>
<llsd><map>
<llsd>
<map>
<key>installables</key>
<map>
<key>SDL</key>
@ -3030,9 +3031,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>a3c599595ecc8fb987a5499fca42520a</string>
<string>647e86470e02509b1cf89829d08dfd46</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/108610/946003/viewer_manager-3.0.577252-windows-577252.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/116623/1003293/viewer_manager-3.0.580913-windows-580913.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3700,7 +3701,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<string>/t:Build</string>
<string>/p:useenv=true</string>
<string>/verbosity:minimal</string>
<string>/toolsversion:4.0</string>
<string>/p:VCBuildAdditionalOptions= /incremental</string>
</array>
</map>
@ -3774,7 +3774,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<string>/t:Build</string>
<string>/p:useenv=true</string>
<string>/verbosity:minimal</string>
<string>/toolsversion:4.0</string>
<string>/p:VCBuildAdditionalOptions= /incremental</string>
</array>
</map>
@ -3811,4 +3810,5 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<string>autobuild</string>
<key>version</key>
<string>1.3</string>
</map></llsd>
</map>
</llsd>

View File

@ -593,6 +593,7 @@ Henri Beauchamp
VWR-4157
SL-15175
SL-19110
SL-19159
herina Bode
Hikkoshi Sakai
VWR-429
@ -931,6 +932,8 @@ Lexi Frua
Lillie Cordeaux
Lilly Zenovka
Lizzy Macarthur
Logue Takacs
INTL-490
Luban Yiyuan
Luc Starsider
Luminous Luminos
@ -1187,6 +1190,7 @@ PanteraPolnocy
SL-18891
SL-18904
SL-18937
SL-19207
SL-19681
Parvati Silverweb
Patric Mills

View File

@ -167,6 +167,10 @@ if (DARWIN)
## Really?? On developer machines too?
##set(ENABLE_SIGNING TRUE)
##set(SIGNING_IDENTITY "Developer ID Application: Linden Research, 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)

View File

@ -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 the user has their own version of Python installed, prefer that
@ -43,7 +47,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")

View File

@ -32,7 +32,6 @@
#include "llsaleinfo.h"
#include "llwearabletype.h"
class LLMD5;
class LLVisualParam;
class LLTexGlobalColorInfo;
class LLTexGlobalColor;
@ -110,9 +109,6 @@ public:
// Something happened that requires the wearable to be updated (e.g. worn/unworn).
virtual void setUpdated() const = 0;
// Update the baked texture hash.
virtual void addToBakedTextureHash(LLMD5& hash) const = 0;
typedef std::map<S32, LLVisualParam *> visual_param_index_map_t;
visual_param_index_map_t mVisualParamIndexMap;

View File

@ -31,7 +31,6 @@
#include "llavatarappearance.h"
#include "llavatarappearancedefines.h"
#include "lldriverparam.h"
#include "llmd5.h"
LLWearableData::LLWearableData() :
mAvatarAppearance(NULL)
@ -343,42 +342,3 @@ U32 LLWearableData::getWearableCount(const U32 tex_index) const
const LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index);
return getWearableCount(wearable_type);
}
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
{
LLUUID hash_id;
bool hash_computed = false;
LLMD5 hash;
const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index);
for (U8 i=0; i < baked_dict->mWearables.size(); i++)
{
const LLWearableType::EType baked_type = baked_dict->mWearables[i];
const U32 num_wearables = getWearableCount(baked_type);
for (U32 index = 0; index < num_wearables; ++index)
{
const LLWearable* wearable = getWearable(baked_type,index);
if (wearable)
{
wearable->addToBakedTextureHash(hash);
hash_computed = true;
}
}
}
if (hash_computed)
{
hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES);
if (!generate_valid_hash)
{
invalidateBakedTextureHash(hash);
}
hash.finalize();
hash.raw_digest(hash_id.mData);
}
return hash_id;
}

View File

@ -85,15 +85,6 @@ protected:
private:
void pullCrossWearableValues(const LLWearableType::EType type);
//--------------------------------------------------------------------
// Server Communication
//--------------------------------------------------------------------
public:
LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index,
BOOL generate_valid_hash = TRUE);
protected:
virtual void invalidateBakedTextureHash(LLMD5& hash) const {}
//--------------------------------------------------------------------
// Member variables
//--------------------------------------------------------------------

View File

@ -204,7 +204,8 @@ std::string LLAudioEngine::getInternetStreamURL()
{
if (mStreamingAudioImpl)
return mStreamingAudioImpl->getURL();
else return std::string();
return std::string();
}
@ -345,42 +346,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();
}
}
}
}
@ -396,18 +398,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();
}
}
@ -737,7 +732,7 @@ F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
}
return (gain);
}
}
F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
@ -964,11 +959,10 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
else
{
LL_DEBUGS("AudioEngine") << "Cleaning up audio sources for "<< asp->getID() <<LL_ENDL;
delete asp;
mAllSources.erase(iter);
delete asp;
mAllSources.erase(iter);
}
}
}
bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
{
@ -1687,19 +1681,18 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
{
LL_DEBUGS("AudioEngine") << "( id: " << sourcep->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()
{

View File

@ -91,6 +91,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
@ -469,13 +470,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;
}
};

View File

@ -208,10 +208,6 @@ bool LLAudioEngine_FMODSTUDIO::init(void* userdata, const std::string &app_title
}
#endif
// 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;
int r_numbuffers, r_samplerate, r_channels;
@ -253,6 +249,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)
{
mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem);

View File

@ -53,6 +53,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();

View File

@ -1352,7 +1352,6 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
dp.packS32(joint->mNumRotKeys, "num_rot_keys");
LLQuaternion::Order order = bvhStringToOrder( joint->mOrder );
S32 outcount = 0;
S32 frame = 0;
for (Key& key : joint->mKeys)
{
@ -1418,7 +1417,6 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
dp.packU16(x, "rot_angle_x");
dp.packU16(y, "rot_angle_y");
dp.packU16(z, "rot_angle_z");
outcount++;
frame++;
}

View File

@ -497,13 +497,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:

View File

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

View File

@ -345,6 +345,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!!

View File

@ -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 <typename T1, typename T2>
inline auto llmax(T1 d1, T2 d2)
// recursion tail
template <typename T>
inline auto llmax(T data)
{
return (d1 > d2) ? d1 : d2;
return data;
}
template <typename T1, typename T2, typename T3>
inline auto llmax(T1 d1, T2 d2, T3 d3)
template <typename T0, typename T1, typename... Ts>
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 <typename T1, typename T2, typename T3, typename T4>
inline auto llmax(T1 d1, T2 d2, T3 d3, T4 d4)
// recursion tail
template <typename T>
inline auto llmin(T data)
{
auto r1 = llmax(d1,d2);
auto r2 = llmax(d3,d4);
return llmax(r1, r2);
return data;
}
template <typename T1, typename T2>
inline auto llmin(T1 d1, T2 d2)
template <typename T0, typename T1, typename... Ts>
inline auto llmin(T0 d0, T1 d1, Ts... rest)
{
return (d1 < d2) ? d1 : d2;
}
template <typename T1, typename T2, typename T3>
inline auto llmin(T1 d1, T2 d2, T3 d3)
{
auto r = llmin(d1,d2);
return (r < d3 ? r : d3);
}
template <typename T1, typename T2, typename T3, typename T4>
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 <typename A, typename MIN, typename MAX>

View File

@ -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<U64>(buffer.tellp()) << " != "
<< "str().length() -> " << strdata.length() << LL_ENDL;
}
// DEBUGGING ONLY: reading back is terribly inefficient.
std::istringstream readback(strdata);
LLSD echo;
LLPointer<LLSDParser> 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<LLSDParser> 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");
}

View File

@ -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<uint4*>(&count), 8);
// Treat count, a uint64_t, as uint32_t[2].
encode (bits, reinterpret_cast<uint32_t*>(&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);
}

View File

@ -67,6 +67,8 @@ documentation and/or software.
*/
#include <cstdint> // 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);
};

View File

@ -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 <class Formatter>
void format_using(const LLSD& data, std::ostream& ostr,
LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY)
{
LLPointer<Formatter> f{ new Formatter };
f->format(data, ostr, options);
}
template <class Parser>
S32 parse_using(std::istream& istr, LLSD& data, size_t max_bytes, S32 max_depth=-1)
{
LLPointer<Parser> 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<LLSDParser> 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<std::string::size_type>(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<LLSDBinaryParser>(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<LLSDXMLParser>(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<LLSDNotationParser>(str, sd, max_bytes-inbuf) > 0);
}
else
else // no header we recognize
{
LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
LLPointer<LLSDParser> 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<const U8*>(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<char> wholemsg((max_bytes == size_t(SIZE_UNLIMITED))? 1024 : max_bytes);
prepend.read(wholemsg.data(), std::min(max_bytes, wholemsg.size()));
LLMemoryStream replay(reinterpret_cast<const U8*>(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;
}
/**
@ -2193,9 +2248,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size)
{
U8* result = NULL;
U32 cur_size = 0;
llssize cur_size = 0;
z_stream strm;
constexpr U32 CHUNK = 1024 * 512;
static thread_local std::unique_ptr<U8[]> out;
@ -2388,7 +2443,7 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size
return result;
}
char* strip_deprecated_header(char* in, U32& 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;

View File

@ -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, U32& 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

View File

@ -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<char>::eof()
: std::char_traits<char>::to_int_type(*gptr());
}

View File

@ -27,8 +27,10 @@
#ifndef LL_STREAM_TOOLS_H
#define LL_STREAM_TOOLS_H
#include <deque>
#include <iostream>
#include <string>
#include <vector>
// 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<std::streambuf*> mInputs;
std::vector<char> mBuffer;
public:
// only valid for std::streambuf* arguments
template <typename... Inputs>
cat_streambuf(Inputs... inputs):
mInputs{inputs...},
mBuffer(1024)
{}
int underflow() override;
};
#endif

View File

@ -577,10 +577,12 @@ S32 Recording::getSampleCount( const StatType<EventAccumulator>& 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<Recording>::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
std::vector<Recording>::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<Recording&>(
const_cast<const PeriodicRecording*>(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<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 min_val = std::numeric_limits<F64>::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<EventAccumulator>& stat, siz
: NaN;
}
F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 max_val = std::numeric_limits<F64>::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<EventAccumulator>& stat, siz
}
// calculates means using aggregates per period
F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@ -842,7 +828,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& 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<EventAccumulator>& stat, si
: NaN;
}
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@ -866,7 +852,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
F64 sum_of_squares = 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))
@ -882,14 +868,14 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
: NaN;
}
F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 min_val = std::numeric_limits<F64>::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<SampleAccumulator>& stat, si
: NaN;
}
F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/)
F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
F64 max_val = std::numeric_limits<F64>::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<SampleAccumulator>& stat, siz
}
F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@ -935,7 +921,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& 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<SampleAccumulator>& stat, s
: NaN;
}
F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
std::vector<F64> 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<SampleAccumulator>& 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<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@ -985,7 +971,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
S32 valid_period_count = 0;
F64 sum_of_squares = 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))
@ -1002,13 +988,13 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
}
F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes min_val(std::numeric_limits<F64>::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<const StatType<MemAccumulator>&>(stat), num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/)
F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::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<const StatType<MemAccumulator>&>(stat), num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::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<const StatType<MemAccumulator>&>(stat), num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
@ -1072,7 +1058,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAc
S32 valid_period_count = 0;
F64 sum_of_squares = 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))

View File

@ -33,6 +33,7 @@
#include "lltimer.h"
#include "lltraceaccumulators.h"
#include "llpointer.h"
#include <limits>
class LLStopWatchControlsMixinCommon
{
@ -330,7 +331,7 @@ namespace LLTrace
: public LLStopWatchControlsMixin<PeriodicRecording>
{
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 <typename T>
auto getSampleCount(const StatType<T>& stat, size_t num_periods = S32_MAX)
auto getSampleCount(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::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>
typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = S32_MAX)
typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::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<typename T::value_t>::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<typename T>
T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::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 T>
typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
@ -449,14 +450,14 @@ namespace LLTrace
// catch all for stats that have a defined sum
template <typename T>
typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = S32_MAX)
typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::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<typename T::value_t>::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<typename T>
T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 max_val = std::numeric_limits<F64>::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 T>
typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
@ -525,14 +526,14 @@ namespace LLTrace
// catch all for stats that have a defined sum
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes<typename T::value_t>::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 T>
typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes<typename T::value_t>::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 T>
typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
for (S32 i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.getDuration() > (F32Seconds)0.f)
{
buf.push_back(recording.getPerSec(stat));
}
}
std::sort(buf.begin(), buf.end());
std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.getDuration() > (F32Seconds)0.f)
{
buf.push_back(recording.getPerSec(stat));
}
}
std::sort(buf.begin(), buf.end());
return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
}
return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
}
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
}
//
// PERIODIC STANDARD DEVIATION
//
F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
}
F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
}
F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = S32_MAX);
F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
private:
// implementation for LLStopWatchControlsMixin
@ -659,6 +660,35 @@ namespace LLTrace
/*virtual*/ void handleReset();
/*virtual*/ void handleSplitTo(PeriodicRecording& other);
// helper methods for wraparound ring-buffer arithmetic
inline
size_t wrapi(size_t i) const
{
return i % mRecordingPeriods.size();
}
inline
size_t nexti(size_t i, size_t offset=1) const
{
return wrapi(i + offset);
}
inline
size_t previ(size_t i, size_t offset=1) const
{
auto num_periods = mRecordingPeriods.size();
// constrain offset
offset = llclamp(offset, 0, num_periods - 1);
// add size() so expression can't go (unsigned) "negative"
return wrapi(i + num_periods - offset);
}
inline
void inci(size_t& i, size_t offset=1) const
{
i = nexti(i, offset);
}
private:
std::vector<Recording> mRecordingPeriods;
const bool mAutoResize;

View File

@ -884,7 +884,7 @@ U32 LLUUID::getRandomSeed()
seed[7]=(unsigned char)(pid);
getSystemTime((uuid_time_t *)(&seed[8]));
U64 seed64 = HBXXH64((const void*)seed, 16).digest();
U64 seed64 = HBXXH64::digest((const void*)seed, 16);
return U32(seed64) ^ U32(seed64 >> 32);
}

View File

@ -116,6 +116,14 @@ public:
U16 getCRC16() const;
U32 getCRC32() const;
// Returns a 64 bits digest of the UUID, by XORing its two 64 bits long
// words. HB
inline U64 getDigest64() const
{
U64* tmp = (U64*)mData;
return tmp[0] ^ tmp[1];
}
static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.
static const LLUUID null;
@ -165,36 +173,22 @@ public:
LLAssetID makeAssetID(const LLUUID& session) const;
};
// Generate a hash of an LLUUID object using the boost hash templates.
template <>
struct boost::hash<LLUUID>
{
typedef LLUUID argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& s) const
{
result_type seed(0);
for (S32 i = 0; i < UUID_BYTES; ++i)
{
boost::hash_combine(seed, s.mData[i]);
}
return seed;
}
};
// Adapt boost hash to std hash
// std::hash implementation for LLUUID
namespace std
{
template<> struct hash<LLUUID>
{
std::size_t operator()(LLUUID const& s) const noexcept
{
return boost::hash<LLUUID>()(s);
}
};
template<> struct hash<LLUUID>
{
inline size_t operator()(const LLUUID& id) const noexcept
{
return (size_t)id.getDigest64();
}
};
}
#endif
// For use with boost containers.
inline size_t hash_value(const LLUUID& id) noexcept
{
return (size_t)id.getDigest64();
}
#endif // LL_LLUUID_H

View File

@ -41,7 +41,7 @@ typedef unsigned int U32;
// to express an index that might go negative
// (ssize_t is provided by SOME compilers, don't collide)
typedef typename std::make_signed<size_t>::type llssize;
typedef typename std::make_signed<std::size_t>::type llssize;
#if LL_WINDOWS
// https://docs.microsoft.com/en-us/cpp/build/reference/zc-wchar-t-wchar-t-is-native-type

View File

@ -114,26 +114,26 @@ namespace tut
" pass\n"
"\n"
"def get():\n"
" hdr = ''\n"
" while ':' not in hdr and len(hdr) < 20:\n"
" hdr += sys.stdin.read(1)\n"
" hdr = []\n"
" while b':' not in hdr and len(hdr) < 20:\n"
" hdr.append(sys.stdin.buffer.read(1))\n"
" if not hdr:\n"
" sys.exit(0)\n"
" if not hdr.endswith(':'):\n"
" if not hdr[-1] == b':':\n"
" raise ProtocolError('Expected len:data, got %r' % hdr, hdr)\n"
" try:\n"
" length = int(hdr[:-1])\n"
" length = int(b''.join(hdr[:-1]))\n"
" except ValueError:\n"
" raise ProtocolError('Non-numeric len %r' % hdr[:-1], hdr[:-1])\n"
" parts = []\n"
" received = 0\n"
" while received < length:\n"
" parts.append(sys.stdin.read(length - received))\n"
" parts.append(sys.stdin.buffer.read(length - received))\n"
" received += len(parts[-1])\n"
" data = ''.join(parts)\n"
" data = b''.join(parts)\n"
" assert len(data) == length\n"
" try:\n"
" return llsd.parse(data.encode())\n"
" return llsd.parse(data)\n"
// Seems the old indra.base.llsd module didn't properly
// convert IndexError (from running off end of string) to
// LLSDParseError.
@ -173,11 +173,11 @@ namespace tut
" return _reply\n"
"\n"
"def put(req):\n"
" sys.stdout.write(':'.join((str(len(req)), req)))\n"
" sys.stdout.buffer.write(b'%d:%b' % (len(req), req))\n"
" sys.stdout.flush()\n"
"\n"
"def send(pump, data):\n"
" put(llsd.format_notation(dict(pump=pump, data=data)).decode())\n"
" put(llsd.format_notation(dict(pump=pump, data=data)))\n"
"\n"
"def request(pump, data):\n"
" # we expect 'data' is a dict\n"

View File

@ -46,14 +46,19 @@ typedef U32 uint32_t;
#include "boost/range.hpp"
#include "../llsd.h"
#include "../llsdserialize.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llsdutil.h"
#include "../llformat.h"
#include "llformat.h"
#include "llmemorystream.h"
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
#include "stringize.h"
#include <functional>
typedef std::function<void(const LLSD& data, std::ostream& str)> FormatterFunction;
typedef std::function<bool(std::istream& istr, LLSD& data, llssize max_bytes)> ParserFunction;
std::vector<U8> string_to_vector(const std::string& str)
{
@ -106,7 +111,7 @@ namespace tut
mSD = LLUUID::null;
expected = "<llsd><uuid /></llsd>\n";
xml_test("null uuid", expected);
mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
xml_test("uuid", expected);
@ -130,7 +135,7 @@ namespace tut
expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
xml_test("binary", expected);
}
template<> template<>
void sd_xml_object::test<2>()
{
@ -219,7 +224,7 @@ namespace tut
expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
xml_test("2 element map", expected);
}
template<> template<>
void sd_xml_object::test<6>()
{
@ -235,7 +240,7 @@ namespace tut
expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
xml_test("binary", expected);
}
class TestLLSDSerializeData
{
public:
@ -244,9 +249,34 @@ namespace tut
void doRoundTripTests(const std::string&);
void checkRoundTrip(const std::string&, const LLSD& v);
LLPointer<LLSDFormatter> mFormatter;
LLPointer<LLSDParser> mParser;
void setFormatterParser(LLPointer<LLSDFormatter> formatter, LLPointer<LLSDParser> parser)
{
mFormatter = [formatter](const LLSD& data, std::ostream& str)
{
formatter->format(data, str);
};
// this lambda must be mutable since otherwise the bound 'parser'
// is assumed to point to a const LLSDParser
mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable
{
// reset() call is needed since test code re-uses parser object
parser->reset();
return (parser->parse(istr, data, max_bytes) > 0);
};
}
void setParser(bool (*parser)(LLSD&, std::istream&, llssize))
{
// why does LLSDSerialize::deserialize() reverse the parse() params??
mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes)
{
return parser(data, istr, max_bytes);
};
}
FormatterFunction mFormatter;
ParserFunction mParser;
};
TestLLSDSerializeData::TestLLSDSerializeData()
@ -259,12 +289,11 @@ namespace tut
void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
{
std::stringstream stream;
mFormatter->format(v, stream);
std::stringstream stream;
mFormatter(v, stream);
//LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
LLSD w;
mParser->reset(); // reset() call is needed since test code re-uses mParser
mParser->parse(stream, w, stream.str().size());
mParser(stream, w, stream.str().size());
try
{
@ -293,52 +322,52 @@ namespace tut
fillmap(root[key], width, depth - 1);
}
}
void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
{
LLSD v;
checkRoundTrip(msg + " undefined", v);
v = true;
checkRoundTrip(msg + " true bool", v);
v = false;
checkRoundTrip(msg + " false bool", v);
v = 1;
checkRoundTrip(msg + " positive int", v);
v = 0;
checkRoundTrip(msg + " zero int", v);
v = -1;
checkRoundTrip(msg + " negative int", v);
v = 1234.5f;
checkRoundTrip(msg + " positive float", v);
v = 0.0f;
checkRoundTrip(msg + " zero float", v);
v = -1234.5f;
checkRoundTrip(msg + " negative float", v);
// FIXME: need a NaN test
v = LLUUID::null;
checkRoundTrip(msg + " null uuid", v);
LLUUID newUUID;
newUUID.generate();
v = newUUID;
checkRoundTrip(msg + " new uuid", v);
v = "";
checkRoundTrip(msg + " empty string", v);
v = "some string";
checkRoundTrip(msg + " non-empty string", v);
v =
"Second Life is a 3-D virtual world entirely built and owned by its residents. "
"Since opening to the public in 2003, it has grown explosively and today is "
@ -366,7 +395,7 @@ namespace tut
for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
{
std::ostringstream out;
for (U32 c = block; c < block + block_size; ++c)
{
if (c <= 0x000001f
@ -380,7 +409,7 @@ namespace tut
if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
if ((c & 0x00fffe) == 0x00fffe) { continue; }
// see Unicode standard, section 15.8
if (c <= 0x00007f)
{
out << (char)(c & 0x7f);
@ -404,55 +433,55 @@ namespace tut
out << (char)(0x80 | ((c >> 0) & 0x3f));
}
}
v = out.str();
std::ostringstream blockmsg;
blockmsg << msg << " unicode string block 0x" << std::hex << block;
checkRoundTrip(blockmsg.str(), v);
}
LLDate epoch;
v = epoch;
checkRoundTrip(msg + " epoch date", v);
LLDate aDay("2002-12-07T05:07:15.00Z");
v = aDay;
checkRoundTrip(msg + " date", v);
LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
v = path;
checkRoundTrip(msg + " url", v);
const char source[] = "it must be a blue moon again";
std::vector<U8> data;
// note, includes terminating '\0'
copy(&source[0], &source[sizeof(source)], back_inserter(data));
v = data;
checkRoundTrip(msg + " binary", v);
v = LLSD::emptyMap();
checkRoundTrip(msg + " empty map", v);
v = LLSD::emptyMap();
v["name"] = "luke"; //v.insert("name", "luke");
v["age"] = 3; //v.insert("age", 3);
checkRoundTrip(msg + " map", v);
v.clear();
v["a"]["1"] = true;
v["b"]["0"] = false;
checkRoundTrip(msg + " nested maps", v);
v = LLSD::emptyArray();
checkRoundTrip(msg + " empty array", v);
v = LLSD::emptyArray();
v.append("ali");
v.append(28);
checkRoundTrip(msg + " array", v);
v.clear();
v[0][0] = true;
v[1][0] = false;
@ -462,7 +491,7 @@ namespace tut
fillmap(v, 10, 3); // 10^6 maps
checkRoundTrip(msg + " many nested maps", v);
}
typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerializeGroup;
typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject;
TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization");
@ -470,35 +499,106 @@ namespace tut
template<> template<>
void TestLLSDSerializeObject::test<1>()
{
mFormatter = new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY);
mParser = new LLSDNotationParser();
setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY),
new LLSDNotationParser());
doRoundTripTests("pretty binary notation serialization");
}
template<> template<>
void TestLLSDSerializeObject::test<2>()
{
mFormatter = new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE);
mParser = new LLSDNotationParser();
setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
new LLSDNotationParser());
doRoundTripTests("raw binary notation serialization");
}
template<> template<>
void TestLLSDSerializeObject::test<3>()
{
mFormatter = new LLSDXMLFormatter();
mParser = new LLSDXMLParser();
setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser());
doRoundTripTests("xml serialization");
}
template<> template<>
void TestLLSDSerializeObject::test<4>()
{
mFormatter = new LLSDBinaryFormatter();
mParser = new LLSDBinaryParser();
setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser());
doRoundTripTests("binary serialization");
}
template<> template<>
void TestLLSDSerializeObject::test<5>()
{
mFormatter = [](const LLSD& sd, std::ostream& str)
{
LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY);
};
setParser(LLSDSerialize::deserialize);
doRoundTripTests("serialize(LLSD_BINARY)");
};
template<> template<>
void TestLLSDSerializeObject::test<6>()
{
mFormatter = [](const LLSD& sd, std::ostream& str)
{
LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML);
};
setParser(LLSDSerialize::deserialize);
doRoundTripTests("serialize(LLSD_XML)");
};
template<> template<>
void TestLLSDSerializeObject::test<7>()
{
mFormatter = [](const LLSD& sd, std::ostream& str)
{
LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION);
};
setParser(LLSDSerialize::deserialize);
// In this test, serialize(LLSD_NOTATION) emits a header recognized by
// deserialize().
doRoundTripTests("serialize(LLSD_NOTATION)");
};
template<> template<>
void TestLLSDSerializeObject::test<8>()
{
setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
new LLSDNotationParser());
setParser(LLSDSerialize::deserialize);
// This is an interesting test because LLSDNotationFormatter does not
// emit an llsd/notation header.
doRoundTripTests("LLSDNotationFormatter -> deserialize");
};
template<> template<>
void TestLLSDSerializeObject::test<9>()
{
setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
new LLSDXMLParser());
setParser(LLSDSerialize::deserialize);
// This is an interesting test because LLSDXMLFormatter does not
// emit an LLSD/XML header.
doRoundTripTests("LLSDXMLFormatter -> deserialize");
};
/*==========================================================================*|
// We do not expect this test to succeed. Without a header, neither
// notation LLSD nor binary LLSD reliably start with a distinct character,
// the way XML LLSD starts with '<'. By convention, we default to notation
// rather than binary.
template<> template<>
void TestLLSDSerializeObject::test<10>()
{
setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
new LLSDBinaryParser());
setParser(LLSDSerialize::deserialize);
// This is an interesting test because LLSDBinaryFormatter does not
// emit an LLSD/Binary header.
doRoundTripTests("LLSDBinaryFormatter -> deserialize");
};
|*==========================================================================*/
/**
* @class TestLLSDParsing
@ -549,7 +649,7 @@ namespace tut
public:
TestLLSDXMLParsing() {}
};
typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
@ -580,8 +680,8 @@ namespace tut
LLSD(),
LLSDParser::PARSE_FAILURE);
}
template<> template<>
void TestLLSDXMLParsingObject::test<2>()
{
@ -590,7 +690,7 @@ namespace tut
v["amy"] = 23;
v["bob"] = LLSD();
v["cam"] = 1.23;
ensureParse(
"unknown data type",
"<llsd><map>"
@ -601,16 +701,16 @@ namespace tut
v,
v.size() + 1);
}
template<> template<>
void TestLLSDXMLParsingObject::test<3>()
{
// test handling of nested bad data
LLSD v;
v["amy"] = 23;
v["cam"] = 1.23;
ensureParse(
"map with html",
"<llsd><map>"
@ -620,7 +720,7 @@ namespace tut
"</map></llsd>",
v,
v.size() + 1);
v.clear();
v["amy"] = 23;
v["cam"] = 1.23;
@ -633,7 +733,7 @@ namespace tut
"</map></llsd>",
v,
v.size() + 1);
v.clear();
v["amy"] = 23;
v["bob"] = LLSD::emptyMap();
@ -655,7 +755,7 @@ namespace tut
v[0] = 23;
v[1] = LLSD();
v[2] = 1.23;
ensureParse(
"array value of html",
"<llsd><array>"
@ -665,7 +765,7 @@ namespace tut
"</array></llsd>",
v,
v.size() + 1);
v.clear();
v[0] = 23;
v[1] = LLSD::emptyMap();
@ -1219,7 +1319,7 @@ namespace tut
vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
LLSD value = vec;
vec.resize(11);
vec[0] = 'b'; // for binary
vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
@ -1688,85 +1788,83 @@ namespace tut
ensureBinaryAndXML("map", test);
}
struct TestPythonCompatible
// helper for TestPythonCompatible
static std::string import_llsd("import os.path\n"
"import sys\n"
"try:\n"
// new freestanding llsd package
" import llsd\n"
"except ImportError:\n"
// older llbase.llsd module
" from llbase import llsd\n");
// helper for TestPythonCompatible
template <typename CONTENT>
void python(const std::string& desc, const CONTENT& script, int expect=0)
{
TestPythonCompatible():
// Note the peculiar insertion of __FILE__ into this string. Since
// this script is being written into a platform-dependent temp
// directory, we can't locate indra/lib/python relative to
// Python's __file__. Use __FILE__ instead, navigating relative
// to this C++ source file. Use Python raw-string syntax so
// Windows pathname backslashes won't mislead Python's string
// scanner.
import_llsd("import os.path\n"
"import sys\n"
"import llsd\n")
{}
~TestPythonCompatible() {}
auto PYTHON(LLStringUtil::getenv("PYTHON"));
ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
std::string import_llsd;
template <typename CONTENT>
void python(const std::string& desc, const CONTENT& script, int expect=0)
{
auto PYTHON(LLStringUtil::getenv("PYTHON"));
ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
NamedTempFile scriptfile("py", script);
NamedTempFile scriptfile("py", script);
#if LL_WINDOWS
std::string q("\"");
std::string qPYTHON(q + PYTHON + q);
std::string qscript(q + scriptfile.getName() + q);
int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL);
if (rc == -1)
{
char buffer[256];
strerror_s(buffer, errno); // C++ can infer the buffer size! :-O
ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false);
}
else
{
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect);
}
std::string q("\"");
std::string qPYTHON(q + PYTHON + q);
std::string qscript(q + scriptfile.getName() + q);
int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL);
if (rc == -1)
{
char buffer[256];
strerror_s(buffer, errno); // C++ can infer the buffer size! :-O
ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false);
}
else
{
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect);
}
#else // LL_DARWIN, LL_LINUX
LLProcess::Params params;
params.executable = PYTHON;
params.args.add(scriptfile.getName());
LLProcessPtr py(LLProcess::create(params));
ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py));
// Implementing timeout would mean messing with alarm() and
// catching SIGALRM... later maybe...
int status(0);
if (waitpid(py->getProcessID(), &status, 0) == -1)
LLProcess::Params params;
params.executable = PYTHON;
params.args.add(scriptfile.getName());
LLProcessPtr py(LLProcess::create(params));
ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py));
// Implementing timeout would mean messing with alarm() and
// catching SIGALRM... later maybe...
int status(0);
if (waitpid(py->getProcessID(), &status, 0) == -1)
{
int waitpid_errno(errno);
ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
"waitpid() errno " << waitpid_errno),
waitpid_errno, ECHILD);
}
else
{
if (WIFEXITED(status))
{
int waitpid_errno(errno);
ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
"waitpid() errno " << waitpid_errno),
waitpid_errno, ECHILD);
int rc(WEXITSTATUS(status));
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc),
rc, expect);
}
else if (WIFSIGNALED(status))
{
ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)),
false);
}
else
{
if (WIFEXITED(status))
{
int rc(WEXITSTATUS(status));
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc),
rc, expect);
}
else if (WIFSIGNALED(status))
{
ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)),
false);
}
else
{
ensure(STRINGIZE(desc << " script produced impossible status " << status),
false);
}
ensure(STRINGIZE(desc << " script produced impossible status " << status),
false);
}
#endif
}
#endif
}
struct TestPythonCompatible
{
TestPythonCompatible() {}
~TestPythonCompatible() {}
};
typedef tut::test_group<TestPythonCompatible> TestPythonCompatibleGroup;
@ -1792,25 +1890,33 @@ namespace tut
"print('Running on', sys.platform)\n");
}
// helper for test<3>
static void writeLLSDArray(std::ostream& out, const LLSD& array)
// helper for test<3> - test<7>
static void writeLLSDArray(const FormatterFunction& serialize,
std::ostream& out, const LLSD& array)
{
for (const LLSD& item: llsd::inArray(array))
{
LLSDSerialize::toNotation(item, out);
// It's important to separate with newlines because Python's llsd
// module doesn't support parsing from a file stream, only from a
// string, so we have to know how much of the file to read into a
// string.
out << '\n';
// It's important to delimit the entries in this file somehow
// because, although Python's llsd.parse() can accept a file
// stream, the XML parser expects EOF after a single outer element
// -- it doesn't just stop. So we must extract a sequence of bytes
// strings from the file. But since one of the serialization
// formats we want to test is binary, we can't pick any single
// byte value as a delimiter! Use a binary integer length prefix
// instead.
std::ostringstream buffer;
serialize(item, buffer);
auto buffstr{ buffer.str() };
int bufflen{ static_cast<int>(buffstr.length()) };
out.write(reinterpret_cast<const char*>(&bufflen), sizeof(bufflen));
out.write(buffstr.c_str(), buffstr.length());
}
}
template<> template<>
void TestPythonCompatibleObject::test<3>()
// helper for test<3> - test<7>
static void toPythonUsing(const std::string& desc,
const FormatterFunction& serialize)
{
set_test_name("verify sequence to Python");
LLSD cdata(llsd::array(17, 3.14,
"This string\n"
"has several\n"
@ -1830,7 +1936,7 @@ namespace tut
" except StopIteration:\n"
" pass\n"
" else:\n"
" assert False, 'Too many data items'\n";
" raise AssertionError('Too many data items')\n";
// Create an llsdXXXXXX file containing 'data' serialized to
// notation.
@ -1839,32 +1945,128 @@ namespace tut
// takes a callable. To this callable it passes the
// std::ostream with which it's writing the
// NamedTempFile.
[&](std::ostream& out){ writeLLSDArray(out, cdata); });
[serialize, cdata]
(std::ostream& out)
{ writeLLSDArray(serialize, out, cdata); });
python("read C++ notation",
python("read C++ " + desc,
[&](std::ostream& out){ out <<
import_llsd <<
"def parse_each(iterable):\n"
" for item in iterable:\n"
" yield llsd.parse(item)\n" <<
pydata <<
"from functools import partial\n"
"import io\n"
"import struct\n"
"lenformat = struct.Struct('i')\n"
"def parse_each(inf):\n"
" for rawlen in iter(partial(inf.read, lenformat.size), b''):\n"
" len = lenformat.unpack(rawlen)[0]\n"
// Since llsd.parse() has no max_bytes argument, instead of
// passing the input stream directly to parse(), read the item
// into a distinct bytes object and parse that.
" data = inf.read(len)\n"
" try:\n"
" frombytes = llsd.parse(data)\n"
" except llsd.LLSDParseError as err:\n"
" print(f'*** {err}')\n"
" print(f'Bad content:\\n{data!r}')\n"
" raise\n"
// Also try parsing from a distinct stream.
" stream = io.BytesIO(data)\n"
" fromstream = llsd.parse(stream)\n"
" assert frombytes == fromstream\n"
" yield frombytes\n"
<< pydata <<
// Don't forget raw-string syntax for Windows pathnames.
"verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n";});
}
template<> template<>
void TestPythonCompatibleObject::test<3>()
{
set_test_name("to Python using LLSDSerialize::serialize(LLSD_XML)");
toPythonUsing("LLSD_XML",
[](const LLSD& sd, std::ostream& out)
{ LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_XML); });
}
template<> template<>
void TestPythonCompatibleObject::test<4>()
{
set_test_name("verify sequence from Python");
set_test_name("to Python using LLSDSerialize::serialize(LLSD_NOTATION)");
toPythonUsing("LLSD_NOTATION",
[](const LLSD& sd, std::ostream& out)
{ LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_NOTATION); });
}
template<> template<>
void TestPythonCompatibleObject::test<5>()
{
set_test_name("to Python using LLSDSerialize::serialize(LLSD_BINARY)");
toPythonUsing("LLSD_BINARY",
[](const LLSD& sd, std::ostream& out)
{ LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_BINARY); });
}
template<> template<>
void TestPythonCompatibleObject::test<6>()
{
set_test_name("to Python using LLSDSerialize::toXML()");
toPythonUsing("toXML()", LLSDSerialize::toXML);
}
template<> template<>
void TestPythonCompatibleObject::test<7>()
{
set_test_name("to Python using LLSDSerialize::toNotation()");
toPythonUsing("toNotation()", LLSDSerialize::toNotation);
}
/*==========================================================================*|
template<> template<>
void TestPythonCompatibleObject::test<8>()
{
set_test_name("to Python using LLSDSerialize::toBinary()");
// We don't expect this to work because, without a header,
// llsd.parse() will assume notation rather than binary.
toPythonUsing("toBinary()", LLSDSerialize::toBinary);
}
|*==========================================================================*/
// helper for test<8> - test<12>
bool itemFromStream(std::istream& istr, LLSD& item, const ParserFunction& parse)
{
// reset the output value for debugging clarity
item.clear();
// We use an int length prefix as a foolproof delimiter even for
// binary serialized streams.
int length{ 0 };
istr.read(reinterpret_cast<char*>(&length), sizeof(length));
// return parse(istr, item, length);
// Sadly, as of 2022-12-01 it seems we can't really trust our LLSD
// parsers to honor max_bytes: this test works better when we read
// each item into its own distinct LLMemoryStream, instead of passing
// the original istr with a max_bytes constraint.
std::vector<U8> buffer(length);
istr.read(reinterpret_cast<char*>(buffer.data()), length);
LLMemoryStream stream(buffer.data(), length);
return parse(stream, item, length);
}
// helper for test<8> - test<12>
void fromPythonUsing(const std::string& pyformatter,
const ParserFunction& parse=
[](std::istream& istr, LLSD& data, llssize max_bytes)
{ return LLSDSerialize::deserialize(data, istr, max_bytes); })
{
// Create an empty data file. This is just a placeholder for our
// script to write into. Create it to establish a unique name that
// we know.
NamedTempFile file("llsd", "");
python("write Python notation",
python("Python " + pyformatter,
[&](std::ostream& out){ out <<
import_llsd <<
"import struct\n"
"lenformat = struct.Struct('i')\n"
"DATA = [\n"
" 17,\n"
" 3.14,\n"
@ -1875,34 +2077,87 @@ namespace tut
"]\n"
// Don't forget raw-string syntax for Windows pathnames.
// N.B. Using 'print' implicitly adds newlines.
"with open(r'" << file.getName() << "', 'w') as f:\n"
"with open(r'" << file.getName() << "', 'wb') as f:\n"
" for item in DATA:\n"
" print(llsd.format_notation(item).decode(), file=f)\n";});
" serialized = llsd." << pyformatter << "(item)\n"
" f.write(lenformat.pack(len(serialized)))\n"
" f.write(serialized)\n");
std::ifstream inf(file.getName().c_str());
LLSD item;
// Notice that we're not doing anything special to parse out the
// newlines: LLSDSerialize::fromNotation ignores them. While it would
// seem they're not strictly necessary, going in this direction, we
// want to ensure that notation-separated-by-newlines works in both
// directions -- since in practice, a given file might be read by
// either language.
ensure_equals("Failed to read LLSD::Integer from Python",
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
1);
ensure_equals(item.asInteger(), 17);
ensure_equals("Failed to read LLSD::Real from Python",
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
1);
ensure_approximately_equals("Bad LLSD::Real value from Python",
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
ensure_equals("Failed to read LLSD::String from Python",
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
1);
ensure_equals(item.asString(),
"This string\n"
"has several\n"
"lines.");
try
{
ensure("Failed to read LLSD::Integer from Python",
itemFromStream(inf, item, parse));
ensure_equals(item.asInteger(), 17);
ensure("Failed to read LLSD::Real from Python",
itemFromStream(inf, item, parse));
ensure_approximately_equals("Bad LLSD::Real value from Python",
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
ensure("Failed to read LLSD::String from Python",
itemFromStream(inf, item, parse));
ensure_equals(item.asString(),
"This string\n"
"has several\n"
"lines.");
}
catch (const tut::failure& err)
{
std::cout << "for " << err.what() << ", item = " << item << std::endl;
throw;
}
}
template<> template<>
void TestPythonCompatibleObject::test<8>()
{
set_test_name("from Python XML using LLSDSerialize::deserialize()");
fromPythonUsing("format_xml");
}
template<> template<>
void TestPythonCompatibleObject::test<9>()
{
set_test_name("from Python notation using LLSDSerialize::deserialize()");
fromPythonUsing("format_notation");
}
template<> template<>
void TestPythonCompatibleObject::test<10>()
{
set_test_name("from Python binary using LLSDSerialize::deserialize()");
fromPythonUsing("format_binary");
}
template<> template<>
void TestPythonCompatibleObject::test<11>()
{
set_test_name("from Python XML using fromXML()");
// fromXML()'s optional 3rd param isn't max_bytes, it's emit_errors
fromPythonUsing("format_xml",
[](std::istream& istr, LLSD& data, llssize)
{ return LLSDSerialize::fromXML(data, istr) > 0; });
}
template<> template<>
void TestPythonCompatibleObject::test<12>()
{
set_test_name("from Python notation using fromNotation()");
fromPythonUsing("format_notation",
[](std::istream& istr, LLSD& data, llssize max_bytes)
{ return LLSDSerialize::fromNotation(data, istr, max_bytes) > 0; });
}
/*==========================================================================*|
template<> template<>
void TestPythonCompatibleObject::test<13>()
{
set_test_name("from Python binary using fromBinary()");
// We don't expect this to work because format_binary() emits a
// header, but fromBinary() won't recognize a header.
fromPythonUsing("format_binary",
[](std::istream& istr, LLSD& data, llssize max_bytes)
{ return LLSDSerialize::fromBinary(data, istr, max_bytes) > 0; });
}
|*==========================================================================*/
}

View File

@ -5482,14 +5482,14 @@ bool LLVolumeFace::cacheOptimize()
new_indices.push_back(tri->mVertex[2]->mIdx);
tri->complete();
U32 breaks = 0;
//U32 breaks = 0;
for (U32 i = 1; i < mNumIndices/3; ++i)
{
cache.updateScores();
tri = cache.mBestTriangle;
if (!tri)
{
breaks++;
//breaks++;
for (U32 j = 0; j < triangle_data.size(); ++j)
{
if (triangle_data[j].mActive)

View File

@ -271,7 +271,6 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
{
S32 resent_packets = 0;
LLReliablePacket *packetp;
@ -375,7 +374,6 @@ S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
// Don't remove it yet, it still gets to try to resend at least once.
++iter;
}
resent_packets++;
}
else
{

View File

@ -1336,6 +1336,48 @@ void HttpCoroutineAdapter::trivialPostCoro(std::string url, LLCore::HttpRequest:
}
/*static*/
void HttpCoroutineAdapter::callbackHttpDel(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success,
completionCallback_t failure)
{
LLCoros::instance().launch("HttpCoroutineAdapter::genericDelCoro",
boost::bind(&HttpCoroutineAdapter::trivialDelCoro, url, policyId, success, failure));
}
/*static*/
void HttpCoroutineAdapter::trivialDelCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success,
completionCallback_t failure)
{
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericDelCoro", policyId));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
httpOpts->setWantHeaders(true);
LL_INFOS("HttpCoroutineAdapter", "genericDelCoro") << "Generic DEL for " << url << LL_ENDL;
LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status)
{
if (failure)
{
failure(httpResults);
}
}
else
{
if (success)
{
success(result);
}
}
}
} // end namespace LLCoreHttpUtil

View File

@ -608,6 +608,9 @@ public:
callbackHttpPost(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, postData, success, failure);
}
static void callbackHttpDel(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success = NULL,
completionCallback_t failure = NULL);
/// Generic Get and post routines for HTTP via coroutines.
/// These static methods do all required setup for the GET or POST operation.
/// When the operation completes successfully they will put the success message in the log at INFO level,
@ -669,6 +672,7 @@ private:
static void trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure);
static void trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure);
static void trivialDelCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure);
void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers);

View File

@ -171,8 +171,9 @@ const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9;
const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10;
const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11;
const S32 ESTATE_MAX_MANAGERS = 15;
const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access, banned
const S32 ESTATE_MAX_MANAGERS = 20;
const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access
const S32 ESTATE_MAX_BANNED_IDS = 750; // max for banned
const S32 ESTATE_MAX_GROUP_IDS = (S32) ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET;
// 'Sim Wide Delete' flags

View File

@ -66,6 +66,14 @@ public:
static const LLMaterialID null;
// Returns a 64 bits digest of the material Id, by XORing its two 64 bits
// long words. HB
inline U64 getDigest64() const
{
U64* tmp = (U64*)mID;
return tmp[0] ^ tmp[1];
}
private:
void parseFromBinary(const LLSD::Binary& pMaterialID);
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
@ -74,5 +82,23 @@ private:
U8 mID[MATERIAL_ID_SIZE];
} ;
// std::hash implementation for LLMaterialID
namespace std
{
template<> struct hash<LLMaterialID>
{
inline size_t operator()(const LLMaterialID& id) const noexcept
{
return (size_t)id.getDigest64();
}
};
}
// For use with boost containers.
inline size_t hash_value(const LLMaterialID& id) noexcept
{
return (size_t)id.getDigest64();
}
#endif // LL_LLMATERIALID_H

View File

@ -2329,9 +2329,7 @@ void LLGLSyncFence::wait()
if (mSync)
{
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
{ //track the number of times we've waited here
static S32 waits = 0;
waits++;
{
}
}
#endif

View File

@ -942,11 +942,8 @@ void LLButton::draw()
break;
}
S32 y_offset = 2 + (getRect().getHeight() - 20)/2;
if (pressed && mDisplayPressedState)
{
y_offset--;
x++;
}

View File

@ -68,6 +68,7 @@ LLDragHandle::LLDragHandle(const LLDragHandle::Params& p)
LLDragHandle::~LLDragHandle()
{
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
removeChild(mTitleBox);
delete mTitleBox;
}

View File

@ -177,6 +177,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
LLFolderViewItem::~LLFolderViewItem()
{
mViewModelItem = NULL;
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
}
BOOL LLFolderViewItem::postBuild()

View File

@ -89,6 +89,8 @@ LLLayoutPanel::~LLLayoutPanel()
// probably not necessary, but...
delete mResizeBar;
mResizeBar = NULL;
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
}
F32 LLLayoutPanel::getAutoResizeFactor() const

View File

@ -487,9 +487,6 @@ void LLMenuItemGL::draw( void )
// let disabled items be highlighted, just don't draw them as such
if( getEnabled() && getHighlight() && !mBriefItem)
{
int debug_count = 0;
if (dynamic_cast<LLMenuItemCallGL*>(this))
debug_count++;
gGL.color4fv( mHighlightBackground.get().mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );

View File

@ -70,6 +70,11 @@ LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p)
}
}
LLResizeHandle::~LLResizeHandle()
{
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
}
BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask)
{

View File

@ -45,6 +45,7 @@ public:
Params();
};
~LLResizeHandle();
protected:
LLResizeHandle(const LLResizeHandle::Params&);
friend class LLUICtrlFactory;

View File

@ -774,7 +774,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
return 0;
}
U32 item = 0;
U32 validitems = 0;
S32 version;
@ -808,8 +807,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
}
// Got an item. Load it up.
item++;
// If not declared, assume it's a string
if (!declared)
{

View File

@ -1 +1 @@
6.6.14
6.6.15

View File

@ -209,6 +209,12 @@
<string>NoAudio</string>
</map>
<key>nofmod</key>
<map>
<key>map-to</key>
<string>UseMediaPluginsForStreamingAudio</string>
</map>
<key>noninteractive</key>
<map>
<key>desc</key>

View File

@ -7077,6 +7077,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>UseMediaPluginsForStreamingAudio</key>
<map>
<key>Comment</key>
<string>Use media plugins (VLC) for streaming audio.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NoHardwareProbe</key>
<map>
<key>Comment</key>
@ -11349,11 +11360,11 @@
<key>ShowBanLines</key>
<map>
<key>Comment</key>
<string>Show in-world ban/access borders</string>
<string>Show in-world ban/access borders, 0 - do not show, 1 - show on collision, 2 - show on proximity</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<string>S32</string>
<key>Value</key>
<integer>1</integer>
</map>
@ -16986,17 +16997,6 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>360CaptureUseInterestListCap</key>
<map>
<key>Comment</key>
<string>Flag if set, uses the new InterestList cap to ask the simulator for full content</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>360CaptureJPEGEncodeQuality</key>
<map>
<key>Comment</key>
@ -17107,5 +17107,38 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>StatsReportMaxDuration</key>
<map>
<key>Comment</key>
<string>Maximum seconds for viewer stats file data, prevents huge file</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>300</real>
</map>
<key>StatsReportFileInterval</key>
<map>
<key>Comment</key>
<string>Interval to save viewer stats file data</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.2</real>
</map>
<key>StatsReportSkipZeroDataSaves</key>
<map>
<key>Comment</key>
<string>In viewer stats data file, skip saving entry if there is no data</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>

View File

@ -506,7 +506,7 @@ Call un.UserSettingsFiles
SectionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make sure the user can install
;; Make sure the user can install/uninstall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function CheckIfAdministrator
DetailPrint $(CheckAdministratorInstDP)
@ -520,21 +520,6 @@ lbl_is_admin:
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make sure the user can uninstall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function un.CheckIfAdministrator
DetailPrint $(CheckAdministratorUnInstDP)
UserInfo::GetAccountType
Pop $R0
StrCmp $R0 "Admin" lbl_is_admin
MessageBox MB_OK $(CheckAdministratorUnInstMB)
Quit
lbl_is_admin:
Return
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function CheckWillUninstallV2
;;

View File

@ -401,6 +401,7 @@ LLAgent::LLAgent() :
mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mTeleportState(TELEPORT_NONE),
mRegionp(NULL),
mInterestListMode(LLViewerRegion::IL_MODE_DEFAULT),
mAgentOriginGlobal(),
mPositionGlobal(),
@ -894,11 +895,19 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal
// static
void LLAgent::capabilityReceivedCallback(const LLUUID &region_id, LLViewerRegion *regionp)
{
if (regionp && regionp->getRegionID() == region_id)
{ // Changed regions and now have the region capabilities
if (regionp)
{
regionp->requestSimulatorFeatures();
LLAppViewer::instance()->updateNameLookupUrl(regionp);
if (regionp->getRegionID() == region_id)
{
regionp->requestSimulatorFeatures();
LLAppViewer::instance()->updateNameLookupUrl(regionp);
}
if (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360)
{
gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360);
}
}
}
@ -1362,26 +1371,21 @@ LLVector3 LLAgent::getReferenceUpVector()
void LLAgent::pitch(F32 angle)
{
// don't let user pitch if pointed almost all the way down or up
mFrameAgent.pitch(clampPitchToLimits(angle));
}
// Radians, positive is forward into ground
//-----------------------------------------------------------------------------
// clampPitchToLimits()
//-----------------------------------------------------------------------------
F32 LLAgent::clampPitchToLimits(F32 angle)
{
// A dot B = mag(A) * mag(B) * cos(angle between A and B)
// so... cos(angle between A and B) = A dot B / mag(A) / mag(B)
// = A dot B for unit vectors
LLVector3 skyward = getReferenceUpVector();
const F32 look_down_limit = 179.f * DEG_TO_RAD;;
const F32 look_up_limit = 1.f * DEG_TO_RAD;
// SL-19286 Avatar is upside down when viewed from below
// after left-clicking the mouse on the avatar and dragging down
//
// The issue is observed on angle below 10 degrees
const F32 look_down_limit = 179.f * DEG_TO_RAD;
const F32 look_up_limit = 10.f * DEG_TO_RAD;
F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward );
F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
// clamp pitch to limits
if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
@ -1392,8 +1396,11 @@ F32 LLAgent::clampPitchToLimits(F32 angle)
{
angle = look_up_limit - angle_from_skyward;
}
return angle;
if (fabs(angle) > 1e-4)
{
mFrameAgent.pitch(angle);
}
}
@ -2910,39 +2917,60 @@ void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferr
handlePreferredMaturityResult(maturity);
}
// Using a new capability, tell the simulator that we want it to send everything
// it knows about and not just what is in front of the camera, in its view
// frustum. We need this feature so that the contents of the region that appears
// in the 6 snapshots which we cannot see and is normally not "considered", is
// also rendered. Typically, this is turned on when the 360 capture floater is
// opened and turned off when it is closed.
// Note: for this version, we do not have a way to determine when "everything"
// has arrived and has been rendered so for now, the proposal is that users
// will need to experiment with the low resolution version and wait for some
// (hopefully) small period of time while the full contents resolves.
// Pass in a flag to ask the simulator/interest list to "send everything" or
// not (the default mode)
void LLAgent::changeInterestListMode(const std::string &new_mode)
{
if (new_mode != mInterestListMode)
{
mInterestListMode = new_mode;
// Change interest list mode for all regions. If they are already set for the current mode,
// the setting will have no effect.
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end();
++iter)
{
LLViewerRegion *regionp = *iter;
if (regionp && regionp->isAlive() && regionp->capabilitiesReceived())
{
regionp->setInterestListMode(mInterestListMode);
}
}
}
else
{
LL_DEBUGS("360Capture") << "Agent interest list mode is already set to " << mInterestListMode << LL_ENDL;
}
}
bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure)
{
if (!getRegion())
if (getRegion())
{
return false;
return getRegion()->requestPostCapability(capName, postData, cbSuccess, cbFailure);
}
std::string url = getRegion()->getCapability(capName);
if (url.empty())
{
LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL;
return false;
}
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, mHttpPolicy, postData, cbSuccess, cbFailure);
return true;
return false;
}
bool LLAgent::requestGetCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure)
{
std::string url;
url = getRegionCapability(capName);
if (url.empty())
if (getRegion())
{
LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL;
return false;
return getRegion()->requestGetCapability(capName, cbSuccess, cbFailure);
}
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(url, mHttpPolicy, cbSuccess, cbFailure);
return true;
return false;
}
BOOL LLAgent::getAdminOverride() const
@ -3708,7 +3736,6 @@ void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **)
// take controls
msg->getU32("Data", "Controls", controls, block_index );
msg->getBOOL("Data", "PassToAgent", passon, block_index );
U32 total_count = 0;
for (i = 0; i < TOTAL_CONTROLS; i++)
{
if (controls & ( 1 << i))
@ -3721,7 +3748,6 @@ void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **)
{
gAgent.mControlsTakenCount[i]++;
}
total_count++;
}
}
}

View File

@ -294,10 +294,16 @@ public:
boost::signals2::connection addRegionChangedCallback(const region_changed_signal_t::slot_type& cb);
void removeRegionChangedCallback(boost::signals2::connection callback);
void changeInterestListMode(const std::string & new_mode);
const std::string & getInterestListMode() const { return mInterestListMode; }
private:
LLViewerRegion *mRegionp;
region_changed_signal_t mRegionChangedSignal;
std::string mInterestListMode; // How agent wants regions to send updates
//--------------------------------------------------------------------
// History
//--------------------------------------------------------------------
@ -548,7 +554,6 @@ public:
void roll(F32 angle);
void yaw(F32 angle);
LLVector3 getReferenceUpVector();
F32 clampPitchToLimits(F32 angle);
//--------------------------------------------------------------------
// Autopilot

View File

@ -401,10 +401,15 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi
// if is avatar - don't do any funk heuristics to position the focal point
// see DEV-30589
if (object->isAvatar() || (object->isAnimatedObject() && object->getControlAvatar()))
if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar()))
{
return original_focus_point - obj_pos;
}
if (object->isAvatar())
{
LLVOAvatar* av = object->asAvatar();
return original_focus_point - av->getCharacterPosition();
}
LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
LLVector3 object_extents = object->getScale();
@ -1759,13 +1764,24 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
LL_WARNS() << "Null avatar drawable!" << LL_ENDL;
return LLVector3d::zero;
}
head_offset.clearVec();
F32 fixup;
if (gAgentAvatarp->hasPelvisFixup(fixup))
{
head_offset[VZ] -= fixup;
}
if (gAgentAvatarp->isSitting())
{
head_offset.mdV[VZ] += 0.1;
}
if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent())
{
gAgentAvatarp->updateHeadOffset();
head_offset.mdV[VX] = gAgentAvatarp->mHeadOffset.mV[VX];
head_offset.mdV[VY] = gAgentAvatarp->mHeadOffset.mV[VY];
head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ] + 0.1f;
head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX];
head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY];
head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ];
const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix();
camera_position_global = gAgent.getPosGlobalFromAgent
((gAgentAvatarp->getPosition()+
@ -1773,11 +1789,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
}
else
{
head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ];
if (gAgentAvatarp->isSitting())
{
head_offset.mdV[VZ] += 0.1;
}
head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ];
camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global;
head_offset = head_offset * gAgentAvatarp->getRenderRotation();
camera_position_global = camera_position_global + head_offset;

View File

@ -35,6 +35,7 @@
#include "llcommandhandler.h"
#include "llslurl.h"
#include "llurldispatcher.h"
#include "llviewernetwork.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
@ -148,7 +149,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
params.append(event_data["x"]);
params.append(event_data["y"]);
params.append(event_data["z"]);
LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true);
LLCommandDispatcher::dispatch("teleport", params, LLSD(), LLGridManager::getInstance()->getGrid(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true);
// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
// should we just compose LLCommandHandler and LLDispatchListener?
}

View File

@ -82,9 +82,9 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const
if (!region || !parcel) return FALSE;
S32 pos_x = S32(agent_pos_region.mV[VX]);
S32 pos_y = S32(agent_pos_region.mV[VY]);
S32 pos_z = S32(agent_pos_region.mV[VZ]);
S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f);
S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f);
S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f);
// Round the numbers based on the velocity
F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();

View File

@ -41,7 +41,6 @@
#include "llinventoryobserver.h"
#include "llinventorypanel.h"
#include "lllocaltextureobject.h"
#include "llmd5.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
#include "llsidepanelappearance.h"

View File

@ -41,7 +41,9 @@
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventoryobserver.h"
#include "llmd5.h"
#include "llnotificationsutil.h"
#include "llmd5.h"
#include "lloutfitobserver.h"
#include "lloutfitslist.h"
#include "llselectmgr.h"
@ -145,7 +147,10 @@ public:
// requests will be throttled from a non-trusted browser
LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
bool handle(const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
// support secondlife:///app/appearance/show, but for now we just
// make all secondlife:///app/appearance SLapps behave this way
@ -4470,8 +4475,10 @@ public:
// not allowed from outside the app
LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
bool handle(const LLSD& tokens,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
LLSD::UUID folder_uuid;

View File

@ -1536,7 +1536,12 @@ bool LLAppViewer::doFrame()
LLFloaterSimpleOutfitSnapshot::update();
gGLActive = FALSE;
}
}
if (LLViewerStatsRecorder::instanceExists())
{
LLViewerStatsRecorder::instance().idle();
}
}
}
{

View File

@ -31,6 +31,7 @@
#include "llagent.h"
#include "llappearancemgr.h"
#include "llinventorymodel.h"
#include "llstartup.h"
#include "lltooldraganddrop.h" // pack_permissions_slam
#include "llviewerinventory.h"
#include "llviewerregion.h"
@ -372,7 +373,7 @@ void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id)
{
LLTimer timer;
bool expected = mAttachmentRequests.getTime(inv_item_id, timer);
if (!expected)
if (!expected && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT)
{
LLInventoryItem *item = gInventory.getItem(inv_item_id);
LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: "
@ -411,11 +412,15 @@ void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL;
}
}
else
else if (!LLApp::isExiting())
{
LL_WARNS() << "ATT unexpected detach for "
<< (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL;
}
else
{
LL_DEBUGS("Avatar") << "ATT detach on shutdown for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL;
}
LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking "
<< (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL;

View File

@ -43,7 +43,7 @@ public:
// requests will be throttled from a non-trusted browser
LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
{
std::string action( "" );
if ( params.size() >= 1 )

View File

@ -82,7 +82,7 @@ public:
// requests will be throttled from a non-trusted browser
LLObjectIMHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
{
if (params.size() < 1)
{

View File

@ -57,7 +57,7 @@ class LLObjectHandler : public LLCommandHandler
public:
LLObjectHandler() : LLCommandHandler("object", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
{
if (params.size() < 2) return false;

View File

@ -64,10 +64,10 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const
// But for testing, allow a caller to specify untrusted.
trusted_browser = params["trusted"].asBoolean();
}
LLCommandDispatcher::dispatch(
params["cmd"],
LLCommandDispatcher::dispatch(params["cmd"],
params["params"],
params["query"],
"",
NULL,
LLCommandHandler::NAV_TYPE_CLICKED,
trusted_browser);

View File

@ -62,6 +62,7 @@ public:
bool dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser);
@ -98,6 +99,7 @@ void LLCommandHandlerRegistry::add(const char* cmd,
bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser)
@ -165,7 +167,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
}
}
if (!info.mHandler) return false;
return info.mHandler->handle(params, query_map, web);
return info.mHandler->handle(params, query_map, grid, web);
}
void LLCommandHandlerRegistry::notifySlurlBlocked()
@ -220,12 +222,13 @@ LLCommandHandler::~LLCommandHandler()
bool LLCommandDispatcher::dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser)
{
return LLCommandHandlerRegistry::instance().dispatch(
cmd, params, query_map, web, nav_type, trusted_browser);
cmd, params, query_map, grid, web, nav_type, trusted_browser);
}
static std::string lookup(LLCommandHandler::EUntrustedAccess value);

View File

@ -42,7 +42,7 @@ public:
LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid,
LLMediaCtrl* web)
{
if (tokens.size() < 1) return false;
@ -90,6 +90,7 @@ public:
virtual bool handle(const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web) = 0;
// For URL secondlife:///app/foo/bar/baz?cat=1&dog=2
// @params - array of "bar", "baz", possibly empty
@ -106,6 +107,7 @@ public:
static bool dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser);

View File

@ -47,6 +47,7 @@ LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewer
mGlobalScale(1.0f),
mMarkedForDeath(false),
mRootVolp(NULL),
mControlAVBridge(NULL),
mScaleConstraintFixup(1.0),
mRegionChanged(false)
{
@ -376,6 +377,12 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
}
}
void LLControlAvatar::markDead()
{
super::markDead();
mControlAVBridge = NULL;
}
bool LLControlAvatar::computeNeedsUpdate()
{
computeUpdatePeriod();

View File

@ -35,9 +35,12 @@ class LLControlAvatar:
{
LOG_CLASS(LLControlAvatar);
using super = LLVOAvatar;
public:
LLControlAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
virtual void initInstance(); // Called after construction to initialize the class.
virtual void initInstance(); // Called after construction to initialize the class.
virtual void markDead();
virtual ~LLControlAvatar();
// If this is an attachment, return the avatar it is attached to. Otherwise NULL.
@ -87,6 +90,7 @@ public:
F32 mGlobalScale;
LLVOVolume *mRootVolp;
class LLControlAVBridge* mControlAVBridge;
bool mMarkedForDeath;

View File

@ -763,6 +763,19 @@ void LLDrawable::movePartition()
if (part)
{
part->move(this, getSpatialGroup());
// SL-18251 "On-screen animesh characters using pelvis offset animations
// disappear when root goes off-screen"
//
// Update extents of the root node when Control Avatar changes it's bounds
if (mRenderType == LLPipeline::RENDER_TYPE_CONTROL_AV && isRoot())
{
LLControlAvatar* controlAvatar = dynamic_cast<LLControlAvatar*>(getVObj().get());
if (controlAvatar && controlAvatar->mControlAVBridge)
{
((LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0))->setState(LLViewerOctreeGroup::DIRTY);
}
}
}
}
@ -1216,10 +1229,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
{
setSpatialBridge(new LLHUDBridge(this, getRegion()));
}
else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
{
setSpatialBridge(new LLControlAVBridge(this, getRegion()));
}
else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
{
setSpatialBridge(new LLControlAVBridge(this, getRegion()));
mVObjp->getControlAvatar()->mControlAVBridge = (LLControlAVBridge*)getSpatialBridge();
}
// check HUD first, because HUD is also attachment
else if (mVObjp->isAttachment())
{

View File

@ -43,8 +43,10 @@ class LLEventHandler : public LLCommandHandler
public:
// requires trusted browser to trigger
LLEventHandler() : LLCommandHandler("event", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
bool handle(const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
if (params.size() < 2)
{

View File

@ -103,7 +103,6 @@ std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::st
}
}
}
return outfiles;
}
@ -150,7 +149,7 @@ void doLoadDialogModeless(const std::vector<std::string>* allowed_types,
}
}
std::unique_ptr<std::string> doSaveDialog(const std::string* file,
std::unique_ptr<std::string> doSaveDialog(const std::string* file,
const std::string* type,
const std::string* creator,
const std::string* extension,

View File

@ -64,12 +64,10 @@ LLFloater360Capture::LLFloater360Capture(const LLSD& key)
// such time as we ask it not to (the dtor). If we crash or
// otherwise, exit before this is turned off, the Simulator
// will take care of cleaning up for us.
if (gSavedSettings.getBOOL("360CaptureUseInterestListCap"))
{
// send everything to us for as long as this floater is open
const bool send_everything = true;
changeInterestListMode(send_everything);
}
mStartILMode = gAgent.getInterestListMode();
// send everything to us for as long as this floater is open
gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360);
}
LLFloater360Capture::~LLFloater360Capture()
@ -81,13 +79,15 @@ LLFloater360Capture::~LLFloater360Capture()
mWebBrowser->unloadMediaSource();
}
// Tell the Simulator not to send us everything anymore
// and revert to the regular "keyhole" frustum of interest
// Restore interest list mode to the state when started
// Normally LLFloater360Capture tells the Simulator send everything
// and now reverts to the regular "keyhole" frustum of interest
// list updates.
if (!LLApp::isExiting() && gSavedSettings.getBOOL("360CaptureUseInterestListCap"))
if (!LLApp::isExiting() &&
gSavedSettings.getBOOL("360CaptureUseInterestListCap") &&
mStartILMode != gAgent.getInterestListMode())
{
const bool send_everything = false;
changeInterestListMode(send_everything);
gAgent.changeInterestListMode(mStartILMode);
}
}
@ -170,52 +170,6 @@ void LLFloater360Capture::onChooseQualityRadioGroup()
setSourceImageSize();
}
// Using a new capability, tell the simulator that we want it to send everything
// it knows about and not just what is in front of the camera, in its view
// frustum. We need this feature so that the contents of the region that appears
// in the 6 snapshots which we cannot see and is normally not "considered", is
// also rendered. Typically, this is turned on when the 360 capture floater is
// opened and turned off when it is closed.
// Note: for this version, we do not have a way to determine when "everything"
// has arrived and has been rendered so for now, the proposal is that users
// will need to experiment with the low resolution version and wait for some
// (hopefully) small period of time while the full contents resolves.
// Pass in a flag to ask the simulator/interest list to "send everything" or
// not (the default mode)
void LLFloater360Capture::changeInterestListMode(bool send_everything)
{
LLSD body;
if (send_everything)
{
body["mode"] = LLSD::String("360");
}
else
{
body["mode"] = LLSD::String("default");
}
if (gAgent.requestPostCapability("InterestList", body, [](const LLSD & response)
{
LL_INFOS("360Capture") <<
"InterestList capability responded: \n" <<
ll_pretty_print_sd(response) <<
LL_ENDL;
}))
{
LL_INFOS("360Capture") <<
"Successfully posted an InterestList capability request with payload: \n" <<
ll_pretty_print_sd(body) <<
LL_ENDL;
}
else
{
LL_INFOS("360Capture") <<
"Unable to post an InterestList capability request with payload: \n" <<
ll_pretty_print_sd(body) <<
LL_ENDL;
}
}
// There is is a setting (360CaptureSourceImageSize) that holds the size
// (width == height since it's a square) of each of the 6 source snapshots.
@ -632,11 +586,8 @@ void LLFloater360Capture::capture360Images()
// display time to encode all 6 images. It tends to be a fairly linear
// time for each so we don't need to worry about displaying the time
// for each - this gives us plenty to use for optimizing
LL_INFOS("360Capture") <<
"Time to encode and save 6 images was " <<
encode_time_total <<
" seconds" <<
LL_ENDL;
LL_INFOS("360Capture") << "Time to encode and save 6 images was " <<
encode_time_total << " seconds" << LL_ENDL;
// Write the JavaScript file footer (the bottom of the file after the
// declarations of the actual data URLs array). The footer comprises of
@ -668,7 +619,7 @@ void LLFloater360Capture::capture360Images()
// as a change - only the subsequent 5 are
if (camera_changed_times < 5)
{
LL_INFOS("360Capture") << "Warning: we only captured " << camera_changed_times << " images." << LL_ENDL;
LL_WARNS("360Capture") << "360 image capture expected 5 or more images, only captured " << camera_changed_times << " images." << LL_ENDL;
}
// now we have the 6 shots saved in a well specified location,

View File

@ -50,8 +50,6 @@ class LLFloater360Capture:
void onOpen(const LLSD& key) override;
void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override;
void changeInterestListMode(bool send_everything);
const std::string getHTMLBaseFolder();
void capture360Images();
@ -93,6 +91,8 @@ class LLFloater360Capture:
std::string mImageSaveDir;
LLPointer<LLImageRaw> mRawImages[6];
std::string mStartILMode;
};
#endif // LL_FLOATER_360CAPTURE_H

View File

@ -24,6 +24,7 @@
*/
#include "llviewerprecompiledheaders.h"
#include "llfloatercamera.h"
#include "llfloatercamerapresets.h"
#include "llfloaterreg.h"
#include "llnotificationsutil.h"
@ -40,7 +41,8 @@ LLFloaterCameraPresets::~LLFloaterCameraPresets()
BOOL LLFloaterCameraPresets::postBuild()
{
mPresetList = getChild<LLFlatListView>("preset_list");
mPresetList->setCommitCallback(boost::bind(&LLFloaterCameraPresets::onSelectionChange, this));
mPresetList->setCommitOnSelectionChange(true);
LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCameraPresets::populateList, this));
return TRUE;
@ -58,6 +60,7 @@ void LLFloaterCameraPresets::populateList()
std::list<std::string> preset_names;
presetsMgr->loadPresetNamesFromDir(PRESETS_CAMERA, preset_names, DEFAULT_BOTTOM);
std::string active_preset = gSavedSettings.getString("PresetCameraActive");
for (std::list<std::string>::const_iterator it = preset_names.begin(); it != preset_names.end(); ++it)
{
@ -66,6 +69,19 @@ void LLFloaterCameraPresets::populateList()
LLCameraPresetFlatItem* item = new LLCameraPresetFlatItem(name, is_default);
item->postBuild();
mPresetList->addItem(item);
if(name == active_preset)
{
mPresetList->selectItem(item);
}
}
}
void LLFloaterCameraPresets::onSelectionChange()
{
LLCameraPresetFlatItem* selected_preset = dynamic_cast<LLCameraPresetFlatItem*>(mPresetList->getSelectedItem());
if(selected_preset)
{
LLFloaterCamera::switchToPreset(selected_preset->getPresetName());
}
}

View File

@ -38,6 +38,7 @@ class LLFloaterCameraPresets : public LLFloater
virtual void onOpen(const LLSD& key);
void populateList();
void onSelectionChange();
private:
LLFloaterCameraPresets(const LLSD& key);
@ -58,6 +59,8 @@ public:
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
std::string getPresetName() { return mPresetName; }
private:
void onDeleteBtnClick();
void onResetBtnClick();

View File

@ -92,8 +92,10 @@ class LLExperienceHandler : public LLCommandHandler
public:
LLExperienceHandler() : LLCommandHandler("experience", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
bool handle(const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
if(params.size() != 2 || params[1].asString() != "profile")
return false;

View File

@ -49,7 +49,7 @@ LLFloater* get_parent_floater(LLView* view)
}
bool LLFloaterHandler::handle(const LLSD &params, const LLSD &query_map, LLMediaCtrl *web)
bool LLFloaterHandler::handle(const LLSD &params, const LLSD &query_map, const std::string& grid, LLMediaCtrl *web)
{
if (params.size() < 1) return false;
LLFloater* floater = NULL;

View File

@ -33,7 +33,7 @@ class LLFloaterHandler
{
public:
LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web);
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web);
};
#endif

View File

@ -903,8 +903,10 @@ public:
LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
bool handle(const LLSD& tokens,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
bool retval = false;
// Need at least 2 tokens to have a valid message.

View File

@ -2795,7 +2795,7 @@ BOOL LLPanelEstateAccess::postBuild()
if (banned_name_list)
{
banned_name_list->setCommitOnSelectionChange(TRUE);
banned_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS);
banned_name_list->setMaxItemCount(ESTATE_MAX_BANNED_IDS);
}
getChild<LLUICtrl>("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2));
@ -2939,10 +2939,10 @@ void LLPanelEstateAccess::onClickAddBannedAgent()
{
LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list");
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
if (list->getItemCount() >= ESTATE_MAX_BANNED_IDS)
{
LLSD args;
args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_BANNED_IDS);
LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args);
return;
}
@ -3180,13 +3180,13 @@ void LLPanelEstateAccess::accessAddCore3(const uuid_vec_t& ids, std::vector<LLAv
LLNameListCtrl* name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list");
LLNameListCtrl* em_list = panel->getChild<LLNameListCtrl>("estate_manager_name_list");
int currentCount = (name_list ? name_list->getItemCount() : 0);
if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS)
if (ids.size() + currentCount > ESTATE_MAX_BANNED_IDS)
{
LLSD args;
args["NUM_ADDED"] = llformat("%d", ids.size());
args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_BANNED_IDS);
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");
args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_ACCESS_IDS);
args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_BANNED_IDS);
LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
@ -3565,7 +3565,7 @@ void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url)
{
LLStringUtil::format_map_t args;
args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size());
args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_BANNED_IDS);
std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);
panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));

View File

@ -46,7 +46,7 @@ class LLSearchHandler : public LLCommandHandler
public:
// requires trusted browser to trigger
LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
{
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch"))
{

View File

@ -49,6 +49,7 @@
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "lluictrlfactory.h"
#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
#include "llfloaterregioninfo.h"
@ -83,6 +84,8 @@ LLFloaterTopObjects::LLFloaterTopObjects(const LLSD& key)
mCommitCallbackRegistrar.add("TopObjects.GetByOwnerName", boost::bind(&LLFloaterTopObjects::onGetByOwnerName, this));
mCommitCallbackRegistrar.add("TopObjects.GetByParcelName", boost::bind(&LLFloaterTopObjects::onGetByParcelName, this));
mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this));
mCommitCallbackRegistrar.add("TopObjects.TeleportToSelected", boost::bind(&LLFloaterTopObjects::teleportToSelectedObject, this));
}
LLFloaterTopObjects::~LLFloaterTopObjects()
@ -92,10 +95,11 @@ LLFloaterTopObjects::~LLFloaterTopObjects()
// virtual
BOOL LLFloaterTopObjects::postBuild()
{
LLScrollListCtrl *objects_list = getChild<LLScrollListCtrl>("objects_list");
getChild<LLUICtrl>("objects_list")->setFocus(TRUE);
objects_list->setDoubleClickCallback(onDoubleClickObjectsList, this);
objects_list->setCommitOnSelectionChange(TRUE);
mObjectsScrollList = getChild<LLScrollListCtrl>("objects_list");
mObjectsScrollList->setFocus(TRUE);
mObjectsScrollList->setDoubleClickCallback(onDoubleClickObjectsList, this);
mObjectsScrollList->setCommitOnSelectionChange(TRUE);
mObjectsScrollList->setCommitCallback(boost::bind(&LLFloaterTopObjects::onSelectionChanged, this));
setDefaultBtn("show_beacon_btn");
@ -421,6 +425,8 @@ void LLFloaterTopObjects::clearList()
mObjectListData.clear();
mObjectListIDs.clear();
mtotalScore = 0.f;
onSelectionChanged();
}
@ -507,3 +513,38 @@ void LLFloaterTopObjects::showBeacon()
std::string tooltip("");
LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);
}
void LLFloaterTopObjects::teleportToSelectedObject()
{
std::vector<LLScrollListItem*> selected_items = mObjectsScrollList->getAllSelected();
if (selected_items.size() == 1)
{
LLScrollListItem* first_selected = selected_items.front();
LLVector3d teleport_location;
LLViewerObject *viewer_object = gObjectList.findObject(first_selected->getUUID());
if (viewer_object == NULL)
{
// If we cannot find the object in the viewer list, teleport to the last reported position
std::string pos_string = first_selected->getColumn(3)->getValue().asString();
F32 x, y, z;
S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
if (matched != 3) return;
LLVector3 pos_agent(x, y, z);
teleport_location = gAgent.getPosGlobalFromAgent(pos_agent);
}
else
{
// If we can find the object in the viewer list, teleport to the known current position
teleport_location = viewer_object->getPositionGlobal();
}
gAgent.teleportViaLocationLookAt(teleport_location);
}
}
void LLFloaterTopObjects::onSelectionChanged()
{
getChildView("teleport_btn")->setEnabled(mObjectsScrollList->getNumSelected() == 1);
}

View File

@ -30,6 +30,7 @@
#include "llfloater.h"
class LLUICtrl;
class LLScrollListCtrl;
// Bits for simulator performance query flags
enum LAND_STAT_FLAGS
@ -75,6 +76,7 @@ private:
void initColumns(LLCtrlListInterface *list);
void onCommitObjectsList();
void onSelectionChanged();
static void onDoubleClickObjectsList(void* data);
void onClickShowBeacon();
@ -90,6 +92,7 @@ private:
void onGetByParcelName();
void showBeacon();
void teleportToSelectedObject();
private:
std::string mMethod;
@ -106,6 +109,7 @@ private:
F32 mtotalScore;
static LLFloaterTopObjects* sInstance;
LLScrollListCtrl* mObjectsScrollList;
};
#endif

View File

@ -124,8 +124,10 @@ public:
// requires trusted browser to trigger
LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
bool handle(const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap"))
{
@ -163,7 +165,10 @@ public:
{
}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
bool handle(const LLSD& params,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap"))
{

View File

@ -741,6 +741,12 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV
gGL.end();
}
void LLViewerParcelMgr::resetCollisionTimer()
{
mCollisionTimer.reset();
mRenderCollision = TRUE;
}
void draw_line_cube(F32 width, const LLVector3& center)
{
width = 0.5f * width;

View File

@ -78,8 +78,10 @@ public:
return true;
}
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
bool handle(const LLSD& tokens,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
if (LLStartUp::getStartupState() < STATE_STARTED)
{

View File

@ -1631,14 +1631,19 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
from_group = message_data["from_group"].asString() == "Y";
}
EInstantMessage dialog = static_cast<EInstantMessage>(message_data["dialog"].asInteger());
LLUUID session_id = message_data["transaction-id"].asUUID();
if (session_id.isNull() && dialog == IM_FROM_TASK)
{
session_id = message_data["asset_id"].asUUID();
}
LLIMProcessing::processNewMessage(
message_data["from_agent_id"].asUUID(),
from_group,
message_data["to_agent_id"].asUUID(),
message_data.has("offline") ? static_cast<U8>(message_data["offline"].asInteger()) : IM_OFFLINE,
static_cast<EInstantMessage>(message_data["dialog"].asInteger()),
message_data["transaction-id"].asUUID(),
dialog,
session_id,
static_cast<U32>(message_data["timestamp"].asInteger()),
message_data["from_agent_name"].asString(),
message_data["message"].asString(),

View File

@ -213,8 +213,7 @@ bool contains_nocopy_items(const LLUUID& id)
return false;
}
// Generates a string containing the path to the item specified by
// item_id.
// Generates a string containing the path to the item specified by id.
void append_path(const LLUUID& id, std::string& path)
{
std::string temp;
@ -234,6 +233,36 @@ void append_path(const LLUUID& id, std::string& path)
path.append(temp);
}
// Generates a string containing the path name of the object.
std::string make_path(const LLInventoryObject* object)
{
std::string path;
append_path(object->getUUID(), path);
return path + "/" + object->getName();
}
// Generates a string containing the path name of the object specified by id.
std::string make_inventory_path(const LLUUID& id)
{
if (LLInventoryObject* object = gInventory.getObject(id))
return make_path(object);
return "";
}
// Generates a string containing the path name and id of the object.
std::string make_info(const LLInventoryObject* object)
{
return "'" + make_path(object) + "' (" + object->getUUID().asString() + ")";
}
// Generates a string containing the path name and id of the object specified by id.
std::string make_inventory_info(const LLUUID& id)
{
if (LLInventoryObject* object = gInventory.getObject(id))
return make_info(object);
return "<Inventory object not found!> (" + id.asString() + ")";
}
void update_marketplace_folder_hierarchy(const LLUUID cat_id)
{
// When changing the marketplace status of a folder, the only thing that needs to happen is
@ -1415,6 +1444,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
if (copy)
{
// Copy the item
LL_INFOS("SLM") << "Copy item '" << make_info(viewer_inv_item) << "' to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL;
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder));
copy_inventory_item(
gAgent.getID(),
@ -1426,6 +1456,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
}
else
{
LL_INFOS("SLM") << "Move item '" << make_info(viewer_inv_item) << "' to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL;
// Reparent the item
gInventory.changeItemParent(viewer_inv_item, dest_folder, true);
}
@ -1472,6 +1503,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
}
else
{
LL_INFOS("SLM") << "Move category " << make_info(viewer_inv_cat) << " to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL;
// Reparent the folder
gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false);
// Check the destination folder recursively for no copy items and promote the including folders if any

View File

@ -78,9 +78,19 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory*
void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items);
// Generates a string containing the path to the item specified by item_id.
// Generates a string containing the path to the object specified by id (not including the object name).
void append_path(const LLUUID& id, std::string& path);
// Generates a string containing the path name of the object.
std::string make_path(const LLInventoryObject* object);
// Generates a string containing the path name of the object specified by id.
std::string make_inventory_path(const LLUUID& id);
// Generates a string containing the path name and id of the object.
std::string make_info(const LLInventoryObject* object);
// Generates a string containing the path name and id of the object specified by id.
std::string make_inventory_info(const LLUUID& id);
typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t;
bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);

View File

@ -62,6 +62,7 @@
#include "bufferarray.h"
#include "bufferstream.h"
#include "llcorehttputil.h"
#include "hbxxh.h"
//#define DIFF_INVENTORY_FILES
#ifdef DIFF_INVENTORY_FILES
@ -451,17 +452,16 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
items = get_ptr_in_map(mParentChildItemTree, cat_id);
}
LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
LLInventoryModel::digest_t LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
{
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
getDirectDescendentsOf(cat_id,cat_array,item_array);
LLMD5 item_name_hash;
if (!item_array)
{
item_name_hash.finalize();
return item_name_hash;
return LLUUID::null;
}
HBXXH128 item_name_hash;
for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin();
iter != item_array->end();
iter++)
@ -471,8 +471,7 @@ LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
continue;
item_name_hash.update(item->getName());
}
item_name_hash.finalize();
return item_name_hash;
return item_name_hash.digest();
}
// SJB: Added version to lock the arrays to catch potential logic bugs
@ -673,6 +672,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
const std::string& pname,
inventory_func_type callback)
{
LL_DEBUGS(LOG_INV) << "Create '" << pname << "' in '" << make_inventory_path(parent_id) << "'" << LL_ENDL;
LLUUID id;
if (!isInventoryUsable())
{
@ -764,6 +764,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
cat->packMessage(msg);
gAgent.sendReliableMessage();
LL_INFOS(LOG_INV) << "Created new category '" << make_inventory_path(id) << "'" << LL_ENDL;
// return the folder id of the newly created folder
return id;
}
@ -1352,6 +1353,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
if(cat && (cat->getParentUUID() != cat_id))
{
LL_DEBUGS(LOG_INV) << "Move category '" << make_path(cat) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
cat_array_t* cat_array;
cat_array = getUnlockedCatArray(cat->getParentUUID());
if(cat_array) vector_replace_with_last(*cat_array, cat);
@ -1364,6 +1366,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
LLPointer<LLViewerInventoryItem> item = getItem(object_id);
if(item && (item->getParentUUID() != cat_id))
{
LL_DEBUGS(LOG_INV) << "Move item '" << make_path(item) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
item_array_t* item_array;
item_array = getUnlockedItemArray(item->getParentUUID());
if(item_array) vector_replace_with_last(*item_array, item);
@ -1382,14 +1385,14 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item,
{
if (item->getParentUUID() == new_parent_id)
{
LL_DEBUGS(LOG_INV) << "'" << item->getName() << "' (" << item->getUUID()
<< ") is already in folder " << new_parent_id << LL_ENDL;
LL_DEBUGS(LOG_INV) << make_info(item) << " is already in folder " << make_inventory_info(new_parent_id) << LL_ENDL;
}
else
{
LL_INFOS(LOG_INV) << "Moving '" << item->getName() << "' (" << item->getUUID()
<< ") from " << item->getParentUUID() << " to folder "
<< new_parent_id << LL_ENDL;
LL_INFOS(LOG_INV) << "Move item " << make_info(item)
<< " from " << make_inventory_info(item->getParentUUID())
<< " to " << make_inventory_info(new_parent_id) << LL_ENDL;
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
update.push_back(old_folder);
@ -1421,6 +1424,10 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
return;
}
LL_INFOS(LOG_INV) << "Move category " << make_info(cat)
<< " from " << make_inventory_info(cat->getParentUUID())
<< " to " << make_inventory_info(new_parent_id) << LL_ENDL;
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
update.push_back(old_folder);

View File

@ -39,7 +39,6 @@
#include "llpermissionsflags.h"
#include "llviewerinventory.h"
#include "llstring.h"
#include "llmd5.h"
#include "httpcommon.h"
#include "httprequest.h"
#include "httpoptions.h"
@ -257,8 +256,9 @@ public:
cat_array_t*& categories,
item_array_t*& items) const;
typedef LLUUID digest_t; // To clarify the actual usage of this "UUID"
// Compute a hash of direct descendant names (for detecting child name changes)
LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const;
digest_t hashDirectDescendentNames(const LLUUID& cat_id) const;
// Starting with the object specified, add its descendants to the
// array provided, but do not add the inventory object specified

View File

@ -640,7 +640,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
// computed, or (b) a name has changed.
if (!cat_data.mIsNameHashInitialized || (mask & LLInventoryObserver::LABEL))
{
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
if (cat_data.mItemNameHash != item_name_hash)
{
cat_data.mIsNameHashInitialized = true;
@ -701,7 +701,7 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t
{
if(init_name_hash)
{
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents,item_name_hash)));
}
else
@ -727,11 +727,10 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
, mDescendentsCount(num_descendents)
, mIsNameHashInitialized(false)
{
mItemNameHash.finalize();
}
LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash)
const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash)
: mCatID(cat_id)
, mCallback(cb)

View File

@ -28,7 +28,6 @@
#define LL_LLINVENTORYOBSERVERS_H
#include "lluuid.h"
#include "llmd5.h"
#include <string>
#include <vector>
@ -271,14 +270,15 @@ public:
void removeCategory(const LLUUID& cat_id);
protected:
typedef LLUUID digest_t; // To clarify the actual usage of this "UUID"
struct LLCategoryData
{
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents);
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash);
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash);
callback_t mCallback;
S32 mVersion;
S32 mDescendentsCount;
LLMD5 mItemNameHash;
digest_t mItemNameHash;
bool mIsNameHashInitialized;
LLUUID mCatID;
};

View File

@ -87,6 +87,7 @@ void LLLoginHandler::parse(const LLSD& queryMap)
bool LLLoginHandler::handle(const LLSD& tokens,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
// do nothing if we are already logged in

View File

@ -35,7 +35,7 @@ class LLLoginHandler : public LLCommandHandler
public:
// allow from external browsers
LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { }
/*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web);
/*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web);
// Fill in our internal fields from a SLURL like
// secondlife:///app/login?first=Bob&last=Dobbs

View File

@ -93,7 +93,11 @@ private:
bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
};
// definitions follow class
friend std::hash<TEMaterialPair>;
friend size_t hash_value(const TEMaterialPair&) noexcept;
friend inline bool operator<(
const LLMaterialMgr::TEMaterialPair& lhs,
const LLMaterialMgr::TEMaterialPair& rhs)
@ -102,13 +106,6 @@ private:
(lhs.materialID < rhs.materialID);
}
struct TEMaterialPairHasher
{
enum { bucket_size = 8 };
size_t operator()(const TEMaterialPair& key_value) const { return *((size_t*)key_value.materialID.get()); } // cheesy, but effective
bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; }
};
typedef std::set<LLMaterialID> material_queue_t;
typedef std::map<LLUUID, material_queue_t> get_queue_t;
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
@ -116,7 +113,7 @@ private:
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
typedef std::set<LLUUID> getall_queue_t;
typedef std::map<LLUUID, F64> getall_pending_map_t;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
@ -146,5 +143,23 @@ private:
U32 getMaxEntries(const LLViewerRegion* regionp);
};
// std::hash implementation for TEMaterialPair
namespace std
{
template<> struct hash<LLMaterialMgr::TEMaterialPair>
{
inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept
{
return size_t((p.te + 1) * p.materialID.getDigest64());
}
};
}
// For use with boost containers.
inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept
{
return size_t((p.te + 1) * p.materialID.getDigest64());
}
#endif // LL_LLMATERIALMGR_H

View File

@ -56,6 +56,7 @@
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerstatsrecorder.h"
#include "llviewertexturelist.h"
#include "llvolume.h"
#include "llvolumemgr.h"
@ -1862,10 +1863,10 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
const LLUUID mesh_id = mesh_params.getSculptID();
LLSD header;
U32 header_size = 0;
llssize header_size = 0;
if (data_size > 0)
{
U32 dsize = data_size;
llssize dsize = data_size;
char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size);
data_size = dsize;
@ -4089,6 +4090,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
}
mLoadingMeshes[detail].erase(obj_iter);
LLViewerStatsRecorder::instance().meshLoaded();
}
}

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