diff options
| author | angela <angela@lindenlab.com> | 2009-11-19 11:43:47 +0800 | 
|---|---|---|
| committer | angela <angela@lindenlab.com> | 2009-11-19 11:43:47 +0800 | 
| commit | 6e5f529a7adb53fa021986aed6e6b1b229cc0efd (patch) | |
| tree | a031044cfb6618a5b36a0e80d0fc3a918dfa07a9 /indra/llcommon | |
| parent | a35fbddb910fa0dd068622c3dc64af1b27ca19b7 (diff) | |
| parent | 81eca4a7823f7fa06327b8185b6603d1f3c9ac9a (diff) | |
branch merge
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llcommon/llallocator.h | 126 | ||||
| -rw-r--r-- | indra/llcommon/llchat.h | 2 | ||||
| -rw-r--r-- | indra/llcommon/llcoros.h | 298 | ||||
| -rw-r--r-- | indra/llcommon/llfasttimer.h | 634 | ||||
| -rw-r--r-- | indra/llcommon/llmemory.h | 130 | ||||
| -rw-r--r-- | indra/llcommon/llmemtype.h | 496 | ||||
| -rw-r--r-- | indra/llcommon/llpreprocessor.h | 338 | ||||
| -rw-r--r-- | indra/llcommon/llstacktrace.cpp | 284 | ||||
| -rw-r--r-- | indra/llcommon/llstacktrace.h | 88 | ||||
| -rw-r--r-- | indra/llcommon/llstring.h | 2600 | 
11 files changed, 2501 insertions, 2497 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index e41c75846b..416303342a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -9,6 +9,7 @@ include(Linking)  include(Boost)  include(Pth)  include(LLSharedLibs) +include(GooglePerfTools)  include(Copy3rdPartyLibs)  include_directories( @@ -259,6 +260,7 @@ target_link_libraries(      ${BOOST_PROGRAM_OPTIONS_LIBRARY}      ${BOOST_REGEX_LIBRARY}      ${PTH_LIBRARIES} +    ${GOOGLE_PERFTOOLS_LIBRARIES}      )  add_dependencies(llcommon stage_third_party_libs) diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h index 50129b4526..0d6f18c5d4 100644 --- a/indra/llcommon/llallocator.h +++ b/indra/llcommon/llallocator.h @@ -1,63 +1,63 @@ -/**  - * @file llallocator.h - * @brief Declaration of the LLAllocator class. - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - *  - * Copyright (c) 2009-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$ - */ - -#ifndef LL_LLALLOCATOR_H -#define LL_LLALLOCATOR_H - -#include <string> - -#include "llmemtype.h" -#include "llallocator_heap_profile.h" - -class LL_COMMON_API LLAllocator { -    friend class LLMemoryView; -    friend class LLMemType; - -private: -	static void pushMemType(S32 type); -	static S32 popMemType(); - -public: -    void setProfilingEnabled(bool should_enable); - -    static bool isProfiling(); - -    LLAllocatorHeapProfile const & getProfile(); - -private: -    std::string getRawProfile(); - -private: -    LLAllocatorHeapProfile mProf; -}; - -#endif // LL_LLALLOCATOR_H +/** 
 + * @file llallocator.h
 + * @brief Declaration of the LLAllocator class.
 + *
 + * $LicenseInfo:firstyear=2009&license=viewergpl$
 + * 
 + * Copyright (c) 2009-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$
 + */
 +
 +#ifndef LL_LLALLOCATOR_H
 +#define LL_LLALLOCATOR_H
 +
 +#include <string>
 +
 +#include "llmemtype.h"
 +#include "llallocator_heap_profile.h"
 +
 +class LL_COMMON_API LLAllocator {
 +    friend class LLMemoryView;
 +    friend class LLMemType;
 +
 +private:
 +	static void pushMemType(S32 type);
 +	static S32 popMemType();
 +
 +public:
 +    void setProfilingEnabled(bool should_enable);
 +
 +    static bool isProfiling();
 +
 +    LLAllocatorHeapProfile const & getProfile();
 +
 +private:
 +    std::string getRawProfile();
 +
 +private:
 +    LLAllocatorHeapProfile mProf;
 +};
 +
 +#endif // LL_LLALLOCATOR_H
 diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h index acd0da61a4..5af7991006 100644 --- a/indra/llcommon/llchat.h +++ b/indra/llcommon/llchat.h @@ -84,6 +84,7 @@ public:  		mAudible(CHAT_AUDIBLE_FULLY),  		mMuted(FALSE),  		mTime(0.0), +		mTimeStr(),  		mPosAgent(),  		mURL(),  		mChatStyle(CHAT_STYLE_NORMAL) @@ -97,6 +98,7 @@ public:  	EChatAudible	mAudible;  	BOOL			mMuted;		// pass muted chat to maintain list of chatters  	F64				mTime;		// viewer only, seconds from viewer start +	std::string		mTimeStr;  	LLVector3		mPosAgent;  	std::string		mURL;  	EChatStyle		mChatStyle; diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 141b0df43c..6c5fa5af6d 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -1,149 +1,149 @@ -/** - * @file   llcoros.h - * @author Nat Goodspeed - * @date   2009-06-02 - * @brief  Manage running boost::coroutine instances - *  - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * Copyright (c) 2009, Linden Research, Inc. - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLCOROS_H) -#define LL_LLCOROS_H - -#include <boost/coroutine/coroutine.hpp> -#include "llsingleton.h" -#include <boost/ptr_container/ptr_map.hpp> -#include <string> -#include <boost/preprocessor/repetition/enum_params.hpp> -#include <boost/preprocessor/repetition/enum_binary_params.hpp> -#include <boost/preprocessor/iteration/local.hpp> -#include <stdexcept> - -/** - * Registry of named Boost.Coroutine instances - * - * The Boost.Coroutine library supports the general case of a coroutine - * accepting arbitrary parameters and yielding multiple (sets of) results. For - * such use cases, it's natural for the invoking code to retain the coroutine - * instance: the consumer repeatedly calls into the coroutine, perhaps passing - * new parameter values, prompting it to yield its next result. - * - * Our typical coroutine usage is different, though. For us, coroutines - * provide an alternative to the @c Responder pattern. Our typical coroutine - * has @c void return, invoked in fire-and-forget mode: the handler for some - * user gesture launches the coroutine and promptly returns to the main loop. - * The coroutine initiates some action that will take multiple frames (e.g. a - * capability request), waits for its result, processes it and silently steals - * away. - * - * This usage poses two (related) problems: - * - * # Who should own the coroutine instance? If it's simply local to the - *   handler code that launches it, return from the handler will destroy the - *   coroutine object, terminating the coroutine. - * # Once the coroutine terminates, in whatever way, who's responsible for - *   cleaning up the coroutine object? - * - * LLCoros is a Singleton collection of currently-active coroutine instances. - * Each has a name. You ask LLCoros to launch a new coroutine with a suggested - * name prefix; from your prefix it generates a distinct name, registers the - * new coroutine and returns the actual name. - * - * The name can be used to kill off the coroutine prematurely, if needed. It - * can also provide diagnostic info: we can look up the name of the - * currently-running coroutine. - * - * Finally, the next frame ("mainloop" event) after the coroutine terminates, - * LLCoros will notice its demise and destroy it. - */ -class LL_COMMON_API LLCoros: public LLSingleton<LLCoros> -{ -public: -    /// Canonical boost::coroutines::coroutine signature we use -    typedef boost::coroutines::coroutine<void()> coro; -    /// Canonical 'self' type -    typedef coro::self self; - -    /** -     * Create and start running a new coroutine with specified name. The name -     * string you pass is a suggestion; it will be tweaked for uniqueness. The -     * actual name is returned to you. -     * -     * Usage looks like this, for (e.g.) two coroutine parameters: -     * @code -     * class MyClass -     * { -     * public: -     *     ... -     *     // Do NOT NOT NOT accept reference params other than 'self'! -     *     // Pass by value only! -     *     void myCoroutineMethod(LLCoros::self& self, std::string, LLSD); -     *     ... -     * }; -     * ... -     * std::string name = LLCoros::instance().launch( -     *    "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1, -     *                          "somestring", LLSD(17)); -     * @endcode -     * -     * Your function/method must accept LLCoros::self& as its first parameter. -     * It can accept any other parameters you want -- but ONLY BY VALUE! -     * Other reference parameters are a BAD IDEA! You Have Been Warned. See -     * DEV-32777 comments for an explanation. -     * -     * Pass a callable that accepts the single LLCoros::self& parameter. It -     * may work to pass a free function whose only parameter is 'self'; for -     * all other cases use boost::bind(). Of course, for a non-static class -     * method, the first parameter must be the class instance. Use the -     * placeholder _1 for the 'self' parameter. Any other parameters should be -     * passed via the bind() expression. -     * -     * launch() tweaks the suggested name so it won't collide with any -     * existing coroutine instance, creates the coroutine instance, registers -     * it with the tweaked name and runs it until its first wait. At that -     * point it returns the tweaked name. -     */ -    template <typename CALLABLE> -    std::string launch(const std::string& prefix, const CALLABLE& callable) -    { -        return launchImpl(prefix, new coro(callable)); -    } - -    /** -     * Abort a running coroutine by name. Normally, when a coroutine either -     * runs to completion or terminates with an exception, LLCoros quietly -     * cleans it up. This is for use only when you must explicitly interrupt -     * one prematurely. Returns @c true if the specified name was found and -     * still running at the time. -     */ -    bool kill(const std::string& name); - -    /** -     * From within a coroutine, pass its @c self object to look up the -     * (tweaked) name string by which this coroutine is registered. Returns -     * the empty string if not found (e.g. if the coroutine was launched by -     * hand rather than using LLCoros::launch()). -     */ -    template <typename COROUTINE_SELF> -    std::string getName(const COROUTINE_SELF& self) const -    { -        return getNameByID(self.get_id()); -    } - -    /// getName() by self.get_id() -    std::string getNameByID(const void* self_id) const; - -private: -    friend class LLSingleton<LLCoros>; -    LLCoros(); -    std::string launchImpl(const std::string& prefix, coro* newCoro); -    std::string generateDistinctName(const std::string& prefix) const; -    bool cleanup(const LLSD&); - -    typedef boost::ptr_map<std::string, coro> CoroMap; -    CoroMap mCoros; -}; - -#endif /* ! defined(LL_LLCOROS_H) */ +/**
 + * @file   llcoros.h
 + * @author Nat Goodspeed
 + * @date   2009-06-02
 + * @brief  Manage running boost::coroutine instances
 + * 
 + * $LicenseInfo:firstyear=2009&license=viewergpl$
 + * Copyright (c) 2009, Linden Research, Inc.
 + * $/LicenseInfo$
 + */
 +
 +#if ! defined(LL_LLCOROS_H)
 +#define LL_LLCOROS_H
 +
 +#include <boost/coroutine/coroutine.hpp>
 +#include "llsingleton.h"
 +#include <boost/ptr_container/ptr_map.hpp>
 +#include <string>
 +#include <boost/preprocessor/repetition/enum_params.hpp>
 +#include <boost/preprocessor/repetition/enum_binary_params.hpp>
 +#include <boost/preprocessor/iteration/local.hpp>
 +#include <stdexcept>
 +
 +/**
 + * Registry of named Boost.Coroutine instances
 + *
 + * The Boost.Coroutine library supports the general case of a coroutine
 + * accepting arbitrary parameters and yielding multiple (sets of) results. For
 + * such use cases, it's natural for the invoking code to retain the coroutine
 + * instance: the consumer repeatedly calls into the coroutine, perhaps passing
 + * new parameter values, prompting it to yield its next result.
 + *
 + * Our typical coroutine usage is different, though. For us, coroutines
 + * provide an alternative to the @c Responder pattern. Our typical coroutine
 + * has @c void return, invoked in fire-and-forget mode: the handler for some
 + * user gesture launches the coroutine and promptly returns to the main loop.
 + * The coroutine initiates some action that will take multiple frames (e.g. a
 + * capability request), waits for its result, processes it and silently steals
 + * away.
 + *
 + * This usage poses two (related) problems:
 + *
 + * # Who should own the coroutine instance? If it's simply local to the
 + *   handler code that launches it, return from the handler will destroy the
 + *   coroutine object, terminating the coroutine.
 + * # Once the coroutine terminates, in whatever way, who's responsible for
 + *   cleaning up the coroutine object?
 + *
 + * LLCoros is a Singleton collection of currently-active coroutine instances.
 + * Each has a name. You ask LLCoros to launch a new coroutine with a suggested
 + * name prefix; from your prefix it generates a distinct name, registers the
 + * new coroutine and returns the actual name.
 + *
 + * The name can be used to kill off the coroutine prematurely, if needed. It
 + * can also provide diagnostic info: we can look up the name of the
 + * currently-running coroutine.
 + *
 + * Finally, the next frame ("mainloop" event) after the coroutine terminates,
 + * LLCoros will notice its demise and destroy it.
 + */
 +class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
 +{
 +public:
 +    /// Canonical boost::coroutines::coroutine signature we use
 +    typedef boost::coroutines::coroutine<void()> coro;
 +    /// Canonical 'self' type
 +    typedef coro::self self;
 +
 +    /**
 +     * Create and start running a new coroutine with specified name. The name
 +     * string you pass is a suggestion; it will be tweaked for uniqueness. The
 +     * actual name is returned to you.
 +     *
 +     * Usage looks like this, for (e.g.) two coroutine parameters:
 +     * @code
 +     * class MyClass
 +     * {
 +     * public:
 +     *     ...
 +     *     // Do NOT NOT NOT accept reference params other than 'self'!
 +     *     // Pass by value only!
 +     *     void myCoroutineMethod(LLCoros::self& self, std::string, LLSD);
 +     *     ...
 +     * };
 +     * ...
 +     * std::string name = LLCoros::instance().launch(
 +     *    "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1,
 +     *                          "somestring", LLSD(17));
 +     * @endcode
 +     *
 +     * Your function/method must accept LLCoros::self& as its first parameter.
 +     * It can accept any other parameters you want -- but ONLY BY VALUE!
 +     * Other reference parameters are a BAD IDEA! You Have Been Warned. See
 +     * DEV-32777 comments for an explanation.
 +     *
 +     * Pass a callable that accepts the single LLCoros::self& parameter. It
 +     * may work to pass a free function whose only parameter is 'self'; for
 +     * all other cases use boost::bind(). Of course, for a non-static class
 +     * method, the first parameter must be the class instance. Use the
 +     * placeholder _1 for the 'self' parameter. Any other parameters should be
 +     * passed via the bind() expression.
 +     *
 +     * launch() tweaks the suggested name so it won't collide with any
 +     * existing coroutine instance, creates the coroutine instance, registers
 +     * it with the tweaked name and runs it until its first wait. At that
 +     * point it returns the tweaked name.
 +     */
 +    template <typename CALLABLE>
 +    std::string launch(const std::string& prefix, const CALLABLE& callable)
 +    {
 +        return launchImpl(prefix, new coro(callable));
 +    }
 +
 +    /**
 +     * Abort a running coroutine by name. Normally, when a coroutine either
 +     * runs to completion or terminates with an exception, LLCoros quietly
 +     * cleans it up. This is for use only when you must explicitly interrupt
 +     * one prematurely. Returns @c true if the specified name was found and
 +     * still running at the time.
 +     */
 +    bool kill(const std::string& name);
 +
 +    /**
 +     * From within a coroutine, pass its @c self object to look up the
 +     * (tweaked) name string by which this coroutine is registered. Returns
 +     * the empty string if not found (e.g. if the coroutine was launched by
 +     * hand rather than using LLCoros::launch()).
 +     */
 +    template <typename COROUTINE_SELF>
 +    std::string getName(const COROUTINE_SELF& self) const
 +    {
 +        return getNameByID(self.get_id());
 +    }
 +
 +    /// getName() by self.get_id()
 +    std::string getNameByID(const void* self_id) const;
 +
 +private:
 +    friend class LLSingleton<LLCoros>;
 +    LLCoros();
 +    std::string launchImpl(const std::string& prefix, coro* newCoro);
 +    std::string generateDistinctName(const std::string& prefix) const;
 +    bool cleanup(const LLSD&);
 +
 +    typedef boost::ptr_map<std::string, coro> CoroMap;
 +    CoroMap mCoros;
 +};
 +
 +#endif /* ! defined(LL_LLCOROS_H) */
 diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 45b84ea3ea..905d736d62 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -1,317 +1,317 @@ -/**  - * @file llfasttimer.h - * @brief Declaration of a fast timer. - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - *  - * Copyright (c) 2004-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$ - */ - -#ifndef LL_FASTTIMER_H -#define LL_FASTTIMER_H - -#include "llinstancetracker.h" - -#define FAST_TIMER_ON 1 - -#if LL_WINDOWS - -// shift off lower 8 bits for lower resolution but longer term timing -// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing -inline U32 get_cpu_clock_count_32() -{ -	U32 ret_val; -	__asm  -	{ -        _emit   0x0f -        _emit   0x31 -		shr eax,8 -		shl edx,24 -		or eax, edx -		mov dword ptr [ret_val], eax -	} -    return ret_val; -} - -// return full timer value, still shifted by 8 bits -inline U64 get_cpu_clock_count_64() -{ -	U64 ret_val; -	__asm  -	{ -        _emit   0x0f -        _emit   0x31 -		mov eax,eax -		mov edx,edx -		mov dword ptr [ret_val+4], edx -		mov dword ptr [ret_val], eax -	} -    return ret_val >> 8; -} - -#endif // LL_WINDOWS - -#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) -inline U32 get_cpu_clock_count_32() -{																	 -	U64 x;															 -	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));					 -	return (U32)x >> 8;													 -} - -inline U32 get_cpu_clock_count_64() -{																	 -	U64 x; -	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); -	return x >> 8; -} -#endif - -#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__)) -// -// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock -// -// Just use gettimeofday implementation for now - -inline U32 get_cpu_clock_count_32() -{ -	return (U32)get_clock_count(); -} - -inline U32 get_cpu_clock_count_64() -{																	 -	return get_clock_count(); -} -#endif - -class LLMutex; - -#include <queue> -#include "llsd.h" - - -class LL_COMMON_API LLFastTimer -{ -public: -	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances -	class LL_COMMON_API NamedTimer  -	:	public LLInstanceTracker<NamedTimer> -	{ -		friend class DeclareTimer; -	public: -		~NamedTimer(); - -		enum { HISTORY_NUM = 60 }; - -		const std::string& getName() const { return mName; } -		NamedTimer* getParent() const { return mParent; } -		void setParent(NamedTimer* parent); -		S32 getDepth(); -		std::string getToolTip(S32 history_index = -1); - -		typedef std::vector<NamedTimer*>::const_iterator child_const_iter; -		child_const_iter beginChildren(); -		child_const_iter endChildren(); -		std::vector<NamedTimer*>& getChildren(); - -		void setCollapsed(bool collapsed) { mCollapsed = collapsed; } -		bool getCollapsed() const { return mCollapsed; } - -		U32 getCountAverage() const { return mCountAverage; } -		U32 getCallAverage() const { return mCallAverage; } - -		U32 getHistoricalCount(S32 history_index = 0) const; -		U32 getHistoricalCalls(S32 history_index = 0) const; - -		static NamedTimer& getRootNamedTimer(); - -		struct FrameState -		{ -			FrameState(NamedTimer* timerp); - -			U32 		mSelfTimeCounter; -			U32 		mCalls; -			FrameState*	mParent;		// info for caller timer -			FrameState*	mLastCaller;	// used to bootstrap tree construction -			NamedTimer*	mTimer; -			U16			mActiveCount;	// number of timers with this ID active on stack -			bool		mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame -		}; - -		S32 getFrameStateIndex() const { return mFrameStateIndex; } - -		FrameState& getFrameState() const; - - -	private:  -		friend class LLFastTimer; -		friend class NamedTimerFactory; - -		// -		// methods -		// -		NamedTimer(const std::string& name); -		// recursive call to gather total time from children -		static void accumulateTimings(); - -		// updates cumulative times and hierarchy,  -		// can be called multiple times in a frame, at any point -		static void processTimes(); - -		static void buildHierarchy(); -		static void resetFrame(); -		static void reset(); - -	 -		// -		// members -		// -		S32			mFrameStateIndex; - -		std::string	mName; - -		U32 		mTotalTimeCounter; - -		U32 		mCountAverage; -		U32			mCallAverage; - -		U32*		mCountHistory; -		U32*		mCallHistory; - -		// tree structure -		NamedTimer*					mParent;				// NamedTimer of caller(parent) -		std::vector<NamedTimer*>	mChildren; -		bool						mCollapsed;				// don't show children -		bool						mNeedsSorting;			// sort children whenever child added - -	}; - -	// used to statically declare a new named timer -	class LL_COMMON_API DeclareTimer -	:	public LLInstanceTracker<DeclareTimer> -	{ -	public: -		DeclareTimer(const std::string& name, bool open); -		DeclareTimer(const std::string& name); - -		static void updateCachedPointers(); - -		// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) -		operator NamedTimer::FrameState&() { return *mFrameState; } -	private: -		NamedTimer&				mTimer; -		NamedTimer::FrameState* mFrameState;  -	}; - - -public: -	static LLMutex* sLogLock; -	static std::queue<LLSD> sLogQueue; -	static BOOL sLog; -	static BOOL sMetricLog; - -	typedef std::vector<NamedTimer::FrameState> info_list_t; -	static info_list_t& getFrameStateList(); - -	enum RootTimerMarker { ROOT }; -	LLFastTimer(RootTimerMarker); - -	LLFastTimer(NamedTimer::FrameState& timer) -	:	mFrameState(&timer) -	{ -#if FAST_TIMER_ON -		NamedTimer::FrameState* frame_state = &timer; -		U32 cur_time = get_cpu_clock_count_32(); -		mStartSelfTime = cur_time; -		mStartTotalTime = cur_time; - -		frame_state->mActiveCount++; -		frame_state->mCalls++; -		// keep current parent as long as it is active when we are -		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); -	 -		mLastTimer = sCurTimer; -		sCurTimer = this; -#endif -	} - -	~LLFastTimer() -	{ -#if FAST_TIMER_ON -		NamedTimer::FrameState* frame_state = mFrameState; -		U32 cur_time = get_cpu_clock_count_32(); -		frame_state->mSelfTimeCounter += cur_time - mStartSelfTime; - -		frame_state->mActiveCount--; -		LLFastTimer* last_timer = mLastTimer; -		sCurTimer = last_timer; - -		// store last caller to bootstrap tree creation -		frame_state->mLastCaller = last_timer->mFrameState; - -		// we are only tracking self time, so subtract our total time delta from parents -		U32 total_time = cur_time - mStartTotalTime; -		last_timer->mStartSelfTime += total_time; -#endif -	} - - -	// call this once a frame to reset timers -	static void nextFrame(); - -	// dumps current cumulative frame stats to log -	// call nextFrame() to reset timers -	static void dumpCurTimes();  - -	// call this to reset timer hierarchy, averages, etc. -	static void reset(); - -	static U64 countsPerSecond(); -	static S32 getLastFrameIndex() { return sLastFrameIndex; } -	static S32 getCurFrameIndex() { return sCurFrameIndex; } - -	static void writeLog(std::ostream& os); -	static const NamedTimer* getTimerByName(const std::string& name); - -public: -	static bool 		sPauseHistory; -	static bool 		sResetHistory; -	 -private: -	typedef std::vector<LLFastTimer*> timer_stack_t; -	static LLFastTimer*		sCurTimer; -	static S32				sCurFrameIndex; -	static S32				sLastFrameIndex; -	static U64				sLastFrameTime; -	static info_list_t*		sTimerInfos; - -	U32						mStartSelfTime;	// start time + time of all child timers -	U32						mStartTotalTime;	// start time + time of all child timers -	NamedTimer::FrameState*	mFrameState; -	LLFastTimer*			mLastTimer; -}; - -#endif // LL_LLFASTTIMER_H +/** 
 + * @file llfasttimer.h
 + * @brief Declaration of a fast timer.
 + *
 + * $LicenseInfo:firstyear=2004&license=viewergpl$
 + * 
 + * Copyright (c) 2004-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$
 + */
 +
 +#ifndef LL_FASTTIMER_H
 +#define LL_FASTTIMER_H
 +
 +#include "llinstancetracker.h"
 +
 +#define FAST_TIMER_ON 1
 +
 +#if LL_WINDOWS
 +
 +// shift off lower 8 bits for lower resolution but longer term timing
 +// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
 +inline U32 get_cpu_clock_count_32()
 +{
 +	U32 ret_val;
 +	__asm 
 +	{
 +        _emit   0x0f
 +        _emit   0x31
 +		shr eax,8
 +		shl edx,24
 +		or eax, edx
 +		mov dword ptr [ret_val], eax
 +	}
 +    return ret_val;
 +}
 +
 +// return full timer value, still shifted by 8 bits
 +inline U64 get_cpu_clock_count_64()
 +{
 +	U64 ret_val;
 +	__asm 
 +	{
 +        _emit   0x0f
 +        _emit   0x31
 +		mov eax,eax
 +		mov edx,edx
 +		mov dword ptr [ret_val+4], edx
 +		mov dword ptr [ret_val], eax
 +	}
 +    return ret_val >> 8;
 +}
 +
 +#endif // LL_WINDOWS
 +
 +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
 +inline U32 get_cpu_clock_count_32()
 +{																	
 +	U64 x;															
 +	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));					
 +	return (U32)x >> 8;													
 +}
 +
 +inline U32 get_cpu_clock_count_64()
 +{																	
 +	U64 x;
 +	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
 +	return x >> 8;
 +}
 +#endif
 +
 +#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
 +//
 +// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
 +//
 +// Just use gettimeofday implementation for now
 +
 +inline U32 get_cpu_clock_count_32()
 +{
 +	return (U32)get_clock_count();
 +}
 +
 +inline U32 get_cpu_clock_count_64()
 +{																	
 +	return get_clock_count();
 +}
 +#endif
 +
 +class LLMutex;
 +
 +#include <queue>
 +#include "llsd.h"
 +
 +
 +class LL_COMMON_API LLFastTimer
 +{
 +public:
 +	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
 +	class LL_COMMON_API NamedTimer 
 +	:	public LLInstanceTracker<NamedTimer>
 +	{
 +		friend class DeclareTimer;
 +	public:
 +		~NamedTimer();
 +
 +		enum { HISTORY_NUM = 60 };
 +
 +		const std::string& getName() const { return mName; }
 +		NamedTimer* getParent() const { return mParent; }
 +		void setParent(NamedTimer* parent);
 +		S32 getDepth();
 +		std::string getToolTip(S32 history_index = -1);
 +
 +		typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
 +		child_const_iter beginChildren();
 +		child_const_iter endChildren();
 +		std::vector<NamedTimer*>& getChildren();
 +
 +		void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
 +		bool getCollapsed() const { return mCollapsed; }
 +
 +		U32 getCountAverage() const { return mCountAverage; }
 +		U32 getCallAverage() const { return mCallAverage; }
 +
 +		U32 getHistoricalCount(S32 history_index = 0) const;
 +		U32 getHistoricalCalls(S32 history_index = 0) const;
 +
 +		static NamedTimer& getRootNamedTimer();
 +
 +		struct FrameState
 +		{
 +			FrameState(NamedTimer* timerp);
 +
 +			U32 		mSelfTimeCounter;
 +			U32 		mCalls;
 +			FrameState*	mParent;		// info for caller timer
 +			FrameState*	mLastCaller;	// used to bootstrap tree construction
 +			NamedTimer*	mTimer;
 +			U16			mActiveCount;	// number of timers with this ID active on stack
 +			bool		mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
 +		};
 +
 +		S32 getFrameStateIndex() const { return mFrameStateIndex; }
 +
 +		FrameState& getFrameState() const;
 +
 +
 +	private: 
 +		friend class LLFastTimer;
 +		friend class NamedTimerFactory;
 +
 +		//
 +		// methods
 +		//
 +		NamedTimer(const std::string& name);
 +		// recursive call to gather total time from children
 +		static void accumulateTimings();
 +
 +		// updates cumulative times and hierarchy, 
 +		// can be called multiple times in a frame, at any point
 +		static void processTimes();
 +
 +		static void buildHierarchy();
 +		static void resetFrame();
 +		static void reset();
 +
 +	
 +		//
 +		// members
 +		//
 +		S32			mFrameStateIndex;
 +
 +		std::string	mName;
 +
 +		U32 		mTotalTimeCounter;
 +
 +		U32 		mCountAverage;
 +		U32			mCallAverage;
 +
 +		U32*		mCountHistory;
 +		U32*		mCallHistory;
 +
 +		// tree structure
 +		NamedTimer*					mParent;				// NamedTimer of caller(parent)
 +		std::vector<NamedTimer*>	mChildren;
 +		bool						mCollapsed;				// don't show children
 +		bool						mNeedsSorting;			// sort children whenever child added
 +
 +	};
 +
 +	// used to statically declare a new named timer
 +	class LL_COMMON_API DeclareTimer
 +	:	public LLInstanceTracker<DeclareTimer>
 +	{
 +	public:
 +		DeclareTimer(const std::string& name, bool open);
 +		DeclareTimer(const std::string& name);
 +
 +		static void updateCachedPointers();
 +
 +		// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
 +		operator NamedTimer::FrameState&() { return *mFrameState; }
 +	private:
 +		NamedTimer&				mTimer;
 +		NamedTimer::FrameState* mFrameState; 
 +	};
 +
 +
 +public:
 +	static LLMutex* sLogLock;
 +	static std::queue<LLSD> sLogQueue;
 +	static BOOL sLog;
 +	static BOOL sMetricLog;
 +
 +	typedef std::vector<NamedTimer::FrameState> info_list_t;
 +	static info_list_t& getFrameStateList();
 +
 +	enum RootTimerMarker { ROOT };
 +	LLFastTimer(RootTimerMarker);
 +
 +	LLFastTimer(NamedTimer::FrameState& timer)
 +	:	mFrameState(&timer)
 +	{
 +#if FAST_TIMER_ON
 +		NamedTimer::FrameState* frame_state = &timer;
 +		U32 cur_time = get_cpu_clock_count_32();
 +		mStartSelfTime = cur_time;
 +		mStartTotalTime = cur_time;
 +
 +		frame_state->mActiveCount++;
 +		frame_state->mCalls++;
 +		// keep current parent as long as it is active when we are
 +		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
 +	
 +		mLastTimer = sCurTimer;
 +		sCurTimer = this;
 +#endif
 +	}
 +
 +	~LLFastTimer()
 +	{
 +#if FAST_TIMER_ON
 +		NamedTimer::FrameState* frame_state = mFrameState;
 +		U32 cur_time = get_cpu_clock_count_32();
 +		frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
 +
 +		frame_state->mActiveCount--;
 +		LLFastTimer* last_timer = mLastTimer;
 +		sCurTimer = last_timer;
 +
 +		// store last caller to bootstrap tree creation
 +		frame_state->mLastCaller = last_timer->mFrameState;
 +
 +		// we are only tracking self time, so subtract our total time delta from parents
 +		U32 total_time = cur_time - mStartTotalTime;
 +		last_timer->mStartSelfTime += total_time;
 +#endif
 +	}
 +
 +
 +	// call this once a frame to reset timers
 +	static void nextFrame();
 +
 +	// dumps current cumulative frame stats to log
 +	// call nextFrame() to reset timers
 +	static void dumpCurTimes(); 
 +
 +	// call this to reset timer hierarchy, averages, etc.
 +	static void reset();
 +
 +	static U64 countsPerSecond();
 +	static S32 getLastFrameIndex() { return sLastFrameIndex; }
 +	static S32 getCurFrameIndex() { return sCurFrameIndex; }
 +
 +	static void writeLog(std::ostream& os);
 +	static const NamedTimer* getTimerByName(const std::string& name);
 +
 +public:
 +	static bool 		sPauseHistory;
 +	static bool 		sResetHistory;
 +	
 +private:
 +	typedef std::vector<LLFastTimer*> timer_stack_t;
 +	static LLFastTimer*		sCurTimer;
 +	static S32				sCurFrameIndex;
 +	static S32				sLastFrameIndex;
 +	static U64				sLastFrameTime;
 +	static info_list_t*		sTimerInfos;
 +
 +	U32						mStartSelfTime;	// start time + time of all child timers
 +	U32						mStartTotalTime;	// start time + time of all child timers
 +	NamedTimer::FrameState*	mFrameState;
 +	LLFastTimer*			mLastTimer;
 +};
 +
 +#endif // LL_LLFASTTIMER_H
 diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 1c6f64dd8b..09f19532b7 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -1,65 +1,65 @@ -/**  - * @file llmemory.h - * @brief Memory allocation/deallocation header-stuff goes here. - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - *  - * Copyright (c) 2002-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$ - */ -#ifndef LLMEMORY_H -#define LLMEMORY_H - - - -extern S32 gTotalDAlloc; -extern S32 gTotalDAUse; -extern S32 gDACount; - -extern void* ll_allocate (size_t size); -extern void ll_release (void *p); - -class LL_COMMON_API LLMemory -{ -public: -	static void initClass(); -	static void cleanupClass(); -	static void freeReserve(); -	// Return the resident set size of the current process, in bytes. -	// Return value is zero if not known. -	static U64 getCurrentRSS(); -private: -	static char* reserveMem; -}; - -// LLRefCount moved to llrefcount.h - -// LLPointer moved to llpointer.h - -// LLSafeHandle moved to llsafehandle.h - -// LLSingleton moved to llsingleton.h - -#endif +/** 
 + * @file llmemory.h
 + * @brief Memory allocation/deallocation header-stuff goes here.
 + *
 + * $LicenseInfo:firstyear=2002&license=viewergpl$
 + * 
 + * Copyright (c) 2002-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$
 + */
 +#ifndef LLMEMORY_H
 +#define LLMEMORY_H
 +
 +
 +
 +extern S32 gTotalDAlloc;
 +extern S32 gTotalDAUse;
 +extern S32 gDACount;
 +
 +extern void* ll_allocate (size_t size);
 +extern void ll_release (void *p);
 +
 +class LL_COMMON_API LLMemory
 +{
 +public:
 +	static void initClass();
 +	static void cleanupClass();
 +	static void freeReserve();
 +	// Return the resident set size of the current process, in bytes.
 +	// Return value is zero if not known.
 +	static U64 getCurrentRSS();
 +private:
 +	static char* reserveMem;
 +};
 +
 +// LLRefCount moved to llrefcount.h
 +
 +// LLPointer moved to llpointer.h
 +
 +// LLSafeHandle moved to llsafehandle.h
 +
 +// LLSingleton moved to llsingleton.h
 +
 +#endif
 diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h index 677fad3034..5952a3a7c5 100644 --- a/indra/llcommon/llmemtype.h +++ b/indra/llcommon/llmemtype.h @@ -1,248 +1,248 @@ -/**  - * @file llmemtype.h - * @brief Runtime memory usage debugging utilities. - * - * $LicenseInfo:firstyear=2005&license=viewergpl$ - *  - * Copyright (c) 2005-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$ - */ - -#ifndef LL_MEMTYPE_H -#define LL_MEMTYPE_H - -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- - -#include "linden_common.h" -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// WARNING: Never commit with MEM_TRACK_MEM == 1 -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -#define MEM_TRACK_MEM (0 && LL_WINDOWS) - -#include <vector> - -#define MEM_TYPE_NEW(T) - -class LL_COMMON_API LLMemType -{ -public: - -	// class we'll initialize all instances of as -	// static members of MemType.  Then use -	// to construct any new mem type. -	class LL_COMMON_API DeclareMemType -	{ -	public: -		DeclareMemType(char const * st); -		~DeclareMemType(); -	 -		S32 mID; -		char const * mName; -		 -		// array so we can map an index ID to Name -		static std::vector<char const *> mNameList; -	}; - -	LLMemType(DeclareMemType& dt); -	~LLMemType(); - -	static char const * getNameFromID(S32 id); - -	static DeclareMemType MTYPE_INIT; -	static DeclareMemType MTYPE_STARTUP; -	static DeclareMemType MTYPE_MAIN; -	static DeclareMemType MTYPE_FRAME; - -	static DeclareMemType MTYPE_GATHER_INPUT; -	static DeclareMemType MTYPE_JOY_KEY; - -	static DeclareMemType MTYPE_IDLE; -	static DeclareMemType MTYPE_IDLE_PUMP; -	static DeclareMemType MTYPE_IDLE_NETWORK; -	static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS; -	static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION; -	static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE; -	static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY; -	static DeclareMemType MTYPE_IDLE_AUDIO; - -	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING; -	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS; -	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES; - -	static DeclareMemType MTYPE_MESSAGE_CHECK_ALL; -	static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS; - -	static DeclareMemType MTYPE_RENDER; -	static DeclareMemType MTYPE_SLEEP; - -	static DeclareMemType MTYPE_NETWORK; -	static DeclareMemType MTYPE_PHYSICS; -	static DeclareMemType MTYPE_INTERESTLIST; - -	static DeclareMemType MTYPE_IMAGEBASE; -	static DeclareMemType MTYPE_IMAGERAW; -	static DeclareMemType MTYPE_IMAGEFORMATTED; -	 -	static DeclareMemType MTYPE_APPFMTIMAGE; -	static DeclareMemType MTYPE_APPRAWIMAGE; -	static DeclareMemType MTYPE_APPAUXRAWIMAGE; -	 -	static DeclareMemType MTYPE_DRAWABLE; -	 -	static DeclareMemType MTYPE_OBJECT; -	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE; -	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE; - -	static DeclareMemType MTYPE_DISPLAY; -	static DeclareMemType MTYPE_DISPLAY_UPDATE; -	static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA; -	static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM; -	static DeclareMemType MTYPE_DISPLAY_SWAP; -	static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD; -	static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION; -	static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE; -	static DeclareMemType MTYPE_DISPLAY_STATE_SORT; -	static DeclareMemType MTYPE_DISPLAY_SKY; -	static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM; -	static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH; -	static DeclareMemType MTYPE_DISPLAY_RENDER_UI; -	static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS; - -	static DeclareMemType MTYPE_VERTEX_DATA; -	static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR; -	static DeclareMemType MTYPE_VERTEX_DESTRUCTOR; -	static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES; -	static DeclareMemType MTYPE_VERTEX_CREATE_INDICES; -	static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;	 -	static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES; -	static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS; -	static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES; -	static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER; -	static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER; -	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER; -	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES; -	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES; -	static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER; -	static DeclareMemType MTYPE_VERTEX_SET_STRIDE; -	static DeclareMemType MTYPE_VERTEX_SET_BUFFER; -	static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER; -	static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS; - -	static DeclareMemType MTYPE_SPACE_PARTITION; - -	static DeclareMemType MTYPE_PIPELINE; -	static DeclareMemType MTYPE_PIPELINE_INIT; -	static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS; -	static DeclareMemType MTYPE_PIPELINE_RESTORE_GL; -	static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS; -	static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL; -	static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE; -	static DeclareMemType MTYPE_PIPELINE_ADD_POOL; -	static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE; -	static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT; -	static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS; -	static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE; -	static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM; -	static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE; -	static DeclareMemType MTYPE_PIPELINE_MARK_MOVED; -	static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT; -	static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS; -	static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED; -	static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD; -	static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL; -	static DeclareMemType MTYPE_PIPELINE_STATE_SORT; -	static DeclareMemType MTYPE_PIPELINE_POST_SORT; -	 -	static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS; -	static DeclareMemType MTYPE_PIPELINE_RENDER_HL; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW; -	static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT; -	static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS; -	static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP; -	static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS; -	static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR; -	static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM; - -	static DeclareMemType MTYPE_UPKEEP_POOLS; - -	static DeclareMemType MTYPE_AVATAR; -	static DeclareMemType MTYPE_AVATAR_MESH; -	static DeclareMemType MTYPE_PARTICLES; -	static DeclareMemType MTYPE_REGIONS; - -	static DeclareMemType MTYPE_INVENTORY; -	static DeclareMemType MTYPE_INVENTORY_DRAW; -	static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS; -	static DeclareMemType MTYPE_INVENTORY_DO_FOLDER; -	static DeclareMemType MTYPE_INVENTORY_POST_BUILD; -	static DeclareMemType MTYPE_INVENTORY_FROM_XML; -	static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM; -	static DeclareMemType MTYPE_INVENTORY_VIEW_INIT; -	static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW; -	static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE; - -	static DeclareMemType MTYPE_ANIMATION; -	static DeclareMemType MTYPE_VOLUME; -	static DeclareMemType MTYPE_PRIMITIVE; -	 -	static DeclareMemType MTYPE_SCRIPT; -	static DeclareMemType MTYPE_SCRIPT_RUN; -	static DeclareMemType MTYPE_SCRIPT_BYTECODE; -	 -	static DeclareMemType MTYPE_IO_PUMP; -	static DeclareMemType MTYPE_IO_TCP; -	static DeclareMemType MTYPE_IO_BUFFER; -	static DeclareMemType MTYPE_IO_HTTP_SERVER; -	static DeclareMemType MTYPE_IO_SD_SERVER; -	static DeclareMemType MTYPE_IO_SD_CLIENT; -	static DeclareMemType MTYPE_IO_URL_REQUEST; - -	static DeclareMemType MTYPE_DIRECTX_INIT; - -	static DeclareMemType MTYPE_TEMP1; -	static DeclareMemType MTYPE_TEMP2; -	static DeclareMemType MTYPE_TEMP3; -	static DeclareMemType MTYPE_TEMP4; -	static DeclareMemType MTYPE_TEMP5; -	static DeclareMemType MTYPE_TEMP6; -	static DeclareMemType MTYPE_TEMP7; -	static DeclareMemType MTYPE_TEMP8; -	static DeclareMemType MTYPE_TEMP9; - -	static DeclareMemType MTYPE_OTHER; // Special; used by display code - -	S32 mTypeIndex; -}; - -//---------------------------------------------------------------------------- - -#endif - +/** 
 + * @file llmemtype.h
 + * @brief Runtime memory usage debugging utilities.
 + *
 + * $LicenseInfo:firstyear=2005&license=viewergpl$
 + * 
 + * Copyright (c) 2005-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$
 + */
 +
 +#ifndef LL_MEMTYPE_H
 +#define LL_MEMTYPE_H
 +
 +//----------------------------------------------------------------------------
 +//----------------------------------------------------------------------------
 +
 +//----------------------------------------------------------------------------
 +
 +#include "linden_common.h"
 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 +// WARNING: Never commit with MEM_TRACK_MEM == 1
 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 +#define MEM_TRACK_MEM (0 && LL_WINDOWS)
 +
 +#include <vector>
 +
 +#define MEM_TYPE_NEW(T)
 +
 +class LL_COMMON_API LLMemType
 +{
 +public:
 +
 +	// class we'll initialize all instances of as
 +	// static members of MemType.  Then use
 +	// to construct any new mem type.
 +	class LL_COMMON_API DeclareMemType
 +	{
 +	public:
 +		DeclareMemType(char const * st);
 +		~DeclareMemType();
 +	
 +		S32 mID;
 +		char const * mName;
 +		
 +		// array so we can map an index ID to Name
 +		static std::vector<char const *> mNameList;
 +	};
 +
 +	LLMemType(DeclareMemType& dt);
 +	~LLMemType();
 +
 +	static char const * getNameFromID(S32 id);
 +
 +	static DeclareMemType MTYPE_INIT;
 +	static DeclareMemType MTYPE_STARTUP;
 +	static DeclareMemType MTYPE_MAIN;
 +	static DeclareMemType MTYPE_FRAME;
 +
 +	static DeclareMemType MTYPE_GATHER_INPUT;
 +	static DeclareMemType MTYPE_JOY_KEY;
 +
 +	static DeclareMemType MTYPE_IDLE;
 +	static DeclareMemType MTYPE_IDLE_PUMP;
 +	static DeclareMemType MTYPE_IDLE_NETWORK;
 +	static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
 +	static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
 +	static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
 +	static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
 +	static DeclareMemType MTYPE_IDLE_AUDIO;
 +
 +	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
 +	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
 +	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
 +
 +	static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
 +	static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
 +
 +	static DeclareMemType MTYPE_RENDER;
 +	static DeclareMemType MTYPE_SLEEP;
 +
 +	static DeclareMemType MTYPE_NETWORK;
 +	static DeclareMemType MTYPE_PHYSICS;
 +	static DeclareMemType MTYPE_INTERESTLIST;
 +
 +	static DeclareMemType MTYPE_IMAGEBASE;
 +	static DeclareMemType MTYPE_IMAGERAW;
 +	static DeclareMemType MTYPE_IMAGEFORMATTED;
 +	
 +	static DeclareMemType MTYPE_APPFMTIMAGE;
 +	static DeclareMemType MTYPE_APPRAWIMAGE;
 +	static DeclareMemType MTYPE_APPAUXRAWIMAGE;
 +	
 +	static DeclareMemType MTYPE_DRAWABLE;
 +	
 +	static DeclareMemType MTYPE_OBJECT;
 +	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
 +	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
 +
 +	static DeclareMemType MTYPE_DISPLAY;
 +	static DeclareMemType MTYPE_DISPLAY_UPDATE;
 +	static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
 +	static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
 +	static DeclareMemType MTYPE_DISPLAY_SWAP;
 +	static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
 +	static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
 +	static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
 +	static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
 +	static DeclareMemType MTYPE_DISPLAY_SKY;
 +	static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
 +	static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
 +	static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
 +	static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
 +
 +	static DeclareMemType MTYPE_VERTEX_DATA;
 +	static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
 +	static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
 +	static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
 +	static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
 +	static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;	
 +	static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
 +	static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
 +	static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
 +	static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
 +	static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
 +	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
 +	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
 +	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
 +	static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
 +	static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
 +	static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
 +	static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
 +	static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
 +
 +	static DeclareMemType MTYPE_SPACE_PARTITION;
 +
 +	static DeclareMemType MTYPE_PIPELINE;
 +	static DeclareMemType MTYPE_PIPELINE_INIT;
 +	static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
 +	static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
 +	static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
 +	static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
 +	static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
 +	static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
 +	static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
 +	static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
 +	static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
 +	static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
 +	static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
 +	static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
 +	static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
 +	static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
 +	static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
 +	static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
 +	static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
 +	static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
 +	static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
 +	static DeclareMemType MTYPE_PIPELINE_POST_SORT;
 +	
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
 +	static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
 +	static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
 +	static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
 +	static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
 +
 +	static DeclareMemType MTYPE_UPKEEP_POOLS;
 +
 +	static DeclareMemType MTYPE_AVATAR;
 +	static DeclareMemType MTYPE_AVATAR_MESH;
 +	static DeclareMemType MTYPE_PARTICLES;
 +	static DeclareMemType MTYPE_REGIONS;
 +
 +	static DeclareMemType MTYPE_INVENTORY;
 +	static DeclareMemType MTYPE_INVENTORY_DRAW;
 +	static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
 +	static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
 +	static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
 +	static DeclareMemType MTYPE_INVENTORY_FROM_XML;
 +	static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
 +	static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
 +	static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
 +	static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
 +
 +	static DeclareMemType MTYPE_ANIMATION;
 +	static DeclareMemType MTYPE_VOLUME;
 +	static DeclareMemType MTYPE_PRIMITIVE;
 +	
 +	static DeclareMemType MTYPE_SCRIPT;
 +	static DeclareMemType MTYPE_SCRIPT_RUN;
 +	static DeclareMemType MTYPE_SCRIPT_BYTECODE;
 +	
 +	static DeclareMemType MTYPE_IO_PUMP;
 +	static DeclareMemType MTYPE_IO_TCP;
 +	static DeclareMemType MTYPE_IO_BUFFER;
 +	static DeclareMemType MTYPE_IO_HTTP_SERVER;
 +	static DeclareMemType MTYPE_IO_SD_SERVER;
 +	static DeclareMemType MTYPE_IO_SD_CLIENT;
 +	static DeclareMemType MTYPE_IO_URL_REQUEST;
 +
 +	static DeclareMemType MTYPE_DIRECTX_INIT;
 +
 +	static DeclareMemType MTYPE_TEMP1;
 +	static DeclareMemType MTYPE_TEMP2;
 +	static DeclareMemType MTYPE_TEMP3;
 +	static DeclareMemType MTYPE_TEMP4;
 +	static DeclareMemType MTYPE_TEMP5;
 +	static DeclareMemType MTYPE_TEMP6;
 +	static DeclareMemType MTYPE_TEMP7;
 +	static DeclareMemType MTYPE_TEMP8;
 +	static DeclareMemType MTYPE_TEMP9;
 +
 +	static DeclareMemType MTYPE_OTHER; // Special; used by display code
 +
 +	S32 mTypeIndex;
 +};
 +
 +//----------------------------------------------------------------------------
 +
 +#endif
 +
 diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index bb3301df9f..dda9a95597 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -1,169 +1,169 @@ -/**  - * @file llpreprocessor.h - * @brief This file should be included in all Linden Lab files and - * should only contain special preprocessor directives - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - *  - * Copyright (c) 2001-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$ - */ - -#ifndef LLPREPROCESSOR_H -#define LLPREPROCESSOR_H - -// Figure out endianness of platform -#ifdef LL_LINUX -#define __ENABLE_WSTRING -#include <endian.h> -#endif	//	LL_LINUX - -#if LL_SOLARIS -#   ifdef  __sparc     // Since we're talking Solaris 10 and up, only 64 bit is supported. -#      define LL_BIG_ENDIAN 1 -#      define LL_SOLARIS_ALIGNED_CPU 1     //  used to designate issues where SPARC alignment is addressed -#      define LL_SOLARIS_NON_MESA_GL 1      //  The SPARC GL does not provide a MESA-based GL API -#   endif -#   include <sys/isa_defs.h> // ensure we know which end is up -#endif // LL_SOLARIS - -#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386))) -#define LL_LITTLE_ENDIAN 1 -#else -#define LL_BIG_ENDIAN 1 -#endif - -// Per-compiler switches -#ifdef __GNUC__ -#define LL_FORCE_INLINE inline __attribute__((always_inline)) -#else -#define LL_FORCE_INLINE __forceinline -#endif - -// Figure out differences between compilers -#if defined(__GNUC__) -	#define GCC_VERSION (__GNUC__ * 10000 \ -						+ __GNUC_MINOR__ * 100 \ -						+ __GNUC_PATCHLEVEL__) -	#ifndef LL_GNUC -		#define LL_GNUC 1 -	#endif -#elif defined(__MSVC_VER__) || defined(_MSC_VER) -	#ifndef LL_MSVC -		#define LL_MSVC 1 -	#endif -	#if _MSC_VER < 1400 -		#define LL_MSVC7 //Visual C++ 2003 or earlier -	#endif -#endif - -// Deal with minor differences on Unixy OSes. -#if LL_DARWIN || LL_LINUX -	// Different name, same functionality. -	#define stricmp strcasecmp -	#define strnicmp strncasecmp - -	// Not sure why this is different, but... -	#ifndef MAX_PATH -		#define MAX_PATH PATH_MAX -	#endif	//	not MAX_PATH - -#endif - - -// Static linking with apr on windows needs to be declared. -#if LL_WINDOWS && !LL_COMMON_LINK_SHARED -#ifndef APR_DECLARE_STATIC -#define APR_DECLARE_STATIC // For APR on Windows -#endif -#ifndef APU_DECLARE_STATIC -#define APU_DECLARE_STATIC // For APR util on Windows -#endif -#endif - -#if defined(LL_WINDOWS) -#define BOOST_REGEX_NO_LIB 1 -#define CURL_STATICLIB 1 -#ifndef XML_STATIC -#define XML_STATIC -#endif -#endif	//	LL_WINDOWS - - -// Deal with VC6 problems -#if LL_MSVC -#pragma warning( 3	     : 4701 )	// "local variable used without being initialized"  Treat this as level 3, not level 4. -#pragma warning( 3	     : 4702 )	// "unreachable code"  Treat this as level 3, not level 4. -#pragma warning( 3	     : 4189 )	// "local variable initialized but not referenced"  Treat this as level 3, not level 4. -//#pragma warning( 3	: 4018 )	// "signed/unsigned mismatch"  Treat this as level 3, not level 4. -#pragma warning( 3      :  4263 )	// 'function' : member function does not override any base class virtual member function -#pragma warning( 3      :  4264 )	// "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden" -#pragma warning( 3       : 4265 )	// "class has virtual functions, but destructor is not virtual" -#pragma warning( 3      :  4266 )	// 'function' : no override available for virtual member function from base 'type'; function is hidden -#pragma warning (disable : 4180)	// qualifier applied to function type has no meaning; ignored -#pragma warning( disable : 4284 )	// silly MS warning deep inside their <map> include file -#pragma warning( disable : 4503 )	// 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. -#pragma warning( disable : 4800 )	// 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) -#pragma warning( disable : 4996 )	// warning: deprecated - -// level 4 warnings that we need to disable: -#pragma warning (disable : 4100) // unreferenced formal parameter -#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) ) -#pragma warning (disable : 4244) // possible loss of data on conversions -#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template -#pragma warning (disable : 4512) // assignment operator could not be generated -#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) ) - -#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class -#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class -#endif	//	LL_MSVC - -#if LL_WINDOWS -#define LL_DLLEXPORT __declspec(dllexport) -#define LL_DLLIMPORT __declspec(dllimport) -#elif LL_LINUX -#define LL_DLLEXPORT __attribute__ ((visibility("default"))) -#define LL_DLLIMPORT -#else -#define LL_DLLEXPORT -#define LL_DLLIMPORT -#endif // LL_WINDOWS - -#if LL_COMMON_LINK_SHARED -// CMake automagically defines llcommon_EXPORTS only when building llcommon -// sources, and only when llcommon is a shared library (i.e. when -// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because -// otherwise we can't distinguish between (non-llcommon source) and (llcommon -// not shared). -# if defined(llcommon_EXPORTS) -#   define LL_COMMON_API LL_DLLEXPORT -# else //llcommon_EXPORTS -#   define LL_COMMON_API LL_DLLIMPORT -# endif //llcommon_EXPORTS -#else // LL_COMMON_LINK_SHARED -# define LL_COMMON_API -#endif // LL_COMMON_LINK_SHARED - -#endif	//	not LL_LINDEN_PREPROCESSOR_H +/** 
 + * @file llpreprocessor.h
 + * @brief This file should be included in all Linden Lab files and
 + * should only contain special preprocessor directives
 + *
 + * $LicenseInfo:firstyear=2001&license=viewergpl$
 + * 
 + * Copyright (c) 2001-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$
 + */
 +
 +#ifndef LLPREPROCESSOR_H
 +#define LLPREPROCESSOR_H
 +
 +// Figure out endianness of platform
 +#ifdef LL_LINUX
 +#define __ENABLE_WSTRING
 +#include <endian.h>
 +#endif	//	LL_LINUX
 +
 +#if LL_SOLARIS
 +#   ifdef  __sparc     // Since we're talking Solaris 10 and up, only 64 bit is supported.
 +#      define LL_BIG_ENDIAN 1
 +#      define LL_SOLARIS_ALIGNED_CPU 1     //  used to designate issues where SPARC alignment is addressed
 +#      define LL_SOLARIS_NON_MESA_GL 1      //  The SPARC GL does not provide a MESA-based GL API
 +#   endif
 +#   include <sys/isa_defs.h> // ensure we know which end is up
 +#endif // LL_SOLARIS
 +
 +#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386)))
 +#define LL_LITTLE_ENDIAN 1
 +#else
 +#define LL_BIG_ENDIAN 1
 +#endif
 +
 +// Per-compiler switches
 +#ifdef __GNUC__
 +#define LL_FORCE_INLINE inline __attribute__((always_inline))
 +#else
 +#define LL_FORCE_INLINE __forceinline
 +#endif
 +
 +// Figure out differences between compilers
 +#if defined(__GNUC__)
 +	#define GCC_VERSION (__GNUC__ * 10000 \
 +						+ __GNUC_MINOR__ * 100 \
 +						+ __GNUC_PATCHLEVEL__)
 +	#ifndef LL_GNUC
 +		#define LL_GNUC 1
 +	#endif
 +#elif defined(__MSVC_VER__) || defined(_MSC_VER)
 +	#ifndef LL_MSVC
 +		#define LL_MSVC 1
 +	#endif
 +	#if _MSC_VER < 1400
 +		#define LL_MSVC7 //Visual C++ 2003 or earlier
 +	#endif
 +#endif
 +
 +// Deal with minor differences on Unixy OSes.
 +#if LL_DARWIN || LL_LINUX
 +	// Different name, same functionality.
 +	#define stricmp strcasecmp
 +	#define strnicmp strncasecmp
 +
 +	// Not sure why this is different, but...
 +	#ifndef MAX_PATH
 +		#define MAX_PATH PATH_MAX
 +	#endif	//	not MAX_PATH
 +
 +#endif
 +
 +
 +// Static linking with apr on windows needs to be declared.
 +#if LL_WINDOWS && !LL_COMMON_LINK_SHARED
 +#ifndef APR_DECLARE_STATIC
 +#define APR_DECLARE_STATIC // For APR on Windows
 +#endif
 +#ifndef APU_DECLARE_STATIC
 +#define APU_DECLARE_STATIC // For APR util on Windows
 +#endif
 +#endif
 +
 +#if defined(LL_WINDOWS)
 +#define BOOST_REGEX_NO_LIB 1
 +#define CURL_STATICLIB 1
 +#ifndef XML_STATIC
 +#define XML_STATIC
 +#endif
 +#endif	//	LL_WINDOWS
 +
 +
 +// Deal with VC6 problems
 +#if LL_MSVC
 +#pragma warning( 3	     : 4701 )	// "local variable used without being initialized"  Treat this as level 3, not level 4.
 +#pragma warning( 3	     : 4702 )	// "unreachable code"  Treat this as level 3, not level 4.
 +#pragma warning( 3	     : 4189 )	// "local variable initialized but not referenced"  Treat this as level 3, not level 4.
 +//#pragma warning( 3	: 4018 )	// "signed/unsigned mismatch"  Treat this as level 3, not level 4.
 +#pragma warning( 3      :  4263 )	// 'function' : member function does not override any base class virtual member function
 +#pragma warning( 3      :  4264 )	// "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
 +#pragma warning( 3       : 4265 )	// "class has virtual functions, but destructor is not virtual"
 +#pragma warning( 3      :  4266 )	// 'function' : no override available for virtual member function from base 'type'; function is hidden
 +#pragma warning (disable : 4180)	// qualifier applied to function type has no meaning; ignored
 +#pragma warning( disable : 4284 )	// silly MS warning deep inside their <map> include file
 +#pragma warning( disable : 4503 )	// 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
 +#pragma warning( disable : 4800 )	// 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
 +#pragma warning( disable : 4996 )	// warning: deprecated
 +
 +// level 4 warnings that we need to disable:
 +#pragma warning (disable : 4100) // unreferenced formal parameter
 +#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
 +#pragma warning (disable : 4244) // possible loss of data on conversions
 +#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
 +#pragma warning (disable : 4512) // assignment operator could not be generated
 +#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
 +
 +#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
 +#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
 +#endif	//	LL_MSVC
 +
 +#if LL_WINDOWS
 +#define LL_DLLEXPORT __declspec(dllexport)
 +#define LL_DLLIMPORT __declspec(dllimport)
 +#elif LL_LINUX
 +#define LL_DLLEXPORT __attribute__ ((visibility("default")))
 +#define LL_DLLIMPORT
 +#else
 +#define LL_DLLEXPORT
 +#define LL_DLLIMPORT
 +#endif // LL_WINDOWS
 +
 +#if LL_COMMON_LINK_SHARED
 +// CMake automagically defines llcommon_EXPORTS only when building llcommon
 +// sources, and only when llcommon is a shared library (i.e. when
 +// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because
 +// otherwise we can't distinguish between (non-llcommon source) and (llcommon
 +// not shared).
 +# if defined(llcommon_EXPORTS)
 +#   define LL_COMMON_API LL_DLLEXPORT
 +# else //llcommon_EXPORTS
 +#   define LL_COMMON_API LL_DLLIMPORT
 +# endif //llcommon_EXPORTS
 +#else // LL_COMMON_LINK_SHARED
 +# define LL_COMMON_API
 +#endif // LL_COMMON_LINK_SHARED
 +
 +#endif	//	not LL_LINDEN_PREPROCESSOR_H
 diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index 6558df70a4..3cb074257b 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -1,142 +1,142 @@ -/**  - * @file llstacktrace.cpp - * @brief stack tracing functionality - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - *  - * Copyright (c) 2001-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 "linden_common.h" -#include "llstacktrace.h" - -#ifdef LL_WINDOWS - -#include <iostream> -#include <sstream> - -#include "windows.h" -#include "Dbghelp.h" - -typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( -    IN ULONG frames_to_skip, -    IN ULONG frames_to_capture, -    OUT PVOID *backtrace, -    OUT PULONG backtrace_hash); - -static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = -   (RtlCaptureStackBackTrace_Function*) -   GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); - -bool ll_get_stack_trace(std::vector<std::string>& lines) -{ -	const S32 MAX_STACK_DEPTH = 32; -	const S32 STRING_NAME_LENGTH = 200; -	const S32 FRAME_SKIP = 2; -	static BOOL symbolsLoaded = false; -	static BOOL firstCall = true; - -	HANDLE hProc = GetCurrentProcess(); - -	// load the symbols if they're not loaded -	if(!symbolsLoaded && firstCall) -	{ -		symbolsLoaded = SymInitialize(hProc, NULL, true); -		firstCall = false; -	} - -	// if loaded, get the call stack -	if(symbolsLoaded) -	{ -		// create the frames to hold the addresses -		void* frames[MAX_STACK_DEPTH]; -		memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); -		S32 depth = 0; - -		// get the addresses -		depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); - -		IMAGEHLP_LINE64 line; -		memset(&line, 0, sizeof(IMAGEHLP_LINE64)); -		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - -		// create something to hold address info -		PIMAGEHLP_SYMBOL64 pSym; -		pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); -		memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); -		pSym->MaxNameLength = STRING_NAME_LENGTH; -		pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); - -		// get address info for each address frame -		// and store -		for(S32 i=0; i < depth; i++) -		{ -			std::stringstream stack_line; -			BOOL ret; - -			DWORD64 addr = (DWORD64)frames[i]; -			ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); -			if(ret) -			{ -				stack_line << pSym->Name << " "; -			} - -			DWORD dummy; -			ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); -			if(ret) -			{ -				std::string file_name = line.FileName; -				std::string::size_type index = file_name.rfind("\\"); -				stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;  -			} - -			lines.push_back(stack_line.str()); -		} -		 -		free(pSym); - -		// TODO: figure out a way to cleanup symbol loading -		// Not hugely necessary, however. -		//SymCleanup(hProc); -		return true; -	} -	else -	{ -		lines.push_back("Stack Trace Failed.  PDB symbol info not loaded"); -	} - -	return false; -} - -#else - -bool ll_get_stack_trace(std::vector<std::string>& lines) -{ -	return false; -} - -#endif - +/** 
 + * @file llstacktrace.cpp
 + * @brief stack tracing functionality
 + *
 + * $LicenseInfo:firstyear=2001&license=viewergpl$
 + * 
 + * Copyright (c) 2001-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 "linden_common.h"
 +#include "llstacktrace.h"
 +
 +#ifdef LL_WINDOWS
 +
 +#include <iostream>
 +#include <sstream>
 +
 +#include "windows.h"
 +#include "Dbghelp.h"
 +
 +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
 +    IN ULONG frames_to_skip,
 +    IN ULONG frames_to_capture,
 +    OUT PVOID *backtrace,
 +    OUT PULONG backtrace_hash);
 +
 +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
 +   (RtlCaptureStackBackTrace_Function*)
 +   GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
 +
 +bool ll_get_stack_trace(std::vector<std::string>& lines)
 +{
 +	const S32 MAX_STACK_DEPTH = 32;
 +	const S32 STRING_NAME_LENGTH = 200;
 +	const S32 FRAME_SKIP = 2;
 +	static BOOL symbolsLoaded = false;
 +	static BOOL firstCall = true;
 +
 +	HANDLE hProc = GetCurrentProcess();
 +
 +	// load the symbols if they're not loaded
 +	if(!symbolsLoaded && firstCall)
 +	{
 +		symbolsLoaded = SymInitialize(hProc, NULL, true);
 +		firstCall = false;
 +	}
 +
 +	// if loaded, get the call stack
 +	if(symbolsLoaded)
 +	{
 +		// create the frames to hold the addresses
 +		void* frames[MAX_STACK_DEPTH];
 +		memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
 +		S32 depth = 0;
 +
 +		// get the addresses
 +		depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
 +
 +		IMAGEHLP_LINE64 line;
 +		memset(&line, 0, sizeof(IMAGEHLP_LINE64));
 +		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
 +
 +		// create something to hold address info
 +		PIMAGEHLP_SYMBOL64 pSym;
 +		pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
 +		memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
 +		pSym->MaxNameLength = STRING_NAME_LENGTH;
 +		pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
 +
 +		// get address info for each address frame
 +		// and store
 +		for(S32 i=0; i < depth; i++)
 +		{
 +			std::stringstream stack_line;
 +			BOOL ret;
 +
 +			DWORD64 addr = (DWORD64)frames[i];
 +			ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
 +			if(ret)
 +			{
 +				stack_line << pSym->Name << " ";
 +			}
 +
 +			DWORD dummy;
 +			ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
 +			if(ret)
 +			{
 +				std::string file_name = line.FileName;
 +				std::string::size_type index = file_name.rfind("\\");
 +				stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; 
 +			}
 +
 +			lines.push_back(stack_line.str());
 +		}
 +		
 +		free(pSym);
 +
 +		// TODO: figure out a way to cleanup symbol loading
 +		// Not hugely necessary, however.
 +		//SymCleanup(hProc);
 +		return true;
 +	}
 +	else
 +	{
 +		lines.push_back("Stack Trace Failed.  PDB symbol info not loaded");
 +	}
 +
 +	return false;
 +}
 +
 +#else
 +
 +bool ll_get_stack_trace(std::vector<std::string>& lines)
 +{
 +	return false;
 +}
 +
 +#endif
 +
 diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h index 9f857f0fd3..b84b1aa6ad 100644 --- a/indra/llcommon/llstacktrace.h +++ b/indra/llcommon/llstacktrace.h @@ -1,44 +1,44 @@ -/**  - * @file llstacktrace.h - * @brief stack trace functions - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - *  - * Copyright (c) 2001-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$ - */ - - -#ifndef LL_LLSTACKTRACE_H -#define LL_LLSTACKTRACE_H - -#include "stdtypes.h" -#include <vector> -#include <string> - -LL_COMMON_API bool ll_get_stack_trace(std::vector<std::string>& lines); - -#endif - +/** 
 + * @file llstacktrace.h
 + * @brief stack trace functions
 + *
 + * $LicenseInfo:firstyear=2001&license=viewergpl$
 + * 
 + * Copyright (c) 2001-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$
 + */
 +
 +
 +#ifndef LL_LLSTACKTRACE_H
 +#define LL_LLSTACKTRACE_H
 +
 +#include "stdtypes.h"
 +#include <vector>
 +#include <string>
 +
 +LL_COMMON_API bool ll_get_stack_trace(std::vector<std::string>& lines);
 +
 +#endif
 +
 diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 31e70e0fe4..edbb007f61 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -1,1300 +1,1300 @@ -/**  - * @file llstring.h - * @brief String utility functions and std::string class. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - *  - * Copyright (c) 2001-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$ - */ - -#ifndef LL_LLSTRING_H -#define LL_LLSTRING_H - -#include <string> -#include <cstdio> -#include <locale> -#include <iomanip> -#include "llsd.h" -#include "llfasttimer.h" - -#if LL_LINUX || LL_SOLARIS -#include <wctype.h> -#include <wchar.h> -#endif - -#include <string.h> - -#if LL_SOLARIS -// stricmp and strnicmp do not exist on Solaris: -#define stricmp strcasecmp -#define strnicmp strncasecmp -#endif - -const char LL_UNKNOWN_CHAR = '?'; - -#if LL_DARWIN || LL_LINUX || LL_SOLARIS -// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already) -#include <cstring> - -namespace std -{ -template<> -struct char_traits<U16> -{ -	typedef U16 		char_type; -	typedef int 	    int_type; -	typedef streampos 	pos_type; -	typedef streamoff 	off_type; -	typedef mbstate_t 	state_type; -	 -	static void  -		assign(char_type& __c1, const char_type& __c2) -	{ __c1 = __c2; } -	 -	static bool  -		eq(const char_type& __c1, const char_type& __c2) -	{ return __c1 == __c2; } -	 -	static bool  -		lt(const char_type& __c1, const char_type& __c2) -	{ return __c1 < __c2; } -	 -	static int  -		compare(const char_type* __s1, const char_type* __s2, size_t __n) -	{ return memcmp(__s1, __s2, __n * sizeof(char_type)); } -	 -	static size_t -		length(const char_type* __s) -	{ -		const char_type *cur_char = __s; -		while (*cur_char != 0) -		{ -			++cur_char; -		} -		return cur_char - __s; -	} -	 -	static const char_type*  -		find(const char_type* __s, size_t __n, const char_type& __a) -	{ return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); } -	 -	static char_type*  -		move(char_type* __s1, const char_type* __s2, size_t __n) -	{ return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); } -	 -	static char_type*  -		copy(char_type* __s1, const char_type* __s2, size_t __n) -	{  return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); }	/* Flawfinder: ignore */ -	 -	static char_type*  -		assign(char_type* __s, size_t __n, char_type __a) -	{  -		// This isn't right. -		//return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type)));  -		 -		// I don't think there's a standard 'memset' for 16-bit values. -		// Do this the old-fashioned way. -		 -		size_t __i; -		for(__i = 0; __i < __n; __i++) -		{ -			__s[__i] = __a; -		} -		return __s;  -	} -	 -	static char_type  -		to_char_type(const int_type& __c) -	{ return static_cast<char_type>(__c); } -	 -	static int_type  -		to_int_type(const char_type& __c) -	{ return static_cast<int_type>(__c); } -	 -	static bool  -		eq_int_type(const int_type& __c1, const int_type& __c2) -	{ return __c1 == __c2; } -	 -	static int_type  -		eof() { return static_cast<int_type>(EOF); } -	 -	static int_type  -		not_eof(const int_type& __c) -      { return (__c == eof()) ? 0 : __c; } -  }; -}; -#endif - -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 char toUpper(char elem) { return toupper((unsigned char)elem); } -	static llwchar toUpper(llwchar elem) { return towupper(elem); } -	 -	static char toLower(char elem) { return tolower((unsigned char)elem); } -	static llwchar toLower(llwchar elem) { return towlower(elem); } - -	static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; } -	static bool isSpace(llwchar elem) { return iswspace(elem) != 0; } - -	static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; } -	static bool isUpper(llwchar elem) { return iswupper(elem) != 0; } - -	static bool isLower(char elem) { return islower((unsigned char)elem) != 0; } -	static bool isLower(llwchar elem) { return iswlower(elem) != 0; } - -	static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; } -	static bool isDigit(llwchar a) { return iswdigit(a) != 0; } - -	static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } -	static bool isPunct(llwchar a) { return iswpunct(a) != 0; } - -	static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } -	static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } - -	static S32	collate(const char* a, const char* b) { return strcoll(a, b); } -	static S32	collate(const llwchar* a, const llwchar* b); - -	static void setupDatetimeInfo(bool pacific_daylight_time); -	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. - */ -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 -// *really* error-prone, so subclass std::string with just basic c'tors. -class LLFormatMapString -{ -public: -	LLFormatMapString() {}; -	LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {}; -	LLFormatMapString(const std::string& s) : mString(s) {}; -	operator std::string() const { return mString; } -	bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; } -	std::size_t length() const { return mString.length(); } -	 -private: -	std::string mString; -}; - -template <class T> -class LLStringUtilBase -{ -private: -	static std::string sLocale; - -public: -	typedef typename std::basic_string<T>::size_type size_type; -	 -public: -	///////////////////////////////////////////////////////////////////////////////////////// -	// Static Utility functions that operate on std::strings - -	static std::basic_string<T> null; -	 -	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; -	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); -	static void setLocale (std::string inLocale) {sLocale = inLocale;}; -	static std::string getLocale (void) {return sLocale;}; -	 -	static bool isValidIndex(const std::basic_string<T>& string, size_type i) -	{ -		return !string.empty() && (0 <= i) && (i <= string.size()); -	} - -	static void	trimHead(std::basic_string<T>& string); -	static void	trimTail(std::basic_string<T>& string); -	static void	trim(std::basic_string<T>& string)	{ trimHead(string); trimTail(string); } -	static void truncate(std::basic_string<T>& string, size_type count); - -	static void	toUpper(std::basic_string<T>& string); -	static void	toLower(std::basic_string<T>& string); -	 -	// 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); - -	static void	replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab ); -	static void	replaceNonstandardASCII( std::basic_string<T>& string, T replacement ); -	static void	replaceChar( std::basic_string<T>& string, T target, T replacement ); -	static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement ); -	 -	static BOOL	containsNonprintable(const std::basic_string<T>& string); -	static void	stripNonprintable(std::basic_string<T>& string); - -	/** -	 * @brief Unsafe way to make ascii characters. You should probably -	 * only call this when interacting with the host operating system. -	 * The 1 byte std::string does not work correctly. -	 * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII -	 * should work. -	 */ -	static void _makeASCII(std::basic_string<T>& string); - -	// Conversion to other data types -	static BOOL	convertToBOOL(const std::basic_string<T>& string, BOOL& value); -	static BOOL	convertToU8(const std::basic_string<T>& string, U8& value); -	static BOOL	convertToS8(const std::basic_string<T>& string, S8& value); -	static BOOL	convertToS16(const std::basic_string<T>& string, S16& value); -	static BOOL	convertToU16(const std::basic_string<T>& string, U16& value); -	static BOOL	convertToU32(const std::basic_string<T>& string, U32& value); -	static BOOL	convertToS32(const std::basic_string<T>& string, S32& value); -	static BOOL	convertToF32(const std::basic_string<T>& string, F32& value); -	static BOOL	convertToF64(const std::basic_string<T>& string, F64& value); - -	///////////////////////////////////////////////////////////////////////////////////////// -	// Utility functions for working with char*'s and strings - -	// Like strcmp but also handles empty strings. Uses -	// current locale. -	static S32		compareStrings(const T* lhs, const T* rhs); -	static S32		compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs); -	 -	// case insensitive version of above. Uses current locale on -	// Win32, and falls back to a non-locale aware comparison on -	// Linux. -	static S32		compareInsensitive(const T* lhs, const T* rhs); -	static S32		compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs); - -	// Case sensitive comparison with good handling of numbers.  Does not use current locale. -	// a.k.a. strdictcmp() -	static S32		compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b); - -	// Case *in*sensitive comparison with good handling of numbers.  Does not use current locale. -	// a.k.a. strdictcmp() -	static S32		compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b); - -	// Puts compareDict() in a form appropriate for LL container classes to use for sorting. -	static BOOL		precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b ); - -	// A replacement for strncpy. -	// If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds -	// up to dst_size-1 characters of src. -	static void		copy(T* dst, const T* src, size_type dst_size); -	 -	// 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	 -	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> LLStringUtilBase<T>::null; -template<class T> std::string LLStringUtilBase<T>::sLocale; - -typedef LLStringUtilBase<char> LLStringUtil; -typedef LLStringUtilBase<llwchar> LLWStringUtil; -typedef std::basic_string<llwchar> LLWString; - -//@ Use this where we want to disallow input in the form of "foo" -//  This is used to catch places where english text is embedded in the code -//  instead of in a translatable XUI file. -class LLStringExplicit : public std::string -{ -public: -	explicit LLStringExplicit(const char* s) : std::string(s) {} -	LLStringExplicit(const std::string& s) : std::string(s) {} -	LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {} -}; - -struct LLDictionaryLess -{ -public: -	bool operator()(const std::string& a, const std::string& b) -	{ -		return (LLStringUtil::precedesDict(a, b) ? true : false); -	} -}; - - -/** - * Simple support functions - */ - -/** - * @brief chop off the trailing characters in a string. - * - * This function works on bytes rather than glyphs, so this will - * incorrectly truncate non-single byte strings. - * Use utf8str_truncate() for utf8 strings - * @return a copy of in string minus the trailing count bytes. - */ -inline std::string chop_tail_copy( -	const std::string& in, -	std::string::size_type count) -{ -	return std::string(in, 0, in.length() - count); -} - -/** - * @brief This translates a nybble stored as a hex value from 0-f back - * to a nybble in the low order bits of the return byte. - */ -LL_COMMON_API U8 hex_as_nybble(char hex); - -/** - * @brief read the contents of a file into a string. - * - * Since this function has no concept of character encoding, most - * anything you do with this method ill-advised. Please avoid. - * @param str [out] The string which will have. - * @param filename The full name of the file to read. - * @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 - */ - -// Make the incoming string a utf8 string. Replaces any unknown glyph -// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest -// of the data may not be recovered. -LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw); - -// -// We should never use UTF16 except when communicating with Win32! -// -typedef std::basic_string<U16> llutf16string; - -LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); -LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); - -LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); -LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str); - -LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); -LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str ); - -LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); -LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str); -// Same function, better name. JC -inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } - -// -LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars); - -LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); -LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str); - -LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); -LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str); - -// Length of this UTF32 string in bytes when transformed to UTF8 -LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);  - -// Length in bytes of this wide char in a UTF8 string -LL_COMMON_API S32 wchar_utf8_length(const llwchar wc);  - -LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str); - -// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string. -LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len); - -// Length in utf16string (UTF-16) of wlen wchars beginning at woffset. -LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); - -// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) -LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); - -/** - * @brief Properly truncate a utf8 string to a maximum byte count. - *  - * The returned string may be less than max_len if the truncation - * happens in the middle of a glyph. If max_len is longer than the - * string passed in, the return value == utf8str. - * @param utf8str A valid utf8 string to truncate. - * @param max_len The maximum number of bytes in the return value. - * @return Returns a valid utf8 string with byte count <= max_len. - */ -LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len); - -LL_COMMON_API std::string utf8str_trim(const std::string& utf8str); - -LL_COMMON_API S32 utf8str_compare_insensitive( -	const std::string& lhs, -	const std::string& rhs); - -/** - * @brief Replace all occurences of target_char with replace_char - * - * @param utf8str A utf8 string to process. - * @param target_char The wchar to be replaced - * @param replace_char The wchar which is written on replace - */ -LL_COMMON_API std::string utf8str_substChar( -	const std::string& utf8str, -	const llwchar target_char, -	const llwchar replace_char); - -LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str); - -// Hack - used for evil notecards. -LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);  - -LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); - - -#if LL_WINDOWS -/* @name Windows string helpers - */ -//@{ - -/** - * @brief Implementation the expected snprintf interface. - * - * If the size of the passed in buffer is not large enough to hold the string, - * two bad things happen: - * 1. resulting formatted string is NOT null terminated - * 2. Depending on the platform, the return value could be a) the required - *    size of the buffer to copy the entire formatted string or b) -1. - *    On Windows with VS.Net 2003, it returns -1 e.g.  - * - * safe_snprintf always adds a NULL terminator so that the caller does not - * need to check for return value or need to add the NULL terminator. - * It does not, however change the return value - to let the caller know - * that the passed in buffer size was not large enough to hold the - * formatted string. - * - */ - -// Deal with the differeneces on Windows -namespace snprintf_hack -{ -	LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...); -} - -using snprintf_hack::snprintf; - -/** - * @brief Convert a wide string to std::string - * - * This replaces the unsafe W2A macro from ATL. - */ -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); - -//@} -#endif // LL_WINDOWS - -/** - * Many of the 'strip' and 'replace' methods of LLStringUtilBase need - * specialization to work with the signed char type. - * Sadly, it is not possible (AFAIK) to specialize a single method of - * a template class. - * That stuff should go here. - */ -namespace LLStringFn -{ -	/** -	 * @brief Replace all non-printable characters with replacement in -	 * string. -	 * NOTE - this will zap non-ascii -	 * -	 * @param [in,out] string the to modify. out value is the string -	 * with zero non-printable characters. -	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. -	 */ -	LL_COMMON_API void replace_nonprintable_in_ascii( -		std::basic_string<char>& string, -		char replacement); - - -	/** -	 * @brief Replace all non-printable characters and pipe characters -	 * with replacement in a string. -	 * NOTE - this will zap non-ascii -	 * -	 * @param [in,out] the string to modify. out value is the string -	 * with zero non-printable characters and zero pipe characters. -	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. -	 */ -	LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str, -									   char replacement); - - -	/** -	 * @brief Remove all characters that are not allowed in XML 1.0. -	 * Returns a copy of the string with those characters removed. -	 * Works with US ASCII and UTF-8 encoded strings.  JC -	 */ -	LL_COMMON_API std::string strip_invalid_xml(const std::string& input); - - -	/** -	 * @brief Replace all control characters (0 <= c < 0x20) with replacement in -	 * string.   This is safe for utf-8 -	 * -	 * @param [in,out] string the to modify. out value is the string -	 * with zero non-printable characters. -	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. -	 */ -	LL_COMMON_API void replace_ascii_controlchars( -		std::basic_string<char>& string, -		char replacement); -} - -//////////////////////////////////////////////////////////// -// 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. - -//////////////////////////////////////////////////////////// - - -// static -template<class T>  -S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs) -{	 -	S32 result; -	if( lhs == rhs ) -	{ -		result = 0; -	} -	else -	if ( !lhs || !lhs[0] ) -	{ -		result = ((!rhs || !rhs[0]) ? 0 : 1); -	} -	else -	if ( !rhs || !rhs[0]) -	{ -		result = -1; -	} -	else -	{ -		result = LLStringOps::collate(lhs, rhs); -	} -	return result; -} - -//static  -template<class T>  -S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs) -{ -	return LLStringOps::collate(lhs.c_str(), rhs.c_str()); -} - -// static -template<class T>  -S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs ) -{ -	S32 result; -	if( lhs == rhs ) -	{ -		result = 0; -	} -	else -	if ( !lhs || !lhs[0] ) -	{ -		result = ((!rhs || !rhs[0]) ? 0 : 1); -	} -	else -	if ( !rhs || !rhs[0] ) -	{ -		result = -1; -	} -	else -	{ -		std::basic_string<T> lhs_string(lhs); -		std::basic_string<T> rhs_string(rhs); -		LLStringUtilBase<T>::toUpper(lhs_string); -		LLStringUtilBase<T>::toUpper(rhs_string); -		result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); -	} -	return result; -} - -//static  -template<class T>  -S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs) -{ -	std::basic_string<T> lhs_string(lhs); -	std::basic_string<T> rhs_string(rhs); -	LLStringUtilBase<T>::toUpper(lhs_string); -	LLStringUtilBase<T>::toUpper(rhs_string); -	return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); -} - -// Case sensitive comparison with good handling of numbers.  Does not use current locale. -// a.k.a. strdictcmp() - -//static  -template<class T> -S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr) -{ -	const T* a = astr.c_str(); -	const T* b = bstr.c_str(); -	T ca, cb; -	S32 ai, bi, cnt = 0; -	S32 bias = 0; - -	ca = *(a++); -	cb = *(b++); -	while( ca && cb ){ -		if( bias==0 ){ -			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; } -			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; } -		}else{ -			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); } -			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); } -		} -		if( LLStringOps::isDigit(ca) ){ -			if( cnt-->0 ){ -				if( cb!=ca ) break; -			}else{ -				if( !LLStringOps::isDigit(cb) ) break; -				for(ai=0; LLStringOps::isDigit(a[ai]); ai++); -				for(bi=0; LLStringOps::isDigit(b[bi]); bi++); -				if( ai<bi ){ ca=0; break; } -				if( bi<ai ){ cb=0; break; } -				if( ca!=cb ) break; -				cnt = ai; -			} -		}else if( ca!=cb ){   break; -		} -		ca = *(a++); -		cb = *(b++); -	} -	if( ca==cb ) ca += bias; -	return ca-cb; -} - -// static -template<class T> -S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr) -{ -	const T* a = astr.c_str(); -	const T* b = bstr.c_str(); -	T ca, cb; -	S32 ai, bi, cnt = 0; - -	ca = *(a++); -	cb = *(b++); -	while( ca && cb ){ -		if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); } -		if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); } -		if( LLStringOps::isDigit(ca) ){ -			if( cnt-->0 ){ -				if( cb!=ca ) break; -			}else{ -				if( !LLStringOps::isDigit(cb) ) break; -				for(ai=0; LLStringOps::isDigit(a[ai]); ai++); -				for(bi=0; LLStringOps::isDigit(b[bi]); bi++); -				if( ai<bi ){ ca=0; break; } -				if( bi<ai ){ cb=0; break; } -				if( ca!=cb ) break; -				cnt = ai; -			} -		}else if( ca!=cb ){   break; -		} -		ca = *(a++); -		cb = *(b++); -	} -	return ca-cb; -} - -// Puts compareDict() in a form appropriate for LL container classes to use for sorting. -// static  -template<class T>  -BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b ) -{ -	if( a.size() && b.size() ) -	{ -		return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0); -	} -	else -	{ -		return (!b.empty()); -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)	 -{  -	if( !string.empty() ) -	{  -		std::transform( -			string.begin(), -			string.end(), -			string.begin(), -			(T(*)(T)) &LLStringOps::toUpper); -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::toLower(std::basic_string<T>& string) -{  -	if( !string.empty() ) -	{  -		std::transform( -			string.begin(), -			string.end(), -			string.begin(), -			(T(*)(T)) &LLStringOps::toLower); -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string) -{			 -	if( !string.empty() ) -	{ -		size_type i = 0; -		while( i < string.length() && LLStringOps::isSpace( string[i] ) ) -		{ -			i++; -		} -		string.erase(0, i); -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string) -{			 -	if( string.size() ) -	{ -		size_type len = string.length(); -		size_type i = len; -		while( i > 0 && LLStringOps::isSpace( string[i-1] ) ) -		{ -			i--; -		} - -		string.erase( i, len - i ); -	} -} - - -// Replace line feeds with carriage return-line feed pairs. -//static -template<class T> -void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string) -{ -	const T LF = 10; -	const T CR = 13; - -	// Count the number of line feeds -	size_type count = 0; -	size_type len = string.size(); -	size_type i; -	for( i = 0; i < len; i++ ) -	{ -		if( string[i] == LF ) -		{ -			count++; -		} -	} - -	// Insert a carriage return before each line feed -	if( count ) -	{ -		size_type size = len + count; -		T *t = new T[size]; -		size_type j = 0; -		for( i = 0; i < len; ++i ) -		{ -			if( string[i] == LF ) -			{ -				t[j] = CR; -				++j; -			} -			t[j] = string[i]; -			++j; -		} - -		string.assign(t, size); -	} -} - -// Remove all carriage returns -//static -template<class T>  -void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string) -{ -	const T CR = 13; - -	size_type cr_count = 0; -	size_type len = string.size(); -	size_type i; -	for( i = 0; i < len - cr_count; i++ ) -	{ -		if( string[i+cr_count] == CR ) -		{ -			cr_count++; -		} - -		string[i] = string[i+cr_count]; -	} -	string.erase(i, cr_count); -} - -//static -template<class T>  -void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement ) -{ -	size_type found_pos = 0; -	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )  -	{ -		string[found_pos] = replacement; -		found_pos++; // avoid infinite defeat if target == replacement -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement ) -{ -	size_type found_pos = 0; -	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) -	{ -		string.replace( found_pos, target.length(), replacement ); -		found_pos += replacement.length(); // avoid infinite defeat if replacement contains target -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement ) -{ -	const char LF = 10; -	const S8 MIN = 32; -//	const S8 MAX = 127; - -	size_type len = string.size(); -	for( size_type i = 0; i < len; i++ ) -	{ -		// No need to test MAX < mText[i] because we treat mText[i] as a signed char, -		// which has a max value of 127. -		if( ( S8(string[i]) < MIN ) && (string[i] != LF) ) -		{ -			string[i] = replacement; -		} -	} -} - -//static -template<class T>  -void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab ) -{ -	const T TAB = '\t'; -	const T SPACE = ' '; - -	std::basic_string<T> out_str; -	// Replace tabs with spaces -	for (size_type i = 0; i < str.length(); i++) -	{ -		if (str[i] == TAB) -		{ -			for (size_type j = 0; j < spaces_per_tab; j++) -				out_str += SPACE; -		} -		else -		{ -			out_str += str[i]; -		} -	} -	str = out_str; -} - -//static -template<class T>  -BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string) -{ -	const char MIN = 32; -	BOOL rv = FALSE; -	for (size_type i = 0; i < string.size(); i++) -	{ -		if(string[i] < MIN) -		{ -			rv = TRUE; -			break; -		} -	} -	return rv; -} - -//static -template<class T>  -void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string) -{ -	const char MIN = 32; -	size_type j = 0; -	if (string.empty()) -	{ -		return; -	} -	size_t src_size = string.size(); -	char* c_string = new char[src_size + 1]; -	if(c_string == NULL) -	{ -		return; -	} -	copy(c_string, string.c_str(), src_size+1); -	char* write_head = &c_string[0]; -	for (size_type i = 0; i < src_size; i++) -	{ -		char* read_head = &string[i]; -		write_head = &c_string[j]; -		if(!(*read_head < MIN)) -		{ -			*write_head = *read_head; -			++j; -		} -	} -	c_string[j]= '\0'; -	string = c_string; -	delete []c_string; -} - -template<class T>  -void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string) -{ -	// Replace non-ASCII chars with LL_UNKNOWN_CHAR -	for (size_type i = 0; i < string.length(); i++) -	{ -		if (string[i] > 0x7f) -		{ -			string[i] = LL_UNKNOWN_CHAR; -		} -	} -} - -// static -template<class T>  -void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size ) -{ -	if( dst_size > 0 ) -	{ -		size_type min_len = 0; -		if( src ) -		{ -			min_len = llmin( dst_size - 1, strlen( src ) );  /* Flawfinder: ignore */ -			memcpy(dst, src, min_len * sizeof(T));		/* Flawfinder: ignore */ -		} -		dst[min_len] = '\0'; -	} -} - -// static -template<class T>  -void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset) -{ -	if ( offset == dst.length() ) -	{ -		// special case - append to end of string and avoid expensive -		// (when strings are large) string manipulations -		dst += src; -	} -	else -	{ -		std::basic_string<T> tail = dst.substr(offset); - -		dst = dst.substr(0, offset); -		dst += src; -		dst += tail; -	}; -} - -// True if this is the head of s. -//static -template<class T>  -BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s )  -{  -	if( string.empty() ) -	{ -		// Early exit -		return FALSE; -	} -	else -	{ -		return (strncmp( s, string.c_str(), string.size() ) == 0); -	} -} - -// 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) -{ -	if( string.empty() ) -	{ -		return FALSE; -	} - -	std::basic_string<T> temp( string ); -	trim(temp); -	if(  -		(temp == "1") ||  -		(temp == "T") ||  -		(temp == "t") ||  -		(temp == "TRUE") ||  -		(temp == "true") ||  -		(temp == "True") ) -	{ -		value = TRUE; -		return TRUE; -	} -	else -	if(  -		(temp == "0") ||  -		(temp == "F") ||  -		(temp == "f") ||  -		(temp == "FALSE") ||  -		(temp == "false") ||  -		(temp == "False") ) -	{ -		value = FALSE; -		return TRUE; -	} - -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value)  -{ -	S32 value32 = 0; -	BOOL success = convertToS32(string, value32); -	if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) ) -	{ -		value = (U8) value32; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value)  -{ -	S32 value32 = 0; -	BOOL success = convertToS32(string, value32); -	if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) ) -	{ -		value = (S8) value32; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value)  -{ -	S32 value32 = 0; -	BOOL success = convertToS32(string, value32); -	if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) ) -	{ -		value = (S16) value32; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value)  -{ -	S32 value32 = 0; -	BOOL success = convertToS32(string, value32); -	if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) ) -	{ -		value = (U16) value32; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value)  -{ -	if( string.empty() ) -	{ -		return FALSE; -	} - -	std::basic_string<T> temp( string ); -	trim(temp); -	U32 v; -	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); -	if(i_stream >> v) -	{ -		value = v; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value)  -{ -	if( string.empty() ) -	{ -		return FALSE; -	} - -	std::basic_string<T> temp( string ); -	trim(temp); -	S32 v; -	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); -	if(i_stream >> v) -	{ -		//TODO: figure out overflow and underflow reporting here -		//if((LONG_MAX == v) || (LONG_MIN == v)) -		//{ -		//	// Underflow or overflow -		//	return FALSE; -		//} - -		value = v; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value)  -{ -	F64 value64 = 0.0; -	BOOL success = convertToF64(string, value64); -	if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) ) -	{ -		value = (F32) value64; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value) -{ -	if( string.empty() ) -	{ -		return FALSE; -	} - -	std::basic_string<T> temp( string ); -	trim(temp); -	F64 v; -	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); -	if(i_stream >> v) -	{ -		//TODO: figure out overflow and underflow reporting here -		//if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) ) -		//{ -		//	// Underflow or overflow -		//	return FALSE; -		//} - -		value = v; -		return TRUE; -	} -	return FALSE; -} - -template<class T>  -void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count) -{ -	size_type cur_size = string.size(); -	string.resize(count < cur_size ? count : cur_size); -} - -#endif  // LL_STRING_H +/** 
 + * @file llstring.h
 + * @brief String utility functions and std::string class.
 + *
 + * $LicenseInfo:firstyear=2001&license=viewergpl$
 + * 
 + * Copyright (c) 2001-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$
 + */
 +
 +#ifndef LL_LLSTRING_H
 +#define LL_LLSTRING_H
 +
 +#include <string>
 +#include <cstdio>
 +#include <locale>
 +#include <iomanip>
 +#include "llsd.h"
 +#include "llfasttimer.h"
 +
 +#if LL_LINUX || LL_SOLARIS
 +#include <wctype.h>
 +#include <wchar.h>
 +#endif
 +
 +#include <string.h>
 +
 +#if LL_SOLARIS
 +// stricmp and strnicmp do not exist on Solaris:
 +#define stricmp strcasecmp
 +#define strnicmp strncasecmp
 +#endif
 +
 +const char LL_UNKNOWN_CHAR = '?';
 +
 +#if LL_DARWIN || LL_LINUX || LL_SOLARIS
 +// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
 +#include <cstring>
 +
 +namespace std
 +{
 +template<>
 +struct char_traits<U16>
 +{
 +	typedef U16 		char_type;
 +	typedef int 	    int_type;
 +	typedef streampos 	pos_type;
 +	typedef streamoff 	off_type;
 +	typedef mbstate_t 	state_type;
 +	
 +	static void 
 +		assign(char_type& __c1, const char_type& __c2)
 +	{ __c1 = __c2; }
 +	
 +	static bool 
 +		eq(const char_type& __c1, const char_type& __c2)
 +	{ return __c1 == __c2; }
 +	
 +	static bool 
 +		lt(const char_type& __c1, const char_type& __c2)
 +	{ return __c1 < __c2; }
 +	
 +	static int 
 +		compare(const char_type* __s1, const char_type* __s2, size_t __n)
 +	{ return memcmp(__s1, __s2, __n * sizeof(char_type)); }
 +	
 +	static size_t
 +		length(const char_type* __s)
 +	{
 +		const char_type *cur_char = __s;
 +		while (*cur_char != 0)
 +		{
 +			++cur_char;
 +		}
 +		return cur_char - __s;
 +	}
 +	
 +	static const char_type* 
 +		find(const char_type* __s, size_t __n, const char_type& __a)
 +	{ return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
 +	
 +	static char_type* 
 +		move(char_type* __s1, const char_type* __s2, size_t __n)
 +	{ return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
 +	
 +	static char_type* 
 +		copy(char_type* __s1, const char_type* __s2, size_t __n)
 +	{  return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); }	/* Flawfinder: ignore */
 +	
 +	static char_type* 
 +		assign(char_type* __s, size_t __n, char_type __a)
 +	{ 
 +		// This isn't right.
 +		//return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type))); 
 +		
 +		// I don't think there's a standard 'memset' for 16-bit values.
 +		// Do this the old-fashioned way.
 +		
 +		size_t __i;
 +		for(__i = 0; __i < __n; __i++)
 +		{
 +			__s[__i] = __a;
 +		}
 +		return __s; 
 +	}
 +	
 +	static char_type 
 +		to_char_type(const int_type& __c)
 +	{ return static_cast<char_type>(__c); }
 +	
 +	static int_type 
 +		to_int_type(const char_type& __c)
 +	{ return static_cast<int_type>(__c); }
 +	
 +	static bool 
 +		eq_int_type(const int_type& __c1, const int_type& __c2)
 +	{ return __c1 == __c2; }
 +	
 +	static int_type 
 +		eof() { return static_cast<int_type>(EOF); }
 +	
 +	static int_type 
 +		not_eof(const int_type& __c)
 +      { return (__c == eof()) ? 0 : __c; }
 +  };
 +};
 +#endif
 +
 +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 char toUpper(char elem) { return toupper((unsigned char)elem); }
 +	static llwchar toUpper(llwchar elem) { return towupper(elem); }
 +	
 +	static char toLower(char elem) { return tolower((unsigned char)elem); }
 +	static llwchar toLower(llwchar elem) { return towlower(elem); }
 +
 +	static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
 +	static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
 +
 +	static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
 +	static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
 +
 +	static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
 +	static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
 +
 +	static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
 +	static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
 +
 +	static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
 +	static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
 +
 +	static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
 +	static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
 +
 +	static S32	collate(const char* a, const char* b) { return strcoll(a, b); }
 +	static S32	collate(const llwchar* a, const llwchar* b);
 +
 +	static void setupDatetimeInfo(bool pacific_daylight_time);
 +	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.
 + */
 +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
 +// *really* error-prone, so subclass std::string with just basic c'tors.
 +class LLFormatMapString
 +{
 +public:
 +	LLFormatMapString() {};
 +	LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {};
 +	LLFormatMapString(const std::string& s) : mString(s) {};
 +	operator std::string() const { return mString; }
 +	bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
 +	std::size_t length() const { return mString.length(); }
 +	
 +private:
 +	std::string mString;
 +};
 +
 +template <class T>
 +class LLStringUtilBase
 +{
 +private:
 +	static std::string sLocale;
 +
 +public:
 +	typedef typename std::basic_string<T>::size_type size_type;
 +	
 +public:
 +	/////////////////////////////////////////////////////////////////////////////////////////
 +	// Static Utility functions that operate on std::strings
 +
 +	static std::basic_string<T> null;
 +	
 +	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
 +	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);
 +	static void setLocale (std::string inLocale) {sLocale = inLocale;};
 +	static std::string getLocale (void) {return sLocale;};
 +	
 +	static bool isValidIndex(const std::basic_string<T>& string, size_type i)
 +	{
 +		return !string.empty() && (0 <= i) && (i <= string.size());
 +	}
 +
 +	static void	trimHead(std::basic_string<T>& string);
 +	static void	trimTail(std::basic_string<T>& string);
 +	static void	trim(std::basic_string<T>& string)	{ trimHead(string); trimTail(string); }
 +	static void truncate(std::basic_string<T>& string, size_type count);
 +
 +	static void	toUpper(std::basic_string<T>& string);
 +	static void	toLower(std::basic_string<T>& string);
 +	
 +	// 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);
 +
 +	static void	replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
 +	static void	replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
 +	static void	replaceChar( std::basic_string<T>& string, T target, T replacement );
 +	static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
 +	
 +	static BOOL	containsNonprintable(const std::basic_string<T>& string);
 +	static void	stripNonprintable(std::basic_string<T>& string);
 +
 +	/**
 +	 * @brief Unsafe way to make ascii characters. You should probably
 +	 * only call this when interacting with the host operating system.
 +	 * The 1 byte std::string does not work correctly.
 +	 * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
 +	 * should work.
 +	 */
 +	static void _makeASCII(std::basic_string<T>& string);
 +
 +	// Conversion to other data types
 +	static BOOL	convertToBOOL(const std::basic_string<T>& string, BOOL& value);
 +	static BOOL	convertToU8(const std::basic_string<T>& string, U8& value);
 +	static BOOL	convertToS8(const std::basic_string<T>& string, S8& value);
 +	static BOOL	convertToS16(const std::basic_string<T>& string, S16& value);
 +	static BOOL	convertToU16(const std::basic_string<T>& string, U16& value);
 +	static BOOL	convertToU32(const std::basic_string<T>& string, U32& value);
 +	static BOOL	convertToS32(const std::basic_string<T>& string, S32& value);
 +	static BOOL	convertToF32(const std::basic_string<T>& string, F32& value);
 +	static BOOL	convertToF64(const std::basic_string<T>& string, F64& value);
 +
 +	/////////////////////////////////////////////////////////////////////////////////////////
 +	// Utility functions for working with char*'s and strings
 +
 +	// Like strcmp but also handles empty strings. Uses
 +	// current locale.
 +	static S32		compareStrings(const T* lhs, const T* rhs);
 +	static S32		compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
 +	
 +	// case insensitive version of above. Uses current locale on
 +	// Win32, and falls back to a non-locale aware comparison on
 +	// Linux.
 +	static S32		compareInsensitive(const T* lhs, const T* rhs);
 +	static S32		compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
 +
 +	// Case sensitive comparison with good handling of numbers.  Does not use current locale.
 +	// a.k.a. strdictcmp()
 +	static S32		compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
 +
 +	// Case *in*sensitive comparison with good handling of numbers.  Does not use current locale.
 +	// a.k.a. strdictcmp()
 +	static S32		compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
 +
 +	// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
 +	static BOOL		precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
 +
 +	// A replacement for strncpy.
 +	// If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
 +	// up to dst_size-1 characters of src.
 +	static void		copy(T* dst, const T* src, size_type dst_size);
 +	
 +	// 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	
 +	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> LLStringUtilBase<T>::null;
 +template<class T> std::string LLStringUtilBase<T>::sLocale;
 +
 +typedef LLStringUtilBase<char> LLStringUtil;
 +typedef LLStringUtilBase<llwchar> LLWStringUtil;
 +typedef std::basic_string<llwchar> LLWString;
 +
 +//@ Use this where we want to disallow input in the form of "foo"
 +//  This is used to catch places where english text is embedded in the code
 +//  instead of in a translatable XUI file.
 +class LLStringExplicit : public std::string
 +{
 +public:
 +	explicit LLStringExplicit(const char* s) : std::string(s) {}
 +	LLStringExplicit(const std::string& s) : std::string(s) {}
 +	LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {}
 +};
 +
 +struct LLDictionaryLess
 +{
 +public:
 +	bool operator()(const std::string& a, const std::string& b)
 +	{
 +		return (LLStringUtil::precedesDict(a, b) ? true : false);
 +	}
 +};
 +
 +
 +/**
 + * Simple support functions
 + */
 +
 +/**
 + * @brief chop off the trailing characters in a string.
 + *
 + * This function works on bytes rather than glyphs, so this will
 + * incorrectly truncate non-single byte strings.
 + * Use utf8str_truncate() for utf8 strings
 + * @return a copy of in string minus the trailing count bytes.
 + */
 +inline std::string chop_tail_copy(
 +	const std::string& in,
 +	std::string::size_type count)
 +{
 +	return std::string(in, 0, in.length() - count);
 +}
 +
 +/**
 + * @brief This translates a nybble stored as a hex value from 0-f back
 + * to a nybble in the low order bits of the return byte.
 + */
 +LL_COMMON_API U8 hex_as_nybble(char hex);
 +
 +/**
 + * @brief read the contents of a file into a string.
 + *
 + * Since this function has no concept of character encoding, most
 + * anything you do with this method ill-advised. Please avoid.
 + * @param str [out] The string which will have.
 + * @param filename The full name of the file to read.
 + * @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
 + */
 +
 +// Make the incoming string a utf8 string. Replaces any unknown glyph
 +// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
 +// of the data may not be recovered.
 +LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
 +
 +//
 +// We should never use UTF16 except when communicating with Win32!
 +//
 +typedef std::basic_string<U16> llutf16string;
 +
 +LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
 +LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
 +
 +LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
 +LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
 +
 +LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
 +LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
 +
 +LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
 +LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
 +// Same function, better name. JC
 +inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
 +
 +//
 +LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
 +
 +LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
 +LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
 +
 +LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
 +LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
 +
 +// Length of this UTF32 string in bytes when transformed to UTF8
 +LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); 
 +
 +// Length in bytes of this wide char in a UTF8 string
 +LL_COMMON_API S32 wchar_utf8_length(const llwchar wc); 
 +
 +LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str);
 +
 +// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
 +LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
 +
 +// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
 +LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
 +
 +// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
 +LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
 +
 +/**
 + * @brief Properly truncate a utf8 string to a maximum byte count.
 + * 
 + * The returned string may be less than max_len if the truncation
 + * happens in the middle of a glyph. If max_len is longer than the
 + * string passed in, the return value == utf8str.
 + * @param utf8str A valid utf8 string to truncate.
 + * @param max_len The maximum number of bytes in the return value.
 + * @return Returns a valid utf8 string with byte count <= max_len.
 + */
 +LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
 +
 +LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
 +
 +LL_COMMON_API S32 utf8str_compare_insensitive(
 +	const std::string& lhs,
 +	const std::string& rhs);
 +
 +/**
 + * @brief Replace all occurences of target_char with replace_char
 + *
 + * @param utf8str A utf8 string to process.
 + * @param target_char The wchar to be replaced
 + * @param replace_char The wchar which is written on replace
 + */
 +LL_COMMON_API std::string utf8str_substChar(
 +	const std::string& utf8str,
 +	const llwchar target_char,
 +	const llwchar replace_char);
 +
 +LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
 +
 +// Hack - used for evil notecards.
 +LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str); 
 +
 +LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
 +
 +
 +#if LL_WINDOWS
 +/* @name Windows string helpers
 + */
 +//@{
 +
 +/**
 + * @brief Implementation the expected snprintf interface.
 + *
 + * If the size of the passed in buffer is not large enough to hold the string,
 + * two bad things happen:
 + * 1. resulting formatted string is NOT null terminated
 + * 2. Depending on the platform, the return value could be a) the required
 + *    size of the buffer to copy the entire formatted string or b) -1.
 + *    On Windows with VS.Net 2003, it returns -1 e.g. 
 + *
 + * safe_snprintf always adds a NULL terminator so that the caller does not
 + * need to check for return value or need to add the NULL terminator.
 + * It does not, however change the return value - to let the caller know
 + * that the passed in buffer size was not large enough to hold the
 + * formatted string.
 + *
 + */
 +
 +// Deal with the differeneces on Windows
 +namespace snprintf_hack
 +{
 +	LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
 +}
 +
 +using snprintf_hack::snprintf;
 +
 +/**
 + * @brief Convert a wide string to std::string
 + *
 + * This replaces the unsafe W2A macro from ATL.
 + */
 +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
 +
 +//@}
 +#endif // LL_WINDOWS
 +
 +/**
 + * Many of the 'strip' and 'replace' methods of LLStringUtilBase need
 + * specialization to work with the signed char type.
 + * Sadly, it is not possible (AFAIK) to specialize a single method of
 + * a template class.
 + * That stuff should go here.
 + */
 +namespace LLStringFn
 +{
 +	/**
 +	 * @brief Replace all non-printable characters with replacement in
 +	 * string.
 +	 * NOTE - this will zap non-ascii
 +	 *
 +	 * @param [in,out] string the to modify. out value is the string
 +	 * with zero non-printable characters.
 +	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
 +	 */
 +	LL_COMMON_API void replace_nonprintable_in_ascii(
 +		std::basic_string<char>& string,
 +		char replacement);
 +
 +
 +	/**
 +	 * @brief Replace all non-printable characters and pipe characters
 +	 * with replacement in a string.
 +	 * NOTE - this will zap non-ascii
 +	 *
 +	 * @param [in,out] the string to modify. out value is the string
 +	 * with zero non-printable characters and zero pipe characters.
 +	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
 +	 */
 +	LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
 +									   char replacement);
 +
 +
 +	/**
 +	 * @brief Remove all characters that are not allowed in XML 1.0.
 +	 * Returns a copy of the string with those characters removed.
 +	 * Works with US ASCII and UTF-8 encoded strings.  JC
 +	 */
 +	LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
 +
 +
 +	/**
 +	 * @brief Replace all control characters (0 <= c < 0x20) with replacement in
 +	 * string.   This is safe for utf-8
 +	 *
 +	 * @param [in,out] string the to modify. out value is the string
 +	 * with zero non-printable characters.
 +	 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
 +	 */
 +	LL_COMMON_API void replace_ascii_controlchars(
 +		std::basic_string<char>& string,
 +		char replacement);
 +}
 +
 +////////////////////////////////////////////////////////////
 +// 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.
 +
 +////////////////////////////////////////////////////////////
 +
 +
 +// static
 +template<class T> 
 +S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs)
 +{	
 +	S32 result;
 +	if( lhs == rhs )
 +	{
 +		result = 0;
 +	}
 +	else
 +	if ( !lhs || !lhs[0] )
 +	{
 +		result = ((!rhs || !rhs[0]) ? 0 : 1);
 +	}
 +	else
 +	if ( !rhs || !rhs[0])
 +	{
 +		result = -1;
 +	}
 +	else
 +	{
 +		result = LLStringOps::collate(lhs, rhs);
 +	}
 +	return result;
 +}
 +
 +//static 
 +template<class T> 
 +S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
 +{
 +	return LLStringOps::collate(lhs.c_str(), rhs.c_str());
 +}
 +
 +// static
 +template<class T> 
 +S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
 +{
 +	S32 result;
 +	if( lhs == rhs )
 +	{
 +		result = 0;
 +	}
 +	else
 +	if ( !lhs || !lhs[0] )
 +	{
 +		result = ((!rhs || !rhs[0]) ? 0 : 1);
 +	}
 +	else
 +	if ( !rhs || !rhs[0] )
 +	{
 +		result = -1;
 +	}
 +	else
 +	{
 +		std::basic_string<T> lhs_string(lhs);
 +		std::basic_string<T> rhs_string(rhs);
 +		LLStringUtilBase<T>::toUpper(lhs_string);
 +		LLStringUtilBase<T>::toUpper(rhs_string);
 +		result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
 +	}
 +	return result;
 +}
 +
 +//static 
 +template<class T> 
 +S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
 +{
 +	std::basic_string<T> lhs_string(lhs);
 +	std::basic_string<T> rhs_string(rhs);
 +	LLStringUtilBase<T>::toUpper(lhs_string);
 +	LLStringUtilBase<T>::toUpper(rhs_string);
 +	return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
 +}
 +
 +// Case sensitive comparison with good handling of numbers.  Does not use current locale.
 +// a.k.a. strdictcmp()
 +
 +//static 
 +template<class T>
 +S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
 +{
 +	const T* a = astr.c_str();
 +	const T* b = bstr.c_str();
 +	T ca, cb;
 +	S32 ai, bi, cnt = 0;
 +	S32 bias = 0;
 +
 +	ca = *(a++);
 +	cb = *(b++);
 +	while( ca && cb ){
 +		if( bias==0 ){
 +			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
 +			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
 +		}else{
 +			if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
 +			if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
 +		}
 +		if( LLStringOps::isDigit(ca) ){
 +			if( cnt-->0 ){
 +				if( cb!=ca ) break;
 +			}else{
 +				if( !LLStringOps::isDigit(cb) ) break;
 +				for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
 +				for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
 +				if( ai<bi ){ ca=0; break; }
 +				if( bi<ai ){ cb=0; break; }
 +				if( ca!=cb ) break;
 +				cnt = ai;
 +			}
 +		}else if( ca!=cb ){   break;
 +		}
 +		ca = *(a++);
 +		cb = *(b++);
 +	}
 +	if( ca==cb ) ca += bias;
 +	return ca-cb;
 +}
 +
 +// static
 +template<class T>
 +S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
 +{
 +	const T* a = astr.c_str();
 +	const T* b = bstr.c_str();
 +	T ca, cb;
 +	S32 ai, bi, cnt = 0;
 +
 +	ca = *(a++);
 +	cb = *(b++);
 +	while( ca && cb ){
 +		if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
 +		if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
 +		if( LLStringOps::isDigit(ca) ){
 +			if( cnt-->0 ){
 +				if( cb!=ca ) break;
 +			}else{
 +				if( !LLStringOps::isDigit(cb) ) break;
 +				for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
 +				for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
 +				if( ai<bi ){ ca=0; break; }
 +				if( bi<ai ){ cb=0; break; }
 +				if( ca!=cb ) break;
 +				cnt = ai;
 +			}
 +		}else if( ca!=cb ){   break;
 +		}
 +		ca = *(a++);
 +		cb = *(b++);
 +	}
 +	return ca-cb;
 +}
 +
 +// Puts compareDict() in a form appropriate for LL container classes to use for sorting.
 +// static 
 +template<class T> 
 +BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
 +{
 +	if( a.size() && b.size() )
 +	{
 +		return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
 +	}
 +	else
 +	{
 +		return (!b.empty());
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)	
 +{ 
 +	if( !string.empty() )
 +	{ 
 +		std::transform(
 +			string.begin(),
 +			string.end(),
 +			string.begin(),
 +			(T(*)(T)) &LLStringOps::toUpper);
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
 +{ 
 +	if( !string.empty() )
 +	{ 
 +		std::transform(
 +			string.begin(),
 +			string.end(),
 +			string.begin(),
 +			(T(*)(T)) &LLStringOps::toLower);
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
 +{			
 +	if( !string.empty() )
 +	{
 +		size_type i = 0;
 +		while( i < string.length() && LLStringOps::isSpace( string[i] ) )
 +		{
 +			i++;
 +		}
 +		string.erase(0, i);
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string)
 +{			
 +	if( string.size() )
 +	{
 +		size_type len = string.length();
 +		size_type i = len;
 +		while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
 +		{
 +			i--;
 +		}
 +
 +		string.erase( i, len - i );
 +	}
 +}
 +
 +
 +// Replace line feeds with carriage return-line feed pairs.
 +//static
 +template<class T>
 +void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
 +{
 +	const T LF = 10;
 +	const T CR = 13;
 +
 +	// Count the number of line feeds
 +	size_type count = 0;
 +	size_type len = string.size();
 +	size_type i;
 +	for( i = 0; i < len; i++ )
 +	{
 +		if( string[i] == LF )
 +		{
 +			count++;
 +		}
 +	}
 +
 +	// Insert a carriage return before each line feed
 +	if( count )
 +	{
 +		size_type size = len + count;
 +		T *t = new T[size];
 +		size_type j = 0;
 +		for( i = 0; i < len; ++i )
 +		{
 +			if( string[i] == LF )
 +			{
 +				t[j] = CR;
 +				++j;
 +			}
 +			t[j] = string[i];
 +			++j;
 +		}
 +
 +		string.assign(t, size);
 +	}
 +}
 +
 +// Remove all carriage returns
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string)
 +{
 +	const T CR = 13;
 +
 +	size_type cr_count = 0;
 +	size_type len = string.size();
 +	size_type i;
 +	for( i = 0; i < len - cr_count; i++ )
 +	{
 +		if( string[i+cr_count] == CR )
 +		{
 +			cr_count++;
 +		}
 +
 +		string[i] = string[i+cr_count];
 +	}
 +	string.erase(i, cr_count);
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
 +{
 +	size_type found_pos = 0;
 +	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) 
 +	{
 +		string[found_pos] = replacement;
 +		found_pos++; // avoid infinite defeat if target == replacement
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
 +{
 +	size_type found_pos = 0;
 +	while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
 +	{
 +		string.replace( found_pos, target.length(), replacement );
 +		found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
 +{
 +	const char LF = 10;
 +	const S8 MIN = 32;
 +//	const S8 MAX = 127;
 +
 +	size_type len = string.size();
 +	for( size_type i = 0; i < len; i++ )
 +	{
 +		// No need to test MAX < mText[i] because we treat mText[i] as a signed char,
 +		// which has a max value of 127.
 +		if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
 +		{
 +			string[i] = replacement;
 +		}
 +	}
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
 +{
 +	const T TAB = '\t';
 +	const T SPACE = ' ';
 +
 +	std::basic_string<T> out_str;
 +	// Replace tabs with spaces
 +	for (size_type i = 0; i < str.length(); i++)
 +	{
 +		if (str[i] == TAB)
 +		{
 +			for (size_type j = 0; j < spaces_per_tab; j++)
 +				out_str += SPACE;
 +		}
 +		else
 +		{
 +			out_str += str[i];
 +		}
 +	}
 +	str = out_str;
 +}
 +
 +//static
 +template<class T> 
 +BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string)
 +{
 +	const char MIN = 32;
 +	BOOL rv = FALSE;
 +	for (size_type i = 0; i < string.size(); i++)
 +	{
 +		if(string[i] < MIN)
 +		{
 +			rv = TRUE;
 +			break;
 +		}
 +	}
 +	return rv;
 +}
 +
 +//static
 +template<class T> 
 +void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
 +{
 +	const char MIN = 32;
 +	size_type j = 0;
 +	if (string.empty())
 +	{
 +		return;
 +	}
 +	size_t src_size = string.size();
 +	char* c_string = new char[src_size + 1];
 +	if(c_string == NULL)
 +	{
 +		return;
 +	}
 +	copy(c_string, string.c_str(), src_size+1);
 +	char* write_head = &c_string[0];
 +	for (size_type i = 0; i < src_size; i++)
 +	{
 +		char* read_head = &string[i];
 +		write_head = &c_string[j];
 +		if(!(*read_head < MIN))
 +		{
 +			*write_head = *read_head;
 +			++j;
 +		}
 +	}
 +	c_string[j]= '\0';
 +	string = c_string;
 +	delete []c_string;
 +}
 +
 +template<class T> 
 +void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string)
 +{
 +	// Replace non-ASCII chars with LL_UNKNOWN_CHAR
 +	for (size_type i = 0; i < string.length(); i++)
 +	{
 +		if (string[i] > 0x7f)
 +		{
 +			string[i] = LL_UNKNOWN_CHAR;
 +		}
 +	}
 +}
 +
 +// static
 +template<class T> 
 +void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size )
 +{
 +	if( dst_size > 0 )
 +	{
 +		size_type min_len = 0;
 +		if( src )
 +		{
 +			min_len = llmin( dst_size - 1, strlen( src ) );  /* Flawfinder: ignore */
 +			memcpy(dst, src, min_len * sizeof(T));		/* Flawfinder: ignore */
 +		}
 +		dst[min_len] = '\0';
 +	}
 +}
 +
 +// static
 +template<class T> 
 +void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
 +{
 +	if ( offset == dst.length() )
 +	{
 +		// special case - append to end of string and avoid expensive
 +		// (when strings are large) string manipulations
 +		dst += src;
 +	}
 +	else
 +	{
 +		std::basic_string<T> tail = dst.substr(offset);
 +
 +		dst = dst.substr(0, offset);
 +		dst += src;
 +		dst += tail;
 +	};
 +}
 +
 +// True if this is the head of s.
 +//static
 +template<class T> 
 +BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s ) 
 +{ 
 +	if( string.empty() )
 +	{
 +		// Early exit
 +		return FALSE;
 +	}
 +	else
 +	{
 +		return (strncmp( s, string.c_str(), string.size() ) == 0);
 +	}
 +}
 +
 +// 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)
 +{
 +	if( string.empty() )
 +	{
 +		return FALSE;
 +	}
 +
 +	std::basic_string<T> temp( string );
 +	trim(temp);
 +	if( 
 +		(temp == "1") || 
 +		(temp == "T") || 
 +		(temp == "t") || 
 +		(temp == "TRUE") || 
 +		(temp == "true") || 
 +		(temp == "True") )
 +	{
 +		value = TRUE;
 +		return TRUE;
 +	}
 +	else
 +	if( 
 +		(temp == "0") || 
 +		(temp == "F") || 
 +		(temp == "f") || 
 +		(temp == "FALSE") || 
 +		(temp == "false") || 
 +		(temp == "False") )
 +	{
 +		value = FALSE;
 +		return TRUE;
 +	}
 +
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value) 
 +{
 +	S32 value32 = 0;
 +	BOOL success = convertToS32(string, value32);
 +	if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
 +	{
 +		value = (U8) value32;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value) 
 +{
 +	S32 value32 = 0;
 +	BOOL success = convertToS32(string, value32);
 +	if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
 +	{
 +		value = (S8) value32;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value) 
 +{
 +	S32 value32 = 0;
 +	BOOL success = convertToS32(string, value32);
 +	if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
 +	{
 +		value = (S16) value32;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value) 
 +{
 +	S32 value32 = 0;
 +	BOOL success = convertToS32(string, value32);
 +	if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
 +	{
 +		value = (U16) value32;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value) 
 +{
 +	if( string.empty() )
 +	{
 +		return FALSE;
 +	}
 +
 +	std::basic_string<T> temp( string );
 +	trim(temp);
 +	U32 v;
 +	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
 +	if(i_stream >> v)
 +	{
 +		value = v;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) 
 +{
 +	if( string.empty() )
 +	{
 +		return FALSE;
 +	}
 +
 +	std::basic_string<T> temp( string );
 +	trim(temp);
 +	S32 v;
 +	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
 +	if(i_stream >> v)
 +	{
 +		//TODO: figure out overflow and underflow reporting here
 +		//if((LONG_MAX == v) || (LONG_MIN == v))
 +		//{
 +		//	// Underflow or overflow
 +		//	return FALSE;
 +		//}
 +
 +		value = v;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value) 
 +{
 +	F64 value64 = 0.0;
 +	BOOL success = convertToF64(string, value64);
 +	if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
 +	{
 +		value = (F32) value64;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
 +{
 +	if( string.empty() )
 +	{
 +		return FALSE;
 +	}
 +
 +	std::basic_string<T> temp( string );
 +	trim(temp);
 +	F64 v;
 +	std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
 +	if(i_stream >> v)
 +	{
 +		//TODO: figure out overflow and underflow reporting here
 +		//if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
 +		//{
 +		//	// Underflow or overflow
 +		//	return FALSE;
 +		//}
 +
 +		value = v;
 +		return TRUE;
 +	}
 +	return FALSE;
 +}
 +
 +template<class T> 
 +void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count)
 +{
 +	size_type cur_size = string.size();
 +	string.resize(count < cur_size ? count : cur_size);
 +}
 +
 +#endif  // LL_STRING_H
 | 
