Merge branch 'master' into V2Renderer
This commit is contained in:
@@ -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++;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#include "llquaternion.h"
|
||||
#include "v3dmath.h"
|
||||
#include "v3math.h"
|
||||
#include "llapr.h"
|
||||
#include "llbvhconsts.h"
|
||||
|
||||
class LLKeyframeDataCache;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header Files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <string>
|
||||
|
||||
#include "llmap.h"
|
||||
#include "lljointstate.h"
|
||||
#include "lljoint.h"
|
||||
#include "llmap.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -131,6 +131,19 @@ public:
|
||||
*/
|
||||
bool parseCommandOptions(int argc, char** argv);
|
||||
|
||||
/**
|
||||
* @brief Keep track of live files automatically.
|
||||
*
|
||||
* *TODO: it currently uses the <code>addToEventTimer()</code> 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<LLLiveFile*> mLiveFiles;
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
||||
@@ -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<LLAssetDictionary>,
|
||||
public LLDictionary<LLAssetType::EType, AssetEntry>
|
||||
{
|
||||
{ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -46,4 +46,18 @@
|
||||
*/
|
||||
typedef boost::tokenizer<boost::char_separator<char> > 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<typename InputIterator>
|
||||
bool operator()(InputIterator first, InputIterator last) const
|
||||
{
|
||||
bool res = true;
|
||||
while (first != last)
|
||||
res &= *first++;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
#endif // LL_LLBOOST_H
|
||||
|
||||
@@ -38,10 +38,13 @@
|
||||
#include "apr_time.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <locale.h>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#ifndef LL_LLERRORLEGACY_H
|
||||
#define LL_LLERRORLEGACY_H
|
||||
|
||||
|
||||
#include "llpreprocessor.h"
|
||||
|
||||
/*
|
||||
LEGACY -- DO NOT USE THIS STUFF ANYMORE
|
||||
|
||||
@@ -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"),
|
||||
|
||||
115
indra/llcommon/lleventtimer.cpp
Normal file
115
indra/llcommon/lleventtimer.cpp
Normal file
@@ -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*> 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<LLEventTimer*> completed_timers;
|
||||
|
||||
/*{
|
||||
for (std::list<LLEventTimer*>::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<LLEventTimer*>::iterator completed_iter = completed_timers.begin();
|
||||
completed_iter != completed_timers.end();
|
||||
completed_iter++ )
|
||||
{
|
||||
delete *completed_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
66
indra/llcommon/lleventtimer.h
Normal file
66
indra/llcommon/lleventtimer.h
Normal file
@@ -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<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<LLEventTimer*> sActiveList; // TODO should this be a vector
|
||||
};
|
||||
|
||||
|
||||
#endif //LL_EVENTTIMER_H
|
||||
@@ -51,6 +51,9 @@ public:
|
||||
FTM_IDLE,
|
||||
FTM_SLEEP,
|
||||
|
||||
// general timers
|
||||
FT_STRING_FORMAT,
|
||||
|
||||
// common messaging components
|
||||
FTM_PUMP,
|
||||
FTM_CURL,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,17 +37,41 @@
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
47
indra/llcommon/llinstancetracker.cpp
Normal file
47
indra/llcommon/llinstancetracker.cpp
Normal file
@@ -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<std::string, void *> instances;
|
||||
|
||||
std::string k = info.name();
|
||||
if(instances.find(k) == instances.end())
|
||||
{
|
||||
instances[k] = NULL;
|
||||
}
|
||||
|
||||
return instances[k];
|
||||
}
|
||||
202
indra/llcommon/llinstancetracker.h
Normal file
202
indra/llcommon/llinstancetracker.h
Normal file
@@ -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 <map>
|
||||
|
||||
#include "string_table.h"
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
|
||||
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<typename T, typename KEY = T*>
|
||||
class LLInstanceTracker : public LLInstanceTrackerBase
|
||||
{
|
||||
typedef typename std::map<KEY, T*> InstanceMap;
|
||||
typedef LLInstanceTracker<T, KEY> MyT;
|
||||
typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter;
|
||||
typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter;
|
||||
public:
|
||||
/// Dereferencing key_iter gives you a const KEY&
|
||||
typedef boost::transform_iterator<KeyGetter, typename InstanceMap::iterator> key_iter;
|
||||
/// Dereferencing instance_iter gives you a T&
|
||||
typedef boost::indirect_iterator< boost::transform_iterator<InstancePtrGetter, typename InstanceMap::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<T*>(this);
|
||||
}
|
||||
void remove_()
|
||||
{
|
||||
getMap_().erase(mKey);
|
||||
}
|
||||
|
||||
static InstanceMap& getMap_()
|
||||
{
|
||||
void * & instances = getInstances(typeid(MyT));
|
||||
if (! instances)
|
||||
{
|
||||
instances = new InstanceMap;
|
||||
}
|
||||
return * static_cast<InstanceMap*>(instances);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
KEY mKey;
|
||||
};
|
||||
|
||||
/// explicit specialization for default case where KEY is T*
|
||||
/// use a simple std::set<T*>
|
||||
template<typename T>
|
||||
class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
|
||||
{
|
||||
typedef typename std::set<T*> InstanceSet;
|
||||
typedef LLInstanceTracker<T, T*> 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<key_iter> 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<T*>(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<T*>(this));
|
||||
}
|
||||
|
||||
LLInstanceTracker(const LLInstanceTracker& other)
|
||||
{
|
||||
//llassert(sIterationNestDepth == 0);
|
||||
getSet_().insert(static_cast<T*>(this));
|
||||
}
|
||||
|
||||
static InstanceSet& getSet_()
|
||||
{
|
||||
void * & instances = getInstances(typeid(MyT));
|
||||
if (! instances)
|
||||
{
|
||||
instances = new InstanceSet;
|
||||
}
|
||||
return * static_cast<InstanceSet *>(instances);
|
||||
}
|
||||
|
||||
static S32 sIterationNestDepth;
|
||||
};
|
||||
|
||||
template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* <code>live_config.checkAndReload()</code> 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
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "lllivefile.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lltimer.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ documentation and/or software.
|
||||
#include "llmd5.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <iostream> // cerr
|
||||
|
||||
// how many bytes to grab at a time when checking files
|
||||
const int LLMD5::BLOCK_LEN = 4096;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <memory>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
#include <vector>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "llpreprocessor.h"
|
||||
|
||||
class LLRunnable;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<std::string, std::string> LLStringOps::datetimeToCodes;
|
||||
|
||||
std::vector<std::string> LLStringOps::sWeekDayList;
|
||||
std::vector<std::string> LLStringOps::sWeekDayShortList;
|
||||
std::vector<std::string> LLStringOps::sMonthList;
|
||||
std::vector<std::string> 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<std::string>& 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<std::string, std::string>::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<std::string >& 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<std::string>& 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<std::string> 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<std::string> 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
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <locale>
|
||||
#include <iomanip>
|
||||
#include "llsd.h"
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
#include <wctype.h>
|
||||
@@ -148,7 +151,23 @@ struct char_traits<U16>
|
||||
|
||||
class LL_COMMON_API LLStringOps
|
||||
{
|
||||
private:
|
||||
static long sPacificTimeOffset;
|
||||
static long sLocalTimeOffset;
|
||||
static bool sPacificDaylightTime;
|
||||
|
||||
static std::map<std::string, std::string> datetimeToCodes;
|
||||
|
||||
public:
|
||||
static std::vector<std::string> sWeekDayList;
|
||||
static std::vector<std::string> sWeekDayShortList;
|
||||
static std::vector<std::string> sMonthList;
|
||||
static std::vector<std::string> 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 T>
|
||||
class LLStringUtilBase
|
||||
{
|
||||
private:
|
||||
static std::string sLocale;
|
||||
|
||||
public:
|
||||
typedef typename std::basic_string<T>::size_type size_type;
|
||||
|
||||
@@ -213,10 +252,18 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Static Utility functions that operate on std::strings
|
||||
|
||||
static std::basic_string<T> const null;
|
||||
static const std::basic_string<T> null;
|
||||
|
||||
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
|
||||
static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
|
||||
LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
|
||||
LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
|
||||
LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
|
||||
LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
|
||||
LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
|
||||
LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
|
||||
LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> 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<T>& string, size_type i)
|
||||
{
|
||||
@@ -233,7 +280,25 @@ public:
|
||||
|
||||
// True if this is the head of s.
|
||||
static BOOL isHead( const std::basic_string<T>& 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<T>& string,
|
||||
const std::basic_string<T>& 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<T>& string,
|
||||
const std::basic_string<T>& substr);
|
||||
|
||||
static void addCRLF(std::basic_string<T>& string);
|
||||
static void removeCRLF(std::basic_string<T>& string);
|
||||
|
||||
@@ -298,13 +363,19 @@ public:
|
||||
// Copies src into dst at a given offset.
|
||||
static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& 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<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
|
||||
};
|
||||
|
||||
template<class T> std::basic_string<T> const LLStringUtilBase<T>::null;
|
||||
template<class T> const std::basic_string<T> LLStringUtilBase<T>::null;
|
||||
template<class T> std::string LLStringUtilBase<T>::sLocale;
|
||||
|
||||
typedef LLStringUtilBase<char> LLStringUtil;
|
||||
typedef LLStringUtilBase<llwchar> 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<class T>
|
||||
S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map)
|
||||
{
|
||||
typedef typename std::basic_string<T>::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<T> 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<T>::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<class T>
|
||||
@@ -1003,14 +1037,15 @@ void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& 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<T>::isHead( const std::basic_string<T>& string, const T* s
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
template<class T>
|
||||
bool LLStringUtilBase<T>::startsWith(
|
||||
const std::basic_string<T>& string,
|
||||
const std::basic_string<T>& substr)
|
||||
{
|
||||
if(string.empty() || (substr.empty())) return false;
|
||||
if(0 == string.find(substr)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
template<class T>
|
||||
bool LLStringUtilBase<T>::endsWith(
|
||||
const std::basic_string<T>& string,
|
||||
const std::basic_string<T>& 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<class T>
|
||||
BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -49,11 +49,11 @@
|
||||
#endif
|
||||
|
||||
#if STRING_TABLE_HASH_MAP
|
||||
#if LL_WINDOWS
|
||||
#include <hash_map>
|
||||
#else
|
||||
#include <ext/hash_map>
|
||||
#endif
|
||||
# if LL_WINDOWS
|
||||
# include <hash_map>
|
||||
# else
|
||||
# include <ext/hash_map>
|
||||
# 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; }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*> 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<LLEventTimer*> completed_timers;
|
||||
for (std::list<LLEventTimer*>::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<LLEventTimer*>::iterator completed_iter = completed_timers.begin();
|
||||
completed_iter != completed_timers.end();
|
||||
completed_iter++ )
|
||||
{
|
||||
delete *completed_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<LLEventTimer*> sActiveList; // TODO should this be a vector
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// <edit>
|
||||
#ifndef LL_LLDELAYEDUIDELETE_H
|
||||
#define LL_LLDELAYEDUIDELETE_H
|
||||
#include "lltimer.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llview.h"
|
||||
class LLDeleteJob
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<typename T, typename KEY = T*>
|
||||
class LLInstanceTracker : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef typename std::map<KEY, T*>::iterator instance_iter;
|
||||
typedef typename std::map<KEY, T*>::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<T*>(this);
|
||||
}
|
||||
void remove() { sInstances.erase(mKey); }
|
||||
|
||||
private:
|
||||
|
||||
KEY mKey;
|
||||
static std::map<KEY, T*> sInstances;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class LLInstanceTracker<T, T*> : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef typename std::set<T*>::iterator instance_iter;
|
||||
typedef typename std::set<T*>::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<T*>(this)); }
|
||||
virtual ~LLInstanceTracker() { sInstances.erase(static_cast<T*>(this)); }
|
||||
|
||||
static std::set<T*> sInstances;
|
||||
};
|
||||
|
||||
template <typename T, typename KEY> std::map<KEY, T*> LLInstanceTracker<T, KEY>::sInstances;
|
||||
template <typename T> std::set<T*> LLInstanceTracker<T, T*>::sInstances;
|
||||
|
||||
class LLCallbackRegistry
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "llviewerregion.h"
|
||||
#include "llworld.h"
|
||||
#include "lluuid.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
#include "material_codes.h"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "llfloater.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llagent.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
|
||||
class AONoteCardDropTarget;
|
||||
|
||||
@@ -42,6 +42,7 @@ tag: vaa emerald local_asset_browser
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "lltexturectrl.h"
|
||||
#include "lldrawable.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
|
||||
/*=======================================*/
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// <edit>
|
||||
#include "llinventoryview.h"
|
||||
#include "llinventory.h"
|
||||
#include "lleventtimer.h"
|
||||
class LLBuildNewViewsScheduler : public LLEventTimer
|
||||
{
|
||||
typedef struct
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
class LLFloaterExploreSounds
|
||||
: public LLFloater, public LLEventTimer
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "llpanel.h"
|
||||
#include "llstring.h"
|
||||
#include "lluuid.h"
|
||||
#include "lltimer.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llcallingcard.h"
|
||||
|
||||
class LLFriendObserver;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "llmessagetemplate.h"
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include "llmenugl.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
#include "llagent.h"
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "llfloater.h"
|
||||
#include "llmessagelog.h"
|
||||
#include "lltemplatemessagereader.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
class LLNetListItem
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LLNotifyBox, LLUUID>::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<LLNotifyBox, LLUUID>::getInstance(notification->getID());
|
||||
if (boxp && !boxp->isDead())
|
||||
{
|
||||
boxp->close();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include "llfontgl.h"
|
||||
#include "llpanel.h"
|
||||
#include "lltimer.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llnotifications.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "llcombobox.h"
|
||||
#include "lliconctrl.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lltimer.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
|
||||
class LLMessageSystem;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef LLVIEWERPARCELMEDIAAUTOPLAY_H
|
||||
#define LLVIEWERPARCELMEDIAAUTOPLAY_H
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
// timer to automatically play media
|
||||
class LLViewerParcelMediaAutoPlay : LLEventTimer
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "llstartup.h"
|
||||
#include "llviewerjointattachment.h"
|
||||
#include "llviewerobject.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
#include "rlvcommon.h"
|
||||
#include "rlvhelper.h"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "llviewerinventory.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llwlparamset.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "rlvdefines.h"
|
||||
#include "rlvcommon.h"
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "llviewerjointattachment.h"
|
||||
#include "llviewerobject.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
#include "rlvdefines.h"
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user