From 37c5016c2fa1ab3e7ced19d81a4ce5fa6fee04a9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 15 May 2011 22:17:15 -0500 Subject: [PATCH 1/5] LLAssetType lookup now done through LLDictionary. --- indra/llcommon/llassettype.cpp | 373 ++++++++++++----------------- indra/llcommon/llassettype.h | 31 ++- indra/newview/llinventorymodel.cpp | 17 ++ 3 files changed, 180 insertions(+), 241 deletions(-) diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index f9c73a20a..13c8f649d 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -33,207 +33,115 @@ #include "linden_common.h" #include "llassettype.h" +#include "lldictionary.h" +#include "llmemory.h" -#include "llstring.h" -#include "lltimer.h" - -// I added lookups for exact text of asset type enums in addition to the ones below, so shoot me. -Steve - -struct asset_info_t +///---------------------------------------------------------------------------- +/// Class LLAssetType +///---------------------------------------------------------------------------- +struct AssetEntry : public LLDictionaryEntry { - LLAssetType::EType type; - const char* desc; + AssetEntry(const char *desc_name, + const char *type_name, // 8 character limit! + const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one + bool can_link, // can you create a link to this type? + bool can_fetch, // can you fetch this asset by ID? + bool can_know) // can you see this asset's ID? + : + LLDictionaryEntry(desc_name), + mTypeName(type_name), + mHumanName(human_name), + mCanLink(can_link), + mCanFetch(can_fetch), + mCanKnow(can_know) + { + llassert(strlen(mTypeName) <= 8); + } + + const char *mTypeName; + const char *mHumanName; + bool mCanLink; + bool mCanFetch; + bool mCanKnow; }; -asset_info_t asset_types[] = +class LLAssetDictionary : public LLSingleton, + public LLDictionary { - { LLAssetType::AT_TEXTURE, "TEXTURE" }, - { LLAssetType::AT_SOUND, "SOUND" }, - { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, - { LLAssetType::AT_LANDMARK, "LANDMARK" }, - { LLAssetType::AT_SCRIPT, "SCRIPT" }, - { LLAssetType::AT_CLOTHING, "CLOTHING" }, - { LLAssetType::AT_OBJECT, "OBJECT" }, - { LLAssetType::AT_NOTECARD, "NOTECARD" }, - { LLAssetType::AT_CATEGORY, "CATEGORY" }, - { LLAssetType::AT_ROOT_CATEGORY, "ROOT_CATEGORY" }, - { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, - { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, - { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, - { LLAssetType::AT_BODYPART, "BODYPART" }, - { LLAssetType::AT_TRASH, "TRASH" }, - { LLAssetType::AT_SNAPSHOT_CATEGORY, "SNAPSHOT_CATEGORY" }, - { LLAssetType::AT_LOST_AND_FOUND, "LOST_AND_FOUND" }, - { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, - { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, - { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, - { LLAssetType::AT_ANIMATION, "ANIMATION" }, - { LLAssetType::AT_GESTURE, "GESTURE" }, - { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, - { LLAssetType::AT_FAVORITE, "FAVORITE" }, - { LLAssetType::AT_LINK, "LINK" }, - { LLAssetType::AT_LINK_FOLDER, "CURRENT" }, - { LLAssetType::AT_CURRENT_OUTFIT, "FOLDER_LINK" }, - { LLAssetType::AT_OUTFIT, "OUTFIT" }, - { LLAssetType::AT_MY_OUTFITS, "MY_OUTFITS" }, - { LLAssetType::AT_NONE, "NONE" } +public: + LLAssetDictionary(); }; -LLAssetType::EType LLAssetType::getType(const std::string& sin) +LLAssetDictionary::LLAssetDictionary() { - std::string s = sin; + // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW? + // |--------------------|-----------|-------------------|-----------|-----------|---------| + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false)); + addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", false, false, false)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true)); + addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", false, false, false)); + addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", false, false, false)); + addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", false, false, false)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false)); + addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "", false, false, false)); + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true)); + addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); + addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("FOLDER_LINK", "current", "current outfit", false, false, false)); + addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false)); + addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false)); + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false)); +}; + +// static +LLAssetType::EType LLAssetType::getType(const std::string& desc_name) +{ + std::string s = desc_name; LLStringUtil::toUpper(s); - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (info->type == LLAssetType::AT_NONE) - break; - if (s == info->desc) - return info->type; - } - return LLAssetType::AT_NONE; + return LLAssetDictionary::getInstance()->lookup(s); } -std::string LLAssetType::getDesc(LLAssetType::EType type) -{ - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (type == info->type) - return info->desc; - if (info->type == LLAssetType::AT_NONE) - break; - } - return "BAD TYPE"; -} - -//============================================================================ - -// The asset type names are limited to 8 characters. // static -const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "callcard", - "landmark", - "script", - "clothing", - "object", - "notecard", - "category", - "root", - "lsltext", - "lslbyte", - "txtr_tga",// Intentionally spelled this way. Limited to eight characters. - "bodypart", - "trash", - "snapshot", - "lstndfnd", - "snd_wav", - "img_tga", - "jpeg", - "animatn", - "gesture", - "simstate", - "favorite", - "link", - "link_f", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "current", - "outfit", - "my_otfts" -}; - -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES -const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "calling card", - "landmark", - "legacy script", - "clothing", - "object", - "note card", - "folder", - "root", - "lsl2 script", - "lsl bytecode", - "tga texture", - "body part", - "trash", - "snapshot", - "lost and found", - "sound", - "targa image", - "jpeg image", - "animation", - "gesture", - "simstate", - "", - "symbolic link", - "symbolic folder link" - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "current outfit", - "outfit", - "my outfits" -}; - -///---------------------------------------------------------------------------- -/// class LLAssetType -///---------------------------------------------------------------------------- - -// static -const char* LLAssetType::lookup( LLAssetType::EType type ) +const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type); + if (entry) { - return mAssetTypeNames[ S32( type ) ]; + return entry->mName; } else { - return "-1"; + return badLookup(); + } +} + +// static +const char *LLAssetType::lookup(LLAssetType::EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mTypeName; + } + else + { + return badLookup().c_str(); } } @@ -243,29 +151,35 @@ LLAssetType::EType LLAssetType::lookup( const char* name ) return lookup(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookup( const std::string& name ) +// static +LLAssetType::EType LLAssetType::lookup(const std::string& type_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeNames[i] ) + const AssetEntry *entry = iter->second; + if (type_name == entry->mTypeName) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; } // static -const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type) +const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - return mAssetTypeHumanNames[S32(type)]; + return entry->mHumanName; } else { - return NULL; + return badLookup().c_str(); } } @@ -275,14 +189,18 @@ LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name ) return lookupHumanReadable(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookupHumanReadable( const std::string& name ) +// static +LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeHumanNames[i] ) + const AssetEntry *entry = iter->second; + if (entry->mHumanName && (readable_name == entry->mHumanName)) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; @@ -333,6 +251,16 @@ void LLAssetType::generateDescriptionFor(LLAssetType::EType type, // static bool LLAssetType::lookupCanLink(EType asset_type) { + //Check that enabling all these other types as linkable doesn't break things. + /*const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mCanLink; + } + return false; + */ + return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY || asset_type == AT_BODYPART || asset_type == AT_GESTURE); } @@ -341,45 +269,42 @@ bool LLAssetType::lookupCanLink(EType asset_type) // Not adding this to dictionary since we probably will only have these two types bool LLAssetType::lookupIsLinkType(EType asset_type) { - return (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER); + if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER) + { + return true; + } + return false; +} + +// static +const std::string &LLAssetType::badLookup() +{ + static const std::string sBadLookup = "llassettype_bad_lookup"; + return sBadLookup; + } // static bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type) { - // *FIX: Make this list smaller. - switch(asset_type) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - return true; - default: - return false; + return entry->mCanFetch; } + return false; } // static bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) { - switch(asset_type) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - case LLAssetType::AT_TEXTURE: - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - case LLAssetType::AT_LINK: - case LLAssetType::AT_LINK_FOLDER: - return true; - default: - return false; + return entry->mCanKnow; } + return false; } diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index a769e165c..b4f8ce4cf 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -160,39 +160,36 @@ public: }; // machine transation between type and strings - static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate - static EType lookup(const std::string& name); - static const char* lookup(EType type); + static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate + static EType lookup(const std::string& type_name); + static const char* lookup(EType asset_type); // translation from a type to a human readable form. - static EType lookupHumanReadable( const char* name ); // safe conversion to std::string, *TODO: deprecate - static EType lookupHumanReadable( const std::string& name ); - static const char* lookupHumanReadable(EType type); + static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate + static EType lookupHumanReadable(const std::string& readable_name); + static const char* lookupHumanReadable(EType asset_type); - static EDragAndDropType lookupDragAndDropType( EType ); + static EDragAndDropType lookupDragAndDropType( EType ); // Generate a good default description. You may want to add a verb // or agent name after this depending on your application. static void generateDescriptionFor(LLAssetType::EType type, std::string& desc); - static EType getType(const std::string& sin); - static std::string getDesc(EType type); - + static EType getType(const std::string& desc_name); + static const std::string& getDesc(EType asset_type); + static bool lookupCanLink(EType asset_type); static bool lookupIsLinkType(EType asset_type); static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer -private: - // don't instantiate or derive one of these objects - LLAssetType( void ) {} - ~LLAssetType( void ) {} + static const std::string& badLookup(); // error string when a lookup fails -private: - static const char* mAssetTypeNames[]; - static const char* mAssetTypeHumanNames[]; +protected: + LLAssetType() {} + ~LLAssetType() {} }; #endif // LL_LLASSETTYPE diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 910d94baf..009d7c5b0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1972,6 +1972,23 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) //llinfos << "LLInventoryModel::addItem()" << llendl; if(item) { + // This can happen if assettype enums from llassettype.h ever change. + // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when + // the AT_LINK enum changed from 23 to 24. + if ((item->getType() == LLAssetType::AT_NONE) + || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup()) + { + llwarns << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << llendl; + return; + } + + // This condition means that we tried to add a link without the baseobj being in memory. + // The item will show up as a broken link. + if (item->getIsBrokenLink()) + { + llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl; + } + mItemMap[item->getUUID()] = item; } } From e3435d7ef9c5cc3b51398ad663f375900651ba36 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 15 May 2011 22:22:22 -0500 Subject: [PATCH 2/5] Slight llcharacter updates from v2 (should be safe) --- indra/llcharacter/llbvhloader.cpp | 10 +++++----- indra/llcharacter/llcharacter.h | 2 +- indra/llcharacter/llkeyframemotion.h | 1 - indra/llcharacter/llkeyframestandmotion.cpp | 2 +- indra/llcharacter/llpose.h | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 7a516f838..12bcffac2 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -48,10 +48,10 @@ using namespace std; #define INCHES_TO_METERS 0.02540005f -const F32 POSITION_KEYFRAME_THRESHOLD = 0.03f; +const F32 POSITION_KEYFRAME_THRESHOLD_SQUARED = 0.03f * 0.03f; const F32 ROTATION_KEYFRAME_THRESHOLD = 0.01f; -const F32 POSITION_MOTION_THRESHOLD = 0.001f; +const F32 POSITION_MOTION_THRESHOLD_SQUARED = 0.001f * 0.001f; const F32 ROTATION_MOTION_THRESHOLD = 0.001f; char gInFile[1024]; /* Flawfinder: ignore */ @@ -1202,7 +1202,7 @@ void LLBVHLoader::optimize() if (ki_prev == ki_last_good_pos) { joint->mNumPosKeys++; - if (dist_vec(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD) + if (dist_vec_squared(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } @@ -1215,12 +1215,12 @@ void LLBVHLoader::optimize() LLVector3 current_pos(ki->mPos); LLVector3 interp_pos = lerp(current_pos, last_good_pos, 1.f / (F32)numPosFramesConsidered); - if (dist_vec(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD) + if (dist_vec_squared(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } - if (dist_vec(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD) + if (dist_vec_squared(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD_SQUARED) { ki_prev->mIgnorePos = TRUE; numPosFramesConsidered++; diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 4de59e9ee..f7206f750 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -261,7 +261,7 @@ public: } return 0; } - S32 getVisualParamCount() { return (S32)mVisualParamIndexMap.size(); } + S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); } LLVisualParam* getVisualParam(const char *name); diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index 7e8c84488..50d9d0504 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -47,7 +47,6 @@ #include "llquaternion.h" #include "v3dmath.h" #include "v3math.h" -#include "llapr.h" #include "llbvhconsts.h" class LLKeyframeDataCache; diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp index 1d42298f4..1ae0ddeea 100644 --- a/indra/llcharacter/llkeyframestandmotion.cpp +++ b/indra/llcharacter/llkeyframestandmotion.cpp @@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask) if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD) { mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation(); - mLastGoodPelvisRotation.normQuat(); + mLastGoodPelvisRotation.normalize(); mTrackAnkles = TRUE; } else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD) diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index 5698f2161..80487bd12 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -36,12 +36,12 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include -#include "llmap.h" #include "lljointstate.h" #include "lljoint.h" +#include "llmap.h" #include +#include //----------------------------------------------------------------------------- From 51338470b586ff9912deb752a3143f6ade084654 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 15 May 2011 22:40:59 -0500 Subject: [PATCH 3/5] Pulled LLEventTimer out of lltimer.h/cpp and into lleventtimer.h/cpp LLInstanceTracker added to llcommon (pulled from llui in v2 for usage elsewhere) LLEventTimer now using LLInstanceTracker Updated LLLiveAppConfig (Though it appears unused, really) processor.h is obsolete, thus removed. (llprocessor.h replaces it) --- indra/llcommon/CMakeLists.txt | 5 +- indra/llcommon/llapp.cpp | 18 +- indra/llcommon/llapp.h | 15 ++ indra/llcommon/llerrorthread.cpp | 2 +- indra/llcommon/lleventtimer.cpp | 115 +++++++++++ indra/llcommon/lleventtimer.h | 66 +++++++ indra/llcommon/llinstancetracker.cpp | 47 +++++ indra/llcommon/llinstancetracker.h | 202 ++++++++++++++++++++ indra/llcommon/llliveappconfig.cpp | 13 +- indra/llcommon/llliveappconfig.h | 32 +++- indra/llcommon/lllivefile.cpp | 2 +- indra/llcommon/llprocessor.cpp | 4 +- indra/llcommon/llrun.h | 2 - indra/llcommon/lltimer.cpp | 57 +----- indra/llcommon/lltimer.h | 27 +-- indra/llcommon/processor.h | 33 ---- indra/llcommon/timing.h | 3 +- indra/llui/lldelayeduidelete.h | 2 +- indra/llui/llnotifications.h | 1 + indra/llui/llui.h | 56 ------ indra/newview/chatbar_as_cmdline.cpp | 1 + indra/newview/floaterao.h | 1 + indra/newview/floaterlocalassetbrowse.h | 1 + indra/newview/llappviewer.cpp | 1 + indra/newview/llbuildnewviewsscheduler.h | 1 + indra/newview/lleventpoll.cpp | 5 +- indra/newview/llfloaterexploresounds.h | 1 + indra/newview/llfloaterfriends.cpp | 2 +- indra/newview/llfloaterfriends.h | 2 +- indra/newview/llfloatermessagelog.cpp | 1 + indra/newview/llfloatermessagelog.h | 1 + indra/newview/llnotify.cpp | 6 +- indra/newview/llnotify.h | 2 +- indra/newview/llpreviewscript.h | 2 +- indra/newview/llviewermessage.cpp | 2 +- indra/newview/llviewerparcelmediaautoplay.h | 2 +- indra/newview/rlvhandler.h | 1 + indra/newview/rlvhelper.h | 1 + indra/newview/rlvlocks.h | 1 + 39 files changed, 535 insertions(+), 201 deletions(-) create mode 100644 indra/llcommon/lleventtimer.cpp create mode 100644 indra/llcommon/lleventtimer.h create mode 100644 indra/llcommon/llinstancetracker.cpp create mode 100644 indra/llcommon/llinstancetracker.h delete mode 100644 indra/llcommon/processor.h diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 29fa35619..1c475b78f 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -32,6 +32,7 @@ set(llcommon_SOURCE_FILES llerror.cpp llerrorthread.cpp llevent.cpp + lleventtimer.cpp llfasttimer.cpp llfile.cpp llfindlocale.cpp @@ -39,6 +40,7 @@ set(llcommon_SOURCE_FILES llformat.cpp llframetimer.cpp llheartbeat.cpp + llinstancetracker.cpp llindraconfigfile.cpp llliveappconfig.cpp lllivefile.cpp @@ -122,6 +124,7 @@ set(llcommon_HEADER_FILES llevent.h lleventemitter.h llextendedstatus.h + lleventtimer.h llfasttimer.h llfile.h llfindlocale.h @@ -132,6 +135,7 @@ set(llcommon_HEADER_FILES llheartbeat.h llhttpstatuscodes.h llindexedqueue.h + llinstancetracker.h llindraconfigfile.h llkeythrottle.h lllinkedqueue.h @@ -188,7 +192,6 @@ set(llcommon_HEADER_FILES metaclasst.h metaproperty.h metapropertyt.h - processor.h reflective.h reflectivet.h roles_constants.h diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 3bb833a94..c35a84255 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -38,8 +38,10 @@ #include "llerrorcontrol.h" #include "llerrorthread.h" #include "llframetimer.h" +#include "lllivefile.h" #include "llmemory.h" -#include "lltimer.h" +#include "llstl.h" // for DeletePointer() +#include "lleventtimer.h" // // Signal handling @@ -139,6 +141,11 @@ LLApp::~LLApp() delete sSigChildCount; sSigChildCount = NULL; #endif + + // reclaim live file memory + std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer()); + mLiveFiles.clear(); + setStopped(); // HACK: wait for the error thread to clean itself ms_sleep(20); @@ -212,6 +219,15 @@ bool LLApp::parseCommandOptions(int argc, char** argv) return true; } + +void LLApp::manageLiveFile(LLLiveFile* livefile) +{ + if(!livefile) return; + livefile->checkAndReload(); + livefile->addToEventTimer(); + mLiveFiles.push_back(livefile); +} + bool LLApp::setOptionData(OptionPriority level, LLSD data) { if((level < 0) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index d5cf6ea93..05e2bccaf 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -131,6 +131,19 @@ public: */ bool parseCommandOptions(int argc, char** argv); + /** + * @brief Keep track of live files automatically. + * + * *TODO: it currently uses the addToEventTimer() API + * instead of the runner. I should probalby use the runner. + * + * *NOTE: DO NOT add the livefile instance to any kind of check loop. + * + * @param livefile A valid instance of an LLLiveFile. This LLApp + * instance will delete the livefile instance. + */ + void manageLiveFile(LLLiveFile* livefile); + /** * @brief Set the options at the specified priority. * @@ -285,6 +298,8 @@ private: // The application options. LLSD mOptions; + // The live files for this application + std::vector mLiveFiles; //@} private: diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index e2b106aa2..293379910 100644 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp @@ -32,7 +32,7 @@ #include "linden_common.h" #include "llerrorthread.h" #include "llapp.h" -#include "lltimer.h" +#include "lltimer.h" // ms_sleep() LLErrorThread::LLErrorThread() : LLThread("Error"), diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp new file mode 100644 index 000000000..2720b93ab --- /dev/null +++ b/indra/llcommon/lleventtimer.cpp @@ -0,0 +1,115 @@ +/** + * @file lleventtimer.cpp + * @brief Cross-platform objects for doing timing + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#include "linden_common.h" + +#include "lleventtimer.h" + +#include "u64.h" + + +////////////////////////////////////////////////////////////////////////////// +// +// LLEventTimer Implementation +// +////////////////////////////////////////////////////////////////////////////// + +//std::list LLEventTimer::sActiveList; + +LLEventTimer::LLEventTimer(F32 period) +: mEventTimer() +{ + mPeriod = period; + //sActiveList.push_back(this); +} + +LLEventTimer::LLEventTimer(const LLDate& time) +: mEventTimer() +{ + mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); + //sActiveList.push_back(this); +} + + +LLEventTimer::~LLEventTimer() +{ + //sActiveList.remove(this); +} + +//static +void LLEventTimer::updateClass() +{ + std::list completed_timers; + + /*{ + for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) + { + LLEventTimer* timer = *iter++; + F32 et = timer->mEventTimer.getElapsedTimeF32(); + if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { + timer->mEventTimer.reset(); + if ( timer->tick() ) + { + completed_timers.push_back( timer ); + } + } + } + }*/ + { + LLInstanceTrackerScopedGuard guard; + for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ) + { + LLEventTimer& timer = *iter++; + F32 et = timer.mEventTimer.getElapsedTimeF32(); + if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { + timer.mEventTimer.reset(); + if ( timer.tick() ) + { + completed_timers.push_back( &timer ); + } + } + } + } + + if ( completed_timers.size() > 0 ) + { + for (std::list::iterator completed_iter = completed_timers.begin(); + completed_iter != completed_timers.end(); + completed_iter++ ) + { + delete *completed_iter; + } + } +} + + diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h new file mode 100644 index 000000000..1521b507a --- /dev/null +++ b/indra/llcommon/lleventtimer.h @@ -0,0 +1,66 @@ +/** + * @file lleventtimer.h + * @brief Cross-platform objects for doing timing + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#ifndef LL_EVENTTIMER_H +#define LL_EVENTTIMER_H + +#include "stdtypes.h" +#include "lldate.h" +#include "llinstancetracker.h" +#include "lltimer.h" + +// class for scheduling a function to be called at a given frequency (approximate, inprecise) +class LL_COMMON_API LLEventTimer : public LLInstanceTracker +{ +public: + LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds + LLEventTimer(const LLDate& time); + virtual ~LLEventTimer(); + + //function to be called at the supplied frequency + // Normally return FALSE; TRUE will delete the timer after the function returns. + virtual BOOL tick() = 0; + + static void updateClass(); + +protected: + LLTimer mEventTimer; + F32 mPeriod; + +//private: + //list of active timers +// static std::list sActiveList; // TODO should this be a vector +}; + + +#endif //LL_EVENTTIMER_H diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp new file mode 100644 index 000000000..293a1388f --- /dev/null +++ b/indra/llcommon/llinstancetracker.cpp @@ -0,0 +1,47 @@ +/** + * @file lllinstancetracker.cpp + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinstancetracker.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +//static +void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) +{ + static std::map instances; + + std::string k = info.name(); + if(instances.find(k) == instances.end()) + { + instances[k] = NULL; + } + + return instances[k]; +} diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h new file mode 100644 index 000000000..e4e535222 --- /dev/null +++ b/indra/llcommon/llinstancetracker.h @@ -0,0 +1,202 @@ +/** + * @file llinstancetracker.h + * @brief LLInstanceTracker is a mixin class that automatically tracks object + * instances with or without an associated key + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#ifndef LL_LLINSTANCETRACKER_H +#define LL_LLINSTANCETRACKER_H + +#include + +#include "string_table.h" +#include +#include +#include +#include +#include + +class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +{ + protected: + static void * & getInstances(std::type_info const & info); +}; +/// This mix-in class adds support for tracking all instances of the specified class parameter T +/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup +/// If KEY is not provided, then instances are stored in a simple set +/// @NOTE: see explicit specialization below for default KEY==T* case +template +class LLInstanceTracker : public LLInstanceTrackerBase +{ + typedef typename std::map InstanceMap; + typedef LLInstanceTracker MyT; + typedef boost::function KeyGetter; + typedef boost::function InstancePtrGetter; +public: + /// Dereferencing key_iter gives you a const KEY& + typedef boost::transform_iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator< boost::transform_iterator > instance_iter; + + static T* getInstance(const KEY& k) + { + typename InstanceMap::const_iterator found = getMap_().find(k); + return (found == getMap_().end()) ? NULL : found->second; + } + + static key_iter beginKeys() + { + return boost::make_transform_iterator(getMap_().begin(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static key_iter endKeys() + { + return boost::make_transform_iterator(getMap_().end(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static instance_iter beginInstances() + { + return instance_iter(boost::make_transform_iterator(getMap_().begin(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static instance_iter endInstances() + { + return instance_iter(boost::make_transform_iterator(getMap_().end(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static S32 instanceCount() { return getMap_().size(); } +protected: + LLInstanceTracker(KEY key) { add_(key); } + virtual ~LLInstanceTracker() { remove_(); } + virtual void setKey(KEY key) { remove_(); add_(key); } + virtual const KEY& getKey() const { return mKey; } + +private: + void add_(KEY key) + { + mKey = key; + getMap_()[key] = static_cast(this); + } + void remove_() + { + getMap_().erase(mKey); + } + + static InstanceMap& getMap_() + { + void * & instances = getInstances(typeid(MyT)); + if (! instances) + { + instances = new InstanceMap; + } + return * static_cast(instances); + } + +private: + + KEY mKey; +}; + +/// explicit specialization for default case where KEY is T* +/// use a simple std::set +template +class LLInstanceTracker : public LLInstanceTrackerBase +{ + typedef typename std::set InstanceSet; + typedef LLInstanceTracker MyT; +public: + /// Dereferencing key_iter gives you a T* (since T* is the key) + typedef typename InstanceSet::iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator instance_iter; + + /// for completeness of analogy with the generic implementation + static T* getInstance(T* k) { return k; } + static S32 instanceCount() { return getSet_().size(); } + + // Instantiate this to get access to iterators for this type. It's a 'guard' in the sense + // that it treats deletes of this type as errors as long as there is an instance of + // this class alive in scope somewhere (i.e. deleting while iterating is bad). + class LLInstanceTrackerScopedGuard + { + public: + LLInstanceTrackerScopedGuard() + { + ++sIterationNestDepth; + } + + ~LLInstanceTrackerScopedGuard() + { + --sIterationNestDepth; + } + + static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } + static instance_iter endInstances() { return instance_iter(getSet_().end()); } + static key_iter beginKeys() { return getSet_().begin(); } + static key_iter endKeys() { return getSet_().end(); } + }; + +protected: + LLInstanceTracker() + { + // it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle. + //llassert(sIterationNestDepth == 0); + getSet_().insert(static_cast(this)); + } + virtual ~LLInstanceTracker() + { + // it's unsafe to delete instances of this type while all instances are being iterated over. + llassert(sIterationNestDepth == 0); + getSet_().erase(static_cast(this)); + } + + LLInstanceTracker(const LLInstanceTracker& other) + { + //llassert(sIterationNestDepth == 0); + getSet_().insert(static_cast(this)); + } + + static InstanceSet& getSet_() + { + void * & instances = getInstances(typeid(MyT)); + if (! instances) + { + instances = new InstanceSet; + } + return * static_cast(instances); + } + + static S32 sIterationNestDepth; +}; + +template S32 LLInstanceTracker::sIterationNestDepth = 0; + +#endif diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp index d2744875d..75bdfee8b 100644 --- a/indra/llcommon/llliveappconfig.cpp +++ b/indra/llcommon/llliveappconfig.cpp @@ -38,9 +38,12 @@ #include "llsd.h" #include "llsdserialize.h" -LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period) -: LLLiveFile(filename, refresh_period), - mApp(app) +LLLiveAppConfig::LLLiveAppConfig( + const std::string& filename, + F32 refresh_period, + LLApp::OptionPriority priority) : + LLLiveFile(filename, refresh_period), + mPriority(priority) { } @@ -77,7 +80,7 @@ bool LLLiveAppConfig::loadFile() // to set the config to an empty config, and return that it // changed. - mApp->setOptionData( - LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config); + LLApp* app = LLApp::instance(); + if(app) app->setOptionData(mPriority, config); return true; } diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h index 465dde160..73b3a2335 100644 --- a/indra/llcommon/llliveappconfig.h +++ b/indra/llcommon/llliveappconfig.h @@ -33,25 +33,43 @@ #ifndef LLLIVEAPPCONFIG_H #define LLLIVEAPPCONFIG_H +#include "llapp.h" #include "lllivefile.h" -class LLApp; +/** + * @class LLLiveAppConfig + * @see LLLiveFile + * + * To use this, instantiate a LLLiveAppConfig object inside your main + * loop. The traditional name for it is live_config. Be sure to call + * live_config.checkAndReload() periodically. + */ class LL_COMMON_API LLLiveAppConfig : public LLLiveFile { public: - // To use this, instantiate a LLLiveAppConfig object inside your main loop. - // The traditional name for it is live_config. - // Be sure to call live_config.checkAndReload() periodically. - LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period); - ~LLLiveAppConfig(); + /** + * @brief Constructor + * + * @param filename. The name of the file for periodically checking + * configuration. + * @param refresh_period How often the internal timer should + * bother checking the filesystem. + * @param The application priority level of that configuration file. + */ + LLLiveAppConfig( + const std::string& filename, + F32 refresh_period, + LLApp::OptionPriority priority); + + ~LLLiveAppConfig(); ///< Destructor protected: /*virtual*/ bool loadFile(); private: - LLApp* mApp; + LLApp::OptionPriority mPriority; }; #endif diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index 322f226d5..ce6ac4fac 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -33,7 +33,7 @@ #include "lllivefile.h" #include "llframetimer.h" -#include "lltimer.h" +#include "lleventtimer.h" const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 469e544b1..88c49a10c 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -47,10 +47,8 @@ // solving some compiler conversion problems // - Fixed a bug at family=6, model=6 (Celeron -> P2) ////////////////////////////////////////////////////////////////////////////////// - #include "linden_common.h" - -#include "processor.h" +#include "llprocessor.h" #include diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h index 0f8d51d81..1fc9925df 100644 --- a/indra/llcommon/llrun.h +++ b/indra/llcommon/llrun.h @@ -38,8 +38,6 @@ #include #include -#include "llpreprocessor.h" - class LLRunnable; /** diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index c0d47890c..34e19f83f 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -33,7 +33,6 @@ #include "linden_common.h" #include "lltimer.h" -#include "timing.h" // totalTime prototype. #include "u64.h" @@ -52,6 +51,9 @@ // // Locally used constants // +const U32 SEC_PER_DAY = 86400; +const F64 SEC_TO_MICROSEC = 1000000.f; +const U64 SEC_TO_MICROSEC_U64 = 1000000; const F64 USEC_TO_SEC_F64 = 0.000001; @@ -571,59 +573,6 @@ void timeStructToFormattedString(struct tm * time, std::string format, std::stri } -////////////////////////////////////////////////////////////////////////////// -// -// LLEventTimer Implementation -// -////////////////////////////////////////////////////////////////////////////// - -std::list LLEventTimer::sActiveList; - -LLEventTimer::LLEventTimer(F32 period) -: mEventTimer() -{ - mPeriod = period; - sActiveList.push_back(this); -} - -LLEventTimer::LLEventTimer(const LLDate& time) -: mEventTimer() -{ - mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); - sActiveList.push_back(this); -} -LLEventTimer::~LLEventTimer() -{ - sActiveList.remove(this); -} - -void LLEventTimer::updateClass() -{ - std::list completed_timers; - for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) - { - LLEventTimer* timer = *iter++; - F32 et = timer->mEventTimer.getElapsedTimeF32(); - if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { - timer->mEventTimer.reset(); - if ( timer->tick() ) - { - completed_timers.push_back( timer ); - } - } - } - - if ( completed_timers.size() > 0 ) - { - for (std::list::iterator completed_iter = completed_timers.begin(); - completed_iter != completed_timers.end(); - completed_iter++ ) - { - delete *completed_iter; - } - } -} - diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 26734919c..68f06fdce 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -55,6 +55,8 @@ const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR; const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR; const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC; +LL_COMMON_API U64 totalTime(); // Returns current system time in microseconds + class LL_COMMON_API LLTimer { public: @@ -155,7 +157,7 @@ static inline time_t time_max() } // Correction factor used by time_corrected() above. -LL_COMMON_API extern S32 gUTCOffset; +extern LL_COMMON_API S32 gUTCOffset; // Is the current computer (in its current time zone) // observing daylight savings time? @@ -173,27 +175,4 @@ LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstri LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string ×tr); LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr); -// class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LL_COMMON_API LLEventTimer -{ -public: - LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds - LLEventTimer(const LLDate& time); - virtual ~LLEventTimer(); - - //function to be called at the supplied frequency - // Normally return FALSE; TRUE will delete the timer after the function returns. - virtual BOOL tick() = 0; - - static void updateClass(); - -protected: - LLTimer mEventTimer; - F32 mPeriod; - -private: - //list of active timers - static std::list sActiveList; // TODO should this be a vector -}; - #endif diff --git a/indra/llcommon/processor.h b/indra/llcommon/processor.h deleted file mode 100644 index 5ba55402b..000000000 --- a/indra/llcommon/processor.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file processor.h - * @brief Legacy wrapper header. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llprocessor.h" diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h index cfc637eb6..140ce1fca 100644 --- a/indra/llcommon/timing.h +++ b/indra/llcommon/timing.h @@ -43,7 +43,6 @@ const F32 SEC_TO_MICROSEC = 1000000.f; const U64 SEC_TO_MICROSEC_U64 = 1000000; const U32 SEC_PER_DAY = 86400; -// This is just a stub, implementation in lltimer.cpp. This file will be deprecated in the future. -LL_COMMON_API U64 totalTime(); // Returns current system time in microseconds +// functionality has been moved lltimer.{cpp,h}. This file will be deprecated in the future. #endif diff --git a/indra/llui/lldelayeduidelete.h b/indra/llui/lldelayeduidelete.h index 2f08ee8fa..043e6972e 100644 --- a/indra/llui/lldelayeduidelete.h +++ b/indra/llui/lldelayeduidelete.h @@ -1,7 +1,7 @@ // #ifndef LL_LLDELAYEDUIDELETE_H #define LL_LLDELAYEDUIDELETE_H -#include "lltimer.h" +#include "lleventtimer.h" #include "llview.h" class LLDeleteJob { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index bb379121c..4b325f54d 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -96,6 +96,7 @@ // we want to minimize external dependencies, but this one is important #include "llsd.h" +#include "llinstancetracker.h" // and we need this to manage the notification callbacks #include "llfunctorregistry.h" diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c7b7446a0..abc9a298b 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -602,62 +602,6 @@ public: virtual void cleanUp() = 0; }; -// This mix-in class adds support for tracking all instances of the specificed class parameter T -// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup -// If KEY is not provided, then instances are stored in a simple list -template -class LLInstanceTracker : boost::noncopyable -{ -public: - typedef typename std::map::iterator instance_iter; - typedef typename std::map::const_iterator instance_const_iter; - - static T* getInstance(KEY k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; } - - static instance_iter beginInstances() { return sInstances.begin(); } - static instance_iter endInstances() { return sInstances.end(); } - static S32 instanceCount() { return sInstances.size(); } -protected: - LLInstanceTracker(KEY key) { add(key); } - virtual ~LLInstanceTracker() { remove(); } - virtual void setKey(KEY key) { remove(); add(key); } - virtual const KEY& getKey() const { return mKey; } - -private: - void add(KEY key) - { - mKey = key; - sInstances[key] = static_cast(this); - } - void remove() { sInstances.erase(mKey); } - -private: - - KEY mKey; - static std::map sInstances; -}; - -template -class LLInstanceTracker : boost::noncopyable -{ -public: - typedef typename std::set::iterator instance_iter; - typedef typename std::set::const_iterator instance_const_iter; - - static instance_iter instancesBegin() { return sInstances.begin(); } - static instance_iter instancesEnd() { return sInstances.end(); } - static S32 instanceCount() { return sInstances.size(); } - -protected: - LLInstanceTracker() { sInstances.insert(static_cast(this)); } - virtual ~LLInstanceTracker() { sInstances.erase(static_cast(this)); } - - static std::set sInstances; -}; - -template std::map LLInstanceTracker::sInstances; -template std::set LLInstanceTracker::sInstances; - class LLCallbackRegistry { public: diff --git a/indra/newview/chatbar_as_cmdline.cpp b/indra/newview/chatbar_as_cmdline.cpp index 818df6279..e43a185c6 100644 --- a/indra/newview/chatbar_as_cmdline.cpp +++ b/indra/newview/chatbar_as_cmdline.cpp @@ -41,6 +41,7 @@ #include "llviewerregion.h" #include "llworld.h" #include "lluuid.h" +#include "lleventtimer.h" #include "llviewercontrol.h" #include "material_codes.h" diff --git a/indra/newview/floaterao.h b/indra/newview/floaterao.h index cf8ee2252..55cc7c052 100644 --- a/indra/newview/floaterao.h +++ b/indra/newview/floaterao.h @@ -5,6 +5,7 @@ #include "llfloater.h" #include "llviewercontrol.h" #include "llagent.h" +#include "lleventtimer.h" class AONoteCardDropTarget; diff --git a/indra/newview/floaterlocalassetbrowse.h b/indra/newview/floaterlocalassetbrowse.h index 6ee1c75a3..a727f9939 100644 --- a/indra/newview/floaterlocalassetbrowse.h +++ b/indra/newview/floaterlocalassetbrowse.h @@ -42,6 +42,7 @@ tag: vaa emerald local_asset_browser #include "llscrolllistctrl.h" #include "lltexturectrl.h" #include "lldrawable.h" +#include "lleventtimer.h" /*=======================================*/ diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 420a9ae67..b719ecc4e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -44,6 +44,7 @@ #include "lltexteditor.h" #include "llalertdialog.h" #include "llerrorcontrol.h" +#include "lleventtimer.h" #include "llviewertexturelist.h" #include "llgroupmgr.h" #include "llagent.h" diff --git a/indra/newview/llbuildnewviewsscheduler.h b/indra/newview/llbuildnewviewsscheduler.h index a3d5af66c..2f819288f 100644 --- a/indra/newview/llbuildnewviewsscheduler.h +++ b/indra/newview/llbuildnewviewsscheduler.h @@ -1,6 +1,7 @@ // #include "llinventoryview.h" #include "llinventory.h" +#include "lleventtimer.h" class LLBuildNewViewsScheduler : public LLEventTimer { typedef struct diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 9e79d93d7..8469bcda5 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -39,8 +39,9 @@ #include "llhttpclient.h" #include "llhttpstatuscodes.h" #include "llsdserialize.h" -#include "llsdutil.h" -#include "lltimer.h" +#include "lleventtimer.h" +#include "llsdutil.h" + #include "llviewerregion.h" #include "message.h" #include "lltrans.h" diff --git a/indra/newview/llfloaterexploresounds.h b/indra/newview/llfloaterexploresounds.h index 11a181377..4bdcae820 100644 --- a/indra/newview/llfloaterexploresounds.h +++ b/indra/newview/llfloaterexploresounds.h @@ -5,6 +5,7 @@ #include "llfloater.h" #include "llaudioengine.h" +#include "lleventtimer.h" class LLFloaterExploreSounds : public LLFloater, public LLEventTimer diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 255547933..2da7f7336 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -62,7 +62,7 @@ #include "llmenucommands.h" #include "llviewercontrol.h" #include "llviewermessage.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "lltextbox.h" #include "llvoiceclient.h" diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index 20c996d23..6454e9b55 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -38,7 +38,7 @@ #include "llpanel.h" #include "llstring.h" #include "lluuid.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "llcallingcard.h" class LLFriendObserver; diff --git a/indra/newview/llfloatermessagelog.cpp b/indra/newview/llfloatermessagelog.cpp index 3ee8018ad..74241d35e 100644 --- a/indra/newview/llfloatermessagelog.cpp +++ b/indra/newview/llfloatermessagelog.cpp @@ -10,6 +10,7 @@ #include "llmessagetemplate.h" #include #include "llmenugl.h" +#include "lleventtimer.h" #include "llagent.h" diff --git a/indra/newview/llfloatermessagelog.h b/indra/newview/llfloatermessagelog.h index 104f57ebb..1fa01c5af 100644 --- a/indra/newview/llfloatermessagelog.h +++ b/indra/newview/llfloatermessagelog.h @@ -2,6 +2,7 @@ #include "llfloater.h" #include "llmessagelog.h" #include "lltemplatemessagereader.h" +#include "lleventtimer.h" class LLNetListItem { diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 9a36b6542..ffd264b6c 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -99,7 +99,9 @@ bool LLNotifyBox::onNotification(const LLSD& notify) if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { //bring existing notification to top - LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); + //This getInstance is ugly, as LLNotifyBox is derived from both LLInstanceTracker and LLEventTimer, which also is derived from its own LLInstanceTracker + //Have to explicitly determine which getInstance function to use. + LLNotifyBox* boxp = LLNotifyBox::LLInstanceTracker::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { gNotifyBoxView->showOnly(boxp); @@ -116,7 +118,7 @@ bool LLNotifyBox::onNotification(const LLSD& notify) } else if (notify["sigtype"].asString() == "delete") { - LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); + LLNotifyBox* boxp = LLNotifyBox::LLInstanceTracker::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { boxp->close(); diff --git a/indra/newview/llnotify.h b/indra/newview/llnotify.h index 15b5a7302..439cae239 100644 --- a/indra/newview/llnotify.h +++ b/indra/newview/llnotify.h @@ -35,7 +35,7 @@ #include "llfontgl.h" #include "llpanel.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "llnotifications.h" #include diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 58959e445..6f6ddcac2 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -40,7 +40,7 @@ #include "llcombobox.h" #include "lliconctrl.h" #include "llframetimer.h" -#include "lltimer.h" +#include "lleventtimer.h" class LLMessageSystem; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6c66831c9..81e2abc5a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -64,7 +64,7 @@ #include "llxfermanager.h" #include "message.h" #include "sound_ids.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "llmd5.h" #include "llagent.h" diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h index 16279e7f1..243da2f38 100644 --- a/indra/newview/llviewerparcelmediaautoplay.h +++ b/indra/newview/llviewerparcelmediaautoplay.h @@ -33,7 +33,7 @@ #ifndef LLVIEWERPARCELMEDIAAUTOPLAY_H #define LLVIEWERPARCELMEDIAAUTOPLAY_H -#include "lltimer.h" +#include "lleventtimer.h" // timer to automatically play media class LLViewerParcelMediaAutoPlay : LLEventTimer diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h index 362200aec..69f8ad703 100644 --- a/indra/newview/rlvhandler.h +++ b/indra/newview/rlvhandler.h @@ -22,6 +22,7 @@ #include "llstartup.h" #include "llviewerjointattachment.h" #include "llviewerobject.h" +#include "lleventtimer.h" #include "rlvcommon.h" #include "rlvhelper.h" diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 165797b92..74b527f70 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -24,6 +24,7 @@ #include "llviewerinventory.h" #include "llvoavatar.h" #include "llwlparamset.h" +#include "lleventtimer.h" #include "rlvdefines.h" #include "rlvcommon.h" diff --git a/indra/newview/rlvlocks.h b/indra/newview/rlvlocks.h index e54caa30a..c4139b135 100644 --- a/indra/newview/rlvlocks.h +++ b/indra/newview/rlvlocks.h @@ -28,6 +28,7 @@ #include "llviewerjointattachment.h" #include "llviewerobject.h" #include "llvoavatar.h" +#include "lleventtimer.h" #include "rlvdefines.h" From fe372028dcfcbee817f443b83f63dbdfa497c812 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 15 May 2011 22:47:23 -0500 Subject: [PATCH 4/5] Shuffled LL_COMMON_API around in spots to match v2 Added llformat_to_utf8 Added LLProcessLauncher::getExecutable() LLStringTableEntry() ctor and dtor definitions moved from .h to .cpp (should be safe) --- indra/llcommon/llboost.h | 14 +++++++++++ indra/llcommon/llerror.h | 2 +- indra/llcommon/llerrorlegacy.h | 2 +- indra/llcommon/llfile.h | 4 ++-- indra/llcommon/llformat.cpp | 36 +++++++++++++++++++++++----- indra/llcommon/llformat.h | 5 +++- indra/llcommon/llmd5.cpp | 2 +- indra/llcommon/llmetrics.cpp | 2 +- indra/llcommon/llprocesslauncher.cpp | 5 ++++ indra/llcommon/llprocesslauncher.h | 2 ++ indra/llcommon/llrand.h | 12 +++++----- indra/llcommon/llstreamtools.cpp | 4 ++-- indra/llcommon/llstringtable.cpp | 17 +++++++++++++ indra/llcommon/llstringtable.h | 28 +++++++--------------- indra/llcommon/llsys.cpp | 2 +- indra/llcommon/llsys.h | 6 ++--- indra/llui/llnotifications.cpp | 13 ++++++---- 17 files changed, 107 insertions(+), 49 deletions(-) diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h index 4df9dbf3b..4901d6689 100644 --- a/indra/llcommon/llboost.h +++ b/indra/llcommon/llboost.h @@ -46,4 +46,18 @@ */ typedef boost::tokenizer > boost_tokenizer; +// Useful combiner for boost signals that return a bool (e.g. validation) +// returns false if any of the callbacks return false +struct boost_boolean_combiner +{ + typedef bool result_type; + template + bool operator()(InputIterator first, InputIterator last) const + { + bool res = true; + while (first != last) + res &= *first++; + return res; + } +}; #endif // LL_LLBOOST_H diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 60f3bfad1..e04e59d53 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -179,7 +179,7 @@ namespace LLError { return s; } // used to indicate the end of a message - class NoClassInfo { }; + class LL_COMMON_API NoClassInfo { }; // used to indicate no class info known for logging //LLCallStacks keeps track of call stacks and output the call stacks to log file diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index fc563dc09..476d75380 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -34,7 +34,7 @@ #ifndef LL_LLERRORLEGACY_H #define LL_LLERRORLEGACY_H - +#include "llpreprocessor.h" /* LEGACY -- DO NOT USE THIS STUFF ANYMORE diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 8b28d77bd..31d025bb0 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -233,7 +233,7 @@ public: * and should only be used for config files and the like -- not in a * loop. */ -std::streamsize llifstream_size(llifstream& fstr); -std::streamsize llofstream_size(llofstream& fstr); +std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr); +std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr); #endif // not LL_LLFILE_H diff --git a/indra/llcommon/llformat.cpp b/indra/llcommon/llformat.cpp index 7a500c9e5..f9f16006a 100644 --- a/indra/llcommon/llformat.cpp +++ b/indra/llcommon/llformat.cpp @@ -37,17 +37,41 @@ #include -std::string llformat(const char *fmt, ...) +// common used function with va_list argument +// wrapper for vsnprintf to be called from llformatXXX functions. +static void va_format(std::string& out, const char *fmt, va_list va) { char tstr[1024]; /* Flawfinder: ignore */ - va_list va; - va_start(va, fmt); #if LL_WINDOWS _vsnprintf(tstr, 1024, fmt, va); #else vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */ #endif - va_end(va); - tstr[1023] = '\0'; - return std::string(tstr); + out.assign(tstr); } + +std::string llformat(const char *fmt, ...) +{ + std::string res; + va_list va; + va_start(va, fmt); + va_format(res, fmt, va); + va_end(va); + return res; +} + +std::string llformat_to_utf8(const char *fmt, ...) +{ + std::string res; + va_list va; + va_start(va, fmt); + va_format(res, fmt, va); + va_end(va); + +#if LL_WINDOWS + // made converting to utf8. See EXT-8318. + res = ll_convert_string_to_utf8_string(res); +#endif + return res; +} + diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h index ad30d4fb1..1cf3bfcca 100644 --- a/indra/llcommon/llformat.h +++ b/indra/llcommon/llformat.h @@ -40,6 +40,9 @@ // *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun) // should perhaps be replaced with boost::format. -LL_COMMON_API std::string llformat(const char *fmt, ...); +std::string LL_COMMON_API llformat(const char *fmt, ...); +// the same version as above but ensures that returned string is in utf8 on windows +// to enable correct converting utf8_to_wstring. +std::string LL_COMMON_API llformat_to_utf8(const char *fmt, ...); #endif // LL_LLFORMAT_H diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 35067b3b3..1257af0e3 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -83,7 +83,7 @@ documentation and/or software. #include "llmd5.h" #include -#include +#include // cerr // how many bytes to grab at a time when checking files const int LLMD5::BLOCK_LEN = 4096; diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp index 8db3284c4..30e5d435a 100644 --- a/indra/llcommon/llmetrics.cpp +++ b/indra/llcommon/llmetrics.cpp @@ -71,7 +71,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location, metrics["location"] = location; metrics["stats"] = stats; - llinfos << "LLMETRICS: " << LLSDNotationStreamer(metrics) << llendl; + llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl; } // Store this: diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp index e27aaa3c5..be1cfc7a9 100644 --- a/indra/llcommon/llprocesslauncher.cpp +++ b/indra/llcommon/llprocesslauncher.cpp @@ -64,6 +64,11 @@ void LLProcessLauncher::setWorkingDirectory(const std::string &dir) mWorkingDir = dir; } +const std::string& LLProcessLauncher::getExecutable() const +{ + return mExecutable; +} + void LLProcessLauncher::clearArguments() { mLaunchArguments.clear(); diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h index 9f49a85bd..0b96f3f7b 100644 --- a/indra/llcommon/llprocesslauncher.h +++ b/indra/llcommon/llprocesslauncher.h @@ -53,6 +53,8 @@ public: void setExecutable(const std::string &executable); void setWorkingDirectory(const std::string &dir); + const std::string& getExecutable() const; + void clearArguments(); void addArgument(const std::string &arg); void addArgument(const char *arg); diff --git a/indra/llcommon/llrand.h b/indra/llcommon/llrand.h index 73ea17956..30fec9b98 100644 --- a/indra/llcommon/llrand.h +++ b/indra/llcommon/llrand.h @@ -65,32 +65,32 @@ /** *@brief Generate a float from [0, RAND_MAX). */ -LL_COMMON_API S32 ll_rand(); +S32 LL_COMMON_API ll_rand(); /** *@brief Generate a float from [0, val) or (val, 0]. */ -LL_COMMON_API S32 ll_rand(S32 val); +S32 LL_COMMON_API ll_rand(S32 val); /** *@brief Generate a float from [0, 1.0). */ -LL_COMMON_API F32 ll_frand(); +F32 LL_COMMON_API ll_frand(); /** *@brief Generate a float from [0, val) or (val, 0]. */ -LL_COMMON_API F32 ll_frand(F32 val); +F32 LL_COMMON_API ll_frand(F32 val); /** *@brief Generate a double from [0, 1.0). */ -LL_COMMON_API F64 ll_drand(); +F64 LL_COMMON_API ll_drand(); /** *@brief Generate a double from [0, val) or (val, 0]. */ -LL_COMMON_API F64 ll_drand(F64 val); +F64 LL_COMMON_API ll_drand(F64 val); /** * @brief typedefs for good boost lagged fibonacci. diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index ee4f46318..b60220830 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -436,7 +436,7 @@ void get_keyword_and_value(std::string& keyword, while (line_index < line_size) { c = line[line_index]; - if (!isspace(c)) + if (!LLStringOps::isSpace(c)) { break; } @@ -448,7 +448,7 @@ void get_keyword_and_value(std::string& keyword, while (line_index < line_size) { c = line[line_index]; - if (isspace(c) || '\r' == c || '\n' == c) + if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c) { break; } diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp index 27f9036b8..2f3a994d8 100644 --- a/indra/llcommon/llstringtable.cpp +++ b/indra/llcommon/llstringtable.cpp @@ -38,6 +38,23 @@ LLStringTable gStringTable(32768); +LLStringTableEntry::LLStringTableEntry(const char *str) +: mString(NULL), mCount(1) +{ + // Copy string + U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/ + length = llmin(length, MAX_STRINGS_LENGTH); + mString = new char[length]; + strncpy(mString, str, length); /*Flawfinder: ignore*/ + mString[length - 1] = 0; +} + +LLStringTableEntry::~LLStringTableEntry() +{ + delete [] mString; + mCount = 0; +} + LLStringTable::LLStringTable(int tablesize) : mUniqueEntries(0) { diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index 238701dfd..d40c9d8df 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -49,11 +49,11 @@ #endif #if STRING_TABLE_HASH_MAP -#if LL_WINDOWS -#include -#else -#include -#endif +# if LL_WINDOWS +# include +# else +# include +# endif #endif const U32 MAX_STRINGS_LENGTH = 256; @@ -61,21 +61,9 @@ const U32 MAX_STRINGS_LENGTH = 256; class LL_COMMON_API LLStringTableEntry { public: - LLStringTableEntry(const char *str) - : mString(NULL), mCount(1) - { - // Copy string - U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/ - length = llmin(length, MAX_STRINGS_LENGTH); - mString = new char[length]; - strncpy(mString, str, length); /*Flawfinder: ignore*/ - mString[length - 1] = 0; - } - ~LLStringTableEntry() - { - delete [] mString; - mCount = 0; - } + LLStringTableEntry(const char *str); + ~LLStringTableEntry(); + void incCount() { mCount++; } BOOL decCount() { return --mCount; } diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index bde0cbd6e..d729d9883 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -74,7 +74,7 @@ extern int errno; static const S32 CPUINFO_BUFFER_SIZE = 16383; -LL_COMMON_API LLCPUInfo gSysCPU; +LLCPUInfo gSysCPU; #if LL_WINDOWS #ifndef DLLVERSIONINFO diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index e481c8838..10f963d50 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -131,10 +131,10 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info); LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info); // gunzip srcfile into dstfile. Returns FALSE on error. -LL_COMMON_API BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile); +BOOL LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& dstfile); // gzip srcfile into dstfile. Returns FALSE on error. -LL_COMMON_API BOOL gzip_file(const std::string& srcfile, const std::string& dstfile); +BOOL LL_COMMON_API gzip_file(const std::string& srcfile, const std::string& dstfile); -LL_COMMON_API extern LLCPUInfo gSysCPU; +extern LL_COMMON_API LLCPUInfo gSysCPU; #endif // LL_LLSYS_H diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 6bd4e4f22..13ca40cf9 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -908,8 +908,7 @@ mParent(parent) else { LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); - LLStandardSignal::slot_type f = boost::bind(&LLNotificationChannelBase::updateItem, this, _1); - p->connectChanged(f); + p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); } } @@ -1010,16 +1009,18 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) bool LLNotifications::uniqueHandler(const LLSD& payload) { + std::string cmd = payload["sigtype"]; + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); if (pNotif && pNotif->hasUniquenessConstraints()) { - if (payload["sigtype"].asString() == "add") + if (cmd == "add") { // not a duplicate according to uniqueness criteria, so we keep it // and store it for future uniqueness checks mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); } - else if (payload["sigtype"].asString() == "delete") + else if (cmd == "delete") { mUniqueNotifications.erase(pNotif->getName()); } @@ -1425,6 +1426,8 @@ LLNotificationPtr LLNotifications::add(const LLNotification::Params& p) void LLNotifications::add(const LLNotificationPtr pNotif) { + if (pNotif == NULL) return; + // first see if we already have it -- if so, that's a problem LLNotificationSet::iterator it=mItems.find(pNotif); if (it != mItems.end()) @@ -1437,6 +1440,8 @@ void LLNotifications::add(const LLNotificationPtr pNotif) void LLNotifications::cancel(LLNotificationPtr pNotif) { + if (pNotif == NULL || pNotif->isCancelled()) return; + LLNotificationSet::iterator it=mItems.find(pNotif); if (it == mItems.end()) { From 1a2d75fbe6c7fe6e617f03802491e0e8b9749211 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 15 May 2011 22:50:56 -0500 Subject: [PATCH 5/5] LLStringOps, LLStringUtilBase, and LLDate updated to V2. If dates go wonky this is where it's from --- indra/llcommon/lldate.cpp | 151 +++-- indra/llcommon/lldate.h | 5 +- indra/llcommon/llfasttimer.h | 3 + indra/llcommon/llstring.cpp | 587 +++++++++++++++++- indra/llcommon/llstring.h | 191 ++++-- indra/newview/llfasttimerview.cpp | 1 + indra/newview/llwindebug.cpp | 6 +- .../win_crash_logger/llcrashloggerwindows.cpp | 6 +- 8 files changed, 833 insertions(+), 117 deletions(-) diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index be294480e..e949cbbb4 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -38,10 +38,13 @@ #include "apr_time.h" #include +#include +#include #include #include #include "lltimer.h" +#include "llstring.h" static const F64 DATE_EPOCH = 0.0; @@ -88,47 +91,40 @@ std::string LLDate::asString() const // is one of the standards used and the prefered format std::string LLDate::asRFC1123() const { - std::ostringstream stream; - toHTTPDateStream(stream); - return stream.str(); + return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } -void LLDate::toHTTPDateStream(std::ostream& s) const + +std::string LLDate::toHTTPDateString (std::string fmt) const { - // http://apr.apache.org/docs/apr/0.9/group__apr__time.html - apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + + time_t locSeconds = (time_t) mSecondsSinceEpoch; + struct tm * gmt = gmtime (&locSeconds); + return toHTTPDateString(gmt, fmt); +} - apr_time_exp_t exp_time ; //Apache time module - - if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) - { +std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) +{ // Return Epoch UTC date - s << "Thursday, 01 Jan 1970 00:00:00 GMT" ; - return; - } - s << std::dec << std::setfill('0'); -#if( LL_WINDOWS || __GNUC__ > 2) - s << std::right ; -#else - s.setf(ios::right); -#endif - static char const* const weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; - static char const* const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - std::string day = weekdays[exp_time.tm_wday]; - std::string month = months[exp_time.tm_mon]; + // avoid calling setlocale() unnecessarily - it's expensive. + static std::string prev_locale = ""; + std::string this_locale = LLStringUtil::getLocale(); + if (this_locale != prev_locale) + { + setlocale(LC_TIME, this_locale.c_str()); + prev_locale = this_locale; + } - s << std::setw(day.length()) << (day) - << ", " << std::setw(2) << (exp_time.tm_mday) - << ' ' << std::setw(month.length()) << (month) - << ' ' << std::setw(4) << (exp_time.tm_year + 1900) - << ' ' << std::setw(2) << (exp_time.tm_hour) - << ':' << std::setw(2) << (exp_time.tm_min) - << ':' << std::setw(2) << (exp_time.tm_sec) - << " GMT"; - - // RFC 1123 date does not use microseconds - //llinfos << "Date in RFC 1123 format is " << s << llendl; + // use strftime() as it appears to be faster than std::time_put + char buffer[128]; + strftime(buffer, 128, fmt.c_str(), gmt); + std::string res(buffer); +#if LL_WINDOWS + // Convert from locale-dependant charset to UTF-8 (EXT-8524). + res = ll_convert_string_to_utf8_string(res); +#endif + return res; } void LLDate::toStream(std::ostream& s) const @@ -159,7 +155,39 @@ void LLDate::toStream(std::ostream& s) const s << '.' << std::setw(2) << (int)(exp_time.tm_usec / (LL_APR_USEC_PER_SEC / 100)); } - s << 'Z'; + s << 'Z' + << std::setfill(' '); +} + +bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *sec) const +{ + apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + + apr_time_exp_t exp_time; + if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) + { + return false; + } + + if (year) + *year = exp_time.tm_year + 1900; + + if (month) + *month = exp_time.tm_mon + 1; + + if (day) + *day = exp_time.tm_mday; + + if (hour) + *hour = exp_time.tm_hour; + + if (min) + *min = exp_time.tm_min; + + if (sec) + *sec = exp_time.tm_sec; + + return true; } bool LLDate::fromString(const std::string& iso8601_date) @@ -223,13 +251,62 @@ bool LLDate::fromStream(std::istream& s) s >> fractional; seconds_since_epoch += fractional; } - c = s.get(); // skip the Z - if (c != 'Z') { return false; } + + c = s.peek(); // check for offset + if (c == '+' || c == '-') + { + S32 offset_sign = (c == '+') ? 1 : -1; + S32 offset_hours = 0; + S32 offset_minutes = 0; + S32 offset_in_seconds = 0; + + s >> offset_hours; + + c = s.get(); // skip the colon a get the minutes if there are any + if (c == ':') + { + s >> offset_minutes; + } + + offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60; + seconds_since_epoch -= offset_in_seconds; + } + else if (c != 'Z') { return false; } // skip the Z mSecondsSinceEpoch = seconds_since_epoch; return true; } +bool LLDate::fromYMDHMS(S32 year, S32 month, S32 day, S32 hour, S32 min, S32 sec) +{ + struct apr_time_exp_t exp_time; + + exp_time.tm_year = year - 1900; + exp_time.tm_mon = month - 1; + exp_time.tm_mday = day; + exp_time.tm_hour = hour; + exp_time.tm_min = min; + exp_time.tm_sec = sec; + + // zero out the unused fields + exp_time.tm_usec = 0; + exp_time.tm_wday = 0; + exp_time.tm_yday = 0; + exp_time.tm_isdst = 0; + exp_time.tm_gmtoff = 0; + + // generate a time_t from that + apr_time_t time; + if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS) + { + return false; + } + + mSecondsSinceEpoch = time / LL_APR_USEC_PER_SEC; + + return true; +} + F64 LLDate::secondsSinceEpoch() const { return mSecondsSinceEpoch; diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index d27da79ad..e116e9cdf 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -84,7 +84,9 @@ public: std::string asString() const; std::string asRFC1123() const; void toStream(std::ostream&) const; - void toHTTPDateStream(std::ostream&) const; + bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const; + std::string toHTTPDateString (std::string fmt) const; + static std::string toHTTPDateString (tm * gmt, std::string fmt); /** * @brief Set the date from an ISO-8601 string. * @@ -99,6 +101,7 @@ public: */ bool fromString(const std::string& iso8601_date); bool fromStream(std::istream&); + bool fromYMDHMS(S32 year, S32 month = 1, S32 day = 0, S32 hour = 0, S32 min = 0, S32 sec = 0); /** * @brief Return the date in seconds since epoch. diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 898ed496b..11c4cbdf8 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -51,6 +51,9 @@ public: FTM_IDLE, FTM_SLEEP, + // general timers + FT_STRING_FORMAT, + // common messaging components FTM_PUMP, FTM_CURL, diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f08b4c042..7423726cb 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -34,6 +34,7 @@ #include "llstring.h" #include "llerror.h" +#include "llfasttimer.h" #if LL_WINDOWS #define WIN32_LEAN_AND_MEAN @@ -71,6 +72,24 @@ U8 hex_as_nybble(char hex) return 0; // uh - oh, not hex any more... } +bool iswindividual(llwchar elem) +{ + U32 cur_char = (U32)elem; + bool result = false; + if (0x2E80<= cur_char && cur_char <= 0x9FFF) + { + result = true; + } + else if (0xAC00<= cur_char && cur_char <= 0xD7A0 ) + { + result = true; + } + else if (0xF900<= cur_char && cur_char <= 0xFA60 ) + { + result = true; + } + return result; +} bool _read_file_into_string(std::string& str, const std::string& filename) { @@ -630,14 +649,14 @@ namespace snprintf_hack } } -std::string ll_convert_wide_to_string(const wchar_t* in) +std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) { std::string out; if(in) { int len_in = wcslen(in); int len_out = WideCharToMultiByte( - CP_ACP, + code_page, 0, in, len_in, @@ -652,7 +671,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in) if(pout) { WideCharToMultiByte( - CP_ACP, + code_page, 0, in, len_in, @@ -666,8 +685,55 @@ std::string ll_convert_wide_to_string(const wchar_t* in) } return out; } + +wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page) +{ + // From review: + // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input, + // plus one for a null terminator, and be guaranteed to not overflow. + + // Normally, I'd call that sort of thing premature optimization, + // but we *are* seeing string operations taking a bunch of time, especially when constructing widgets. +// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0); + + // reserve place to NULL terminator + int output_str_len = in.length(); + wchar_t* w_out = new wchar_t[output_str_len + 1]; + + memset(w_out, 0, output_str_len + 1); + int real_output_str_len = MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len); + + //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. + w_out[real_output_str_len] = 0; + + return w_out; +} + +std::string ll_convert_string_to_utf8_string(const std::string& in) +{ + wchar_t* w_mesg = ll_convert_string_to_wide(in, CP_ACP); + std::string out_utf8(ll_convert_wide_to_string(w_mesg, CP_UTF8)); + delete[] w_mesg; + + return out_utf8; +} #endif // LL_WINDOWS +long LLStringOps::sPacificTimeOffset = 0; +long LLStringOps::sLocalTimeOffset = 0; +bool LLStringOps::sPacificDaylightTime = 0; +std::map LLStringOps::datetimeToCodes; + +std::vector LLStringOps::sWeekDayList; +std::vector LLStringOps::sWeekDayShortList; +std::vector LLStringOps::sMonthList; +std::vector LLStringOps::sMonthShortList; + + +std::string LLStringOps::sDayFormat; +std::string LLStringOps::sAM; +std::string LLStringOps::sPM; + S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS @@ -679,6 +745,107 @@ S32 LLStringOps::collate(const llwchar* a, const llwchar* b) #endif } +void LLStringOps::setupDatetimeInfo (bool daylight) +{ + time_t nowT, localT, gmtT; + struct tm * tmpT; + + nowT = time (NULL); + + tmpT = gmtime (&nowT); + gmtT = mktime (tmpT); + + tmpT = localtime (&nowT); + localT = mktime (tmpT); + + sLocalTimeOffset = (long) (gmtT - localT); + if (tmpT->tm_isdst) + { + sLocalTimeOffset -= 60 * 60; // 1 hour + } + + sPacificDaylightTime = daylight; + sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60; + + datetimeToCodes["wkday"] = "%a"; // Thu + datetimeToCodes["weekday"] = "%A"; // Thursday + datetimeToCodes["year4"] = "%Y"; // 2009 + datetimeToCodes["year"] = "%Y"; // 2009 + datetimeToCodes["year2"] = "%y"; // 09 + datetimeToCodes["mth"] = "%b"; // Aug + datetimeToCodes["month"] = "%B"; // August + datetimeToCodes["mthnum"] = "%m"; // 08 + datetimeToCodes["day"] = "%d"; // 31 + datetimeToCodes["sday"] = "%-d"; // 9 + datetimeToCodes["hour24"] = "%H"; // 14 + datetimeToCodes["hour"] = "%H"; // 14 + datetimeToCodes["hour12"] = "%I"; // 02 + datetimeToCodes["min"] = "%M"; // 59 + datetimeToCodes["ampm"] = "%p"; // AM + datetimeToCodes["second"] = "%S"; // 59 + datetimeToCodes["timezone"] = "%Z"; // PST +} + +void tokenizeStringToArray(const std::string& data, std::vector& output) +{ + output.clear(); + size_t length = data.size(); + + // tokenize it and put it in the array + std::string cur_word; + for(size_t i = 0; i < length; ++i) + { + if(data[i] == ':') + { + output.push_back(cur_word); + cur_word.clear(); + } + else + { + cur_word.append(1, data[i]); + } + } + output.push_back(cur_word); +} + +void LLStringOps::setupWeekDaysNames(const std::string& data) +{ + tokenizeStringToArray(data,sWeekDayList); +} +void LLStringOps::setupWeekDaysShortNames(const std::string& data) +{ + tokenizeStringToArray(data,sWeekDayShortList); +} +void LLStringOps::setupMonthNames(const std::string& data) +{ + tokenizeStringToArray(data,sMonthList); +} +void LLStringOps::setupMonthShortNames(const std::string& data) +{ + tokenizeStringToArray(data,sMonthShortList); +} +void LLStringOps::setupDayFormat(const std::string& data) +{ + sDayFormat = data; +} + + +std::string LLStringOps::getDatetimeCode (std::string key) +{ + std::map::iterator iter; + + iter = datetimeToCodes.find (key); + if (iter != datetimeToCodes.end()) + { + return iter->second; + } + else + { + return std::string(""); + } +} + + namespace LLStringFn { // NOTE - this restricts output to ascii @@ -715,12 +882,12 @@ namespace LLStringFn // https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on // allowable code points for XML. Specifically, they are: // 0x09, 0x0a, 0x0d, and 0x20 on up. JC - std::string strip_invalid_xml(const std::string& input) + std::string strip_invalid_xml(const std::string& instr) { std::string output; - output.reserve( input.size() ); - std::string::const_iterator it = input.begin(); - while (it != input.end()) + output.reserve( instr.size() ); + std::string::const_iterator it = instr.begin(); + while (it != instr.end()) { // Must compare as unsigned for >= // Test most likely match first @@ -756,6 +923,412 @@ namespace LLStringFn } } +//////////////////////////////////////////////////////////// + +// Forward specialization of LLStringUtil::format before use in LLStringUtil::formatDatetime. +template<> +S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions); + +//static +template<> +void LLStringUtil::getTokens(const std::string& instr, std::vector& tokens, const std::string& delims) +{ + std::string currToken; + std::string::size_type begIdx, endIdx; + + begIdx = instr.find_first_not_of (delims); + while (begIdx != std::string::npos) + { + endIdx = instr.find_first_of (delims, begIdx); + if (endIdx == std::string::npos) + { + endIdx = instr.length(); + } + + currToken = instr.substr(begIdx, endIdx - begIdx); + LLStringUtil::trim (currToken); + tokens.push_back(currToken); + begIdx = instr.find_first_not_of (delims, endIdx); + } +} + +template<> +LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr, size_type& start, std::vector& tokens) +{ + const std::string delims (","); + + // Find the first ] + size_type pos2 = instr.find(']', start); + if (pos2 == std::string::npos) + return std::string::npos; + + // Find the last [ before ] + size_type pos1 = instr.find_last_of('[', pos2-1); + if (pos1 == std::string::npos || pos1 < start) + return std::string::npos; + + getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims); + start = pos2+1; + + return pos1; +} + +// static +template<> +bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const format_map_t& substitutions) +{ + // see if we have a replacement for the bracketed string (without the brackets) + // test first using has() because if we just look up with operator[] we get back an + // empty string even if the value is missing. We want to distinguish between + // missing replacements and deliberately empty replacement strings. + format_map_t::const_iterator iter = substitutions.find(token); + if (iter != substitutions.end()) + { + replacement = iter->second; + return true; + } + // if not, see if there's one WITH brackets + iter = substitutions.find(std::string("[" + token + "]")); + if (iter != substitutions.end()) + { + replacement = iter->second; + return true; + } + + return false; +} + +// static +template<> +bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const LLSD& substitutions) +{ + // see if we have a replacement for the bracketed string (without the brackets) + // test first using has() because if we just look up with operator[] we get back an + // empty string even if the value is missing. We want to distinguish between + // missing replacements and deliberately empty replacement strings. + if (substitutions.has(token)) + { + replacement = substitutions[token].asString(); + return true; + } + // if not, see if there's one WITH brackets + else if (substitutions.has(std::string("[" + token + "]"))) + { + replacement = substitutions[std::string("[" + token + "]")].asString(); + return true; + } + + return false; +} + +//static +template<> +void LLStringUtil::setLocale(std::string inLocale) +{ + sLocale = inLocale; +}; + +//static +template<> +std::string LLStringUtil::getLocale(void) +{ + return sLocale; +}; + +// static +template<> +void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) +{ + std::stringstream strStream; + S32 intDecimals = 0; + + convertToS32 (decimals, intDecimals); + if (!sLocale.empty()) + { + // std::locale() throws if the locale is unknown! (EXT-7926) + try + { + strStream.imbue(std::locale(sLocale.c_str())); + } catch (const std::exception &) + { + LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL; + } + } + + if (!intDecimals) + { + S32 intStr; + + if (convertToS32(numStr, intStr)) + { + strStream << intStr; + numStr = strStream.str(); + } + } + else + { + F32 floatStr; + + if (convertToF32(numStr, floatStr)) + { + strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr; + numStr = strStream.str(); + } + } +} + +// static +template<> +bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, + std::string param, S32 secFromEpoch) +{ + if (param == "local") // local + { + secFromEpoch -= LLStringOps::getLocalTimeOffset(); + } + else if (param != "utc") // slt + { + secFromEpoch -= LLStringOps::getPacificTimeOffset(); + } + + // if never fell into those two ifs above, param must be utc + if (secFromEpoch < 0) secFromEpoch = 0; + + LLDate datetime((F64)secFromEpoch); + std::string code = LLStringOps::getDatetimeCode (token); + + // special case to handle timezone + if (code == "%Z") { + if (param == "utc") + { + replacement = "GMT"; + } + else if (param == "local") + { + replacement = ""; // user knows their own timezone + } + else + { + // "slt" = Second Life Time, which is deprecated. + // If not utc or user local time, fallback to Pacific time + replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST"; + } + return true; + } + + //EXT-7013 + //few codes are not suppotred by strtime function (example - weekdays for Japanise) + //so use predefined ones + + //if sWeekDayList is not empty than current locale doesn't support + //weekday name. + time_t loc_seconds = (time_t) secFromEpoch; + if(LLStringOps::sWeekDayList.size() == 7 && code == "%A") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayList[gmt->tm_wday]; + } + else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday]; + } + else if(LLStringOps::sMonthList.size() == 12 && code == "%B") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sMonthList[gmt->tm_mon]; + } + else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) + { + struct tm * gmt = gmtime (&loc_seconds); + LLStringUtil::format_map_t args; + args["[MDAY]"] = llformat ("%d", gmt->tm_mday); + replacement = LLStringOps::sDayFormat; + LLStringUtil::format(replacement, args); + } + else if (code == "%-d") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = llformat ("%d", gmt->tm_mday); // day of the month without leading zero + } + else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" ) + { + struct tm * gmt = gmtime (&loc_seconds); + if(gmt->tm_hour<12) + { + replacement = LLStringOps::sAM; + } + else + { + replacement = LLStringOps::sPM; + } + } + else + { + replacement = datetime.toHTTPDateString(code); + } + + // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format + // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738). + // We could have used '%l' format instead, but it's not supported by Windows. + if(code == "%I" && token == "hour12" && replacement.at(0) == '0') + { + replacement = replacement.at(1); + } + + return !code.empty(); +} + +// LLStringUtil::format recogizes the following patterns. +// All substitutions *must* be encased in []'s in the input string. +// The []'s are optional in the substitution map. +// [FOO_123] +// [FOO,number,precision] +// [FOO,datetime,format] + + +// static +template<> +S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) +{ + LLFastTimer ft(LLFastTimer::FT_STRING_FORMAT); + S32 res = 0; + + std::string output; + std::vector tokens; + + std::string::size_type start = 0; + std::string::size_type prev_start = 0; + std::string::size_type key_start = 0; + while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos) + { + output += std::string(s, prev_start, key_start-prev_start); + prev_start = start; + + bool found_replacement = false; + std::string replacement; + + if (tokens.size() == 0) + { + found_replacement = false; + } + else if (tokens.size() == 1) + { + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + } + else if (tokens[1] == "number") + { + std::string param = "0"; + + if (tokens.size() > 2) param = tokens[2]; + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + if (found_replacement) formatNumber (replacement, param); + } + else if (tokens[1] == "datetime") + { + std::string param; + if (tokens.size() > 2) param = tokens[2]; + + format_map_t::const_iterator iter = substitutions.find("datetime"); + if (iter != substitutions.end()) + { + S32 secFromEpoch = 0; + BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch); + if (r) + { + found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch); + } + } + } + + if (found_replacement) + { + output += replacement; + res++; + } + else + { + // we had no replacement, use the string as is + // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-" + output += std::string(s, key_start, start-key_start); + } + tokens.clear(); + } + // send the remainder of the string (with no further matches for bracketed names) + output += std::string(s, start); + s = output; + return res; +} + +//static +template<> +S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) +{ + LLFastTimer ft(LLFastTimer::FT_STRING_FORMAT); + S32 res = 0; + + if (!substitutions.isMap()) + { + return res; + } + + std::string output; + std::vector tokens; + + std::string::size_type start = 0; + std::string::size_type prev_start = 0; + std::string::size_type key_start = 0; + while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos) + { + output += std::string(s, prev_start, key_start-prev_start); + prev_start = start; + + bool found_replacement = false; + std::string replacement; + + if (tokens.size() == 0) + { + found_replacement = false; + } + else if (tokens.size() == 1) + { + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + } + else if (tokens[1] == "number") + { + std::string param = "0"; + + if (tokens.size() > 2) param = tokens[2]; + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + if (found_replacement) formatNumber (replacement, param); + } + else if (tokens[1] == "datetime") + { + std::string param; + if (tokens.size() > 2) param = tokens[2]; + + S32 secFromEpoch = (S32) substitutions["datetime"].asInteger(); + found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch); + } + + if (found_replacement) + { + output += replacement; + res++; + } + else + { + // we had no replacement, use the string as is + // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-" + output += std::string(s, key_start, start-key_start); + } + tokens.clear(); + } + // send the remainder of the string (with no further matches for bracketed names) + output += std::string(s, start); + s = output; + return res; +} //////////////////////////////////////////////////////////// // Testing diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 171747921..bdbefe935 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -37,6 +37,9 @@ #include #include #include +#include +#include +#include "llsd.h" #if LL_LINUX || LL_SOLARIS #include @@ -148,7 +151,23 @@ struct char_traits class LL_COMMON_API LLStringOps { +private: + static long sPacificTimeOffset; + static long sLocalTimeOffset; + static bool sPacificDaylightTime; + + static std::map datetimeToCodes; + public: + static std::vector sWeekDayList; + static std::vector sWeekDayShortList; + static std::vector sMonthList; + static std::vector sMonthShortList; + static std::string sDayFormat; + + static std::string sAM; + static std::string sPM; + static char toUpper(char elem) { return toupper((unsigned char)elem); } static llwchar toUpper(llwchar elem) { return towupper(elem); } @@ -177,14 +196,31 @@ public: static S32 collate(const llwchar* a, const llwchar* b); static bool isHexString(const std::string& str); + + static void setupDatetimeInfo(bool pacific_daylight_time); + + static void setupWeekDaysNames(const std::string& data); + static void setupWeekDaysShortNames(const std::string& data); + static void setupMonthNames(const std::string& data); + static void setupMonthShortNames(const std::string& data); + static void setupDayFormat(const std::string& data); + + + static long getPacificTimeOffset(void) { return sPacificTimeOffset;} + static long getLocalTimeOffset(void) { return sLocalTimeOffset;} + // Is the Pacific time zone (aka server time zone) + // currently in daylight savings time? + static bool getPacificDaylightTime(void) { return sPacificDaylightTime;} + + static std::string getDatetimeCode (std::string key); }; /** * @brief Return a string constructed from in without crashing if the * pointer is NULL. */ -std::string LL_COMMON_API ll_safe_string(const char* in); -std::string LL_COMMON_API ll_safe_string(const char* in, S32 maxlen); +LL_COMMON_API std::string ll_safe_string(const char* in); +LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen); // Allowing assignments from non-strings into format_map_t is apparently @@ -206,6 +242,9 @@ private: template class LLStringUtilBase { +private: + static std::string sLocale; + public: typedef typename std::basic_string::size_type size_type; @@ -213,10 +252,18 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static std::basic_string const null; + static const std::basic_string null; typedef std::map format_map_t; - static S32 format(std::basic_string& s, const format_map_t& fmt_map); + LL_COMMON_API static void getTokens(const std::basic_string& instr, std::vector >& tokens, const std::basic_string& delims); + LL_COMMON_API static void formatNumber(std::basic_string& numStr, std::basic_string decimals); + LL_COMMON_API static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, S32 secFromEpoch); + LL_COMMON_API static S32 format(std::basic_string& s, const format_map_t& substitutions); + LL_COMMON_API static S32 format(std::basic_string& s, const LLSD& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const format_map_t& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); + LL_COMMON_API static void setLocale (std::string inLocale); + LL_COMMON_API static std::string getLocale (void); static bool isValidIndex(const std::basic_string& string, size_type i) { @@ -233,7 +280,25 @@ public: // True if this is the head of s. static BOOL isHead( const std::basic_string& string, const T* s ); - + + /** + * @brief Returns true if string starts with substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool startsWith( + const std::basic_string& string, + const std::basic_string& substr); + + /** + * @brief Returns true if string ends in substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool endsWith( + const std::basic_string& string, + const std::basic_string& substr); + static void addCRLF(std::basic_string& string); static void removeCRLF(std::basic_string& string); @@ -298,13 +363,19 @@ public: // Copies src into dst at a given offset. static void copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset); + static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } + + #ifdef _DEBUG - static void testHarness(); + LL_COMMON_API static void testHarness(); #endif +private: + LL_COMMON_API static size_type getSubstitution(const std::basic_string& instr, size_type& start, std::vector >& tokens); }; -template std::basic_string const LLStringUtilBase::null; +template const std::basic_string LLStringUtilBase::null; +template std::string LLStringUtilBase::sLocale; typedef LLStringUtilBase LLStringUtil; typedef LLStringUtilBase LLWStringUtil; @@ -366,6 +437,7 @@ LL_COMMON_API U8 hex_as_nybble(char hex); * @return Returns true on success. If false, str is unmodified. */ LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename); +LL_COMMON_API bool iswindividual(llwchar elem); /** * Unicode support @@ -495,7 +567,20 @@ using snprintf_hack::snprintf; * * This replaces the unsafe W2A macro from ATL. */ -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page); + +/** + * Converts a string to wide string. + * + * It will allocate memory for result string with "new []". Don't forget to release it with "delete []". + */ +LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page); + +/** + * Converts incoming string into urf8 string + * + */ +LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in); //@} #endif // LL_WINDOWS @@ -558,63 +643,12 @@ namespace LLStringFn } //////////////////////////////////////////////////////////// +// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. +// There is no LLWStringUtil::format implementation currently. +// Calling thse for anything other than LLStringUtil will produce link errors. -// LLStringBase::format() -// -// This function takes a string 's' and a map 'fmt_map' of strings-to-strings. -// All occurances of strings in 's' from the left-hand side of 'fmt_map' are -// then replaced with the corresponding right-hand side of 'fmt_map', non- -// recursively. The function returns the number of substitutions made. +//////////////////////////////////////////////////////////// -// static -template -S32 LLStringUtilBase::format(std::basic_string& s, const format_map_t& fmt_map) -{ - typedef typename std::basic_string::size_type string_size_type_t; - string_size_type_t scanstart = 0; - S32 res = 0; - - // Look for the first match of any keyword, replace that keyword, - // repeat from the end of the replacement string. This avoids - // accidentally performing substitution on a substituted string. - while (1) - { - string_size_type_t first_match_pos = scanstart; - string_size_type_t first_match_str_length = 0; - std::basic_string first_match_str_replacement; - - for (format_map_t::const_iterator iter = fmt_map.begin(); - iter != fmt_map.end(); - ++iter) - { - string_size_type_t n = s.find(iter->first, scanstart); - if (n != std::basic_string::npos && - (n < first_match_pos || - 0 == first_match_str_length)) - { - first_match_pos = n; - first_match_str_length = iter->first.length(); - first_match_str_replacement = iter->second; - } - } - - if (0 == first_match_str_length) - { - // no more keys found to substitute from this point - // in the string forward. - break; - } - else - { - s.erase(first_match_pos, first_match_str_length); - s.insert(first_match_pos, first_match_str_replacement); - scanstart = first_match_pos + - first_match_str_replacement.length(); - ++res; - } - } - return res; -} // static template @@ -1003,14 +1037,15 @@ void LLStringUtilBase::stripNonprintable(std::basic_string& string) { return; } - char* c_string = new char[string.size() + 1]; + size_t src_size = string.size(); + char* c_string = new char[src_size + 1]; if(c_string == NULL) { return; } - strcpy(c_string, string.c_str()); /*Flawfinder: ignore*/ + copy(c_string, string.c_str(), src_size+1); char* write_head = &c_string[0]; - for (size_type i = 0; i < string.size(); i++) + for (size_type i = 0; i < src_size; i++) { char* read_head = &string[i]; write_head = &c_string[j]; @@ -1090,6 +1125,30 @@ BOOL LLStringUtilBase::isHead( const std::basic_string& string, const T* s } } +// static +template +bool LLStringUtilBase::startsWith( + const std::basic_string& string, + const std::basic_string& substr) +{ + if(string.empty() || (substr.empty())) return false; + if(0 == string.find(substr)) return true; + return false; +} + +// static +template +bool LLStringUtilBase::endsWith( + const std::basic_string& string, + const std::basic_string& substr) +{ + if(string.empty() || (substr.empty())) return false; + std::string::size_type idx = string.rfind(substr); + if(std::string::npos == idx) return false; + return (idx == (string.size() - substr.size())); +} + + template BOOL LLStringUtilBase::convertToBOOL(const std::basic_string& string, BOOL& value) { diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 27661567e..27f916327 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -81,6 +81,7 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_MESSAGES, " System Messages", &LLColor4::grey1, 1 }, { LLFastTimer::FTM_MOUSEHANDLER, " Mouse", &LLColor4::grey1, 0 }, { LLFastTimer::FTM_KEYHANDLER, " Keyboard", &LLColor4::grey1, 0 }, + { LLFastTimer::FT_STRING_FORMAT, " String Format", &LLColor4::grey3, 0 }, { LLFastTimer::FTM_SLEEP, " Sleep", &LLColor4::grey2, 0 }, { LLFastTimer::FTM_IDLE, " Idle", &blue0, 0 }, { LLFastTimer::FTM_PUMP, " Pump", &LLColor4::magenta2, 1 }, diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index bc8281480..4d175a071 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -429,7 +429,7 @@ void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) { // Save module's address and full path. - tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); + tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name,CP_ACP); tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); @@ -548,7 +548,7 @@ LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) Get_Version_Str(info); GetModuleFileName(NULL, Str, MAX_PATH); - info["Process"] = ll_convert_wide_to_string(Str); + info["Process"] = ll_convert_wide_to_string(Str,CP_ACP); info["ThreadID"] = (S32)GetCurrentThreadId(); // If exception occurred. @@ -560,7 +560,7 @@ LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) // If module with E.ExceptionAddress found - save its path and date. if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) { - info["Module"] = ll_convert_wide_to_string(Module_Name); + info["Module"] = ll_convert_wide_to_string(Module_Name,CP_ACP); if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index c9e01c841..1a233fe2f 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -145,7 +145,7 @@ void LLCrashLoggerWindows::ProcessCaption(HWND hWnd) TCHAR header[MAX_STRING]; std::string final; GetWindowText(hWnd, templateText, sizeof(templateText)); - final = llformat(ll_convert_wide_to_string(templateText).c_str(), gProductName.c_str()); + final = llformat(ll_convert_wide_to_string(templateText,CP_ACP).c_str(), gProductName.c_str()); ConvertLPCSTRToLPWSTR(final.c_str(), header); SetWindowText(hWnd, header); } @@ -158,7 +158,7 @@ void LLCrashLoggerWindows::ProcessDlgItemText(HWND hWnd, int nIDDlgItem) TCHAR header[MAX_STRING]; std::string final; GetDlgItemText(hWnd, nIDDlgItem, templateText, sizeof(templateText)); - final = llformat(ll_convert_wide_to_string(templateText).c_str(), gProductName.c_str()); + final = llformat(ll_convert_wide_to_string(templateText,CP_ACP).c_str(), gProductName.c_str()); ConvertLPCSTRToLPWSTR(final.c_str(), header); SetDlgItemText(hWnd, nIDDlgItem, header); } @@ -201,7 +201,7 @@ bool handle_button_click(WORD button_id) wbuffer, // pointer to buffer for text 20000 // maximum size of string ); - std::string user_text(ll_convert_wide_to_string(wbuffer)); + std::string user_text(ll_convert_wide_to_string(wbuffer,CP_ACP)); // Activate and show the window. ShowWindow(gHwndProgress, SW_SHOW); // Try doing this second to make the progress window go frontmost.