summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llapp.cpp960
-rw-r--r--indra/llcommon/llcallbacklist.cpp68
-rw-r--r--indra/llcommon/llcallbacklist.h68
-rw-r--r--indra/llcommon/lldate.cpp394
-rw-r--r--indra/llcommon/lldate.h196
-rw-r--r--indra/llcommon/lldependencies.h16
-rw-r--r--indra/llcommon/llerror.cpp1724
-rw-r--r--indra/llcommon/llevents.h42
-rw-r--r--indra/llcommon/lleventtimer.cpp14
-rw-r--r--indra/llcommon/lleventtimer.h36
-rw-r--r--indra/llcommon/lllivefile.cpp152
-rw-r--r--indra/llcommon/llrefcount.h156
-rw-r--r--indra/llcommon/llrun.h204
-rw-r--r--indra/llcommon/llstring.h2452
-rw-r--r--indra/llcommon/tests/llerror_test.cpp1432
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp3048
16 files changed, 5481 insertions, 5481 deletions
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 5722f10f62..852859598b 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llapp.cpp
* @brief Implementation of the LLApp class.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -70,8 +70,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *);
#else
// Called by breakpad exception handler after the minidump has been generated.
bool unix_post_minidump_callback(const char *dump_dir,
- const char *minidump_id,
- void *context, bool succeeded);
+ const char *minidump_id,
+ void *context, bool succeeded);
#endif
# if LL_DARWIN
@@ -94,7 +94,7 @@ LLApp* LLApp::sApplication = NULL;
// Allows the generation of core files for post mortem under gdb
// and disables crashlogger
-BOOL LLApp::sDisableCrashlogger = FALSE;
+BOOL LLApp::sDisableCrashlogger = FALSE;
// Local flag for whether or not to do logging in signal handlers.
//static
@@ -108,222 +108,222 @@ LLAppErrorHandler LLApp::sErrorHandler = NULL;
LLApp::LLApp()
{
- // Set our status to running
- setStatus(APP_STATUS_RUNNING);
+ // Set our status to running
+ setStatus(APP_STATUS_RUNNING);
+
+ LLCommon::initClass();
- LLCommon::initClass();
+ // initialize the options structure. We need to make this an array
+ // because the structured data will not auto-allocate if we
+ // reference an invalid location with the [] operator.
+ mOptions = LLSD::emptyArray();
+ LLSD sd;
+ for(int i = 0; i < PRIORITY_COUNT; ++i)
+ {
+ mOptions.append(sd);
+ }
- // initialize the options structure. We need to make this an array
- // because the structured data will not auto-allocate if we
- // reference an invalid location with the [] operator.
- mOptions = LLSD::emptyArray();
- LLSD sd;
- for(int i = 0; i < PRIORITY_COUNT; ++i)
- {
- mOptions.append(sd);
- }
+ // Make sure we clean up APR when we exit
+ // Don't need to do this if we're cleaning up APR in the destructor
+ //atexit(ll_cleanup_apr);
- // Make sure we clean up APR when we exit
- // Don't need to do this if we're cleaning up APR in the destructor
- //atexit(ll_cleanup_apr);
+ // Set the application to this instance.
+ sApplication = this;
- // Set the application to this instance.
- sApplication = this;
-
- // initialize the buffer to write the minidump filename to
- // (this is used to avoid allocating memory in the crash handler)
- memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH);
- mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
+ // initialize the buffer to write the minidump filename to
+ // (this is used to avoid allocating memory in the crash handler)
+ memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH);
+ mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
}
LLApp::~LLApp()
{
- // reclaim live file memory
- std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer());
- mLiveFiles.clear();
+ // reclaim live file memory
+ std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer());
+ mLiveFiles.clear();
- setStopped();
+ setStopped();
- SUBSYSTEM_CLEANUP_DBG(LLCommon);
+ SUBSYSTEM_CLEANUP_DBG(LLCommon);
}
// static
LLApp* LLApp::instance()
{
- return sApplication;
+ return sApplication;
}
LLSD LLApp::getOption(const std::string& name) const
{
- LLSD rv;
- LLSD::array_const_iterator iter = mOptions.beginArray();
- LLSD::array_const_iterator end = mOptions.endArray();
- for(; iter != end; ++iter)
- {
- rv = (*iter)[name];
- if(rv.isDefined()) break;
- }
- return rv;
+ LLSD rv;
+ LLSD::array_const_iterator iter = mOptions.beginArray();
+ LLSD::array_const_iterator end = mOptions.endArray();
+ for(; iter != end; ++iter)
+ {
+ rv = (*iter)[name];
+ if(rv.isDefined()) break;
+ }
+ return rv;
}
bool LLApp::parseCommandOptions(int argc, char** argv)
{
- LLSD commands;
- std::string name;
- std::string value;
- for(int ii = 1; ii < argc; ++ii)
- {
- if(argv[ii][0] != '-')
- {
- LL_INFOS() << "Did not find option identifier while parsing token: "
- << argv[ii] << LL_ENDL;
- return false;
- }
- int offset = 1;
- if(argv[ii][1] == '-') ++offset;
- name.assign(&argv[ii][offset]);
- if(((ii+1) >= argc) || (argv[ii+1][0] == '-'))
- {
- // we found another option after this one or we have
- // reached the end. simply record that this option was
- // found and continue.
- int flag = name.compare("logfile");
- if (0 == flag)
- {
- commands[name] = "log";
- }
- else
- {
- commands[name] = true;
- }
-
- continue;
- }
- ++ii;
- value.assign(argv[ii]);
+ LLSD commands;
+ std::string name;
+ std::string value;
+ for(int ii = 1; ii < argc; ++ii)
+ {
+ if(argv[ii][0] != '-')
+ {
+ LL_INFOS() << "Did not find option identifier while parsing token: "
+ << argv[ii] << LL_ENDL;
+ return false;
+ }
+ int offset = 1;
+ if(argv[ii][1] == '-') ++offset;
+ name.assign(&argv[ii][offset]);
+ if(((ii+1) >= argc) || (argv[ii+1][0] == '-'))
+ {
+ // we found another option after this one or we have
+ // reached the end. simply record that this option was
+ // found and continue.
+ int flag = name.compare("logfile");
+ if (0 == flag)
+ {
+ commands[name] = "log";
+ }
+ else
+ {
+ commands[name] = true;
+ }
+
+ continue;
+ }
+ ++ii;
+ value.assign(argv[ii]);
#if LL_WINDOWS
- //Windows changed command line parsing. Deal with it.
- S32 slen = value.length() - 1;
- S32 start = 0;
- S32 end = slen;
- if (argv[ii][start]=='"')start++;
- if (argv[ii][end]=='"')end--;
- if (start!=0 || end!=slen)
- {
- value = value.substr (start,end);
- }
+ //Windows changed command line parsing. Deal with it.
+ S32 slen = value.length() - 1;
+ S32 start = 0;
+ S32 end = slen;
+ if (argv[ii][start]=='"')start++;
+ if (argv[ii][end]=='"')end--;
+ if (start!=0 || end!=slen)
+ {
+ value = value.substr (start,end);
+ }
#endif
- commands[name] = value;
- }
- setOptionData(PRIORITY_COMMAND_LINE, commands);
- return true;
+ commands[name] = value;
+ }
+ setOptionData(PRIORITY_COMMAND_LINE, commands);
+ return true;
}
bool LLApp::parseCommandOptions(int argc, wchar_t** wargv)
{
- LLSD commands;
- std::string name;
- std::string value;
- for(int ii = 1; ii < argc; ++ii)
- {
- if(wargv[ii][0] != '-')
- {
- LL_INFOS() << "Did not find option identifier while parsing token: "
- << wargv[ii] << LL_ENDL;
- return false;
- }
- int offset = 1;
- if(wargv[ii][1] == '-') ++offset;
+ LLSD commands;
+ std::string name;
+ std::string value;
+ for(int ii = 1; ii < argc; ++ii)
+ {
+ if(wargv[ii][0] != '-')
+ {
+ LL_INFOS() << "Did not find option identifier while parsing token: "
+ << wargv[ii] << LL_ENDL;
+ return false;
+ }
+ int offset = 1;
+ if(wargv[ii][1] == '-') ++offset;
#if LL_WINDOWS
- name.assign(utf16str_to_utf8str(&wargv[ii][offset]));
+ name.assign(utf16str_to_utf8str(&wargv[ii][offset]));
#else
- name.assign(wstring_to_utf8str(&wargv[ii][offset]));
+ name.assign(wstring_to_utf8str(&wargv[ii][offset]));
#endif
- if(((ii+1) >= argc) || (wargv[ii+1][0] == '-'))
- {
- // we found another option after this one or we have
- // reached the end. simply record that this option was
- // found and continue.
- int flag = name.compare("logfile");
- if (0 == flag)
- {
- commands[name] = "log";
- }
- else
- {
- commands[name] = true;
- }
-
- continue;
- }
- ++ii;
+ if(((ii+1) >= argc) || (wargv[ii+1][0] == '-'))
+ {
+ // we found another option after this one or we have
+ // reached the end. simply record that this option was
+ // found and continue.
+ int flag = name.compare("logfile");
+ if (0 == flag)
+ {
+ commands[name] = "log";
+ }
+ else
+ {
+ commands[name] = true;
+ }
+
+ continue;
+ }
+ ++ii;
#if LL_WINDOWS
- value.assign(utf16str_to_utf8str((wargv[ii])));
+ value.assign(utf16str_to_utf8str((wargv[ii])));
#else
- value.assign(wstring_to_utf8str((wargv[ii])));
+ value.assign(wstring_to_utf8str((wargv[ii])));
#endif
#if LL_WINDOWS
- //Windows changed command line parsing. Deal with it.
- S32 slen = value.length() - 1;
- S32 start = 0;
- S32 end = slen;
- if (wargv[ii][start]=='"')start++;
- if (wargv[ii][end]=='"')end--;
- if (start!=0 || end!=slen)
- {
- value = value.substr (start,end);
- }
+ //Windows changed command line parsing. Deal with it.
+ S32 slen = value.length() - 1;
+ S32 start = 0;
+ S32 end = slen;
+ if (wargv[ii][start]=='"')start++;
+ if (wargv[ii][end]=='"')end--;
+ if (start!=0 || end!=slen)
+ {
+ value = value.substr (start,end);
+ }
#endif
- commands[name] = value;
- }
- setOptionData(PRIORITY_COMMAND_LINE, commands);
- return true;
+ commands[name] = value;
+ }
+ setOptionData(PRIORITY_COMMAND_LINE, commands);
+ return true;
}
void LLApp::manageLiveFile(LLLiveFile* livefile)
{
- if(!livefile) return;
- livefile->checkAndReload();
- livefile->addToEventTimer();
- mLiveFiles.push_back(livefile);
+ if(!livefile) return;
+ livefile->checkAndReload();
+ livefile->addToEventTimer();
+ mLiveFiles.push_back(livefile);
}
bool LLApp::setOptionData(OptionPriority level, LLSD data)
{
- if((level < 0)
- || (level >= PRIORITY_COUNT)
- || (data.type() != LLSD::TypeMap))
- {
- return false;
- }
- mOptions[level] = data;
- return true;
+ if((level < 0)
+ || (level >= PRIORITY_COUNT)
+ || (data.type() != LLSD::TypeMap))
+ {
+ return false;
+ }
+ mOptions[level] = data;
+ return true;
}
LLSD LLApp::getOptionData(OptionPriority level)
{
- if((level < 0) || (level >= PRIORITY_COUNT))
- {
- return LLSD();
- }
- return mOptions[level];
+ if((level < 0) || (level >= PRIORITY_COUNT))
+ {
+ return LLSD();
+ }
+ return mOptions[level];
}
void LLApp::stepFrame()
{
- LLFrameTimer::updateFrameTime();
- LLFrameTimer::updateFrameCount();
- LLCallbackList::instance().callFunctions();
- mRunner.run();
+ LLFrameTimer::updateFrameTime();
+ LLFrameTimer::updateFrameCount();
+ LLCallbackList::instance().callFunctions();
+ mRunner.run();
}
#if LL_WINDOWS
@@ -332,31 +332,31 @@ void LLApp::stepFrame()
//in-depth article on the issue may be found here: http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesn-work/
void EnableCrashingOnCrashes()
{
- typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
- typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
- const DWORD EXCEPTION_SWALLOWING = 0x1;
-
- HMODULE kernel32 = LoadLibraryA("kernel32.dll");
- tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32,
- "GetProcessUserModeExceptionPolicy");
- tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32,
- "SetProcessUserModeExceptionPolicy");
- if (pGetPolicy && pSetPolicy)
- {
- DWORD dwFlags;
- if (pGetPolicy(&dwFlags))
- {
- // Turn off the filter
- pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
- }
- }
+ typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
+ typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
+ const DWORD EXCEPTION_SWALLOWING = 0x1;
+
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32,
+ "GetProcessUserModeExceptionPolicy");
+ tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32,
+ "SetProcessUserModeExceptionPolicy");
+ if (pGetPolicy && pSetPolicy)
+ {
+ DWORD dwFlags;
+ if (pGetPolicy(&dwFlags))
+ {
+ // Turn off the filter
+ pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
+ }
+ }
}
#endif
void LLApp::setupErrorHandling(bool second_instance)
{
- // Error handling is done by starting up an error handling thread, which just sleeps and
- // occasionally checks to see if the app is in an error state, and sees if it needs to be run.
+ // Error handling is done by starting up an error handling thread, which just sleeps and
+ // occasionally checks to see if the app is in an error state, and sees if it needs to be run.
#if LL_WINDOWS
@@ -377,19 +377,19 @@ void LLApp::setupErrorHandling(bool second_instance)
void LLApp::setErrorHandler(LLAppErrorHandler handler)
{
- LLApp::sErrorHandler = handler;
+ LLApp::sErrorHandler = handler;
}
// static
void LLApp::runErrorHandler()
{
- if (LLApp::sErrorHandler)
- {
- LLApp::sErrorHandler();
- }
+ if (LLApp::sErrorHandler)
+ {
+ LLApp::sErrorHandler();
+ }
- //LL_INFOS() << "App status now STOPPED" << LL_ENDL;
- LLApp::setStopped();
+ //LL_INFOS() << "App status now STOPPED" << LL_ENDL;
+ LLApp::setStopped();
}
namespace
@@ -435,14 +435,14 @@ void LLApp::setStatus(EAppStatus status)
// static
void LLApp::setError()
{
- // set app status to ERROR
- setStatus(APP_STATUS_ERROR);
+ // set app status to ERROR
+ setStatus(APP_STATUS_ERROR);
}
void LLApp::setDebugFileNames(const std::string &path)
{
- mStaticDebugFileName = path + "static_debug_info.log";
- mDynamicDebugFileName = path + "dynamic_debug_info.log";
+ mStaticDebugFileName = path + "static_debug_info.log";
+ mDynamicDebugFileName = path + "dynamic_debug_info.log";
}
void LLApp::writeMiniDump()
@@ -452,64 +452,64 @@ void LLApp::writeMiniDump()
// static
void LLApp::setQuitting()
{
- if (!isExiting())
- {
- // If we're already exiting, we don't want to reset our state back to quitting.
- LL_INFOS() << "Setting app state to QUITTING" << LL_ENDL;
- setStatus(APP_STATUS_QUITTING);
- }
+ if (!isExiting())
+ {
+ // If we're already exiting, we don't want to reset our state back to quitting.
+ LL_INFOS() << "Setting app state to QUITTING" << LL_ENDL;
+ setStatus(APP_STATUS_QUITTING);
+ }
}
// static
void LLApp::setStopped()
{
- setStatus(APP_STATUS_STOPPED);
+ setStatus(APP_STATUS_STOPPED);
}
// static
bool LLApp::isStopped()
{
- return (APP_STATUS_STOPPED == sStatus.get());
+ return (APP_STATUS_STOPPED == sStatus.get());
}
// static
bool LLApp::isRunning()
{
- return (APP_STATUS_RUNNING == sStatus.get());
+ return (APP_STATUS_RUNNING == sStatus.get());
}
// static
bool LLApp::isError()
{
- return (APP_STATUS_ERROR == sStatus.get());
+ return (APP_STATUS_ERROR == sStatus.get());
}
// static
bool LLApp::isQuitting()
{
- return (APP_STATUS_QUITTING == sStatus.get());
+ return (APP_STATUS_QUITTING == sStatus.get());
}
// static
bool LLApp::isExiting()
{
- return isQuitting() || isError();
+ return isQuitting() || isError();
}
void LLApp::disableCrashlogger()
{
- sDisableCrashlogger = TRUE;
+ sDisableCrashlogger = TRUE;
}
// static
bool LLApp::isCrashloggerDisabled()
{
- return (sDisableCrashlogger == TRUE);
+ return (sDisableCrashlogger == TRUE);
}
// static
@@ -518,336 +518,336 @@ int LLApp::getPid()
#if LL_WINDOWS
return GetCurrentProcessId();
#else
- return getpid();
+ return getpid();
#endif
}
#if LL_WINDOWS
LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop)
{
- // Translate the signals/exceptions into cross-platform stuff
- // Windows implementation
+ // Translate the signals/exceptions into cross-platform stuff
+ // Windows implementation
- // Make sure the user sees something to indicate that the app crashed.
- LONG retval;
+ // Make sure the user sees something to indicate that the app crashed.
+ LONG retval;
- if (LLApp::isError())
- {
- LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
- retval = EXCEPTION_EXECUTE_HANDLER;
- return retval;
- }
+ if (LLApp::isError())
+ {
+ LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
+ retval = EXCEPTION_EXECUTE_HANDLER;
+ return retval;
+ }
- // Flag status to error, so thread_error starts its work
- LLApp::setError();
+ // Flag status to error, so thread_error starts its work
+ LLApp::setError();
- // Block in the exception handler until the app has stopped
- // This is pretty sketchy, but appears to work just fine
- while (!LLApp::isStopped())
- {
- ms_sleep(10);
- }
+ // Block in the exception handler until the app has stopped
+ // This is pretty sketchy, but appears to work just fine
+ while (!LLApp::isStopped())
+ {
+ ms_sleep(10);
+ }
- //
- // Generate a minidump if we can.
- //
- // TODO: This needs to be ported over form the viewer-specific
- // LLWinDebug class
+ //
+ // Generate a minidump if we can.
+ //
+ // TODO: This needs to be ported over form the viewer-specific
+ // LLWinDebug class
- //
- // At this point, we always want to exit the app. There's no graceful
- // recovery for an unhandled exception.
- //
- // Just kill the process.
- retval = EXCEPTION_EXECUTE_HANDLER;
- return retval;
+ //
+ // At this point, we always want to exit the app. There's no graceful
+ // recovery for an unhandled exception.
+ //
+ // Just kill the process.
+ retval = EXCEPTION_EXECUTE_HANDLER;
+ return retval;
}
// Win32 doesn't support signals. This is used instead.
-BOOL ConsoleCtrlHandler(DWORD fdwCtrlType)
-{
- switch (fdwCtrlType)
- {
- case CTRL_BREAK_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- case CTRL_CLOSE_EVENT: // From end task or the window close button.
- case CTRL_C_EVENT: // from CTRL-C on the keyboard
- // Just set our state to quitting, not error
- if (LLApp::isQuitting() || LLApp::isError())
- {
- // We're already trying to die, just ignore this signal
- if (LLApp::sLogInSignal)
- {
- LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
- }
- return TRUE;
- }
- LLApp::setQuitting();
- return TRUE;
-
- default:
- return FALSE;
- }
-}
+BOOL ConsoleCtrlHandler(DWORD fdwCtrlType)
+{
+ switch (fdwCtrlType)
+ {
+ case CTRL_BREAK_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ case CTRL_CLOSE_EVENT: // From end task or the window close button.
+ case CTRL_C_EVENT: // from CTRL-C on the keyboard
+ // Just set our state to quitting, not error
+ if (LLApp::isQuitting() || LLApp::isError())
+ {
+ // We're already trying to die, just ignore this signal
+ if (LLApp::sLogInSignal)
+ {
+ LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
+ }
+ return TRUE;
+ }
+ LLApp::setQuitting();
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
#else //!LL_WINDOWS
void setup_signals()
{
- //
- // Set up signal handlers that may result in program termination
- //
- struct sigaction act;
- act.sa_sigaction = default_unix_signal_handler;
- sigemptyset( &act.sa_mask );
- act.sa_flags = SA_SIGINFO;
+ //
+ // Set up signal handlers that may result in program termination
+ //
+ struct sigaction act;
+ act.sa_sigaction = default_unix_signal_handler;
+ sigemptyset( &act.sa_mask );
+ act.sa_flags = SA_SIGINFO;
- // Synchronous signals
+ // Synchronous signals
# ifndef LL_BUGSPLAT
- sigaction(SIGABRT, &act, NULL);
+ sigaction(SIGABRT, &act, NULL);
# endif
- sigaction(SIGALRM, &act, NULL);
- sigaction(SIGBUS, &act, NULL);
- sigaction(SIGFPE, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGILL, &act, NULL);
- sigaction(SIGPIPE, &act, NULL);
- sigaction(SIGSEGV, &act, NULL);
- sigaction(SIGSYS, &act, NULL);
-
- sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL);
- sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL);
-
- // Asynchronous signals that are normally ignored
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGILL, &act, NULL);
+ sigaction(SIGPIPE, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGSYS, &act, NULL);
+
+ sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL);
+ sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL);
+
+ // Asynchronous signals that are normally ignored
#ifndef LL_IGNORE_SIGCHLD
- sigaction(SIGCHLD, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
#endif // LL_IGNORE_SIGCHLD
- sigaction(SIGUSR2, &act, NULL);
+ sigaction(SIGUSR2, &act, NULL);
- // Asynchronous signals that result in attempted graceful exit
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
- sigaction(SIGINT, &act, NULL);
+ // Asynchronous signals that result in attempted graceful exit
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
+
+ // Asynchronous signals that result in core
+ sigaction(SIGQUIT, &act, NULL);
- // Asynchronous signals that result in core
- sigaction(SIGQUIT, &act, NULL);
-
}
void clear_signals()
{
- struct sigaction act;
- act.sa_handler = SIG_DFL;
- sigemptyset( &act.sa_mask );
- act.sa_flags = SA_SIGINFO;
+ struct sigaction act;
+ act.sa_handler = SIG_DFL;
+ sigemptyset( &act.sa_mask );
+ act.sa_flags = SA_SIGINFO;
- // Synchronous signals
+ // Synchronous signals
# ifndef LL_BUGSPLAT
- sigaction(SIGABRT, &act, NULL);
+ sigaction(SIGABRT, &act, NULL);
# endif
- sigaction(SIGALRM, &act, NULL);
- sigaction(SIGBUS, &act, NULL);
- sigaction(SIGFPE, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGILL, &act, NULL);
- sigaction(SIGPIPE, &act, NULL);
- sigaction(SIGSEGV, &act, NULL);
- sigaction(SIGSYS, &act, NULL);
-
- sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL);
- sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL);
-
- // Asynchronous signals that are normally ignored
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGILL, &act, NULL);
+ sigaction(SIGPIPE, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGSYS, &act, NULL);
+
+ sigaction(LL_HEARTBEAT_SIGNAL, &act, NULL);
+ sigaction(LL_SMACKDOWN_SIGNAL, &act, NULL);
+
+ // Asynchronous signals that are normally ignored
#ifndef LL_IGNORE_SIGCHLD
- sigaction(SIGCHLD, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
#endif // LL_IGNORE_SIGCHLD
- // Asynchronous signals that result in attempted graceful exit
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
- sigaction(SIGINT, &act, NULL);
+ // Asynchronous signals that result in attempted graceful exit
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
- // Asynchronous signals that result in core
- sigaction(SIGUSR2, &act, NULL);
- sigaction(SIGQUIT, &act, NULL);
+ // Asynchronous signals that result in core
+ sigaction(SIGUSR2, &act, NULL);
+ sigaction(SIGQUIT, &act, NULL);
}
void default_unix_signal_handler(int signum, siginfo_t *info, void *)
{
- // Unix implementation of synchronous signal handler
- // This runs in the thread that threw the signal.
- // We do the somewhat sketchy operation of blocking in here until the error handler
- // has gracefully stopped the app.
+ // Unix implementation of synchronous signal handler
+ // This runs in the thread that threw the signal.
+ // We do the somewhat sketchy operation of blocking in here until the error handler
+ // has gracefully stopped the app.
- if (LLApp::sLogInSignal)
- {
- LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL;
- }
+ if (LLApp::sLogInSignal)
+ {
+ LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL;
+ }
- switch (signum)
- {
- case SIGCHLD:
- if (LLApp::sLogInSignal)
- {
- LL_INFOS() << "Signal handler - Got SIGCHLD from " << info->si_pid << LL_ENDL;
- }
+ switch (signum)
+ {
+ case SIGCHLD:
+ if (LLApp::sLogInSignal)
+ {
+ LL_INFOS() << "Signal handler - Got SIGCHLD from " << info->si_pid << LL_ENDL;
+ }
- return;
- case SIGABRT:
+ return;
+ case SIGABRT:
// Note that this handler is not set for SIGABRT when using Bugsplat
- // Abort just results in termination of the app, no funky error handling.
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - Got SIGABRT, terminating" << LL_ENDL;
- }
- clear_signals();
- raise(signum);
- return;
- case SIGINT:
- case SIGHUP:
- case SIGTERM:
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << LL_ENDL;
- }
- // Graceful exit
- // Just set our state to quitting, not error
- if (LLApp::isQuitting() || LLApp::isError())
- {
- // We're already trying to die, just ignore this signal
- if (LLApp::sLogInSignal)
- {
- LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
- }
- return;
- }
- LLApp::setQuitting();
- return;
- case SIGALRM:
- case SIGPIPE:
- case SIGUSR2:
- default:
- if (signum == LL_SMACKDOWN_SIGNAL ||
- signum == SIGBUS ||
- signum == SIGILL ||
- signum == SIGFPE ||
- signum == SIGSEGV ||
- signum == SIGQUIT)
- {
- if (signum == LL_SMACKDOWN_SIGNAL)
- {
- // Smackdown treated just like any other app termination, for now
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - Handling smackdown signal!" << LL_ENDL;
- }
- else
- {
- // Don't log anything, even errors - this is because this signal could happen anywhere.
- LLError::setDefaultLevel(LLError::LEVEL_NONE);
- }
-
- // Change the signal that we reraise to SIGABRT, so we generate a core dump.
- signum = SIGABRT;
- }
-
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL;
- }
- if (LLApp::isError())
- {
- // Received second fatal signal while handling first, just die right now
- // Set the signal handlers back to default before handling the signal - this makes the next signal wipe out the app.
- clear_signals();
-
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - Got another fatal signal while in the error handler, die now!" << LL_ENDL;
- }
- raise(signum);
- return;
- }
-
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - Flagging error status and waiting for shutdown" << LL_ENDL;
- }
-
- if (LLApp::isCrashloggerDisabled()) // Don't gracefully handle any signal, crash and core for a gdb post mortem
- {
- clear_signals();
- LL_WARNS() << "Fatal signal received, not handling the crash here, passing back to operating system" << LL_ENDL;
- raise(signum);
- return;
- }
-
- // Flag status to ERROR
- LLApp::setError();
-
- if (LLApp::sLogInSignal)
- {
- LL_WARNS() << "Signal handler - App is stopped, reraising signal" << LL_ENDL;
- }
- clear_signals();
- raise(signum);
- return;
- } else {
- if (LLApp::sLogInSignal)
- {
- LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL;
- }
- }
- }
+ // Abort just results in termination of the app, no funky error handling.
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - Got SIGABRT, terminating" << LL_ENDL;
+ }
+ clear_signals();
+ raise(signum);
+ return;
+ case SIGINT:
+ case SIGHUP:
+ case SIGTERM:
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << LL_ENDL;
+ }
+ // Graceful exit
+ // Just set our state to quitting, not error
+ if (LLApp::isQuitting() || LLApp::isError())
+ {
+ // We're already trying to die, just ignore this signal
+ if (LLApp::sLogInSignal)
+ {
+ LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
+ }
+ return;
+ }
+ LLApp::setQuitting();
+ return;
+ case SIGALRM:
+ case SIGPIPE:
+ case SIGUSR2:
+ default:
+ if (signum == LL_SMACKDOWN_SIGNAL ||
+ signum == SIGBUS ||
+ signum == SIGILL ||
+ signum == SIGFPE ||
+ signum == SIGSEGV ||
+ signum == SIGQUIT)
+ {
+ if (signum == LL_SMACKDOWN_SIGNAL)
+ {
+ // Smackdown treated just like any other app termination, for now
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - Handling smackdown signal!" << LL_ENDL;
+ }
+ else
+ {
+ // Don't log anything, even errors - this is because this signal could happen anywhere.
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+ }
+
+ // Change the signal that we reraise to SIGABRT, so we generate a core dump.
+ signum = SIGABRT;
+ }
+
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL;
+ }
+ if (LLApp::isError())
+ {
+ // Received second fatal signal while handling first, just die right now
+ // Set the signal handlers back to default before handling the signal - this makes the next signal wipe out the app.
+ clear_signals();
+
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - Got another fatal signal while in the error handler, die now!" << LL_ENDL;
+ }
+ raise(signum);
+ return;
+ }
+
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - Flagging error status and waiting for shutdown" << LL_ENDL;
+ }
+
+ if (LLApp::isCrashloggerDisabled()) // Don't gracefully handle any signal, crash and core for a gdb post mortem
+ {
+ clear_signals();
+ LL_WARNS() << "Fatal signal received, not handling the crash here, passing back to operating system" << LL_ENDL;
+ raise(signum);
+ return;
+ }
+
+ // Flag status to ERROR
+ LLApp::setError();
+
+ if (LLApp::sLogInSignal)
+ {
+ LL_WARNS() << "Signal handler - App is stopped, reraising signal" << LL_ENDL;
+ }
+ clear_signals();
+ raise(signum);
+ return;
+ } else {
+ if (LLApp::sLogInSignal)
+ {
+ LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL;
+ }
+ }
+ }
}
#if LL_LINUX
#endif
bool unix_post_minidump_callback(const char *dump_dir,
- const char *minidump_id,
- void *context, bool succeeded)
-{
- // Copy minidump file path into fixed buffer in the app instance to avoid
- // heap allocations in a crash handler.
-
- // path format: <dump_dir>/<minidump_id>.dmp
- auto dirPathLength = strlen(dump_dir);
- auto idLength = strlen(minidump_id);
-
- // The path must not be truncated.
- llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
-
- char * path = LLApp::instance()->getMiniDumpFilename();
- auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
- strncpy(path, dump_dir, remaining);
- remaining -= dirPathLength;
- path += dirPathLength;
- if (remaining > 0 && dirPathLength > 0 && path[-1] != '/')
- {
- *path++ = '/';
- --remaining;
- }
- if (remaining > 0)
- {
- strncpy(path, minidump_id, remaining);
- remaining -= idLength;
- path += idLength;
- strncpy(path, ".dmp", remaining);
- }
-
- LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
- LLApp::runErrorHandler();
-
+ const char *minidump_id,
+ void *context, bool succeeded)
+{
+ // Copy minidump file path into fixed buffer in the app instance to avoid
+ // heap allocations in a crash handler.
+
+ // path format: <dump_dir>/<minidump_id>.dmp
+ auto dirPathLength = strlen(dump_dir);
+ auto idLength = strlen(minidump_id);
+
+ // The path must not be truncated.
+ llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
+
+ char * path = LLApp::instance()->getMiniDumpFilename();
+ auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
+ strncpy(path, dump_dir, remaining);
+ remaining -= dirPathLength;
+ path += dirPathLength;
+ if (remaining > 0 && dirPathLength > 0 && path[-1] != '/')
+ {
+ *path++ = '/';
+ --remaining;
+ }
+ if (remaining > 0)
+ {
+ strncpy(path, minidump_id, remaining);
+ remaining -= idLength;
+ path += idLength;
+ strncpy(path, ".dmp", remaining);
+ }
+
+ LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
+ LLApp::runErrorHandler();
+
#ifndef LL_RELEASE_FOR_DOWNLOAD
- clear_signals();
- return false;
+ clear_signals();
+ return false;
#else
- return true;
+ return true;
#endif
}
#endif // !WINDOWS
diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp
index c89f7d12b2..59ff8d3759 100644
--- a/indra/llcommon/llcallbacklist.cpp
+++ b/indra/llcommon/llcallbacklist.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcallbacklist.cpp
* @brief A simple list of callback functions to call.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -39,7 +39,7 @@
*****************************************************************************/
LLCallbackList::LLCallbackList()
{
- // nothing
+ // nothing
}
LLCallbackList::~LLCallbackList()
@@ -48,21 +48,21 @@ LLCallbackList::~LLCallbackList()
LLCallbackList::handle_t LLCallbackList::addFunction( callback_t func, void *data)
{
- if (!func)
- {
- return {};
- }
-
- // only add one callback per func/data pair
- //
- if (containsFunction(func, data))
- {
- return {};
- }
-
- auto handle = addFunction([func, data]{ func(data); });
- mLookup.emplace(callback_pair_t(func, data), handle);
- return handle;
+ if (!func)
+ {
+ return {};
+ }
+
+ // only add one callback per func/data pair
+ //
+ if (containsFunction(func, data))
+ {
+ return {};
+ }
+
+ auto handle = addFunction([func, data]{ func(data); });
+ mLookup.emplace(callback_pair_t(func, data), handle);
+ return handle;
}
LLCallbackList::handle_t LLCallbackList::addFunction( const callable_t& func )
@@ -77,17 +77,17 @@ bool LLCallbackList::containsFunction( callback_t func, void *data)
bool LLCallbackList::deleteFunction( callback_t func, void *data)
{
- auto found = mLookup.find(callback_pair_t(func, data));
- if (found != mLookup.end())
- {
- mLookup.erase(found);
- deleteFunction(found->second);
- return true;
- }
- else
- {
- return false;
- }
+ auto found = mLookup.find(callback_pair_t(func, data));
+ if (found != mLookup.end())
+ {
+ mLookup.erase(found);
+ deleteFunction(found->second);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
void LLCallbackList::deleteFunction( const handle_t& handle )
@@ -97,8 +97,8 @@ void LLCallbackList::deleteFunction( const handle_t& handle )
void LLCallbackList::deleteAllFunctions()
{
- mCallbackList = {};
- mLookup.clear();
+ mCallbackList = {};
+ mLookup.clear();
}
void LLCallbackList::callFunctions()
diff --git a/indra/llcommon/llcallbacklist.h b/indra/llcommon/llcallbacklist.h
index 2fb27d5ea8..b245b3db94 100644
--- a/indra/llcommon/llcallbacklist.h
+++ b/indra/llcommon/llcallbacklist.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcallbacklist.h
* @brief A simple list of callback functions to call.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,43 +41,43 @@
*****************************************************************************/
class LLCallbackList: public LLSingleton<LLCallbackList>
{
- LLSINGLETON(LLCallbackList);
+ LLSINGLETON(LLCallbackList);
public:
- typedef void (*callback_t)(void*);
+ typedef void (*callback_t)(void*);
- typedef boost::signals2::signal<void()> callback_list_t;
- typedef callback_list_t::slot_type callable_t;
- typedef boost::signals2::connection handle_t;
- typedef boost::signals2::scoped_connection temp_handle_t;
- typedef std::function<bool ()> bool_func_t;
+ typedef boost::signals2::signal<void()> callback_list_t;
+ typedef callback_list_t::slot_type callable_t;
+ typedef boost::signals2::connection handle_t;
+ typedef boost::signals2::scoped_connection temp_handle_t;
+ typedef std::function<bool ()> bool_func_t;
- ~LLCallbackList();
+ ~LLCallbackList();
- handle_t addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
- handle_t addFunction( const callable_t& func );
- bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
- bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
- void deleteFunction( const handle_t& handle );
- void callFunctions(); // calls all functions
- void deleteAllFunctions();
+ handle_t addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
+ handle_t addFunction( const callable_t& func );
+ bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
+ bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
+ void deleteFunction( const handle_t& handle );
+ void callFunctions(); // calls all functions
+ void deleteAllFunctions();
- handle_t doOnIdleOneTime( const callable_t& func );
- handle_t doOnIdleRepeating( const bool_func_t& func );
- bool isRunning(const handle_t& handle) const { return handle.connected(); };
+ handle_t doOnIdleOneTime( const callable_t& func );
+ handle_t doOnIdleRepeating( const bool_func_t& func );
+ bool isRunning(const handle_t& handle) const { return handle.connected(); };
- static void test();
+ static void test();
protected:
- callback_list_t mCallbackList;
-
- // "Additional specializations for std::pair and the standard container
- // types, as well as utility functions to compose hashes are available in
- // boost::hash."
- // https://en.cppreference.com/w/cpp/utility/hash
- typedef std::pair< callback_t,void* > callback_pair_t;
- typedef std::unordered_map<callback_pair_t, handle_t,
- boost::hash<callback_pair_t>> lookup_table;
- lookup_table mLookup;
+ callback_list_t mCallbackList;
+
+ // "Additional specializations for std::pair and the standard container
+ // types, as well as utility functions to compose hashes are available in
+ // boost::hash."
+ // https://en.cppreference.com/w/cpp/utility/hash
+ typedef std::pair< callback_t,void* > callback_pair_t;
+ typedef std::unordered_map<callback_pair_t, handle_t,
+ boost::hash<callback_pair_t>> lookup_table;
+ lookup_table mLookup;
};
/*-------------------- legacy names in global namespace --------------------*/
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 6c23444820..592b7cff1b 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lldate.cpp
* @author Phoenix
* @date 2006-02-05
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,36 +44,36 @@
static const LLDate::timestamp DATE_EPOCH = 0.0;
static const LLDate::timestamp LL_APR_USEC_PER_SEC = 1000000.0;
- // should be APR_USEC_PER_SEC, but that relies on INT64_C which
- // isn't defined in glib under our build set up for some reason
+ // should be APR_USEC_PER_SEC, but that relies on INT64_C which
+ // isn't defined in glib under our build set up for some reason
LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH)
{}
LLDate::LLDate(const LLDate& date) :
- mSecondsSinceEpoch(date.mSecondsSinceEpoch)
+ mSecondsSinceEpoch(date.mSecondsSinceEpoch)
{}
LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
- mSecondsSinceEpoch(seconds_since_epoch.value())
+ mSecondsSinceEpoch(seconds_since_epoch.value())
{}
LLDate::LLDate(const std::string& iso8601_date)
{
- if(!fromString(iso8601_date))
- {
- LL_WARNS() << "date " << iso8601_date << " failed to parse; "
- << "ZEROING IT OUT" << LL_ENDL;
- mSecondsSinceEpoch = DATE_EPOCH;
- }
+ if(!fromString(iso8601_date))
+ {
+ LL_WARNS() << "date " << iso8601_date << " failed to parse; "
+ << "ZEROING IT OUT" << LL_ENDL;
+ mSecondsSinceEpoch = DATE_EPOCH;
+ }
}
std::string LLDate::asString() const
{
- std::ostringstream stream;
- toStream(stream);
- return stream.str();
+ std::ostringstream stream;
+ toStream(stream);
+ return stream.str();
}
//@ brief Converts time in seconds since EPOCH
@@ -83,236 +83,236 @@ std::string LLDate::asString() const
// is one of the standards used and the prefered format
std::string LLDate::asRFC1123() const
{
- return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
+ return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
std::string LLDate::toHTTPDateString (std::string fmt) const
{
LL_PROFILE_ZONE_SCOPED;
-
- time_t locSeconds = (time_t) mSecondsSinceEpoch;
- struct tm * gmt = gmtime (&locSeconds);
- return toHTTPDateString(gmt, fmt);
+
+ time_t locSeconds = (time_t) mSecondsSinceEpoch;
+ struct tm * gmt = gmtime (&locSeconds);
+ return toHTTPDateString(gmt, fmt);
}
std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
{
LL_PROFILE_ZONE_SCOPED;
- // avoid calling setlocale() unnecessarily - it's expensive.
- static std::string prev_locale = "";
- std::string this_locale = LLStringUtil::getLocale();
- if (this_locale != prev_locale)
- {
- setlocale(LC_TIME, this_locale.c_str());
- prev_locale = this_locale;
- }
-
- // use strftime() as it appears to be faster than std::time_put
- char buffer[128];
- strftime(buffer, 128, fmt.c_str(), gmt);
- std::string res(buffer);
+ // avoid calling setlocale() unnecessarily - it's expensive.
+ static std::string prev_locale = "";
+ std::string this_locale = LLStringUtil::getLocale();
+ if (this_locale != prev_locale)
+ {
+ setlocale(LC_TIME, this_locale.c_str());
+ prev_locale = this_locale;
+ }
+
+ // use strftime() as it appears to be faster than std::time_put
+ char buffer[128];
+ strftime(buffer, 128, fmt.c_str(), gmt);
+ std::string res(buffer);
#if LL_WINDOWS
- // Convert from locale-dependant charset to UTF-8 (EXT-8524).
- res = ll_convert_string_to_utf8_string(res);
+ // Convert from locale-dependant charset to UTF-8 (EXT-8524).
+ res = ll_convert_string_to_utf8_string(res);
#endif
- return res;
+ return res;
}
void LLDate::toStream(std::ostream& s) const
{
- apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
-
- apr_time_exp_t exp_time;
- if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
- {
- s << "1970-01-01T00:00:00Z";
- return;
- }
-
- s << std::dec << std::setfill('0');
+ apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
+
+ apr_time_exp_t exp_time;
+ if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
+ {
+ s << "1970-01-01T00:00:00Z";
+ return;
+ }
+
+ s << std::dec << std::setfill('0');
#if( LL_WINDOWS || __GNUC__ > 2)
- s << std::right;
+ s << std::right;
#else
- s.setf(ios::right);
+ s.setf(ios::right);
#endif
- s << std::setw(4) << (exp_time.tm_year + 1900)
- << '-' << std::setw(2) << (exp_time.tm_mon + 1)
- << '-' << std::setw(2) << (exp_time.tm_mday)
- << 'T' << std::setw(2) << (exp_time.tm_hour)
- << ':' << std::setw(2) << (exp_time.tm_min)
- << ':' << std::setw(2) << (exp_time.tm_sec);
- if (exp_time.tm_usec > 0)
- {
- s << '.' << std::setw(2)
- << (int)(exp_time.tm_usec / (LL_APR_USEC_PER_SEC / 100));
- }
- s << 'Z'
- << std::setfill(' ');
+ s << std::setw(4) << (exp_time.tm_year + 1900)
+ << '-' << std::setw(2) << (exp_time.tm_mon + 1)
+ << '-' << std::setw(2) << (exp_time.tm_mday)
+ << 'T' << std::setw(2) << (exp_time.tm_hour)
+ << ':' << std::setw(2) << (exp_time.tm_min)
+ << ':' << std::setw(2) << (exp_time.tm_sec);
+ if (exp_time.tm_usec > 0)
+ {
+ s << '.' << std::setw(2)
+ << (int)(exp_time.tm_usec / (LL_APR_USEC_PER_SEC / 100));
+ }
+ s << 'Z'
+ << std::setfill(' ');
}
bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *sec) const
{
- apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
-
- apr_time_exp_t exp_time;
- if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
- {
- return false;
- }
+ apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
+
+ apr_time_exp_t exp_time;
+ if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
+ {
+ return false;
+ }
- if (year)
- *year = exp_time.tm_year + 1900;
+ if (year)
+ *year = exp_time.tm_year + 1900;
- if (month)
- *month = exp_time.tm_mon + 1;
+ if (month)
+ *month = exp_time.tm_mon + 1;
- if (day)
- *day = exp_time.tm_mday;
+ if (day)
+ *day = exp_time.tm_mday;
- if (hour)
- *hour = exp_time.tm_hour;
+ if (hour)
+ *hour = exp_time.tm_hour;
- if (min)
- *min = exp_time.tm_min;
+ if (min)
+ *min = exp_time.tm_min;
- if (sec)
- *sec = exp_time.tm_sec;
+ if (sec)
+ *sec = exp_time.tm_sec;
- return true;
+ return true;
}
bool LLDate::fromString(const std::string& iso8601_date)
{
- std::istringstream stream(iso8601_date);
- return fromStream(stream);
+ std::istringstream stream(iso8601_date);
+ return fromStream(stream);
}
bool LLDate::fromStream(std::istream& s)
{
- struct apr_time_exp_t exp_time;
- apr_int32_t tm_part;
- int c;
-
- s >> tm_part;
- exp_time.tm_year = tm_part - 1900;
- c = s.get(); // skip the hypen
- if (c != '-') { return false; }
- s >> tm_part;
- exp_time.tm_mon = tm_part - 1;
- c = s.get(); // skip the hypen
- if (c != '-') { return false; }
- s >> tm_part;
- exp_time.tm_mday = tm_part;
-
- c = s.get(); // skip the T
- if (c != 'T') { return false; }
-
- s >> tm_part;
- exp_time.tm_hour = tm_part;
- c = s.get(); // skip the :
- if (c != ':') { return false; }
- s >> tm_part;
- exp_time.tm_min = tm_part;
- c = s.get(); // skip the :
- if (c != ':') { return false; }
- s >> tm_part;
- exp_time.tm_sec = tm_part;
-
- // zero out the unused fields
- exp_time.tm_usec = 0;
- exp_time.tm_wday = 0;
- exp_time.tm_yday = 0;
- exp_time.tm_isdst = 0;
- exp_time.tm_gmtoff = 0;
-
- // generate a time_t from that
- apr_time_t time;
- if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS)
- {
- return false;
- }
-
- timestamp seconds_since_epoch = time / LL_APR_USEC_PER_SEC;
-
- // check for fractional
- c = s.peek();
- if(c == '.')
- {
- timestamp fractional = 0.0;
- s >> fractional;
- seconds_since_epoch += fractional;
- }
-
- c = s.peek(); // check for offset
- if (c == '+' || c == '-')
- {
- S32 offset_sign = (c == '+') ? 1 : -1;
- S32 offset_hours = 0;
- S32 offset_minutes = 0;
- S32 offset_in_seconds = 0;
-
- s >> offset_hours;
-
- c = s.get(); // skip the colon a get the minutes if there are any
- if (c == ':')
- {
- s >> offset_minutes;
- }
-
- offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60;
- seconds_since_epoch -= offset_in_seconds;
- }
- else if (c != 'Z') { return false; } // skip the Z
-
- mSecondsSinceEpoch = seconds_since_epoch;
- return true;
+ struct apr_time_exp_t exp_time;
+ apr_int32_t tm_part;
+ int c;
+
+ s >> tm_part;
+ exp_time.tm_year = tm_part - 1900;
+ c = s.get(); // skip the hypen
+ if (c != '-') { return false; }
+ s >> tm_part;
+ exp_time.tm_mon = tm_part - 1;
+ c = s.get(); // skip the hypen
+ if (c != '-') { return false; }
+ s >> tm_part;
+ exp_time.tm_mday = tm_part;
+
+ c = s.get(); // skip the T
+ if (c != 'T') { return false; }
+
+ s >> tm_part;
+ exp_time.tm_hour = tm_part;
+ c = s.get(); // skip the :
+ if (c != ':') { return false; }
+ s >> tm_part;
+ exp_time.tm_min = tm_part;
+ c = s.get(); // skip the :
+ if (c != ':') { return false; }
+ s >> tm_part;
+ exp_time.tm_sec = tm_part;
+
+ // zero out the unused fields
+ exp_time.tm_usec = 0;
+ exp_time.tm_wday = 0;
+ exp_time.tm_yday = 0;
+ exp_time.tm_isdst = 0;
+ exp_time.tm_gmtoff = 0;
+
+ // generate a time_t from that
+ apr_time_t time;
+ if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS)
+ {
+ return false;
+ }
+
+ timestamp seconds_since_epoch = time / LL_APR_USEC_PER_SEC;
+
+ // check for fractional
+ c = s.peek();
+ if(c == '.')
+ {
+ timestamp fractional = 0.0;
+ s >> fractional;
+ seconds_since_epoch += fractional;
+ }
+
+ c = s.peek(); // check for offset
+ if (c == '+' || c == '-')
+ {
+ S32 offset_sign = (c == '+') ? 1 : -1;
+ S32 offset_hours = 0;
+ S32 offset_minutes = 0;
+ S32 offset_in_seconds = 0;
+
+ s >> offset_hours;
+
+ c = s.get(); // skip the colon a get the minutes if there are any
+ if (c == ':')
+ {
+ s >> offset_minutes;
+ }
+
+ offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60;
+ seconds_since_epoch -= offset_in_seconds;
+ }
+ else if (c != 'Z') { return false; } // skip the Z
+
+ mSecondsSinceEpoch = seconds_since_epoch;
+ return true;
}
bool LLDate::fromYMDHMS(S32 year, S32 month, S32 day, S32 hour, S32 min, S32 sec)
{
- struct apr_time_exp_t exp_time;
-
- exp_time.tm_year = year - 1900;
- exp_time.tm_mon = month - 1;
- exp_time.tm_mday = day;
- exp_time.tm_hour = hour;
- exp_time.tm_min = min;
- exp_time.tm_sec = sec;
-
- // zero out the unused fields
- exp_time.tm_usec = 0;
- exp_time.tm_wday = 0;
- exp_time.tm_yday = 0;
- exp_time.tm_isdst = 0;
- exp_time.tm_gmtoff = 0;
-
- // generate a time_t from that
- apr_time_t time;
- if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS)
- {
- return false;
- }
-
- mSecondsSinceEpoch = time / LL_APR_USEC_PER_SEC;
-
- return true;
+ struct apr_time_exp_t exp_time;
+
+ exp_time.tm_year = year - 1900;
+ exp_time.tm_mon = month - 1;
+ exp_time.tm_mday = day;
+ exp_time.tm_hour = hour;
+ exp_time.tm_min = min;
+ exp_time.tm_sec = sec;
+
+ // zero out the unused fields
+ exp_time.tm_usec = 0;
+ exp_time.tm_wday = 0;
+ exp_time.tm_yday = 0;
+ exp_time.tm_isdst = 0;
+ exp_time.tm_gmtoff = 0;
+
+ // generate a time_t from that
+ apr_time_t time;
+ if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS)
+ {
+ return false;
+ }
+
+ mSecondsSinceEpoch = time / LL_APR_USEC_PER_SEC;
+
+ return true;
}
LLDate::timestamp LLDate::secondsSinceEpoch() const
{
- return mSecondsSinceEpoch;
+ return mSecondsSinceEpoch;
}
void LLDate::secondsSinceEpoch(timestamp seconds)
{
- mSecondsSinceEpoch = seconds;
+ mSecondsSinceEpoch = seconds;
}
/* static */ LLDate LLDate::now()
{
- // time() returns seconds, we want fractions of a second, which LLTimer provides --RN
- return LLDate(LLTimer::getTotalSeconds());
+ // time() returns seconds, we want fractions of a second, which LLTimer provides --RN
+ return LLDate(LLTimer::getTotalSeconds());
}
bool LLDate::operator<(const LLDate& rhs) const
@@ -322,13 +322,13 @@ bool LLDate::operator<(const LLDate& rhs) const
std::ostream& operator<<(std::ostream& s, const LLDate& date)
{
- date.toStream(s);
- return s;
+ date.toStream(s);
+ return s;
}
std::istream& operator>>(std::istream& s, LLDate& date)
{
- date.fromStream(s);
- return s;
+ date.fromStream(s);
+ return s;
}
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index c3d0cb97f3..772f45ea7c 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lldate.h
* @author Phoenix
* @date 2006-02-05
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,7 +35,7 @@
#include "stdtypes.h"
#include "llunits.h"
-/**
+/**
* @class LLDate
* @brief This class represents a particular point in time in UTC.
*
@@ -44,112 +44,112 @@
class LL_COMMON_API LLDate
{
public:
- using timestamp = F64;
-
- /**
- * @brief Construct a date equal to epoch.
- */
- LLDate();
-
- /**
- * @brief Construct a date equal to the source date.
- */
- LLDate(const LLDate& date);
-
- /**
- * @brief Construct a date from a seconds since epoch value.
- *
- * @param seconds_since_epoch The number of seconds since UTC epoch.
- */
- LLDate(F64SecondsImplicit seconds_since_epoch);
-
- /**
- * @brief Construct a date from a string representation
- *
- * The date is constructed in the <code>fromString()</code>
- * method. See that method for details of supported formats.
- * If that method fails to parse the date, the date is set to epoch.
- * @param iso8601_date An iso-8601 compatible representation of the date.
- */
- LLDate(const std::string& iso8601_date);
-
- /**
- * @brief Return the date as in ISO-8601 string.
- *
- * @return A string representation of the date.
- */
- std::string asString() const;
- std::string asRFC1123() const;
- void toStream(std::ostream&) const;
- bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
- std::string toHTTPDateString (std::string fmt) const;
- static std::string toHTTPDateString (tm * gmt, std::string fmt);
- /**
- * @brief Set the date from an ISO-8601 string.
- *
- * The parser only supports strings conforming to
- * YYYYF-MM-DDTHH:MM:SS.FFZ where Y is year, M is month, D is day,
- * H is hour, M is minute, S is second, F is sub-second, and all
- * other characters are literal.
- * If this method fails to parse the date, the previous date is
- * retained.
- * @param iso8601_date An iso-8601 compatible representation of the date.
- * @return Returns true if the string was successfully parsed.
- */
- bool fromString(const std::string& iso8601_date);
- bool fromStream(std::istream&);
- bool fromYMDHMS(S32 year, S32 month = 1, S32 day = 0, S32 hour = 0, S32 min = 0, S32 sec = 0);
-
- /**
- * @brief Return the date in seconds since epoch.
- *
- * @return The number of seconds since epoch UTC.
- */
- timestamp secondsSinceEpoch() const;
-
- /**
- * @brief Set the date in seconds since epoch.
- *
- * @param seconds The number of seconds since epoch UTC.
- */
- void secondsSinceEpoch(timestamp seconds);
-
+ using timestamp = F64;
+
+ /**
+ * @brief Construct a date equal to epoch.
+ */
+ LLDate();
+
+ /**
+ * @brief Construct a date equal to the source date.
+ */
+ LLDate(const LLDate& date);
+
+ /**
+ * @brief Construct a date from a seconds since epoch value.
+ *
+ * @param seconds_since_epoch The number of seconds since UTC epoch.
+ */
+ LLDate(F64SecondsImplicit seconds_since_epoch);
+
+ /**
+ * @brief Construct a date from a string representation
+ *
+ * The date is constructed in the <code>fromString()</code>
+ * method. See that method for details of supported formats.
+ * If that method fails to parse the date, the date is set to epoch.
+ * @param iso8601_date An iso-8601 compatible representation of the date.
+ */
+ LLDate(const std::string& iso8601_date);
+
+ /**
+ * @brief Return the date as in ISO-8601 string.
+ *
+ * @return A string representation of the date.
+ */
+ std::string asString() const;
+ std::string asRFC1123() const;
+ void toStream(std::ostream&) const;
+ bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
+ std::string toHTTPDateString (std::string fmt) const;
+ static std::string toHTTPDateString (tm * gmt, std::string fmt);
+ /**
+ * @brief Set the date from an ISO-8601 string.
+ *
+ * The parser only supports strings conforming to
+ * YYYYF-MM-DDTHH:MM:SS.FFZ where Y is year, M is month, D is day,
+ * H is hour, M is minute, S is second, F is sub-second, and all
+ * other characters are literal.
+ * If this method fails to parse the date, the previous date is
+ * retained.
+ * @param iso8601_date An iso-8601 compatible representation of the date.
+ * @return Returns true if the string was successfully parsed.
+ */
+ bool fromString(const std::string& iso8601_date);
+ bool fromStream(std::istream&);
+ bool fromYMDHMS(S32 year, S32 month = 1, S32 day = 0, S32 hour = 0, S32 min = 0, S32 sec = 0);
+
+ /**
+ * @brief Return the date in seconds since epoch.
+ *
+ * @return The number of seconds since epoch UTC.
+ */
+ timestamp secondsSinceEpoch() const;
+
+ /**
+ * @brief Set the date in seconds since epoch.
+ *
+ * @param seconds The number of seconds since epoch UTC.
+ */
+ void secondsSinceEpoch(timestamp seconds);
+
/**
* @brief Create an LLDate object set to the current time.
- *
- * @return The number of seconds since epoch UTC.
- */
+ *
+ * @return The number of seconds since epoch UTC.
+ */
static LLDate now();
- /**
- * @brief Compare dates using operator< so we can order them using STL.
- *
- * @param rhs -- the right hand side of the comparison operator
- */
- bool operator<(const LLDate& rhs) const;
-
- /**
- * @brief Remaining comparison operators in terms of operator<
+ /**
+ * @brief Compare dates using operator< so we can order them using STL.
+ *
+ * @param rhs -- the right hand side of the comparison operator
+ */
+ bool operator<(const LLDate& rhs) const;
+
+ /**
+ * @brief Remaining comparison operators in terms of operator<
* This conforms to the expectation of STL.
- *
- * @param rhs -- the right hand side of the comparison operator
- */
+ *
+ * @param rhs -- the right hand side of the comparison operator
+ */
bool operator>(const LLDate& rhs) const { return rhs < *this; }
bool operator<=(const LLDate& rhs) const { return !(rhs < *this); }
bool operator>=(const LLDate& rhs) const { return !(*this < rhs); }
bool operator!=(const LLDate& rhs) const { return (*this < rhs) || (rhs < *this); }
bool operator==(const LLDate& rhs) const { return !(*this != rhs); }
- /**
- * @brief Compare to epoch UTC.
- */
+ /**
+ * @brief Compare to epoch UTC.
+ */
+
+ bool isNull() const { return mSecondsSinceEpoch == 0.0; }
+ bool notNull() const { return mSecondsSinceEpoch != 0.0; }
- bool isNull() const { return mSecondsSinceEpoch == 0.0; }
- bool notNull() const { return mSecondsSinceEpoch != 0.0; }
-
private:
- timestamp mSecondsSinceEpoch;
+ timestamp mSecondsSinceEpoch;
};
// Helper function to stream out a date
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
index e225119dfb..d19cdd1f25 100644
--- a/indra/llcommon/lldependencies.h
+++ b/indra/llcommon/lldependencies.h
@@ -8,21 +8,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -178,7 +178,7 @@ struct LLDependenciesEmpty
* values such as NULL or 0 rather than having to write
* LLDependenciesEmpty().
*/
- LLDependenciesEmpty(void*) {}
+ LLDependenciesEmpty(void*) {}
};
/**
@@ -210,7 +210,7 @@ class LLDependencies: public LLDependenciesBase
before(before_)
{}
NODE node;
- dep_set after, before;
+ dep_set after, before;
};
typedef std::map<KEY, DepNode> DepNodeMap;
typedef typename DepNodeMap::value_type DepNodeMapEntry;
@@ -240,7 +240,7 @@ public:
* NODE& reference.
*
* @note
- * Actual dependency analysis is deferred to the sort() method, so
+ * Actual dependency analysis is deferred to the sort() method, so
* you can add an arbitrary number of nodes without incurring analysis
* overhead for each. The flip side of this is that add()ing nodes that
* define a cycle leaves this object in a state in which sort() will
@@ -599,7 +599,7 @@ public:
return sorted_range(begin, end);
}
- using LLDependenciesBase::describe; // unhide virtual std::string describe(bool full=true) const;
+ using LLDependenciesBase::describe; // unhide virtual std::string describe(bool full=true) const;
/// Override base-class describe() with actual implementation
virtual std::ostream& describe(std::ostream& out, bool full=true) const
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index b6285db073..3d00fa46c1 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llerror.cpp
* @date December 2006
* @brief error message system
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -65,91 +65,91 @@
namespace {
#if LL_WINDOWS
- void debugger_print(const std::string& s)
- {
- // Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C
- // which works just fine under the windows debugger, but can cause users who
- // have enabled SEHOP exception chain validation to crash due to interactions
- // between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
- //
- if (IsDebuggerPresent())
- {
- // Need UTF16 for Unicode OutputDebugString
- //
- if (s.size())
- {
- OutputDebugString(utf8str_to_utf16str(s).c_str());
- OutputDebugString(TEXT("\n"));
- }
- }
- }
+ void debugger_print(const std::string& s)
+ {
+ // Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C
+ // which works just fine under the windows debugger, but can cause users who
+ // have enabled SEHOP exception chain validation to crash due to interactions
+ // between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
+ //
+ if (IsDebuggerPresent())
+ {
+ // Need UTF16 for Unicode OutputDebugString
+ //
+ if (s.size())
+ {
+ OutputDebugString(utf8str_to_utf16str(s).c_str());
+ OutputDebugString(TEXT("\n"));
+ }
+ }
+ }
#else
- class RecordToSyslog : public LLError::Recorder
- {
- public:
- RecordToSyslog(const std::string& identity)
- : mIdentity(identity)
- {
- openlog(mIdentity.c_str(), LOG_CONS|LOG_PID, LOG_LOCAL0);
- // we need to set the string from a local copy of the string
- // since apparanetly openlog expects the const char* to remain
- // valid even after it returns (presumably until closelog)
- }
-
- ~RecordToSyslog()
- {
- closelog();
- }
+ class RecordToSyslog : public LLError::Recorder
+ {
+ public:
+ RecordToSyslog(const std::string& identity)
+ : mIdentity(identity)
+ {
+ openlog(mIdentity.c_str(), LOG_CONS|LOG_PID, LOG_LOCAL0);
+ // we need to set the string from a local copy of the string
+ // since apparanetly openlog expects the const char* to remain
+ // valid even after it returns (presumably until closelog)
+ }
+
+ ~RecordToSyslog()
+ {
+ closelog();
+ }
virtual bool enabled() override
{
return LLError::getEnabledLogTypesMask() & 0x01;
}
-
- virtual void recordMessage(LLError::ELevel level,
- const std::string& message) override
- {
+
+ virtual void recordMessage(LLError::ELevel level,
+ const std::string& message) override
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
- int syslogPriority = LOG_CRIT;
- switch (level) {
- case LLError::LEVEL_DEBUG: syslogPriority = LOG_DEBUG; break;
- case LLError::LEVEL_INFO: syslogPriority = LOG_INFO; break;
- case LLError::LEVEL_WARN: syslogPriority = LOG_WARNING; break;
- case LLError::LEVEL_ERROR: syslogPriority = LOG_CRIT; break;
- default: syslogPriority = LOG_CRIT;
- }
-
- syslog(syslogPriority, "%s", message.c_str());
- }
- private:
- std::string mIdentity;
- };
+ int syslogPriority = LOG_CRIT;
+ switch (level) {
+ case LLError::LEVEL_DEBUG: syslogPriority = LOG_DEBUG; break;
+ case LLError::LEVEL_INFO: syslogPriority = LOG_INFO; break;
+ case LLError::LEVEL_WARN: syslogPriority = LOG_WARNING; break;
+ case LLError::LEVEL_ERROR: syslogPriority = LOG_CRIT; break;
+ default: syslogPriority = LOG_CRIT;
+ }
+
+ syslog(syslogPriority, "%s", message.c_str());
+ }
+ private:
+ std::string mIdentity;
+ };
#endif
- class RecordToFile : public LLError::Recorder
- {
- public:
- RecordToFile(const std::string& filename):
- mName(filename)
- {
- mFile.open(filename.c_str(), std::ios_base::out | std::ios_base::app);
- if (!mFile)
- {
- LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
- }
- else
- {
- if (!LLError::getAlwaysFlush())
- {
- mFile.sync_with_stdio(false);
- }
- }
- }
-
- ~RecordToFile()
- {
- mFile.close();
- }
+ class RecordToFile : public LLError::Recorder
+ {
+ public:
+ RecordToFile(const std::string& filename):
+ mName(filename)
+ {
+ mFile.open(filename.c_str(), std::ios_base::out | std::ios_base::app);
+ if (!mFile)
+ {
+ LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
+ }
+ else
+ {
+ if (!LLError::getAlwaysFlush())
+ {
+ mFile.sync_with_stdio(false);
+ }
+ }
+ }
+
+ ~RecordToFile()
+ {
+ mFile.close();
+ }
virtual bool enabled() override
{
@@ -159,7 +159,7 @@ namespace {
return LLError::getEnabledLogTypesMask() & 0x02;
#endif
}
-
+
bool okay() const { return mFile.good(); }
std::string getFilename() const { return mName; }
@@ -178,25 +178,25 @@ namespace {
}
}
- private:
- const std::string mName;
- llofstream mFile;
- };
-
-
- class RecordToStderr : public LLError::Recorder
- {
- public:
- RecordToStderr(bool timestamp) : mUseANSI(checkANSI())
- {
+ private:
+ const std::string mName;
+ llofstream mFile;
+ };
+
+
+ class RecordToStderr : public LLError::Recorder
+ {
+ public:
+ RecordToStderr(bool timestamp) : mUseANSI(checkANSI())
+ {
this->showMultiline(true);
- }
-
+ }
+
virtual bool enabled() override
{
return LLError::getEnabledLogTypesMask() & 0x04;
}
-
+
LL_FORCE_INLINE std::string createBoldANSI()
{
std::string ansi_code;
@@ -231,12 +231,12 @@ namespace {
return ansi_code;
}
- virtual void recordMessage(LLError::ELevel level,
- const std::string& message) override
- {
+ virtual void recordMessage(LLError::ELevel level,
+ const std::string& message) override
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
// The default colors for error, warn and debug are now a bit more pastel
- // and easier to read on the default (black) terminal background but you
+ // and easier to read on the default (black) terminal background but you
// now have the option to set the color of each via an environment variables:
// LL_ANSI_ERROR_COLOR_CODE (default is red)
// LL_ANSI_WARN_COLOR_CODE (default is blue)
@@ -256,75 +256,75 @@ namespace {
static std::string s_ansi_warn = createANSI(s_ansi_warn_code); // default is blue
static std::string s_ansi_debug = createANSI(s_ansi_debug_code); // default is magenta
- if (mUseANSI)
- {
+ if (mUseANSI)
+ {
writeANSI((level == LLError::LEVEL_ERROR) ? s_ansi_error :
(level == LLError::LEVEL_WARN) ? s_ansi_warn :
s_ansi_debug, message);
- }
+ }
else
{
LL_PROFILE_ZONE_NAMED("fprintf");
fprintf(stderr, "%s\n", message.c_str());
}
- }
-
- private:
- bool mUseANSI;
+ }
+
+ private:
+ bool mUseANSI;
LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message)
- {
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
static std::string s_ansi_bold = createBoldANSI(); // bold text
static std::string s_ansi_reset = createResetANSI(); // reset
- // ANSI color code escape sequence, message, and reset in one fprintf call
+ // ANSI color code escape sequence, message, and reset in one fprintf call
// Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries.
- fprintf(stderr, "%s%s\n%s", ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() );
- }
-
- static bool checkANSI(void)
- {
- // Check whether it's okay to use ANSI; if stderr is
- // a tty then we assume yes. Can be turned off with
- // the LL_NO_ANSI_COLOR env var.
- return (0 != isatty(2)) &&
- (NULL == getenv("LL_NO_ANSI_COLOR"));
- }
- };
-
- class RecordToFixedBuffer : public LLError::Recorder
- {
- public:
- RecordToFixedBuffer(LLLineBuffer* buffer)
+ fprintf(stderr, "%s%s\n%s", ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() );
+ }
+
+ static bool checkANSI(void)
+ {
+ // Check whether it's okay to use ANSI; if stderr is
+ // a tty then we assume yes. Can be turned off with
+ // the LL_NO_ANSI_COLOR env var.
+ return (0 != isatty(2)) &&
+ (NULL == getenv("LL_NO_ANSI_COLOR"));
+ }
+ };
+
+ class RecordToFixedBuffer : public LLError::Recorder
+ {
+ public:
+ RecordToFixedBuffer(LLLineBuffer* buffer)
: mBuffer(buffer)
{
this->showMultiline(true);
this->showTags(false);
this->showLocation(false);
}
-
+
virtual bool enabled() override
{
return LLError::getEnabledLogTypesMask() & 0x08;
}
-
- virtual void recordMessage(LLError::ELevel level,
- const std::string& message) override
- {
+
+ virtual void recordMessage(LLError::ELevel level,
+ const std::string& message) override
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
- mBuffer->addLine(message);
- }
-
- private:
- LLLineBuffer* mBuffer;
- };
+ mBuffer->addLine(message);
+ }
+
+ private:
+ LLLineBuffer* mBuffer;
+ };
#if LL_WINDOWS
- class RecordToWinDebug: public LLError::Recorder
- {
- public:
- RecordToWinDebug()
- {
+ class RecordToWinDebug: public LLError::Recorder
+ {
+ public:
+ RecordToWinDebug()
+ {
this->showMultiline(true);
this->showTags(false);
this->showLocation(false);
@@ -334,154 +334,154 @@ namespace {
{
return LLError::getEnabledLogTypesMask() & 0x10;
}
-
- virtual void recordMessage(LLError::ELevel level,
- const std::string& message) override
- {
+
+ virtual void recordMessage(LLError::ELevel level,
+ const std::string& message) override
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
- debugger_print(message);
- }
- };
+ debugger_print(message);
+ }
+ };
#endif
}
namespace
{
- std::string className(const std::type_info& type)
- {
- return LLError::Log::demangle(type.name());
- }
+ std::string className(const std::type_info& type)
+ {
+ return LLError::Log::demangle(type.name());
+ }
} // anonymous
namespace LLError
{
- std::string Log::demangle(const char* mangled)
- {
+ std::string Log::demangle(const char* mangled)
+ {
#ifdef __GNUC__
- // GCC: type_info::name() returns a mangled class name,st demangle
- // passing nullptr, 0 forces allocation of a unique buffer we can free
- // fixing MAINT-8724 on OSX 10.14
- int status = -1;
- char* name = abi::__cxa_demangle(mangled, nullptr, 0, &status);
- std::string result(name ? name : mangled);
- free(name);
- return result;
+ // GCC: type_info::name() returns a mangled class name,st demangle
+ // passing nullptr, 0 forces allocation of a unique buffer we can free
+ // fixing MAINT-8724 on OSX 10.14
+ int status = -1;
+ char* name = abi::__cxa_demangle(mangled, nullptr, 0, &status);
+ std::string result(name ? name : mangled);
+ free(name);
+ return result;
#elif LL_WINDOWS
- // Visual Studio: type_info::name() includes the text "class " at the start
- std::string name = mangled;
- for (const auto& prefix : std::vector<std::string>{ "class ", "struct " })
- {
- if (0 == name.compare(0, prefix.length(), prefix))
- {
- return name.substr(prefix.length());
- }
- }
- // huh, that's odd, we should see one or the other prefix -- but don't
- // try to log unless logging is already initialized
- // in Python, " or ".join(vector) -- but in C++, a PITB
- LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '"
- << name << "'" << LL_ENDL;
- return name;
+ // Visual Studio: type_info::name() includes the text "class " at the start
+ std::string name = mangled;
+ for (const auto& prefix : std::vector<std::string>{ "class ", "struct " })
+ {
+ if (0 == name.compare(0, prefix.length(), prefix))
+ {
+ return name.substr(prefix.length());
+ }
+ }
+ // huh, that's odd, we should see one or the other prefix -- but don't
+ // try to log unless logging is already initialized
+ // in Python, " or ".join(vector) -- but in C++, a PITB
+ LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '"
+ << name << "'" << LL_ENDL;
+ return name;
#else // neither GCC nor Visual Studio
- return mangled;
+ return mangled;
#endif
- }
+ }
} // LLError
namespace
{
- std::string functionName(const std::string& preprocessor_name)
- {
+ std::string functionName(const std::string& preprocessor_name)
+ {
#if LL_WINDOWS
- // DevStudio: the __FUNCTION__ macro string includes
- // the type and/or namespace prefixes
+ // DevStudio: the __FUNCTION__ macro string includes
+ // the type and/or namespace prefixes
- std::string::size_type p = preprocessor_name.rfind(':');
- if (p == std::string::npos)
- {
- return preprocessor_name;
- }
- return preprocessor_name.substr(p + 1);
+ std::string::size_type p = preprocessor_name.rfind(':');
+ if (p == std::string::npos)
+ {
+ return preprocessor_name;
+ }
+ return preprocessor_name.substr(p + 1);
#else
- return preprocessor_name;
+ return preprocessor_name;
#endif
- }
-
-
- class LogControlFile : public LLLiveFile
- {
- LOG_CLASS(LogControlFile);
-
- public:
- static LogControlFile& fromDirectory(const std::string& user_dir, const std::string& app_dir);
-
- virtual bool loadFile();
-
- private:
- LogControlFile(const std::string &filename)
- : LLLiveFile(filename)
- { }
- };
-
- LogControlFile& LogControlFile::fromDirectory(const std::string& user_dir, const std::string& app_dir)
- {
+ }
+
+
+ class LogControlFile : public LLLiveFile
+ {
+ LOG_CLASS(LogControlFile);
+
+ public:
+ static LogControlFile& fromDirectory(const std::string& user_dir, const std::string& app_dir);
+
+ virtual bool loadFile();
+
+ private:
+ LogControlFile(const std::string &filename)
+ : LLLiveFile(filename)
+ { }
+ };
+
+ LogControlFile& LogControlFile::fromDirectory(const std::string& user_dir, const std::string& app_dir)
+ {
// NB: We have no abstraction in llcommon for the "proper"
// delimiter but it turns out that "/" works on all three platforms
-
- std::string file = user_dir + "/logcontrol-dev.xml";
-
- llstat stat_info;
- if (LLFile::stat(file, &stat_info)) {
- // NB: stat returns non-zero if it can't read the file, for example
- // if it doesn't exist. LLFile has no better abstraction for
- // testing for file existence.
-
- file = app_dir + "/logcontrol.xml";
- }
- return * new LogControlFile(file);
- // NB: This instance is never freed
- }
-
- bool LogControlFile::loadFile()
- {
- LLSD configuration;
-
- {
- llifstream file(filename().c_str());
- if (!file.is_open())
- {
- LL_WARNS() << filename() << " failed to open file; not changing configuration" << LL_ENDL;
- return false;
- }
-
- if (LLSDSerialize::fromXML(configuration, file) == LLSDParser::PARSE_FAILURE)
- {
- LL_WARNS() << filename() << " parcing error; not changing configuration" << LL_ENDL;
- return false;
- }
-
- if (! configuration || !configuration.isMap())
- {
- LL_WARNS() << filename() << " missing, ill-formed, or simply undefined"
- " content; not changing configuration"
- << LL_ENDL;
- return false;
- }
- }
-
- LLError::configure(configuration);
- LL_INFOS("LogControlFile") << "logging reconfigured from " << filename() << LL_ENDL;
- return true;
- }
-
-
- typedef std::map<std::string, LLError::ELevel> LevelMap;
- typedef std::vector<LLError::RecorderPtr> Recorders;
- typedef std::vector<LLError::CallSite*> CallSiteVector;
+
+ std::string file = user_dir + "/logcontrol-dev.xml";
+
+ llstat stat_info;
+ if (LLFile::stat(file, &stat_info)) {
+ // NB: stat returns non-zero if it can't read the file, for example
+ // if it doesn't exist. LLFile has no better abstraction for
+ // testing for file existence.
+
+ file = app_dir + "/logcontrol.xml";
+ }
+ return * new LogControlFile(file);
+ // NB: This instance is never freed
+ }
+
+ bool LogControlFile::loadFile()
+ {
+ LLSD configuration;
+
+ {
+ llifstream file(filename().c_str());
+ if (!file.is_open())
+ {
+ LL_WARNS() << filename() << " failed to open file; not changing configuration" << LL_ENDL;
+ return false;
+ }
+
+ if (LLSDSerialize::fromXML(configuration, file) == LLSDParser::PARSE_FAILURE)
+ {
+ LL_WARNS() << filename() << " parcing error; not changing configuration" << LL_ENDL;
+ return false;
+ }
+
+ if (! configuration || !configuration.isMap())
+ {
+ LL_WARNS() << filename() << " missing, ill-formed, or simply undefined"
+ " content; not changing configuration"
+ << LL_ENDL;
+ return false;
+ }
+ }
+
+ LLError::configure(configuration);
+ LL_INFOS("LogControlFile") << "logging reconfigured from " << filename() << LL_ENDL;
+ return true;
+ }
+
+
+ typedef std::map<std::string, LLError::ELevel> LevelMap;
+ typedef std::vector<LLError::RecorderPtr> Recorders;
+ typedef std::vector<LLError::CallSite*> CallSiteVector;
class SettingsConfig : public LLRefCount
{
@@ -492,9 +492,9 @@ namespace
LLError::ELevel mDefaultLevel;
- bool mLogAlwaysFlush;
+ bool mLogAlwaysFlush;
- U32 mEnabledLogTypesMask;
+ U32 mEnabledLogTypesMask;
LevelMap mFunctionLevelMap;
LevelMap mClassLevelMap;
@@ -539,34 +539,34 @@ namespace
mRecorders.clear();
}
- class Globals
- {
+ class Globals
+ {
public:
static Globals* getInstance();
protected:
- Globals();
- public:
- std::string mFatalMessage;
+ Globals();
+ public:
+ std::string mFatalMessage;
- void addCallSite(LLError::CallSite&);
- void invalidateCallSites();
+ void addCallSite(LLError::CallSite&);
+ void invalidateCallSites();
SettingsConfigPtr getSettingsConfig();
void resetSettingsConfig();
LLError::SettingsStoragePtr saveAndResetSettingsConfig();
void restore(LLError::SettingsStoragePtr pSettingsStorage);
- private:
- CallSiteVector callSites;
+ private:
+ CallSiteVector callSites;
SettingsConfigPtr mSettingsConfig;
- };
+ };
- Globals::Globals()
- :
- callSites(),
+ Globals::Globals()
+ :
+ callSites(),
mSettingsConfig(new SettingsConfig())
- {
- }
+ {
+ }
Globals* Globals::getInstance()
@@ -579,20 +579,20 @@ namespace
return &inst;
}
- void Globals::addCallSite(LLError::CallSite& site)
- {
- callSites.push_back(&site);
- }
-
- void Globals::invalidateCallSites()
- {
- for (LLError::CallSite* site : callSites)
- {
+ void Globals::addCallSite(LLError::CallSite& site)
+ {
+ callSites.push_back(&site);
+ }
+
+ void Globals::invalidateCallSites()
+ {
+ for (LLError::CallSite* site : callSites)
+ {
site->invalidate();
- }
-
- callSites.clear();
- }
+ }
+
+ callSites.clear();
+ }
SettingsConfigPtr Globals::getSettingsConfig()
{
@@ -622,77 +622,77 @@ namespace
namespace LLError
{
- CallSite::CallSite(ELevel level,
- const char* file,
- int line,
- const std::type_info& class_info,
- const char* function,
- bool printOnce,
- const char** tags,
- size_t tag_count)
- : mLevel(level),
- mFile(file),
- mLine(line),
- mClassInfo(class_info),
- mFunction(function),
- mCached(false),
- mShouldLog(false),
- mPrintOnce(printOnce),
- mTags(new const char* [tag_count]),
- mTagCount(tag_count)
- {
- switch (mLevel)
- {
+ CallSite::CallSite(ELevel level,
+ const char* file,
+ int line,
+ const std::type_info& class_info,
+ const char* function,
+ bool printOnce,
+ const char** tags,
+ size_t tag_count)
+ : mLevel(level),
+ mFile(file),
+ mLine(line),
+ mClassInfo(class_info),
+ mFunction(function),
+ mCached(false),
+ mShouldLog(false),
+ mPrintOnce(printOnce),
+ mTags(new const char* [tag_count]),
+ mTagCount(tag_count)
+ {
+ switch (mLevel)
+ {
case LEVEL_DEBUG: mLevelString = "DEBUG"; break;
case LEVEL_INFO: mLevelString = "INFO"; break;
case LEVEL_WARN: mLevelString = "WARNING"; break;
case LEVEL_ERROR: mLevelString = "ERROR"; break;
default: mLevelString = "XXX"; break;
- };
+ };
- mLocationString = llformat("%s(%d)", abbreviateFile(mFile).c_str(), mLine);
+ mLocationString = llformat("%s(%d)", abbreviateFile(mFile).c_str(), mLine);
#if LL_WINDOWS
- // DevStudio: __FUNCTION__ already includes the full class name
+ // DevStudio: __FUNCTION__ already includes the full class name
#else
#if LL_LINUX
- // gross, but typeid comparison seems to always fail here with gcc4.1
- if (0 != strcmp(mClassInfo.name(), typeid(NoClassInfo).name()))
+ // gross, but typeid comparison seems to always fail here with gcc4.1
+ if (0 != strcmp(mClassInfo.name(), typeid(NoClassInfo).name()))
#else
- if (mClassInfo != typeid(NoClassInfo))
+ if (mClassInfo != typeid(NoClassInfo))
#endif // LL_LINUX
- {
- mFunctionString = className(mClassInfo) + "::";
- }
+ {
+ mFunctionString = className(mClassInfo) + "::";
+ }
#endif
- mFunctionString += std::string(mFunction);
+ mFunctionString += std::string(mFunction);
- for (int i = 0; i < tag_count; i++)
- {
+ for (int i = 0; i < tag_count; i++)
+ {
if (strchr(tags[i], ' '))
{
LL_ERRS() << "Space is not allowed in a log tag at " << mLocationString << LL_ENDL;
}
- mTags[i] = tags[i];
- }
+ mTags[i] = tags[i];
+ }
mTagString.append("#");
// always construct a tag sequence; will be just a single # if no tag
- for (size_t i = 0; i < mTagCount; i++)
- {
- mTagString.append(mTags[i]);
+ for (size_t i = 0; i < mTagCount; i++)
+ {
+ mTagString.append(mTags[i]);
mTagString.append("#");
- }
- }
-
- CallSite::~CallSite()
- {
- delete []mTags;
- }
-
- void CallSite::invalidate()
- {
- mCached = false;
- }
+ }
+ }
+
+ CallSite::~CallSite()
+ {
+ delete []mTags;
+ }
+
+ void CallSite::invalidate()
+ {
+ mCached = false;
+ }
}
namespace
@@ -729,202 +729,202 @@ namespace
#endif
}
- bool stderrLogWantsTime()
- {
+ bool stderrLogWantsTime()
+ {
#if LL_WINDOWS
- return false;
+ return false;
#else
- return true;
+ return true;
#endif
- }
-
-
- void commonInit(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true)
- {
- Globals::getInstance()->resetSettingsConfig();
-
- LLError::setDefaultLevel(LLError::LEVEL_INFO);
- LLError::setAlwaysFlush(true);
- LLError::setEnabledLogTypesMask(0xFFFFFFFF);
- LLError::setTimeFunction(LLError::utcTime);
-
- // log_to_stderr is only false in the unit and integration tests to keep builds quieter
- if (log_to_stderr && shouldLogToStderr())
- {
- LLError::logToStderr();
- }
+ }
+
+
+ void commonInit(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true)
+ {
+ Globals::getInstance()->resetSettingsConfig();
+
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+ LLError::setAlwaysFlush(true);
+ LLError::setEnabledLogTypesMask(0xFFFFFFFF);
+ LLError::setTimeFunction(LLError::utcTime);
+
+ // log_to_stderr is only false in the unit and integration tests to keep builds quieter
+ if (log_to_stderr && shouldLogToStderr())
+ {
+ LLError::logToStderr();
+ }
#if LL_WINDOWS
- LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug());
- LLError::addRecorder(recordToWinDebug);
+ LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug());
+ LLError::addRecorder(recordToWinDebug);
#endif
- LogControlFile& e = LogControlFile::fromDirectory(user_dir, app_dir);
-
- // NOTE: We want to explicitly load the file before we add it to the event timer
- // that checks for changes to the file. Else, we're not actually loading the file yet,
- // and most of the initialization happens without any attention being paid to the
- // log control file. Not to mention that when it finally gets checked later,
- // all log statements that have been evaluated already become dirty and need to be
- // evaluated for printing again. So, make sure to call checkAndReload()
- // before addToEventTimer().
- e.checkAndReload();
- e.addToEventTimer();
- }
+ LogControlFile& e = LogControlFile::fromDirectory(user_dir, app_dir);
+
+ // NOTE: We want to explicitly load the file before we add it to the event timer
+ // that checks for changes to the file. Else, we're not actually loading the file yet,
+ // and most of the initialization happens without any attention being paid to the
+ // log control file. Not to mention that when it finally gets checked later,
+ // all log statements that have been evaluated already become dirty and need to be
+ // evaluated for printing again. So, make sure to call checkAndReload()
+ // before addToEventTimer().
+ e.checkAndReload();
+ e.addToEventTimer();
+ }
}
namespace LLError
{
- void initForApplication(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr)
- {
- commonInit(user_dir, app_dir, log_to_stderr);
- }
-
- void setFatalFunction(const FatalFunction& f)
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- s->mCrashFunction = f;
- }
-
- FatalFunction getFatalFunction()
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- return s->mCrashFunction;
- }
-
- std::string getFatalMessage()
- {
- return Globals::getInstance()->mFatalMessage;
- }
-
- void setTimeFunction(TimeFunction f)
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- s->mTimeFunction = f;
- }
-
- void setDefaultLevel(ELevel level)
- {
- Globals *g = Globals::getInstance();
- g->invalidateCallSites();
- SettingsConfigPtr s = g->getSettingsConfig();
- s->mDefaultLevel = level;
- }
-
- ELevel getDefaultLevel()
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- return s->mDefaultLevel;
- }
-
- void setAlwaysFlush(bool flush)
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- s->mLogAlwaysFlush = flush;
- }
-
- bool getAlwaysFlush()
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- return s->mLogAlwaysFlush;
- }
-
- void setEnabledLogTypesMask(U32 mask)
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- s->mEnabledLogTypesMask = mask;
- }
-
- U32 getEnabledLogTypesMask()
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- return s->mEnabledLogTypesMask;
- }
-
- void setFunctionLevel(const std::string& function_name, ELevel level)
- {
- Globals *g = Globals::getInstance();
- g->invalidateCallSites();
- SettingsConfigPtr s = g->getSettingsConfig();
- s->mFunctionLevelMap[function_name] = level;
- }
-
- void setClassLevel(const std::string& class_name, ELevel level)
- {
- Globals *g = Globals::getInstance();
- g->invalidateCallSites();
- SettingsConfigPtr s = g->getSettingsConfig();
- s->mClassLevelMap[class_name] = level;
- }
-
- void setFileLevel(const std::string& file_name, ELevel level)
- {
- Globals *g = Globals::getInstance();
- g->invalidateCallSites();
- SettingsConfigPtr s = g->getSettingsConfig();
- s->mFileLevelMap[file_name] = level;
- }
-
- void setTagLevel(const std::string& tag_name, ELevel level)
- {
- Globals *g = Globals::getInstance();
- g->invalidateCallSites();
- SettingsConfigPtr s = g->getSettingsConfig();
- s->mTagLevelMap[tag_name] = level;
- }
-
- LLError::ELevel decodeLevel(std::string name)
- {
- static LevelMap level_names;
- if (level_names.empty())
- {
- level_names["ALL"] = LLError::LEVEL_ALL;
- level_names["DEBUG"] = LLError::LEVEL_DEBUG;
- level_names["INFO"] = LLError::LEVEL_INFO;
- level_names["WARN"] = LLError::LEVEL_WARN;
- level_names["ERROR"] = LLError::LEVEL_ERROR;
- level_names["NONE"] = LLError::LEVEL_NONE;
- }
-
- std::transform(name.begin(), name.end(), name.begin(), toupper);
-
- LevelMap::const_iterator i = level_names.find(name);
- if (i == level_names.end())
- {
- LL_WARNS() << "unrecognized logging level: '" << name << "'" << LL_ENDL;
- return LLError::LEVEL_INFO;
- }
-
- return i->second;
- }
+ void initForApplication(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr)
+ {
+ commonInit(user_dir, app_dir, log_to_stderr);
+ }
+
+ void setFatalFunction(const FatalFunction& f)
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ s->mCrashFunction = f;
+ }
+
+ FatalFunction getFatalFunction()
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ return s->mCrashFunction;
+ }
+
+ std::string getFatalMessage()
+ {
+ return Globals::getInstance()->mFatalMessage;
+ }
+
+ void setTimeFunction(TimeFunction f)
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ s->mTimeFunction = f;
+ }
+
+ void setDefaultLevel(ELevel level)
+ {
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
+ s->mDefaultLevel = level;
+ }
+
+ ELevel getDefaultLevel()
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ return s->mDefaultLevel;
+ }
+
+ void setAlwaysFlush(bool flush)
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ s->mLogAlwaysFlush = flush;
+ }
+
+ bool getAlwaysFlush()
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ return s->mLogAlwaysFlush;
+ }
+
+ void setEnabledLogTypesMask(U32 mask)
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ s->mEnabledLogTypesMask = mask;
+ }
+
+ U32 getEnabledLogTypesMask()
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ return s->mEnabledLogTypesMask;
+ }
+
+ void setFunctionLevel(const std::string& function_name, ELevel level)
+ {
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
+ s->mFunctionLevelMap[function_name] = level;
+ }
+
+ void setClassLevel(const std::string& class_name, ELevel level)
+ {
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
+ s->mClassLevelMap[class_name] = level;
+ }
+
+ void setFileLevel(const std::string& file_name, ELevel level)
+ {
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
+ s->mFileLevelMap[file_name] = level;
+ }
+
+ void setTagLevel(const std::string& tag_name, ELevel level)
+ {
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
+ s->mTagLevelMap[tag_name] = level;
+ }
+
+ LLError::ELevel decodeLevel(std::string name)
+ {
+ static LevelMap level_names;
+ if (level_names.empty())
+ {
+ level_names["ALL"] = LLError::LEVEL_ALL;
+ level_names["DEBUG"] = LLError::LEVEL_DEBUG;
+ level_names["INFO"] = LLError::LEVEL_INFO;
+ level_names["WARN"] = LLError::LEVEL_WARN;
+ level_names["ERROR"] = LLError::LEVEL_ERROR;
+ level_names["NONE"] = LLError::LEVEL_NONE;
+ }
+
+ std::transform(name.begin(), name.end(), name.begin(), toupper);
+
+ LevelMap::const_iterator i = level_names.find(name);
+ if (i == level_names.end())
+ {
+ LL_WARNS() << "unrecognized logging level: '" << name << "'" << LL_ENDL;
+ return LLError::LEVEL_INFO;
+ }
+
+ return i->second;
+ }
}
namespace {
- void setLevels(LevelMap& map, const LLSD& list, LLError::ELevel level)
- {
- LLSD::array_const_iterator i, end;
- for (i = list.beginArray(), end = list.endArray(); i != end; ++i)
- {
- map[*i] = level;
- }
- }
+ void setLevels(LevelMap& map, const LLSD& list, LLError::ELevel level)
+ {
+ LLSD::array_const_iterator i, end;
+ for (i = list.beginArray(), end = list.endArray(); i != end; ++i)
+ {
+ map[*i] = level;
+ }
+ }
}
namespace LLError
{
- void configure(const LLSD& config)
- {
- Globals *g = Globals::getInstance();
- g->invalidateCallSites();
- SettingsConfigPtr s = g->getSettingsConfig();
-
- s->mFunctionLevelMap.clear();
- s->mClassLevelMap.clear();
- s->mFileLevelMap.clear();
- s->mTagLevelMap.clear();
- s->mUniqueLogMessages.clear();
-
- setDefaultLevel(decodeLevel(config["default-level"]));
+ void configure(const LLSD& config)
+ {
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
+
+ s->mFunctionLevelMap.clear();
+ s->mClassLevelMap.clear();
+ s->mFileLevelMap.clear();
+ s->mTagLevelMap.clear();
+ s->mUniqueLogMessages.clear();
+
+ setDefaultLevel(decodeLevel(config["default-level"]));
if (config.has("log-always-flush"))
{
setAlwaysFlush(config["log-always-flush"]);
@@ -933,7 +933,7 @@ namespace LLError
{
setEnabledLogTypesMask(config["enabled-log-types-mask"].asInteger());
}
-
+
if (config.has("settings") && config["settings"].isArray())
{
LLSD sets = config["settings"];
@@ -952,66 +952,66 @@ namespace LLError
}
}
}
- }
+ }
}
namespace LLError
{
- Recorder::Recorder()
- : mWantsTime(true)
+ Recorder::Recorder()
+ : mWantsTime(true)
, mWantsTags(true)
, mWantsLevel(true)
, mWantsLocation(true)
, mWantsFunctionName(true)
, mWantsMultiline(false)
- {
- }
-
- Recorder::~Recorder()
- {
- }
-
- bool Recorder::wantsTime()
- {
- return mWantsTime;
- }
-
- // virtual
- bool Recorder::wantsTags()
- {
- return mWantsTags;
- }
-
- // virtual
- bool Recorder::wantsLevel()
- {
- return mWantsLevel;
- }
-
- // virtual
- bool Recorder::wantsLocation()
- {
- return mWantsLocation;
- }
-
- // virtual
- bool Recorder::wantsFunctionName()
- {
- return mWantsFunctionName;
- }
-
- // virtual
- bool Recorder::wantsMultiline()
- {
- return mWantsMultiline;
- }
+ {
+ }
+
+ Recorder::~Recorder()
+ {
+ }
+
+ bool Recorder::wantsTime()
+ {
+ return mWantsTime;
+ }
+
+ // virtual
+ bool Recorder::wantsTags()
+ {
+ return mWantsTags;
+ }
+
+ // virtual
+ bool Recorder::wantsLevel()
+ {
+ return mWantsLevel;
+ }
+
+ // virtual
+ bool Recorder::wantsLocation()
+ {
+ return mWantsLocation;
+ }
+
+ // virtual
+ bool Recorder::wantsFunctionName()
+ {
+ return mWantsFunctionName;
+ }
+
+ // virtual
+ bool Recorder::wantsMultiline()
+ {
+ return mWantsMultiline;
+ }
void Recorder::showTime(bool show)
{
mWantsTime = show;
}
-
+
void Recorder::showTags(bool show)
{
mWantsTags = show;
@@ -1037,28 +1037,28 @@ namespace LLError
mWantsMultiline = show;
}
- void addRecorder(RecorderPtr recorder)
- {
- if (!recorder)
- {
- return;
- }
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- LLMutexLock lock(&s->mRecorderMutex);
- s->mRecorders.push_back(recorder);
- }
-
- void removeRecorder(RecorderPtr recorder)
- {
- if (!recorder)
- {
- return;
- }
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- LLMutexLock lock(&s->mRecorderMutex);
- s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
- s->mRecorders.end());
- }
+ void addRecorder(RecorderPtr recorder)
+ {
+ if (!recorder)
+ {
+ return;
+ }
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLMutexLock lock(&s->mRecorderMutex);
+ s->mRecorders.push_back(recorder);
+ }
+
+ void removeRecorder(RecorderPtr recorder)
+ {
+ if (!recorder)
+ {
+ return;
+ }
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLMutexLock lock(&s->mRecorderMutex);
+ s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
+ s->mRecorders.end());
+ }
// Find an entry in SettingsConfig::mRecorders whose RecorderPtr points to
// a Recorder subclass of type RECORDER. Return, not a RecorderPtr (which
@@ -1127,26 +1127,26 @@ namespace LLError
namespace LLError
{
- void logToFile(const std::string& file_name)
- {
- // remove any previous Recorder filling this role
- removeRecorder<RecordToFile>();
-
- if (!file_name.empty())
- {
- std::shared_ptr<RecordToFile> recordToFile(new RecordToFile(file_name));
- if (recordToFile->okay())
- {
- addRecorder(recordToFile);
- }
- }
- }
-
- std::string logFileName()
- {
- auto found = findRecorder<RecordToFile>();
- return found? found->getFilename() : std::string();
- }
+ void logToFile(const std::string& file_name)
+ {
+ // remove any previous Recorder filling this role
+ removeRecorder<RecordToFile>();
+
+ if (!file_name.empty())
+ {
+ std::shared_ptr<RecordToFile> recordToFile(new RecordToFile(file_name));
+ if (recordToFile->okay())
+ {
+ addRecorder(recordToFile);
+ }
+ }
+ }
+
+ std::string logFileName()
+ {
+ auto found = findRecorder<RecordToFile>();
+ return found? found->getFilename() : std::string();
+ }
void logToStderr()
{
@@ -1157,17 +1157,17 @@ namespace LLError
}
}
- void logToFixedBuffer(LLLineBuffer* fixedBuffer)
- {
- // remove any previous Recorder filling this role
- removeRecorder<RecordToFixedBuffer>();
+ void logToFixedBuffer(LLLineBuffer* fixedBuffer)
+ {
+ // remove any previous Recorder filling this role
+ removeRecorder<RecordToFixedBuffer>();
- if (fixedBuffer)
- {
- RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
- addRecorder(recordToFixedBuffer);
- }
- }
+ if (fixedBuffer)
+ {
+ RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
+ addRecorder(recordToFixedBuffer);
+ }
+ }
}
namespace
@@ -1213,40 +1213,40 @@ namespace
return out.str();
}
- void writeToRecorders(const LLError::CallSite& site, const std::string& message)
- {
+ void writeToRecorders(const LLError::CallSite& site, const std::string& message)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
- LLError::ELevel level = site.mLevel;
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLError::ELevel level = site.mLevel;
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
std::string escaped_message;
LLMutexLock lock(&s->mRecorderMutex);
- for (LLError::RecorderPtr& r : s->mRecorders)
- {
+ for (LLError::RecorderPtr& r : s->mRecorders)
+ {
if (!r->enabled())
{
continue;
}
-
- std::ostringstream message_stream;
- if (r->wantsTime() && s->mTimeFunction != NULL)
- {
- message_stream << s->mTimeFunction();
- }
+ std::ostringstream message_stream;
+
+ if (r->wantsTime() && s->mTimeFunction != NULL)
+ {
+ message_stream << s->mTimeFunction();
+ }
message_stream << " ";
-
- if (r->wantsLevel())
+
+ if (r->wantsLevel())
{
- message_stream << site.mLevelString;
+ message_stream << site.mLevelString;
}
message_stream << " ";
-
- if (r->wantsTags())
- {
- message_stream << site.mTagString;
- }
+
+ if (r->wantsTags())
+ {
+ message_stream << site.mTagString;
+ }
message_stream << " ";
if (r->wantsLocation() || level == LLError::LEVEL_ERROR)
@@ -1255,10 +1255,10 @@ namespace
}
message_stream << " ";
- if (r->wantsFunctionName())
- {
- message_stream << site.mFunctionString;
- }
+ if (r->wantsFunctionName())
+ {
+ message_stream << site.mFunctionString;
+ }
message_stream << " : ";
if (r->wantsMultiline())
@@ -1274,251 +1274,251 @@ namespace
message_stream << escaped_message;
}
- r->recordMessage(level, message_stream.str());
- }
- }
+ r->recordMessage(level, message_stream.str());
+ }
+ }
}
namespace {
- // We need a couple different mutexes, but we want to use the same mechanism
- // for both. Make getMutex() a template function with different instances
- // for different MutexDiscriminator values.
- enum MutexDiscriminator
- {
- LOG_MUTEX,
- STACKS_MUTEX
- };
- // Some logging calls happen very early in processing -- so early that our
- // module-static variables aren't yet initialized. getMutex() wraps a
- // function-static LLMutex so that early calls can still have a valid
- // LLMutex instance.
- template <MutexDiscriminator MTX>
- LLMutex* getMutex()
- {
- // guaranteed to be initialized the first time control reaches here
- static LLMutex sMutex;
- return &sMutex;
- }
-
- bool checkLevelMap(const LevelMap& map, const std::string& key,
- LLError::ELevel& level)
- {
- bool stop_checking;
- LevelMap::const_iterator i = map.find(key);
- if (i == map.end())
- {
- return stop_checking = false;
- }
-
- level = i->second;
- return stop_checking = true;
- }
-
- bool checkLevelMap( const LevelMap& map,
- const char *const * keys,
- size_t count,
- LLError::ELevel& level)
- {
- bool found_level = false;
-
- LLError::ELevel tag_level = LLError::LEVEL_NONE;
-
- for (size_t i = 0; i < count; i++)
- {
- LevelMap::const_iterator it = map.find(keys[i]);
- if (it != map.end())
- {
- found_level = true;
- tag_level = llmin(tag_level, it->second);
- }
- }
-
- if (found_level)
- {
- level = tag_level;
- }
- return found_level;
- }
+ // We need a couple different mutexes, but we want to use the same mechanism
+ // for both. Make getMutex() a template function with different instances
+ // for different MutexDiscriminator values.
+ enum MutexDiscriminator
+ {
+ LOG_MUTEX,
+ STACKS_MUTEX
+ };
+ // Some logging calls happen very early in processing -- so early that our
+ // module-static variables aren't yet initialized. getMutex() wraps a
+ // function-static LLMutex so that early calls can still have a valid
+ // LLMutex instance.
+ template <MutexDiscriminator MTX>
+ LLMutex* getMutex()
+ {
+ // guaranteed to be initialized the first time control reaches here
+ static LLMutex sMutex;
+ return &sMutex;
+ }
+
+ bool checkLevelMap(const LevelMap& map, const std::string& key,
+ LLError::ELevel& level)
+ {
+ bool stop_checking;
+ LevelMap::const_iterator i = map.find(key);
+ if (i == map.end())
+ {
+ return stop_checking = false;
+ }
+
+ level = i->second;
+ return stop_checking = true;
+ }
+
+ bool checkLevelMap( const LevelMap& map,
+ const char *const * keys,
+ size_t count,
+ LLError::ELevel& level)
+ {
+ bool found_level = false;
+
+ LLError::ELevel tag_level = LLError::LEVEL_NONE;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ LevelMap::const_iterator it = map.find(keys[i]);
+ if (it != map.end())
+ {
+ found_level = true;
+ tag_level = llmin(tag_level, it->second);
+ }
+ }
+
+ if (found_level)
+ {
+ level = tag_level;
+ }
+ return found_level;
+ }
}
namespace LLError
{
- bool Log::shouldLog(CallSite& site)
- {
+ bool Log::shouldLog(CallSite& site)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
- LLMutexTrylock lock(getMutex<LOG_MUTEX>(), 5);
- if (!lock.isLocked())
- {
- return false;
- }
-
- Globals *g = Globals::getInstance();
- SettingsConfigPtr s = g->getSettingsConfig();
-
- s->mShouldLogCallCounter++;
-
- const std::string& class_name = className(site.mClassInfo);
- std::string function_name = functionName(site.mFunction);
+ LLMutexTrylock lock(getMutex<LOG_MUTEX>(), 5);
+ if (!lock.isLocked())
+ {
+ return false;
+ }
+
+ Globals *g = Globals::getInstance();
+ SettingsConfigPtr s = g->getSettingsConfig();
+
+ s->mShouldLogCallCounter++;
+
+ const std::string& class_name = className(site.mClassInfo);
+ std::string function_name = functionName(site.mFunction);
#if LL_LINUX
- // gross, but typeid comparison seems to always fail here with gcc4.1
- if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
+ // gross, but typeid comparison seems to always fail here with gcc4.1
+ if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
#else
- if (site.mClassInfo != typeid(NoClassInfo))
+ if (site.mClassInfo != typeid(NoClassInfo))
#endif // LL_LINUX
- {
- function_name = class_name + "::" + function_name;
- }
-
- ELevel compareLevel = s->mDefaultLevel;
-
- // The most specific match found will be used as the log level,
- // since the computation short circuits.
- // So, in increasing order of importance:
- // Default < Tags < File < Class < Function
- checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel)
- || checkLevelMap(s->mClassLevelMap, class_name, compareLevel)
- || checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
- || (site.mTagCount > 0
- ? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel)
- : false);
-
- site.mCached = true;
- g->addCallSite(site);
- return site.mShouldLog = site.mLevel >= compareLevel;
- }
-
-
- void Log::flush(const std::ostringstream& out, const CallSite& site)
- {
+ {
+ function_name = class_name + "::" + function_name;
+ }
+
+ ELevel compareLevel = s->mDefaultLevel;
+
+ // The most specific match found will be used as the log level,
+ // since the computation short circuits.
+ // So, in increasing order of importance:
+ // Default < Tags < File < Class < Function
+ checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel)
+ || checkLevelMap(s->mClassLevelMap, class_name, compareLevel)
+ || checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+ || (site.mTagCount > 0
+ ? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel)
+ : false);
+
+ site.mCached = true;
+ g->addCallSite(site);
+ return site.mShouldLog = site.mLevel >= compareLevel;
+ }
+
+
+ void Log::flush(const std::ostringstream& out, const CallSite& site)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
- LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
- if (!lock.isLocked())
- {
- return;
- }
-
- Globals* g = Globals::getInstance();
- SettingsConfigPtr s = g->getSettingsConfig();
-
- std::string message = out.str();
-
- if (site.mPrintOnce)
- {
- std::ostringstream message_stream;
-
- std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
- if (messageIter != s->mUniqueLogMessages.end())
- {
- messageIter->second++;
- unsigned int num_messages = messageIter->second;
- if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0)
- {
- message_stream << "ONCE (" << num_messages << "th time seen): ";
- }
- else
- {
- return;
- }
- }
- else
- {
- message_stream << "ONCE: ";
- s->mUniqueLogMessages[message] = 1;
- }
- message_stream << message;
- message = message_stream.str();
- }
-
- writeToRecorders(site, message);
-
- if (site.mLevel == LEVEL_ERROR)
- {
- writeToRecorders(site, stringize(boost::stacktrace::stacktrace()));
- g->mFatalMessage = message;
- if (s->mCrashFunction)
- {
- s->mCrashFunction(message);
- }
- }
- }
+ LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
+ if (!lock.isLocked())
+ {
+ return;
+ }
+
+ Globals* g = Globals::getInstance();
+ SettingsConfigPtr s = g->getSettingsConfig();
+
+ std::string message = out.str();
+
+ if (site.mPrintOnce)
+ {
+ std::ostringstream message_stream;
+
+ std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
+ if (messageIter != s->mUniqueLogMessages.end())
+ {
+ messageIter->second++;
+ unsigned int num_messages = messageIter->second;
+ if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0)
+ {
+ message_stream << "ONCE (" << num_messages << "th time seen): ";
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ message_stream << "ONCE: ";
+ s->mUniqueLogMessages[message] = 1;
+ }
+ message_stream << message;
+ message = message_stream.str();
+ }
+
+ writeToRecorders(site, message);
+
+ if (site.mLevel == LEVEL_ERROR)
+ {
+ writeToRecorders(site, stringize(boost::stacktrace::stacktrace()));
+ g->mFatalMessage = message;
+ if (s->mCrashFunction)
+ {
+ s->mCrashFunction(message);
+ }
+ }
+ }
}
namespace LLError
{
- SettingsStoragePtr saveAndResetSettings()
- {
- return Globals::getInstance()->saveAndResetSettingsConfig();
- }
-
- void restoreSettings(SettingsStoragePtr pSettingsStorage)
- {
- return Globals::getInstance()->restore(pSettingsStorage);
- }
-
- std::string removePrefix(std::string& s, const std::string& p)
- {
- std::string::size_type where = s.find(p);
- if (where == std::string::npos)
- {
- return s;
- }
-
- return std::string(s, where + p.size());
- }
-
- void replaceChar(std::string& s, char old, char replacement)
- {
- std::string::size_type i = 0;
- std::string::size_type len = s.length();
- for ( ; i < len; i++ )
- {
- if (s[i] == old)
- {
- s[i] = replacement;
- }
- }
- }
-
- std::string abbreviateFile(const std::string& filePath)
- {
- std::string f = filePath;
+ SettingsStoragePtr saveAndResetSettings()
+ {
+ return Globals::getInstance()->saveAndResetSettingsConfig();
+ }
+
+ void restoreSettings(SettingsStoragePtr pSettingsStorage)
+ {
+ return Globals::getInstance()->restore(pSettingsStorage);
+ }
+
+ std::string removePrefix(std::string& s, const std::string& p)
+ {
+ std::string::size_type where = s.find(p);
+ if (where == std::string::npos)
+ {
+ return s;
+ }
+
+ return std::string(s, where + p.size());
+ }
+
+ void replaceChar(std::string& s, char old, char replacement)
+ {
+ std::string::size_type i = 0;
+ std::string::size_type len = s.length();
+ for ( ; i < len; i++ )
+ {
+ if (s[i] == old)
+ {
+ s[i] = replacement;
+ }
+ }
+ }
+
+ std::string abbreviateFile(const std::string& filePath)
+ {
+ std::string f = filePath;
#if LL_WINDOWS
- replaceChar(f, '\\', '/');
+ replaceChar(f, '\\', '/');
#endif
- static std::string indra_prefix = "indra/";
- f = removePrefix(f, indra_prefix);
+ static std::string indra_prefix = "indra/";
+ f = removePrefix(f, indra_prefix);
#if LL_DARWIN
- static std::string newview_prefix = "newview/../";
- f = removePrefix(f, newview_prefix);
+ static std::string newview_prefix = "newview/../";
+ f = removePrefix(f, newview_prefix);
#endif
- return f;
- }
-
- int shouldLogCallCount()
- {
- SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
- return s->mShouldLogCallCounter;
- }
-
- std::string utcTime()
- {
- time_t now = time(NULL);
- const size_t BUF_SIZE = 64;
- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
-
- auto chars = strftime(time_str, BUF_SIZE,
- "%Y-%m-%dT%H:%M:%SZ",
- gmtime(&now));
-
- return chars ? time_str : "time error";
- }
+ return f;
+ }
+
+ int shouldLogCallCount()
+ {
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ return s->mShouldLogCallCounter;
+ }
+
+ std::string utcTime()
+ {
+ time_t now = time(NULL);
+ const size_t BUF_SIZE = 64;
+ char time_str[BUF_SIZE]; /* Flawfinder: ignore */
+
+ auto chars = strftime(time_str, BUF_SIZE,
+ "%Y-%m-%dT%H:%M:%SZ",
+ gmtime(&now));
+
+ return chars ? time_str : "time error";
+ }
}
namespace LLError
-{
+{
LLCallStacks::StringVector LLCallStacks::sBuffer ;
//static
@@ -1577,7 +1577,7 @@ namespace LLError
LL_INFOS() << " ************* PRINT OUT LL CALL STACKS ************* " << LL_ENDL;
for (StringVector::const_reverse_iterator ri(sBuffer.rbegin()), re(sBuffer.rend());
ri != re; ++ri)
- {
+ {
LL_INFOS() << (*ri) << LL_ENDL;
}
LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 2cc1f91408..d0686bd8b5 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -6,25 +6,25 @@
* https://wiki.lindenlab.com/wiki/Viewer:Messaging/Event_System,
* originally introduced in llnotifications.h. It has nothing
* whatsoever to do with the older system in llevent.h.
- *
+ *
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -39,13 +39,13 @@
#include <deque>
#include <functional>
#if LL_WINDOWS
- #pragma warning (push)
- #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
- #pragma warning (disable : 4264)
+ #pragma warning (push)
+ #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
+ #pragma warning (disable : 4264)
#endif
#include <boost/signals2.hpp>
#if LL_WINDOWS
- #pragma warning (pop)
+ #pragma warning (pop)
#endif
#include <boost/optional/optional.hpp>
@@ -290,9 +290,9 @@ public:
/**
* Find the named LLEventPump instance. If it exists post the message to it.
* If the pump does not exist, do nothing.
- *
+ *
* returns the result of the LLEventPump::post. If no pump exists returns false.
- *
+ *
* This is syntactically similar to LLEventPumps::instance().post(name, message),
* however if the pump does not already exist it will not be created.
*/
@@ -521,10 +521,10 @@ public:
* instantiate your listener, then passing the same name on each listen()
* call, allows us to optimize away the second and subsequent dependency
* sorts.
- *
- * If name is set to LLEventPump::ANONYMOUS listen will bypass the entire
- * dependency and ordering calculation. In this case, it is critical that
- * the result be assigned to a LLTempBoundListener or the listener is
+ *
+ * If name is set to LLEventPump::ANONYMOUS listen will bypass the entire
+ * dependency and ordering calculation. In this case, it is critical that
+ * the result be assigned to a LLTempBoundListener or the listener is
* manually disconnected when no longer needed since there will be no
* way to later find and disconnect this listener manually.
*/
@@ -582,7 +582,7 @@ protected:
virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
const NameList& after,
const NameList& before);
-
+
/// implement the dispatching
std::shared_ptr<LLStandardSignal> mSignal;
@@ -635,21 +635,21 @@ public:
* by all listeners, until some listener consumes it. The caveat is that each
* event *must* eventually reach a listener that will consume it, else the
* queue will grow to arbitrary length.
- *
+ *
* @NOTE: When using an LLEventMailDrop with an LLEventTimeout or
* LLEventFilter attaching the filter downstream, using Timeout's constructor will
- * cause the MailDrop to discharge any of its stored events. The timeout should
- * instead be connected upstream using its listen() method.
+ * cause the MailDrop to discharge any of its stored events. The timeout should
+ * instead be connected upstream using its listen() method.
*/
class LL_COMMON_API LLEventMailDrop : public LLEventStream
{
public:
LLEventMailDrop(const std::string& name, bool tweak = false) : LLEventStream(name, tweak) {}
virtual ~LLEventMailDrop() {}
-
+
/// Post an event to all listeners
virtual bool post(const LLSD& event) override;
-
+
/// Remove any history stored in the mail drop.
void discard();
diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp
index 43c1a255ac..cc227193cd 100644
--- a/indra/llcommon/lleventtimer.cpp
+++ b/indra/llcommon/lleventtimer.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lleventtimer.cpp
- * @brief Cross-platform objects for doing timing
+ * @brief Cross-platform objects for doing timing
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,7 +29,7 @@
//////////////////////////////////////////////////////////////////////////////
//
-// LLEventTimer Implementation
+// LLEventTimer Implementation
//
//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h
index a325c704e0..b37d682d29 100644
--- a/indra/llcommon/lleventtimer.h
+++ b/indra/llcommon/lleventtimer.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lleventtimer.h
- * @brief Cross-platform objects for doing timing
+ * @brief Cross-platform objects for doing timing
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,22 +36,22 @@ class LL_COMMON_API LLEventTimer
{
public:
- LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
- LLEventTimer(const LLDate& time);
- virtual ~LLEventTimer();
+ LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
+ LLEventTimer(const LLDate& time);
+ virtual ~LLEventTimer();
- void start();
- void stop();
- bool isRunning();
- F32 getRemaining();
+ void start();
+ void stop();
+ bool isRunning();
+ F32 getRemaining();
- //function to be called at the supplied frequency
- // Normally return false; true will delete the timer after the function returns.
- virtual bool tick() = 0;
+ //function to be called at the supplied frequency
+ // Normally return false; true will delete the timer after the function returns.
+ virtual bool tick() = 0;
protected:
- LL::Timers::temp_handle_t mTimer;
- F32 mPeriod;
+ LL::Timers::temp_handle_t mTimer;
+ F32 mPeriod;
};
#endif //LL_EVENTTIMER_H
diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp
index 692a21c1f1..774d70eb31 100644
--- a/indra/llcommon/lllivefile.cpp
+++ b/indra/llcommon/lllivefile.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file lllivefile.cpp
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,51 +35,51 @@ const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f;
class LLLiveFile::Impl
{
public:
- Impl(const std::string& filename, const F32 refresh_period);
- ~Impl();
-
- bool check();
- void changed();
-
- bool mForceCheck;
- F32 mRefreshPeriod;
- LLFrameTimer mRefreshTimer;
-
- std::string mFilename;
- time_t mLastModTime;
- time_t mLastStatTime;
- bool mLastExists;
-
- LLEventTimer* mEventTimer;
+ Impl(const std::string& filename, const F32 refresh_period);
+ ~Impl();
+
+ bool check();
+ void changed();
+
+ bool mForceCheck;
+ F32 mRefreshPeriod;
+ LLFrameTimer mRefreshTimer;
+
+ std::string mFilename;
+ time_t mLastModTime;
+ time_t mLastStatTime;
+ bool mLastExists;
+
+ LLEventTimer* mEventTimer;
private:
LOG_CLASS(LLLiveFile);
};
LLLiveFile::Impl::Impl(const std::string& filename, const F32 refresh_period)
- :
- mForceCheck(true),
- mRefreshPeriod(refresh_period),
- mFilename(filename),
- mLastModTime(0),
- mLastStatTime(0),
- mLastExists(false),
- mEventTimer(NULL)
+ :
+ mForceCheck(true),
+ mRefreshPeriod(refresh_period),
+ mFilename(filename),
+ mLastModTime(0),
+ mLastStatTime(0),
+ mLastExists(false),
+ mEventTimer(NULL)
{
}
LLLiveFile::Impl::~Impl()
{
- delete mEventTimer;
+ delete mEventTimer;
}
LLLiveFile::LLLiveFile(const std::string& filename, const F32 refresh_period)
- : impl(* new Impl(filename, refresh_period))
+ : impl(* new Impl(filename, refresh_period))
{
}
LLLiveFile::~LLLiveFile()
{
- delete &impl;
+ delete &impl;
}
@@ -88,8 +88,8 @@ bool LLLiveFile::Impl::check()
bool detected_change = false;
// Skip the check if not enough time has elapsed and we're not
// forcing a check of the file
- if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod)
- {
+ if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod)
+ {
mForceCheck = false; // force only forces one check
mRefreshTimer.reset(); // don't check again until mRefreshPeriod has passed
@@ -98,11 +98,11 @@ bool LLLiveFile::Impl::check()
if (LLFile::stat(mFilename, &stat_data))
{
// Couldn't stat the file, that means it doesn't exist or is
- // broken somehow.
+ // broken somehow.
if (mLastExists)
{
mLastExists = false;
- detected_change = true; // no longer existing is a change!
+ detected_change = true; // no longer existing is a change!
LL_DEBUGS() << "detected deleted file '" << mFilename << "'" << LL_ENDL;
}
}
@@ -134,65 +134,65 @@ bool LLLiveFile::Impl::check()
void LLLiveFile::Impl::changed()
{
- // we wanted to read this file, and we were successful.
- mLastModTime = mLastStatTime;
+ // we wanted to read this file, and we were successful.
+ mLastModTime = mLastStatTime;
}
bool LLLiveFile::checkAndReload()
{
- bool changed = impl.check();
- if (changed)
- {
- if(loadFile())
- {
- impl.changed();
- this->changed();
- }
- else
- {
- changed = false;
- }
- }
- return changed;
+ bool changed = impl.check();
+ if (changed)
+ {
+ if(loadFile())
+ {
+ impl.changed();
+ this->changed();
+ }
+ else
+ {
+ changed = false;
+ }
+ }
+ return changed;
}
std::string LLLiveFile::filename() const
{
- return impl.mFilename;
+ return impl.mFilename;
}
namespace
{
- class LiveFileEventTimer : public LLEventTimer
- {
- public:
- LiveFileEventTimer(LLLiveFile& f, F32 refresh)
- : LLEventTimer(refresh), mLiveFile(f)
- { }
-
- bool tick() override
- {
- mLiveFile.checkAndReload();
- return FALSE;
- }
-
- private:
- LLLiveFile& mLiveFile;
- };
-
+ class LiveFileEventTimer : public LLEventTimer
+ {
+ public:
+ LiveFileEventTimer(LLLiveFile& f, F32 refresh)
+ : LLEventTimer(refresh), mLiveFile(f)
+ { }
+
+ bool tick() override
+ {
+ mLiveFile.checkAndReload();
+ return FALSE;
+ }
+
+ private:
+ LLLiveFile& mLiveFile;
+ };
+
}
void LLLiveFile::addToEventTimer()
{
- impl.mEventTimer = new LiveFileEventTimer(*this, impl.mRefreshPeriod);
+ impl.mEventTimer = new LiveFileEventTimer(*this, impl.mRefreshPeriod);
}
void LLLiveFile::setRefreshPeriod(F32 seconds)
{
- if (seconds < 0.f)
- {
- seconds = -seconds;
- }
- impl.mRefreshPeriod = seconds;
+ if (seconds < 0.f)
+ {
+ seconds = -seconds;
+ }
+ impl.mRefreshPeriod = seconds;
}
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 5789b5de2c..7ac080b5d6 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrefcount.h
* @brief Base class for reference counted objects for use with LLPointer
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -45,42 +45,42 @@ extern const S32 gMaxRefCount;
class LL_COMMON_API LLRefCount
{
protected:
- LLRefCount(const LLRefCount& other);
- LLRefCount& operator=(const LLRefCount&);
- virtual ~LLRefCount(); // use unref()
-
+ LLRefCount(const LLRefCount& other);
+ LLRefCount& operator=(const LLRefCount&);
+ virtual ~LLRefCount(); // use unref()
+
public:
- LLRefCount();
-
- inline void ref() const
- {
- llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
- mRef++;
- llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
- }
-
- inline S32 unref() const
- {
- llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
- llassert(mRef > 0); // ref count below 1, likely corrupted
- if (0 == --mRef)
- {
- mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging
- delete this;
- return 0;
- }
- return mRef;
- }
-
- //NOTE: when passing around a const LLRefCount object, this can return different results
- // at different types, since mRef is mutable
- S32 getNumRefs() const
- {
- return mRef;
- }
+ LLRefCount();
+
+ inline void ref() const
+ {
+ llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
+ mRef++;
+ llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
+ }
+
+ inline S32 unref() const
+ {
+ llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
+ llassert(mRef > 0); // ref count below 1, likely corrupted
+ if (0 == --mRef)
+ {
+ mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging
+ delete this;
+ return 0;
+ }
+ return mRef;
+ }
+
+ //NOTE: when passing around a const LLRefCount object, this can return different results
+ // at different types, since mRef is mutable
+ S32 getNumRefs() const
+ {
+ return mRef;
+ }
private:
- mutable S32 mRef;
+ mutable S32 mRef;
};
@@ -91,50 +91,50 @@ private:
class LL_COMMON_API LLThreadSafeRefCount
{
public:
- static void initThreadSafeRefCount(); // creates sMutex
- static void cleanupThreadSafeRefCount(); // destroys sMutex
+ static void initThreadSafeRefCount(); // creates sMutex
+ static void cleanupThreadSafeRefCount(); // destroys sMutex
private:
- static LLMutex* sMutex;
+ static LLMutex* sMutex;
protected:
- virtual ~LLThreadSafeRefCount(); // use unref()
+ virtual ~LLThreadSafeRefCount(); // use unref()
public:
- LLThreadSafeRefCount();
- LLThreadSafeRefCount(const LLThreadSafeRefCount&);
- LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
- {
- mRef = 0;
- return *this;
- }
-
- void ref()
- {
- mRef++;
- }
-
- void unref()
- {
- llassert(mRef >= 1);
- if ((--mRef) == 0)
- {
- // If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
- // It is technically possible for a vanilla pointer to mess this up, or another thread to
- // jump in, find this object, create another smart pointer and end up dangling, but if
- // the code is that bad and not thread-safe, it's trouble already.
- delete this;
- }
- }
-
- S32 getNumRefs() const
- {
- const S32 currentVal = mRef.CurrentValue();
- return currentVal;
- }
+ LLThreadSafeRefCount();
+ LLThreadSafeRefCount(const LLThreadSafeRefCount&);
+ LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
+ {
+ mRef = 0;
+ return *this;
+ }
+
+ void ref()
+ {
+ mRef++;
+ }
+
+ void unref()
+ {
+ llassert(mRef >= 1);
+ if ((--mRef) == 0)
+ {
+ // If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
+ // It is technically possible for a vanilla pointer to mess this up, or another thread to
+ // jump in, find this object, create another smart pointer and end up dangling, but if
+ // the code is that bad and not thread-safe, it's trouble already.
+ delete this;
+ }
+ }
+
+ S32 getNumRefs() const
+ {
+ const S32 currentVal = mRef.CurrentValue();
+ return currentVal;
+ }
private:
- LLAtomicS32 mRef;
+ LLAtomicS32 mRef;
};
/**
@@ -143,12 +143,12 @@ private:
*/
inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)
{
- p->ref();
+ p->ref();
}
inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
{
- p->unref();
+ p->unref();
}
/**
@@ -157,12 +157,12 @@ inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
*/
inline void intrusive_ptr_add_ref(LLRefCount* p)
{
- p->ref();
+ p->ref();
}
inline void intrusive_ptr_release(LLRefCount* p)
{
- p->unref();
+ p->unref();
}
#endif
diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h
index d85a704376..15e47d6c89 100644
--- a/indra/llcommon/llrun.h
+++ b/indra/llcommon/llrun.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llrun.h
* @author Phoenix
* @date 2006-02-16
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -45,7 +45,7 @@ class LLRunnable;
// LLDeferredChain isn't referenced at all.
//////////////////////////////////////////////////////////////////////////////
-/**
+/**
* @class LLRunner
* @brief This class manages a set of LLRunnable objects.
*
@@ -56,96 +56,96 @@ class LLRunnable;
class LL_COMMON_API LLRunner
{
public:
- /**
- * @brief The pointer to a runnable.
- */
- typedef std::shared_ptr<LLRunnable> run_ptr_t;
-
- /**
- * @brief The handle for use in the API.
- */
- typedef S64 run_handle_t;
-
- /**
- * @brief Constructor.
- */
- LLRunner();
-
- /**
- * @brief Destructor.
- */
- ~LLRunner();
-
- /**
- * @brief Enumeration which specifies when to run.
- */
- enum ERunSchedule
- {
- // The runnable will run in N seconds
- RUN_IN,
-
- // The run every N seconds
- RUN_EVERY,
-
- // A count of the run types
- RUN_SCHEDULE_COUNT
- };
-
- /**
- * @brief Run the runnables which are scheduled to run
- *
- * @return Returns the number of runnables run.
- */
- size_t run();
-
- /**
- * @brief Add a runnable to the run list.
- *
- * The handle of the runnable is unique to each addition. If the
- * same runnable is added a second time with the same or different
- * schedule, this method will return a new handle.
- * @param runnable The runnable to run() on schedule.
- * @param schedule Specifies the run schedule.
- * @param seconds When to run the runnable as interpreted by schedule.
- * @return Returns the handle to the runnable. handle == 0 means failure.
- */
- run_handle_t addRunnable(
- run_ptr_t runnable,
- ERunSchedule schedule,
- F64 seconds);
-
- /**
- * @brief Remove the specified runnable.
- *
- * @param handle The handle of the runnable to remove.
- * @return Returns the pointer to the runnable removed which may
- * be empty.
- */
- run_ptr_t removeRunnable(run_handle_t handle);
+ /**
+ * @brief The pointer to a runnable.
+ */
+ typedef std::shared_ptr<LLRunnable> run_ptr_t;
+
+ /**
+ * @brief The handle for use in the API.
+ */
+ typedef S64 run_handle_t;
+
+ /**
+ * @brief Constructor.
+ */
+ LLRunner();
+
+ /**
+ * @brief Destructor.
+ */
+ ~LLRunner();
+
+ /**
+ * @brief Enumeration which specifies when to run.
+ */
+ enum ERunSchedule
+ {
+ // The runnable will run in N seconds
+ RUN_IN,
+
+ // The run every N seconds
+ RUN_EVERY,
+
+ // A count of the run types
+ RUN_SCHEDULE_COUNT
+ };
+
+ /**
+ * @brief Run the runnables which are scheduled to run
+ *
+ * @return Returns the number of runnables run.
+ */
+ size_t run();
+
+ /**
+ * @brief Add a runnable to the run list.
+ *
+ * The handle of the runnable is unique to each addition. If the
+ * same runnable is added a second time with the same or different
+ * schedule, this method will return a new handle.
+ * @param runnable The runnable to run() on schedule.
+ * @param schedule Specifies the run schedule.
+ * @param seconds When to run the runnable as interpreted by schedule.
+ * @return Returns the handle to the runnable. handle == 0 means failure.
+ */
+ run_handle_t addRunnable(
+ run_ptr_t runnable,
+ ERunSchedule schedule,
+ F64 seconds);
+
+ /**
+ * @brief Remove the specified runnable.
+ *
+ * @param handle The handle of the runnable to remove.
+ * @return Returns the pointer to the runnable removed which may
+ * be empty.
+ */
+ run_ptr_t removeRunnable(run_handle_t handle);
protected:
- struct LLRunInfo
- {
- run_handle_t mHandle;
- run_ptr_t mRunnable;
- ERunSchedule mSchedule;
- F64 mNextRunAt;
- F64 mIncrement;
- LLRunInfo(
- run_handle_t handle,
- run_ptr_t runnable,
- ERunSchedule schedule,
- F64 next_run_at,
- F64 increment);
- };
- typedef std::vector<LLRunInfo> run_list_t;
- run_list_t mRunOnce;
- run_list_t mRunEvery;
- run_handle_t mNextHandle;
+ struct LLRunInfo
+ {
+ run_handle_t mHandle;
+ run_ptr_t mRunnable;
+ ERunSchedule mSchedule;
+ F64 mNextRunAt;
+ F64 mIncrement;
+ LLRunInfo(
+ run_handle_t handle,
+ run_ptr_t runnable,
+ ERunSchedule schedule,
+ F64 next_run_at,
+ F64 increment);
+ };
+ typedef std::vector<LLRunInfo> run_list_t;
+ run_list_t mRunOnce;
+ run_list_t mRunEvery;
+ run_handle_t mNextHandle;
};
-/**
+/**
* @class LLRunnable
* @brief Abstract base class for running some scheduled process.
*
@@ -157,17 +157,17 @@ protected:
class LL_COMMON_API LLRunnable
{
public:
- LLRunnable();
- virtual ~LLRunnable();
-
- /**
- * @brief Do the process.
- *
- * This method will be called from the LLRunner according to
- * @param runner The Runner which call run().
- * @param handle The handle this run instance is run under.
- */
- virtual void run(LLRunner* runner, S64 handle) = 0;
+ LLRunnable();
+ virtual ~LLRunnable();
+
+ /**
+ * @brief Do the process.
+ *
+ * This method will be called from the LLRunner according to
+ * @param runner The Runner which call run().
+ * @param handle The handle this run instance is run under.
+ */
+ virtual void run(LLRunner* runner, S64 handle) = 0;
};
#endif // LL_LLRUN_H
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 9478dff871..196fd1eea8 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstring.h
* @brief String utility functions and std::string class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -61,85 +61,85 @@ 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)
+ 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; }
};
};
@@ -148,72 +148,72 @@ struct char_traits<U16>
class LL_COMMON_API LLStringOps
{
private:
- static long sPacificTimeOffset;
- static long sLocalTimeOffset;
- static bool sPacificDaylightTime;
+ static long sPacificTimeOffset;
+ static long sLocalTimeOffset;
+ static bool sPacificDaylightTime;
- static std::map<std::string, std::string> datetimeToCodes;
+ static std::map<std::string, std::string> datetimeToCodes;
public:
- static std::vector<std::string> sWeekDayList;
- static std::vector<std::string> sWeekDayShortList;
- static std::vector<std::string> sMonthList;
- static std::vector<std::string> sMonthShortList;
- static std::string sDayFormat;
+ static std::vector<std::string> sWeekDayList;
+ static std::vector<std::string> sWeekDayShortList;
+ static std::vector<std::string> sMonthList;
+ static std::vector<std::string> sMonthShortList;
+ static std::string sDayFormat;
- static std::string sAM;
- static std::string sPM;
+ static std::string sAM;
+ static std::string sPM;
- static char toUpper(char elem) { return toupper((unsigned char)elem); }
- static llwchar toUpper(llwchar elem) { return towupper(elem); }
-
- static char toLower(char elem) { return tolower((unsigned char)elem); }
- static llwchar toLower(llwchar elem) { return towlower(elem); }
+ static char toUpper(char elem) { return toupper((unsigned char)elem); }
+ static llwchar toUpper(llwchar elem) { return towupper(elem); }
- static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
- static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
+ static char toLower(char elem) { return tolower((unsigned char)elem); }
+ static llwchar toLower(llwchar elem) { return towlower(elem); }
- static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
- static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
+ static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
+ static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
- static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
- static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
+ static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
+ static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
- static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
- static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
+ static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
+ static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
- static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
- static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
+ static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
+ static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
- static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; }
- static bool isAlpha(llwchar a) { return iswalpha(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 bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; }
+ static bool isAlpha(llwchar a) { return iswalpha(a) != 0; }
- static bool isEmoji(llwchar wch);
+ 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 bool isEmoji(llwchar wch);
- static void setupDatetimeInfo(bool pacific_daylight_time);
+ static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
+ static S32 collate(const llwchar* a, const llwchar* b);
- static void setupWeekDaysNames(const std::string& data);
- static void setupWeekDaysShortNames(const std::string& data);
- static void setupMonthNames(const std::string& data);
- static void setupMonthShortNames(const std::string& data);
- static void setupDayFormat(const std::string& data);
+ static void setupDatetimeInfo(bool pacific_daylight_time);
+ static void setupWeekDaysNames(const std::string& data);
+ static void setupWeekDaysShortNames(const std::string& data);
+ static void setupMonthNames(const std::string& data);
+ static void setupMonthShortNames(const std::string& data);
+ static void setupDayFormat(const std::string& data);
- static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
- static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
- // Is the Pacific time zone (aka server time zone)
- // currently in daylight savings time?
- static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
- static std::string getDatetimeCode (std::string key);
+ 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;}
- // Express a value like 1234567 as "1.23M"
+ static std::string getDatetimeCode (std::string key);
+
+ // Express a value like 1234567 as "1.23M"
static std::string getReadableNumber(F64 num);
};
@@ -230,216 +230,216 @@ LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
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(); }
-
+ 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;
+ std::string mString;
};
template <class T>
class LLStringUtilBase
{
private:
- static std::string sLocale;
+ static std::string sLocale;
public:
- typedef std::basic_string<T> string_type;
- typedef typename string_type::size_type size_type;
-
+ typedef std::basic_string<T> string_type;
+ typedef typename string_type::size_type size_type;
+
public:
- /////////////////////////////////////////////////////////////////////////////////////////
- // Static Utility functions that operate on std::strings
-
- static const string_type null;
-
- typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
- /// considers any sequence of delims as a single field separator
- LL_COMMON_API static void getTokens(const string_type& instr,
- std::vector<string_type >& tokens,
- const string_type& delims);
- /// like simple scan overload, but returns scanned vector
- static std::vector<string_type> getTokens(const string_type& instr,
- const string_type& delims);
- /// add support for keep_delims and quotes (either could be empty string)
- static void getTokens(const string_type& instr,
- std::vector<string_type>& tokens,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes=string_type());
- /// like keep_delims-and-quotes overload, but returns scanned vector
- static std::vector<string_type> getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes=string_type());
- /// add support for escapes (could be empty string)
- static void getTokens(const string_type& instr,
- std::vector<string_type>& tokens,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes,
- const string_type& escapes);
- /// like escapes overload, but returns scanned vector
- static std::vector<string_type> getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes,
- const string_type& escapes);
-
- LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
- LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
- LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions);
- LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions);
- LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions);
- LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions);
- LL_COMMON_API static void setLocale (std::string inLocale);
- LL_COMMON_API static std::string getLocale (void);
-
- static bool isValidIndex(const string_type& string, size_type i)
- {
- return !string.empty() && (0 <= i) && (i <= string.size());
- }
-
- static bool contains(const string_type& string, T c, size_type i=0)
- {
- return string.find(c, i) != string_type::npos;
- }
-
- static void trimHead(string_type& string);
- static void trimTail(string_type& string);
- static void trim(string_type& string) { trimHead(string); trimTail(string); }
- static void truncate(string_type& string, size_type count);
-
- static void toUpper(string_type& string);
- static void toLower(string_type& string);
-
- // True if this is the head of s.
- static BOOL isHead( const string_type& 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 string_type& string,
- const string_type& substr);
-
- /**
- * @brief Returns true if string ends in substr
- *
- * If etither string or substr are empty, this method returns false.
- */
- static bool endsWith(
- const string_type& string,
- const string_type& substr);
-
- /**
- * get environment string value with proper Unicode handling
- * (key is always UTF-8)
- * detect absence by return value == dflt
- */
- static string_type getenv(const std::string& key, const string_type& dflt="");
- /**
- * get optional environment string value with proper Unicode handling
- * (key is always UTF-8)
- * detect absence by (! return value)
- */
- static boost::optional<string_type> getoptenv(const std::string& key);
-
- static void addCRLF(string_type& string);
- static void removeCRLF(string_type& string);
- static void removeWindowsCR(string_type& string);
-
- static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab );
- static void replaceNonstandardASCII( string_type& string, T replacement );
- static void replaceChar( string_type& string, T target, T replacement );
- static void replaceString( string_type& string, string_type target, string_type replacement );
- static string_type capitalize(const string_type& str);
- static void capitalize(string_type& str);
-
- static BOOL containsNonprintable(const string_type& string);
- static void stripNonprintable(string_type& string);
-
- /**
- * Double-quote an argument string if needed, unless it's already
- * double-quoted. Decide whether it's needed based on the presence of any
- * character in @a triggers (default space or double-quote). If we quote
- * it, escape any embedded double-quote with the @a escape string (default
- * backslash).
- *
- * Passing triggers="" means always quote, unless it's already double-quoted.
- */
- static string_type quote(const string_type& str,
- const string_type& triggers=" \"",
- const string_type& escape="\\");
-
- /**
- * @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(string_type& string);
-
- // Conversion to other data types
- static BOOL convertToBOOL(const string_type& string, BOOL& value);
- static BOOL convertToU8(const string_type& string, U8& value);
- static BOOL convertToS8(const string_type& string, S8& value);
- static BOOL convertToS16(const string_type& string, S16& value);
- static BOOL convertToU16(const string_type& string, U16& value);
- static BOOL convertToU32(const string_type& string, U32& value);
- static BOOL convertToS32(const string_type& string, S32& value);
- static BOOL convertToF32(const string_type& string, F32& value);
- static BOOL convertToF64(const string_type& 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 string_type& lhs, const string_type& 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 string_type& lhs, const string_type& rhs);
-
- // Case sensitive comparison with good handling of numbers. Does not use current locale.
- // a.k.a. strdictcmp()
- static S32 compareDict(const string_type& a, const string_type& b);
-
- // Case *in*sensitive comparison with good handling of numbers. Does not use current locale.
- // a.k.a. strdictcmp()
- static S32 compareDictInsensitive(const string_type& a, const string_type& b);
-
- // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
- static BOOL precedesDict( const string_type& a, const string_type& 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(string_type& dst, const string_type& src, size_type offset);
-
- static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
-
-
-#ifdef _DEBUG
- LL_COMMON_API static void testHarness();
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Static Utility functions that operate on std::strings
+
+ static const string_type null;
+
+ typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
+ /// considers any sequence of delims as a single field separator
+ LL_COMMON_API static void getTokens(const string_type& instr,
+ std::vector<string_type >& tokens,
+ const string_type& delims);
+ /// like simple scan overload, but returns scanned vector
+ static std::vector<string_type> getTokens(const string_type& instr,
+ const string_type& delims);
+ /// add support for keep_delims and quotes (either could be empty string)
+ static void getTokens(const string_type& instr,
+ std::vector<string_type>& tokens,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes=string_type());
+ /// like keep_delims-and-quotes overload, but returns scanned vector
+ static std::vector<string_type> getTokens(const string_type& instr,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes=string_type());
+ /// add support for escapes (could be empty string)
+ static void getTokens(const string_type& instr,
+ std::vector<string_type>& tokens,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes,
+ const string_type& escapes);
+ /// like escapes overload, but returns scanned vector
+ static std::vector<string_type> getTokens(const string_type& instr,
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes,
+ const string_type& escapes);
+
+ LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals);
+ LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch);
+ LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions);
+ LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions);
+ LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions);
+ LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions);
+ LL_COMMON_API static void setLocale (std::string inLocale);
+ LL_COMMON_API static std::string getLocale (void);
+
+ static bool isValidIndex(const string_type& string, size_type i)
+ {
+ return !string.empty() && (0 <= i) && (i <= string.size());
+ }
+
+ static bool contains(const string_type& string, T c, size_type i=0)
+ {
+ return string.find(c, i) != string_type::npos;
+ }
+
+ static void trimHead(string_type& string);
+ static void trimTail(string_type& string);
+ static void trim(string_type& string) { trimHead(string); trimTail(string); }
+ static void truncate(string_type& string, size_type count);
+
+ static void toUpper(string_type& string);
+ static void toLower(string_type& string);
+
+ // True if this is the head of s.
+ static BOOL isHead( const string_type& 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 string_type& string,
+ const string_type& substr);
+
+ /**
+ * @brief Returns true if string ends in substr
+ *
+ * If etither string or substr are empty, this method returns false.
+ */
+ static bool endsWith(
+ const string_type& string,
+ const string_type& substr);
+
+ /**
+ * get environment string value with proper Unicode handling
+ * (key is always UTF-8)
+ * detect absence by return value == dflt
+ */
+ static string_type getenv(const std::string& key, const string_type& dflt="");
+ /**
+ * get optional environment string value with proper Unicode handling
+ * (key is always UTF-8)
+ * detect absence by (! return value)
+ */
+ static boost::optional<string_type> getoptenv(const std::string& key);
+
+ static void addCRLF(string_type& string);
+ static void removeCRLF(string_type& string);
+ static void removeWindowsCR(string_type& string);
+
+ static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab );
+ static void replaceNonstandardASCII( string_type& string, T replacement );
+ static void replaceChar( string_type& string, T target, T replacement );
+ static void replaceString( string_type& string, string_type target, string_type replacement );
+ static string_type capitalize(const string_type& str);
+ static void capitalize(string_type& str);
+
+ static BOOL containsNonprintable(const string_type& string);
+ static void stripNonprintable(string_type& string);
+
+ /**
+ * Double-quote an argument string if needed, unless it's already
+ * double-quoted. Decide whether it's needed based on the presence of any
+ * character in @a triggers (default space or double-quote). If we quote
+ * it, escape any embedded double-quote with the @a escape string (default
+ * backslash).
+ *
+ * Passing triggers="" means always quote, unless it's already double-quoted.
+ */
+ static string_type quote(const string_type& str,
+ const string_type& triggers=" \"",
+ const string_type& escape="\\");
+
+ /**
+ * @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(string_type& string);
+
+ // Conversion to other data types
+ static BOOL convertToBOOL(const string_type& string, BOOL& value);
+ static BOOL convertToU8(const string_type& string, U8& value);
+ static BOOL convertToS8(const string_type& string, S8& value);
+ static BOOL convertToS16(const string_type& string, S16& value);
+ static BOOL convertToU16(const string_type& string, U16& value);
+ static BOOL convertToU32(const string_type& string, U32& value);
+ static BOOL convertToS32(const string_type& string, S32& value);
+ static BOOL convertToF32(const string_type& string, F32& value);
+ static BOOL convertToF64(const string_type& 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 string_type& lhs, const string_type& 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 string_type& lhs, const string_type& rhs);
+
+ // Case sensitive comparison with good handling of numbers. Does not use current locale.
+ // a.k.a. strdictcmp()
+ static S32 compareDict(const string_type& a, const string_type& b);
+
+ // Case *in*sensitive comparison with good handling of numbers. Does not use current locale.
+ // a.k.a. strdictcmp()
+ static S32 compareDictInsensitive(const string_type& a, const string_type& b);
+
+ // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
+ static BOOL precedesDict( const string_type& a, const string_type& 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(string_type& dst, const string_type& 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 string_type& instr, size_type& start, std::vector<string_type >& tokens);
+ LL_COMMON_API static size_type getSubstitution(const string_type& instr, size_type& start, std::vector<string_type >& tokens);
};
template<class T> const std::basic_string<T> LLStringUtilBase<T>::null;
@@ -455,18 +455,18 @@ typedef std::basic_string<llwchar> LLWString;
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) {}
+ 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) const
- {
- return (LLStringUtil::precedesDict(a, b) ? true : false);
- }
+ bool operator()(const std::string& a, const std::string& b) const
+ {
+ return (LLStringUtil::precedesDict(a, b) ? true : false);
+ }
};
@@ -483,10 +483,10 @@ public:
* @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)
+ const std::string& in,
+ std::string::size_type count)
{
- return std::string(in, 0, in.length() - count);
+ return std::string(in, 0, in.length() - count);
}
/**
@@ -706,10 +706,10 @@ ll_convert_forms(ll_convert_u16_alias, std::string, llutf16string, utf16str_to_u
inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);}
// Length of this UTF32 string in bytes when transformed to UTF8
-LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
+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 S32 wchar_utf8_length(const llwchar wc);
LL_COMMON_API std::string wchar_utf8_preview(const llwchar wc);
@@ -726,7 +726,7 @@ LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wst
/**
* @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.
@@ -739,8 +739,8 @@ LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32
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);
+ const std::string& lhs,
+ const std::string& rhs);
/**
* @brief Properly truncate a utf8 string to a maximum character count.
@@ -761,14 +761,14 @@ LL_COMMON_API std::string utf8str_symbol_truncate(const std::string& utf8str, co
* @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);
+ 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 mbcsstring_makeASCII(const std::string& str);
LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
@@ -874,52 +874,52 @@ LL_COMMON_API boost::optional<std::string> llstring_getoptenv(const std::string
*/
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);
+ /**
+ * @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);
}
////////////////////////////////////////////////////////////
@@ -934,36 +934,36 @@ template <class T>
std::vector<typename LLStringUtilBase<T>::string_type>
LLStringUtilBase<T>::getTokens(const string_type& instr, const string_type& delims)
{
- std::vector<string_type> tokens;
- getTokens(instr, tokens, delims);
- return tokens;
+ std::vector<string_type> tokens;
+ getTokens(instr, tokens, delims);
+ return tokens;
}
// static
template <class T>
std::vector<typename LLStringUtilBase<T>::string_type>
LLStringUtilBase<T>::getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes)
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes)
{
- std::vector<string_type> tokens;
- getTokens(instr, tokens, drop_delims, keep_delims, quotes);
- return tokens;
+ std::vector<string_type> tokens;
+ getTokens(instr, tokens, drop_delims, keep_delims, quotes);
+ return tokens;
}
// static
template <class T>
std::vector<typename LLStringUtilBase<T>::string_type>
LLStringUtilBase<T>::getTokens(const string_type& instr,
- const string_type& drop_delims,
- const string_type& keep_delims,
- const string_type& quotes,
- const string_type& escapes)
-{
- std::vector<string_type> tokens;
- getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes);
- return tokens;
+ const string_type& drop_delims,
+ const string_type& keep_delims,
+ const string_type& quotes,
+ const string_type& escapes)
+{
+ std::vector<string_type> tokens;
+ getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes);
+ return tokens;
}
namespace LLStringUtilBaseImpl
@@ -979,62 +979,62 @@ namespace LLStringUtilBaseImpl
template <class T>
struct InString
{
- typedef std::basic_string<T> string_type;
- typedef typename string_type::const_iterator const_iterator;
-
- InString(const_iterator b, const_iterator e):
- mIter(b),
- mEnd(e)
- {}
- virtual ~InString() {}
-
- bool done() const { return mIter == mEnd; }
- /// Is the current character (*mIter) escaped? This implementation can
- /// answer trivially because it doesn't support escapes.
- virtual bool escaped() const { return false; }
- /// Obtain the current character and advance @c mIter.
- virtual T next() { return *mIter++; }
- /// Does the current character match specified character?
- virtual bool is(T ch) const { return (! done()) && *mIter == ch; }
- /// Is the current character any one of the specified characters?
- virtual bool oneof(const string_type& delims) const
- {
- return (! done()) && LLStringUtilBase<T>::contains(delims, *mIter);
- }
-
- /**
- * Scan forward from @from until either @a delim or end. This is primarily
- * useful for processing quoted substrings.
- *
- * If we do see @a delim, append everything from @from until (excluding)
- * @a delim to @a into, advance @c mIter to skip @a delim, and return @c
- * true.
- *
- * If we do not see @a delim, do not alter @a into or @c mIter and return
- * @c false. Do not pass GO, do not collect $200.
- *
- * @note The @c false case described above implements normal getTokens()
- * treatment of an unmatched open quote: treat the quote character as if
- * escaped, that is, simply collect it as part of the current token. Other
- * plausible behaviors directly affect the way getTokens() deals with an
- * unmatched quote: e.g. throwing an exception to treat it as an error, or
- * assuming a close quote beyond end of string (in which case return @c
- * true).
- */
- virtual bool collect_until(string_type& into, const_iterator from, T delim)
- {
- const_iterator found = std::find(from, mEnd, delim);
- // If we didn't find delim, change nothing, just tell caller.
- if (found == mEnd)
- return false;
- // Found delim! Append everything between from and found.
- into.append(from, found);
- // advance past delim in input
- mIter = found + 1;
- return true;
- }
-
- const_iterator mIter, mEnd;
+ typedef std::basic_string<T> string_type;
+ typedef typename string_type::const_iterator const_iterator;
+
+ InString(const_iterator b, const_iterator e):
+ mIter(b),
+ mEnd(e)
+ {}
+ virtual ~InString() {}
+
+ bool done() const { return mIter == mEnd; }
+ /// Is the current character (*mIter) escaped? This implementation can
+ /// answer trivially because it doesn't support escapes.
+ virtual bool escaped() const { return false; }
+ /// Obtain the current character and advance @c mIter.
+ virtual T next() { return *mIter++; }
+ /// Does the current character match specified character?
+ virtual bool is(T ch) const { return (! done()) && *mIter == ch; }
+ /// Is the current character any one of the specified characters?
+ virtual bool oneof(const string_type& delims) const
+ {
+ return (! done()) && LLStringUtilBase<T>::contains(delims, *mIter);
+ }
+
+ /**
+ * Scan forward from @from until either @a delim or end. This is primarily
+ * useful for processing quoted substrings.
+ *
+ * If we do see @a delim, append everything from @from until (excluding)
+ * @a delim to @a into, advance @c mIter to skip @a delim, and return @c
+ * true.
+ *
+ * If we do not see @a delim, do not alter @a into or @c mIter and return
+ * @c false. Do not pass GO, do not collect $200.
+ *
+ * @note The @c false case described above implements normal getTokens()
+ * treatment of an unmatched open quote: treat the quote character as if
+ * escaped, that is, simply collect it as part of the current token. Other
+ * plausible behaviors directly affect the way getTokens() deals with an
+ * unmatched quote: e.g. throwing an exception to treat it as an error, or
+ * assuming a close quote beyond end of string (in which case return @c
+ * true).
+ */
+ virtual bool collect_until(string_type& into, const_iterator from, T delim)
+ {
+ const_iterator found = std::find(from, mEnd, delim);
+ // If we didn't find delim, change nothing, just tell caller.
+ if (found == mEnd)
+ return false;
+ // Found delim! Append everything between from and found.
+ into.append(from, found);
+ // advance past delim in input
+ mIter = found + 1;
+ return true;
+ }
+
+ const_iterator mIter, mEnd;
};
/// InString subclass that handles escape characters
@@ -1042,177 +1042,177 @@ template <class T>
class InEscString: public InString<T>
{
public:
- typedef InString<T> super;
- typedef typename super::string_type string_type;
- typedef typename super::const_iterator const_iterator;
- using super::done;
- using super::mIter;
- using super::mEnd;
-
- InEscString(const_iterator b, const_iterator e, const string_type& escapes):
- super(b, e),
- mEscapes(escapes)
- {
- // Even though we've already initialized 'mIter' via our base-class
- // constructor, set it again to check for initial escape char.
- setiter(b);
- }
-
- /// This implementation uses the answer cached by setiter().
- virtual bool escaped() const { return mIsEsc; }
- virtual T next()
- {
- // If we're looking at the escape character of an escape sequence,
- // skip that character. This is the one time we can modify 'mIter'
- // without using setiter: for this one case we DO NOT CARE if the
- // escaped character is itself an escape.
- if (mIsEsc)
- ++mIter;
- // If we were looking at an escape character, this is the escaped
- // character; otherwise it's just the next character.
- T result(*mIter);
- // Advance mIter, checking for escape sequence.
- setiter(mIter + 1);
- return result;
- }
-
- virtual bool is(T ch) const
- {
- // Like base-class is(), except that an escaped character matches
- // nothing.
- return (! done()) && (! mIsEsc) && *mIter == ch;
- }
-
- virtual bool oneof(const string_type& delims) const
- {
- // Like base-class oneof(), except that an escaped character matches
- // nothing.
- return (! done()) && (! mIsEsc) && LLStringUtilBase<T>::contains(delims, *mIter);
- }
-
- virtual bool collect_until(string_type& into, const_iterator from, T delim)
- {
- // Deal with escapes in the characters we collect; that is, an escaped
- // character must become just that character without the preceding
- // escape. Collect characters in a separate string rather than
- // directly appending to 'into' in case we do not find delim, in which
- // case we're supposed to leave 'into' unmodified.
- string_type collected;
- // For scanning purposes, we're going to work directly with 'mIter'.
- // Save its current value in case we fail to see delim.
- const_iterator save_iter(mIter);
- // Okay, set 'mIter', checking for escape.
- setiter(from);
- while (! done())
- {
- // If we see an unescaped delim, stop and report success.
- if ((! mIsEsc) && *mIter == delim)
- {
- // Append collected chars to 'into'.
- into.append(collected);
- // Don't forget to advance 'mIter' past delim.
- setiter(mIter + 1);
- return true;
- }
- // We're not at end, and either we're not looking at delim or it's
- // escaped. Collect this character and keep going.
- collected.push_back(next());
- }
- // Here we hit 'mEnd' without ever seeing delim. Restore mIter and tell
- // caller.
- setiter(save_iter);
- return false;
- }
+ typedef InString<T> super;
+ typedef typename super::string_type string_type;
+ typedef typename super::const_iterator const_iterator;
+ using super::done;
+ using super::mIter;
+ using super::mEnd;
+
+ InEscString(const_iterator b, const_iterator e, const string_type& escapes):
+ super(b, e),
+ mEscapes(escapes)
+ {
+ // Even though we've already initialized 'mIter' via our base-class
+ // constructor, set it again to check for initial escape char.
+ setiter(b);
+ }
+
+ /// This implementation uses the answer cached by setiter().
+ virtual bool escaped() const { return mIsEsc; }
+ virtual T next()
+ {
+ // If we're looking at the escape character of an escape sequence,
+ // skip that character. This is the one time we can modify 'mIter'
+ // without using setiter: for this one case we DO NOT CARE if the
+ // escaped character is itself an escape.
+ if (mIsEsc)
+ ++mIter;
+ // If we were looking at an escape character, this is the escaped
+ // character; otherwise it's just the next character.
+ T result(*mIter);
+ // Advance mIter, checking for escape sequence.
+ setiter(mIter + 1);
+ return result;
+ }
+
+ virtual bool is(T ch) const
+ {
+ // Like base-class is(), except that an escaped character matches
+ // nothing.
+ return (! done()) && (! mIsEsc) && *mIter == ch;
+ }
+
+ virtual bool oneof(const string_type& delims) const
+ {
+ // Like base-class oneof(), except that an escaped character matches
+ // nothing.
+ return (! done()) && (! mIsEsc) && LLStringUtilBase<T>::contains(delims, *mIter);
+ }
+
+ virtual bool collect_until(string_type& into, const_iterator from, T delim)
+ {
+ // Deal with escapes in the characters we collect; that is, an escaped
+ // character must become just that character without the preceding
+ // escape. Collect characters in a separate string rather than
+ // directly appending to 'into' in case we do not find delim, in which
+ // case we're supposed to leave 'into' unmodified.
+ string_type collected;
+ // For scanning purposes, we're going to work directly with 'mIter'.
+ // Save its current value in case we fail to see delim.
+ const_iterator save_iter(mIter);
+ // Okay, set 'mIter', checking for escape.
+ setiter(from);
+ while (! done())
+ {
+ // If we see an unescaped delim, stop and report success.
+ if ((! mIsEsc) && *mIter == delim)
+ {
+ // Append collected chars to 'into'.
+ into.append(collected);
+ // Don't forget to advance 'mIter' past delim.
+ setiter(mIter + 1);
+ return true;
+ }
+ // We're not at end, and either we're not looking at delim or it's
+ // escaped. Collect this character and keep going.
+ collected.push_back(next());
+ }
+ // Here we hit 'mEnd' without ever seeing delim. Restore mIter and tell
+ // caller.
+ setiter(save_iter);
+ return false;
+ }
private:
- void setiter(const_iterator i)
- {
- mIter = i;
-
- // Every time we change 'mIter', set 'mIsEsc' to be able to repetitively
- // answer escaped() without having to rescan 'mEscapes'. mIsEsc caches
- // contains(mEscapes, *mIter).
-
- // We're looking at an escaped char if we're not already at end (that
- // is, *mIter is even meaningful); if *mIter is in fact one of the
- // specified escape characters; and if there's one more character
- // following it. That is, if an escape character is the very last
- // character of the input string, it loses its special meaning.
- mIsEsc = (! done()) &&
- LLStringUtilBase<T>::contains(mEscapes, *mIter) &&
- (mIter+1) != mEnd;
- }
-
- const string_type mEscapes;
- bool mIsEsc;
+ void setiter(const_iterator i)
+ {
+ mIter = i;
+
+ // Every time we change 'mIter', set 'mIsEsc' to be able to repetitively
+ // answer escaped() without having to rescan 'mEscapes'. mIsEsc caches
+ // contains(mEscapes, *mIter).
+
+ // We're looking at an escaped char if we're not already at end (that
+ // is, *mIter is even meaningful); if *mIter is in fact one of the
+ // specified escape characters; and if there's one more character
+ // following it. That is, if an escape character is the very last
+ // character of the input string, it loses its special meaning.
+ mIsEsc = (! done()) &&
+ LLStringUtilBase<T>::contains(mEscapes, *mIter) &&
+ (mIter+1) != mEnd;
+ }
+
+ const string_type mEscapes;
+ bool mIsEsc;
};
/// getTokens() implementation based on InString concept
template <typename INSTRING, typename string_type>
void getTokens(INSTRING& instr, std::vector<string_type>& tokens,
- const string_type& drop_delims, const string_type& keep_delims,
- const string_type& quotes)
-{
- // There are times when we want to match either drop_delims or
- // keep_delims. Concatenate them up front to speed things up.
- string_type all_delims(drop_delims + keep_delims);
- // no tokens yet
- tokens.clear();
-
- // try for another token
- while (! instr.done())
- {
- // scan past any drop_delims
- while (instr.oneof(drop_delims))
- {
- // skip this drop_delim
- instr.next();
- // but if that was the end of the string, done
- if (instr.done())
- return;
- }
- // found the start of another token: make a slot for it
- tokens.push_back(string_type());
- if (instr.oneof(keep_delims))
- {
- // *iter is a keep_delim, a token of exactly 1 character. Append
- // that character to the new token and proceed.
- tokens.back().push_back(instr.next());
- continue;
- }
- // Here we have a non-delimiter token, which might consist of a mix of
- // quoted and unquoted parts. Use bash rules for quoting: you can
- // embed a quoted substring in the midst of an unquoted token (e.g.
- // ~/"sub dir"/myfile.txt); you can ram two quoted substrings together
- // to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge
- // from bash in that bash considers an unmatched quote an error. Our
- // param signature doesn't allow for errors, so just pretend it's not
- // a quote and embed it.
- // At this level, keep scanning until we hit the next delimiter of
- // either type (drop_delims or keep_delims).
- while (! instr.oneof(all_delims))
- {
- // If we're looking at an open quote, search forward for
- // a close quote, collecting characters along the way.
- if (instr.oneof(quotes) &&
- instr.collect_until(tokens.back(), instr.mIter+1, *instr.mIter))
- {
- // collect_until is cleverly designed to do exactly what we
- // need here. No further action needed if it returns true.
- }
- else
- {
- // Either *iter isn't a quote, or there's no matching close
- // quote: in other words, just an ordinary char. Append it to
- // current token.
- tokens.back().push_back(instr.next());
- }
- // having scanned that segment of this token, if we've reached the
- // end of the string, we're done
- if (instr.done())
- return;
- }
- }
+ const string_type& drop_delims, const string_type& keep_delims,
+ const string_type& quotes)
+{
+ // There are times when we want to match either drop_delims or
+ // keep_delims. Concatenate them up front to speed things up.
+ string_type all_delims(drop_delims + keep_delims);
+ // no tokens yet
+ tokens.clear();
+
+ // try for another token
+ while (! instr.done())
+ {
+ // scan past any drop_delims
+ while (instr.oneof(drop_delims))
+ {
+ // skip this drop_delim
+ instr.next();
+ // but if that was the end of the string, done
+ if (instr.done())
+ return;
+ }
+ // found the start of another token: make a slot for it
+ tokens.push_back(string_type());
+ if (instr.oneof(keep_delims))
+ {
+ // *iter is a keep_delim, a token of exactly 1 character. Append
+ // that character to the new token and proceed.
+ tokens.back().push_back(instr.next());
+ continue;
+ }
+ // Here we have a non-delimiter token, which might consist of a mix of
+ // quoted and unquoted parts. Use bash rules for quoting: you can
+ // embed a quoted substring in the midst of an unquoted token (e.g.
+ // ~/"sub dir"/myfile.txt); you can ram two quoted substrings together
+ // to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge
+ // from bash in that bash considers an unmatched quote an error. Our
+ // param signature doesn't allow for errors, so just pretend it's not
+ // a quote and embed it.
+ // At this level, keep scanning until we hit the next delimiter of
+ // either type (drop_delims or keep_delims).
+ while (! instr.oneof(all_delims))
+ {
+ // If we're looking at an open quote, search forward for
+ // a close quote, collecting characters along the way.
+ if (instr.oneof(quotes) &&
+ instr.collect_until(tokens.back(), instr.mIter+1, *instr.mIter))
+ {
+ // collect_until is cleverly designed to do exactly what we
+ // need here. No further action needed if it returns true.
+ }
+ else
+ {
+ // Either *iter isn't a quote, or there's no matching close
+ // quote: in other words, just an ordinary char. Append it to
+ // current token.
+ tokens.back().push_back(instr.next());
+ }
+ // having scanned that segment of this token, if we've reached the
+ // end of the string, we're done
+ if (instr.done())
+ return;
+ }
+ }
}
} // namespace LLStringUtilBaseImpl
@@ -1220,256 +1220,256 @@ void getTokens(INSTRING& instr, std::vector<string_type>& tokens,
// static
template <class T>
void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens,
- const string_type& drop_delims, const string_type& keep_delims,
- const string_type& quotes)
+ const string_type& drop_delims, const string_type& keep_delims,
+ const string_type& quotes)
{
- // Because this overload doesn't support escapes, use simple InString to
- // manage input range.
- LLStringUtilBaseImpl::InString<T> instring(string.begin(), string.end());
- LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes);
+ // Because this overload doesn't support escapes, use simple InString to
+ // manage input range.
+ LLStringUtilBaseImpl::InString<T> instring(string.begin(), string.end());
+ LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes);
}
// static
template <class T>
void LLStringUtilBase<T>::getTokens(const string_type& string, std::vector<string_type>& tokens,
- const string_type& drop_delims, const string_type& keep_delims,
- const string_type& quotes, const string_type& escapes)
-{
- // This overload must deal with escapes. Delegate that to InEscString
- // (unless there ARE no escapes).
- std::unique_ptr< LLStringUtilBaseImpl::InString<T> > instrp;
- if (escapes.empty())
- instrp.reset(new LLStringUtilBaseImpl::InString<T>(string.begin(), string.end()));
- else
- instrp.reset(new LLStringUtilBaseImpl::InEscString<T>(string.begin(), string.end(), escapes));
- LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes);
+ const string_type& drop_delims, const string_type& keep_delims,
+ const string_type& quotes, const string_type& escapes)
+{
+ // This overload must deal with escapes. Delegate that to InEscString
+ // (unless there ARE no escapes).
+ std::unique_ptr< LLStringUtilBaseImpl::InString<T> > instrp;
+ if (escapes.empty())
+ instrp.reset(new LLStringUtilBaseImpl::InString<T>(string.begin(), string.end()));
+ else
+ instrp.reset(new LLStringUtilBaseImpl::InEscString<T>(string.begin(), string.end(), escapes));
+ LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes);
}
// static
-template<class T>
+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;
+{
+ 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>
+//static
+template<class T>
S32 LLStringUtilBase<T>::compareStrings(const string_type& lhs, const string_type& rhs)
{
- return LLStringOps::collate(lhs.c_str(), rhs.c_str());
+ return LLStringOps::collate(lhs.c_str(), rhs.c_str());
}
// static
-template<class T>
+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
- {
- string_type lhs_string(lhs);
- string_type 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;
+ 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
+ {
+ string_type lhs_string(lhs);
+ string_type 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>
+//static
+template<class T>
S32 LLStringUtilBase<T>::compareInsensitive(const string_type& lhs, const string_type& rhs)
{
- string_type lhs_string(lhs);
- string_type rhs_string(rhs);
- LLStringUtilBase<T>::toUpper(lhs_string);
- LLStringUtilBase<T>::toUpper(rhs_string);
- return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
+ string_type lhs_string(lhs);
+ string_type 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
+//static
template<class T>
S32 LLStringUtilBase<T>::compareDict(const string_type& astr, const string_type& 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;
+ 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 string_type& astr, const string_type& 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;
+ 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>
+// static
+template<class T>
BOOL LLStringUtilBase<T>::precedesDict( const string_type& a, const string_type& b )
{
- if( a.size() && b.size() )
- {
- return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
- }
- else
- {
- return (!b.empty());
- }
+ 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(string_type& string)
-{
- if( !string.empty() )
- {
- std::transform(
- string.begin(),
- string.end(),
- string.begin(),
- (T(*)(T)) &LLStringOps::toUpper);
- }
+template<class T>
+void LLStringUtilBase<T>::toUpper(string_type& string)
+{
+ if( !string.empty() )
+ {
+ std::transform(
+ string.begin(),
+ string.end(),
+ string.begin(),
+ (T(*)(T)) &LLStringOps::toUpper);
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::toLower(string_type& string)
-{
- if( !string.empty() )
- {
- std::transform(
- string.begin(),
- string.end(),
- string.begin(),
- (T(*)(T)) &LLStringOps::toLower);
- }
+{
+ if( !string.empty() )
+ {
+ std::transform(
+ string.begin(),
+ string.end(),
+ string.begin(),
+ (T(*)(T)) &LLStringOps::toLower);
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::trimHead(string_type& string)
-{
- if( !string.empty() )
- {
- size_type i = 0;
- while( i < string.length() && LLStringOps::isSpace( string[i] ) )
- {
- i++;
- }
- string.erase(0, i);
- }
+{
+ if( !string.empty() )
+ {
+ size_type i = 0;
+ while( i < string.length() && LLStringOps::isSpace( string[i] ) )
+ {
+ i++;
+ }
+ string.erase(0, i);
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::trimTail(string_type& 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 );
- }
+{
+ 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 );
+ }
}
@@ -1478,67 +1478,67 @@ void LLStringUtilBase<T>::trimTail(string_type& string)
template<class T>
void LLStringUtilBase<T>::addCRLF(string_type& 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);
- delete[] t;
- }
+ 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);
+ delete[] t;
+ }
}
// Remove all carriage returns
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::removeCRLF(string_type& 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);
+ 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>
+template<class T>
void LLStringUtilBase<T>::removeWindowsCR(string_type& string)
{
if (string.empty())
@@ -1567,269 +1567,269 @@ void LLStringUtilBase<T>::removeWindowsCR(string_type& string)
template<class T>
void LLStringUtilBase<T>::replaceChar( string_type& string, T target, T replacement )
{
- size_type found_pos = 0;
- while( (found_pos = string.find(target, found_pos)) != string_type::npos )
- {
- string[found_pos] = replacement;
- found_pos++; // avoid infinite defeat if target == replacement
- }
+ size_type found_pos = 0;
+ while( (found_pos = string.find(target, found_pos)) != string_type::npos )
+ {
+ string[found_pos] = replacement;
+ found_pos++; // avoid infinite defeat if target == replacement
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::replaceString( string_type& string, string_type target, string_type replacement )
{
- size_type found_pos = 0;
- while( (found_pos = string.find(target, found_pos)) != string_type::npos )
- {
- string.replace( found_pos, target.length(), replacement );
- found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
- }
+ size_type found_pos = 0;
+ while( (found_pos = string.find(target, found_pos)) != string_type::npos )
+ {
+ string.replace( found_pos, target.length(), replacement );
+ found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
+ }
}
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::replaceNonstandardASCII( string_type& 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;
- }
- }
+ 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>
+template<class T>
void LLStringUtilBase<T>::replaceTabsWithSpaces( string_type& str, size_type spaces_per_tab )
{
- const T TAB = '\t';
- const T SPACE = ' ';
-
- string_type 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;
+ const T TAB = '\t';
+ const T SPACE = ' ';
+
+ string_type 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>
std::basic_string<T> LLStringUtilBase<T>::capitalize(const string_type& str)
{
- string_type result(str);
- capitalize(result);
- return result;
+ string_type result(str);
+ capitalize(result);
+ return result;
}
//static
template<class T>
void LLStringUtilBase<T>::capitalize(string_type& str)
{
- if (str.size())
- {
- auto last = str[0] = toupper(str[0]);
- for (U32 i = 1; i < str.size(); ++i)
- {
- last = (last == ' ' || last == '-' || last == '_') ? str[i] = toupper(str[i]) : str[i];
- }
- }
+ if (str.size())
+ {
+ auto last = str[0] = toupper(str[0]);
+ for (U32 i = 1; i < str.size(); ++i)
+ {
+ last = (last == ' ' || last == '-' || last == '_') ? str[i] = toupper(str[i]) : str[i];
+ }
+ }
}
//static
-template<class T>
+template<class T>
BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& 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;
+ 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;
}
-// *TODO: reimplement in terms of algorithm
+// *TODO: reimplement in terms of algorithm
//static
-template<class T>
+template<class T>
void LLStringUtilBase<T>::stripNonprintable(string_type& 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;
+ 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;
}
-// *TODO: reimplement in terms of algorithm
+// *TODO: reimplement in terms of algorithm
template<class T>
std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str,
- const string_type& triggers,
- const string_type& escape)
-{
- size_type len(str.length());
- // If the string is already quoted, assume user knows what s/he's doing.
- if (len >= 2 && str[0] == '"' && str[len-1] == '"')
- {
- return str;
- }
-
- // Not already quoted: do we need to? triggers.empty() is a special case
- // meaning "always quote."
- if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos)
- {
- // no trigger characters, don't bother quoting
- return str;
- }
-
- // For whatever reason, we must quote this string.
- string_type result;
- result.push_back('"');
- for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
- {
- if (*ci == '"')
- {
- result.append(escape);
- }
- result.push_back(*ci);
- }
- result.push_back('"');
- return result;
+ const string_type& triggers,
+ const string_type& escape)
+{
+ size_type len(str.length());
+ // If the string is already quoted, assume user knows what s/he's doing.
+ if (len >= 2 && str[0] == '"' && str[len-1] == '"')
+ {
+ return str;
+ }
+
+ // Not already quoted: do we need to? triggers.empty() is a special case
+ // meaning "always quote."
+ if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos)
+ {
+ // no trigger characters, don't bother quoting
+ return str;
+ }
+
+ // For whatever reason, we must quote this string.
+ string_type result;
+ result.push_back('"');
+ for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci)
+ {
+ if (*ci == '"')
+ {
+ result.append(escape);
+ }
+ result.push_back(*ci);
+ }
+ result.push_back('"');
+ return result;
}
-template<class T>
+template<class T>
void LLStringUtilBase<T>::_makeASCII(string_type& 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;
- }
- }
+ // 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>
+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';
- }
+ 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>
+template<class T>
void LLStringUtilBase<T>::copyInto(string_type& dst, const string_type& 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
- {
- string_type tail = dst.substr(offset);
-
- dst = dst.substr(0, offset);
- dst += src;
- dst += tail;
- };
+ if ( offset == dst.length() )
+ {
+ // special case - append to end of string and avoid expensive
+ // (when strings are large) string manipulations
+ dst += src;
+ }
+ else
+ {
+ string_type 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 string_type& string, const T* s )
-{
- if( string.empty() )
- {
- // Early exit
- return FALSE;
- }
- else
- {
- return (strncmp( s, string.c_str(), string.size() ) == 0);
- }
+template<class T>
+BOOL LLStringUtilBase<T>::isHead( const string_type& 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>
+template<class T>
bool LLStringUtilBase<T>::startsWith(
- const string_type& string,
- const string_type& substr)
+ const string_type& string,
+ const string_type& substr)
{
- if(string.empty() || (substr.empty())) return false;
- if (substr.length() > string.length()) return false;
- if (0 == string.compare(0, substr.length(), substr)) return true;
- return false;
+ if(string.empty() || (substr.empty())) return false;
+ if (substr.length() > string.length()) return false;
+ if (0 == string.compare(0, substr.length(), substr)) return true;
+ return false;
}
// static
-template<class T>
+template<class T>
bool LLStringUtilBase<T>::endsWith(
- const string_type& string,
- const string_type& substr)
-{
- if(string.empty() || (substr.empty())) return false;
- size_t sub_len = substr.length();
- size_t str_len = string.length();
- if (sub_len > str_len) return false;
- if (0 == string.compare(str_len - sub_len, sub_len, substr)) return true;
- return false;
+ const string_type& string,
+ const string_type& substr)
+{
+ if(string.empty() || (substr.empty())) return false;
+ size_t sub_len = substr.length();
+ size_t str_len = string.length();
+ if (sub_len > str_len) return false;
+ if (0 == string.compare(str_len - sub_len, sub_len, substr)) return true;
+ return false;
}
// static
@@ -1864,187 +1864,187 @@ auto LLStringUtilBase<T>::getenv(const std::string& key, const string_type& dflt
}
}
-template<class T>
+template<class T>
BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value)
{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type 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;
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type 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 string_type& 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>::convertToU8(const string_type& 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 string_type& 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>::convertToS8(const string_type& 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 string_type& 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>::convertToS16(const string_type& 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 string_type& 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>::convertToU16(const string_type& 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 string_type& string, U32& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- U32 v;
- std::basic_istringstream<T> i_stream((string_type)temp);
- if(i_stream >> v)
- {
- value = v;
- return TRUE;
- }
- return FALSE;
+template<class T>
+BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value)
+{
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ U32 v;
+ std::basic_istringstream<T> i_stream((string_type)temp);
+ if(i_stream >> v)
+ {
+ value = v;
+ return TRUE;
+ }
+ return FALSE;
}
-template<class T>
-BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value)
-{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- S32 v;
- std::basic_istringstream<T> i_stream((string_type)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>::convertToS32(const string_type& string, S32& value)
+{
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ S32 v;
+ std::basic_istringstream<T> i_stream((string_type)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 string_type& 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>::convertToF32(const string_type& 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>
+template<class T>
BOOL LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value)
{
- if( string.empty() )
- {
- return FALSE;
- }
-
- string_type temp( string );
- trim(temp);
- F64 v;
- std::basic_istringstream<T> i_stream((string_type)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;
+ if( string.empty() )
+ {
+ return FALSE;
+ }
+
+ string_type temp( string );
+ trim(temp);
+ F64 v;
+ std::basic_istringstream<T> i_stream((string_type)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>
+template<class T>
void LLStringUtilBase<T>::truncate(string_type& string, size_type count)
{
- size_type cur_size = string.size();
- string.resize(count < cur_size ? count : cur_size);
+ size_type cur_size = string.size();
+ string.resize(count < cur_size ? count : cur_size);
}
// The good thing about *declaration* macros, vs. usage macros, is that now
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 63d5bdbb70..d597e90ba0 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -47,7 +47,7 @@ enum LogFieldIndex
MSG_FIELD
};
-static const char* FieldName[] =
+static const char* FieldName[] =
{
"TIME",
"LEVEL",
@@ -62,15 +62,15 @@ namespace
#ifdef __clang__
# pragma clang diagnostic ignored "-Wunused-function"
#endif
- void test_that_error_h_includes_enough_things_to_compile_a_message()
- {
- LL_INFOS() << "!" << LL_ENDL;
- }
+ void test_that_error_h_includes_enough_things_to_compile_a_message()
+ {
+ LL_INFOS() << "!" << LL_ENDL;
+ }
}
namespace
{
- static bool fatalWasCalled = false;
+ static bool fatalWasCalled = false;
struct FatalWasCalled: public std::runtime_error
{
FatalWasCalled(const std::string& what): std::runtime_error(what) {}
@@ -96,465 +96,465 @@ namespace
namespace tut
{
- class TestRecorder : public LLError::Recorder
- {
- public:
- TestRecorder()
- {
- showTime(false);
- }
- virtual ~TestRecorder()
- {}
-
- virtual void recordMessage(LLError::ELevel level,
- const std::string& message)
- {
- mMessages.push_back(message);
- }
-
- int countMessages() const { return (int) mMessages.size(); }
- void clearMessages() { mMessages.clear(); }
-
- std::string message(int n) const
- {
- std::ostringstream test_name;
- test_name << "testing message " << n << ", not enough messages";
-
- tut::ensure(test_name.str(), n < countMessages());
- return mMessages[n];
- }
-
- void reportMessages() const
- {
- std::cerr << '\n';
- int n = 0;
- for (const auto& msg : mMessages)
- {
- std::cerr << std::setw(2) << n++ << ": " << msg.substr(0, 100) << '\n';
- }
- }
-
- private:
- typedef std::vector<std::string> MessageVector;
- MessageVector mMessages;
- };
-
- struct ErrorTestData
- {
- LLError::RecorderPtr mRecorder;
- LLError::SettingsStoragePtr mPriorErrorSettings;
-
- auto recorder() { return std::dynamic_pointer_cast<TestRecorder>(mRecorder); }
-
- ErrorTestData():
- mRecorder(new TestRecorder())
- {
- fatalWasCalled = false;
-
- mPriorErrorSettings = LLError::saveAndResetSettings();
- LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- LLError::setFatalFunction(fatalCall);
- LLError::addRecorder(mRecorder);
- }
-
- ~ErrorTestData()
- {
- LLError::removeRecorder(mRecorder);
- LLError::restoreSettings(mPriorErrorSettings);
- }
-
- int countMessages()
- {
- return recorder()->countMessages();
- }
-
- void clearMessages()
- {
- recorder()->clearMessages();
- }
-
- void setWantsTime(bool t)
- {
- recorder()->showTime(t);
- }
-
- void setWantsMultiline(bool t)
- {
- recorder()->showMultiline(t);
- }
-
- std::string message(int n)
- {
- return recorder()->message(n);
- }
-
- void reportMessages()
- {
- recorder()->reportMessages();
- }
-
- void ensure_message_count(int expectedCount)
- {
- ensure_equals("message count", countMessages(), expectedCount);
- }
-
- std::string message_field(int msgnum, LogFieldIndex fieldnum)
- {
- std::ostringstream test_name;
- test_name << "testing message " << msgnum << ", not enough messages";
- tut::ensure(test_name.str(), msgnum < countMessages());
-
- std::string msg(message(msgnum));
-
- std::string field_value;
-
- // find the start of the field; fields are separated by a single space
- size_t scan = 0;
- int on_field = 0;
- while ( scan < msg.length() && on_field < fieldnum )
- {
- // fields are delimited by one space
- if ( ' ' == msg[scan] )
- {
- if ( on_field < FUNCTION_FIELD )
- {
- on_field++;
- }
- // except function, which may have embedded spaces so ends with " : "
- else if (( on_field == FUNCTION_FIELD )
- && ( ':' == msg[scan+1] && ' ' == msg[scan+2] )
- )
- {
- on_field++;
- scan +=2;
- }
- }
- scan++;
- }
- size_t start_field = scan;
- size_t fieldlen = 0;
- if ( fieldnum < FUNCTION_FIELD )
- {
- fieldlen = msg.find(' ', start_field) - start_field;
- }
- else if ( fieldnum == FUNCTION_FIELD )
- {
- fieldlen = msg.find(" : ", start_field) - start_field;
- }
- else if ( MSG_FIELD == fieldnum ) // no delimiter, just everything to the end
- {
- fieldlen = msg.length() - start_field;
- }
-
- return msg.substr(start_field, fieldlen);
- }
-
- void ensure_message_field_equals(int msgnum, LogFieldIndex fieldnum, const std::string& expectedText)
- {
- std::ostringstream test_name;
- test_name << "testing message " << msgnum << " field " << FieldName[fieldnum] << "\n message: \"" << message(msgnum).substr(0, 100) << "\"\n ";
-
- try
- {
- ensure_equals(test_name.str(), message_field(msgnum, fieldnum), expectedText);
- }
- catch (const failure&)
- {
- reportMessages();
- throw;
- }
- }
-
- void ensure_message_does_not_contain(int n, const std::string& expectedText)
- {
- std::ostringstream test_name;
- test_name << "testing message " << n;
-
- try
- {
- ensure_does_not_contain(test_name.str(), message(n), expectedText);
- }
- catch (const failure&)
- {
- reportMessages();
- throw;
- }
- }
- };
-
- typedef test_group<ErrorTestData> ErrorTestGroup;
- typedef ErrorTestGroup::object ErrorTestObject;
-
- ErrorTestGroup errorTestGroup("error");
-
- template<> template<>
- void ErrorTestObject::test<1>()
- // basic test of output
- {
- LL_INFOS() << "test" << LL_ENDL;
- LL_INFOS() << "bob" << LL_ENDL;
-
- ensure_message_field_equals(0, MSG_FIELD, "test");
- ensure_message_field_equals(1, MSG_FIELD, "bob");
- }
+ class TestRecorder : public LLError::Recorder
+ {
+ public:
+ TestRecorder()
+ {
+ showTime(false);
+ }
+ virtual ~TestRecorder()
+ {}
+
+ virtual void recordMessage(LLError::ELevel level,
+ const std::string& message)
+ {
+ mMessages.push_back(message);
+ }
+
+ int countMessages() const { return (int) mMessages.size(); }
+ void clearMessages() { mMessages.clear(); }
+
+ std::string message(int n) const
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n << ", not enough messages";
+
+ tut::ensure(test_name.str(), n < countMessages());
+ return mMessages[n];
+ }
+
+ void reportMessages() const
+ {
+ std::cerr << '\n';
+ int n = 0;
+ for (const auto& msg : mMessages)
+ {
+ std::cerr << std::setw(2) << n++ << ": " << msg.substr(0, 100) << '\n';
+ }
+ }
+
+ private:
+ typedef std::vector<std::string> MessageVector;
+ MessageVector mMessages;
+ };
+
+ struct ErrorTestData
+ {
+ LLError::RecorderPtr mRecorder;
+ LLError::SettingsStoragePtr mPriorErrorSettings;
+
+ auto recorder() { return std::dynamic_pointer_cast<TestRecorder>(mRecorder); }
+
+ ErrorTestData():
+ mRecorder(new TestRecorder())
+ {
+ fatalWasCalled = false;
+
+ mPriorErrorSettings = LLError::saveAndResetSettings();
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ LLError::setFatalFunction(fatalCall);
+ LLError::addRecorder(mRecorder);
+ }
+
+ ~ErrorTestData()
+ {
+ LLError::removeRecorder(mRecorder);
+ LLError::restoreSettings(mPriorErrorSettings);
+ }
+
+ int countMessages()
+ {
+ return recorder()->countMessages();
+ }
+
+ void clearMessages()
+ {
+ recorder()->clearMessages();
+ }
+
+ void setWantsTime(bool t)
+ {
+ recorder()->showTime(t);
+ }
+
+ void setWantsMultiline(bool t)
+ {
+ recorder()->showMultiline(t);
+ }
+
+ std::string message(int n)
+ {
+ return recorder()->message(n);
+ }
+
+ void reportMessages()
+ {
+ recorder()->reportMessages();
+ }
+
+ void ensure_message_count(int expectedCount)
+ {
+ ensure_equals("message count", countMessages(), expectedCount);
+ }
+
+ std::string message_field(int msgnum, LogFieldIndex fieldnum)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << msgnum << ", not enough messages";
+ tut::ensure(test_name.str(), msgnum < countMessages());
+
+ std::string msg(message(msgnum));
+
+ std::string field_value;
+
+ // find the start of the field; fields are separated by a single space
+ size_t scan = 0;
+ int on_field = 0;
+ while ( scan < msg.length() && on_field < fieldnum )
+ {
+ // fields are delimited by one space
+ if ( ' ' == msg[scan] )
+ {
+ if ( on_field < FUNCTION_FIELD )
+ {
+ on_field++;
+ }
+ // except function, which may have embedded spaces so ends with " : "
+ else if (( on_field == FUNCTION_FIELD )
+ && ( ':' == msg[scan+1] && ' ' == msg[scan+2] )
+ )
+ {
+ on_field++;
+ scan +=2;
+ }
+ }
+ scan++;
+ }
+ size_t start_field = scan;
+ size_t fieldlen = 0;
+ if ( fieldnum < FUNCTION_FIELD )
+ {
+ fieldlen = msg.find(' ', start_field) - start_field;
+ }
+ else if ( fieldnum == FUNCTION_FIELD )
+ {
+ fieldlen = msg.find(" : ", start_field) - start_field;
+ }
+ else if ( MSG_FIELD == fieldnum ) // no delimiter, just everything to the end
+ {
+ fieldlen = msg.length() - start_field;
+ }
+
+ return msg.substr(start_field, fieldlen);
+ }
+
+ void ensure_message_field_equals(int msgnum, LogFieldIndex fieldnum, const std::string& expectedText)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << msgnum << " field " << FieldName[fieldnum] << "\n message: \"" << message(msgnum).substr(0, 100) << "\"\n ";
+
+ try
+ {
+ ensure_equals(test_name.str(), message_field(msgnum, fieldnum), expectedText);
+ }
+ catch (const failure&)
+ {
+ reportMessages();
+ throw;
+ }
+ }
+
+ void ensure_message_does_not_contain(int n, const std::string& expectedText)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n;
+
+ try
+ {
+ ensure_does_not_contain(test_name.str(), message(n), expectedText);
+ }
+ catch (const failure&)
+ {
+ reportMessages();
+ throw;
+ }
+ }
+ };
+
+ typedef test_group<ErrorTestData> ErrorTestGroup;
+ typedef ErrorTestGroup::object ErrorTestObject;
+
+ ErrorTestGroup errorTestGroup("error");
+
+ template<> template<>
+ void ErrorTestObject::test<1>()
+ // basic test of output
+ {
+ LL_INFOS() << "test" << LL_ENDL;
+ LL_INFOS() << "bob" << LL_ENDL;
+
+ ensure_message_field_equals(0, MSG_FIELD, "test");
+ ensure_message_field_equals(1, MSG_FIELD, "bob");
+ }
}
namespace
{
- void writeSome()
- {
- LL_DEBUGS("WriteTag","AnotherTag") << "one" << LL_ENDL;
- LL_INFOS("WriteTag") << "two" << LL_ENDL;
- LL_WARNS("WriteTag") << "three" << LL_ENDL;
- CATCH(LL_ERRS("WriteTag"), "four");
- }
+ void writeSome()
+ {
+ LL_DEBUGS("WriteTag","AnotherTag") << "one" << LL_ENDL;
+ LL_INFOS("WriteTag") << "two" << LL_ENDL;
+ LL_WARNS("WriteTag") << "three" << LL_ENDL;
+ CATCH(LL_ERRS("WriteTag"), "four");
+ }
};
namespace tut
{
- template<> template<>
- void ErrorTestObject::test<2>()
- // messages are filtered based on default level
- {
- LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- writeSome();
- ensure_message_field_equals(0, MSG_FIELD, "one");
- ensure_message_field_equals(0, LEVEL_FIELD, "DEBUG");
- ensure_message_field_equals(0, TAGS_FIELD, "#WriteTag#AnotherTag#");
- ensure_message_field_equals(1, MSG_FIELD, "two");
- ensure_message_field_equals(1, LEVEL_FIELD, "INFO");
- ensure_message_field_equals(1, TAGS_FIELD, "#WriteTag#");
- ensure_message_field_equals(2, MSG_FIELD, "three");
- ensure_message_field_equals(2, LEVEL_FIELD, "WARNING");
- ensure_message_field_equals(2, TAGS_FIELD, "#WriteTag#");
- ensure_message_field_equals(3, MSG_FIELD, "four");
- ensure_message_field_equals(3, LEVEL_FIELD, "ERROR");
- ensure_message_field_equals(3, TAGS_FIELD, "#WriteTag#");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(5);
-
- LLError::setDefaultLevel(LLError::LEVEL_INFO);
- writeSome();
- ensure_message_field_equals(5, MSG_FIELD, "two");
- ensure_message_field_equals(6, MSG_FIELD, "three");
- ensure_message_field_equals(7, MSG_FIELD, "four");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(9);
-
- LLError::setDefaultLevel(LLError::LEVEL_WARN);
- writeSome();
- ensure_message_field_equals(9, MSG_FIELD, "three");
- ensure_message_field_equals(10, MSG_FIELD, "four");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(12);
-
- LLError::setDefaultLevel(LLError::LEVEL_ERROR);
- writeSome();
- ensure_message_field_equals(12, MSG_FIELD, "four");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(14);
-
- LLError::setDefaultLevel(LLError::LEVEL_NONE);
- writeSome();
- ensure_message_count(14);
- }
-
- template<> template<>
- void ErrorTestObject::test<3>()
- // error type string in output
- {
- writeSome();
- ensure_message_field_equals(0, LEVEL_FIELD, "DEBUG");
- ensure_message_field_equals(1, LEVEL_FIELD, "INFO");
- ensure_message_field_equals(2, LEVEL_FIELD, "WARNING");
- ensure_message_field_equals(3, LEVEL_FIELD, "ERROR");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(5);
- }
-
- template<> template<>
- void ErrorTestObject::test<4>()
- // file abbreviation
- {
- std::string prev, abbreviateFile = __FILE__;
- do
- {
- prev = abbreviateFile;
- abbreviateFile = LLError::abbreviateFile(abbreviateFile);
- // __FILE__ is assumed to end with
- // indra/llcommon/tests/llerror_test.cpp. This test used to call
- // abbreviateFile() exactly once, then check below whether it
- // still contained the string 'indra'. That fails if the FIRST
- // part of the pathname also contains indra! Certain developer
- // machine images put local directory trees under
- // /ngi-persist/indra, which is where we observe the problem. So
- // now, keep calling abbreviateFile() until it returns its
- // argument unchanged, THEN check.
- } while (abbreviateFile != prev);
-
- ensure_ends_with("file name abbreviation",
- abbreviateFile,
- "llcommon/tests/llerror_test.cpp"
- );
- ensure_does_not_contain("file name abbreviation",
- abbreviateFile, "indra");
-
- std::string someFile =
+ template<> template<>
+ void ErrorTestObject::test<2>()
+ // messages are filtered based on default level
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ writeSome();
+ ensure_message_field_equals(0, MSG_FIELD, "one");
+ ensure_message_field_equals(0, LEVEL_FIELD, "DEBUG");
+ ensure_message_field_equals(0, TAGS_FIELD, "#WriteTag#AnotherTag#");
+ ensure_message_field_equals(1, MSG_FIELD, "two");
+ ensure_message_field_equals(1, LEVEL_FIELD, "INFO");
+ ensure_message_field_equals(1, TAGS_FIELD, "#WriteTag#");
+ ensure_message_field_equals(2, MSG_FIELD, "three");
+ ensure_message_field_equals(2, LEVEL_FIELD, "WARNING");
+ ensure_message_field_equals(2, TAGS_FIELD, "#WriteTag#");
+ ensure_message_field_equals(3, MSG_FIELD, "four");
+ ensure_message_field_equals(3, LEVEL_FIELD, "ERROR");
+ ensure_message_field_equals(3, TAGS_FIELD, "#WriteTag#");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(5);
+
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+ writeSome();
+ ensure_message_field_equals(5, MSG_FIELD, "two");
+ ensure_message_field_equals(6, MSG_FIELD, "three");
+ ensure_message_field_equals(7, MSG_FIELD, "four");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(9);
+
+ LLError::setDefaultLevel(LLError::LEVEL_WARN);
+ writeSome();
+ ensure_message_field_equals(9, MSG_FIELD, "three");
+ ensure_message_field_equals(10, MSG_FIELD, "four");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(12);
+
+ LLError::setDefaultLevel(LLError::LEVEL_ERROR);
+ writeSome();
+ ensure_message_field_equals(12, MSG_FIELD, "four");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(14);
+
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+ writeSome();
+ ensure_message_count(14);
+ }
+
+ template<> template<>
+ void ErrorTestObject::test<3>()
+ // error type string in output
+ {
+ writeSome();
+ ensure_message_field_equals(0, LEVEL_FIELD, "DEBUG");
+ ensure_message_field_equals(1, LEVEL_FIELD, "INFO");
+ ensure_message_field_equals(2, LEVEL_FIELD, "WARNING");
+ ensure_message_field_equals(3, LEVEL_FIELD, "ERROR");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(5);
+ }
+
+ template<> template<>
+ void ErrorTestObject::test<4>()
+ // file abbreviation
+ {
+ std::string prev, abbreviateFile = __FILE__;
+ do
+ {
+ prev = abbreviateFile;
+ abbreviateFile = LLError::abbreviateFile(abbreviateFile);
+ // __FILE__ is assumed to end with
+ // indra/llcommon/tests/llerror_test.cpp. This test used to call
+ // abbreviateFile() exactly once, then check below whether it
+ // still contained the string 'indra'. That fails if the FIRST
+ // part of the pathname also contains indra! Certain developer
+ // machine images put local directory trees under
+ // /ngi-persist/indra, which is where we observe the problem. So
+ // now, keep calling abbreviateFile() until it returns its
+ // argument unchanged, THEN check.
+ } while (abbreviateFile != prev);
+
+ ensure_ends_with("file name abbreviation",
+ abbreviateFile,
+ "llcommon/tests/llerror_test.cpp"
+ );
+ ensure_does_not_contain("file name abbreviation",
+ abbreviateFile, "indra");
+
+ std::string someFile =
#if LL_WINDOWS
- "C:/amy/bob/cam.cpp"
+ "C:/amy/bob/cam.cpp"
#else
- "/amy/bob/cam.cpp"
+ "/amy/bob/cam.cpp"
#endif
- ;
- std::string someAbbreviation = LLError::abbreviateFile(someFile);
+ ;
+ std::string someAbbreviation = LLError::abbreviateFile(someFile);
- ensure_equals("non-indra file abbreviation",
- someAbbreviation, someFile);
- }
+ ensure_equals("non-indra file abbreviation",
+ someAbbreviation, someFile);
+ }
}
namespace
{
- std::string locationString(int line)
- {
- std::ostringstream location;
- location << LLError::abbreviateFile(__FILE__)
- << "(" << line << ")";
-
- return location.str();
- }
-
- std::string writeReturningLocation()
- {
- LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__;
- return locationString(this_line);
- }
-
- void writeReturningLocationAndFunction(std::string& location, std::string& function)
- {
- LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__;
- location = locationString(this_line);
- function = __FUNCTION__;
- }
-
- std::string errorReturningLocation()
- {
- int this_line = __LINE__; CATCH(LL_ERRS(), "die");
- return locationString(this_line);
- }
+ std::string locationString(int line)
+ {
+ std::ostringstream location;
+ location << LLError::abbreviateFile(__FILE__)
+ << "(" << line << ")";
+
+ return location.str();
+ }
+
+ std::string writeReturningLocation()
+ {
+ LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__;
+ return locationString(this_line);
+ }
+
+ void writeReturningLocationAndFunction(std::string& location, std::string& function)
+ {
+ LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__;
+ location = locationString(this_line);
+ function = __FUNCTION__;
+ }
+
+ std::string errorReturningLocation()
+ {
+ int this_line = __LINE__; CATCH(LL_ERRS(), "die");
+ return locationString(this_line);
+ }
}
/* The following helper functions and class members all log a simple message
- from some particular function scope. Each function takes a bool argument
- that indicates if it should log its own name or not (in the manner that
- existing log messages often do.) The functions all return their C++
- name so that test can be substantial mechanized.
+ from some particular function scope. Each function takes a bool argument
+ that indicates if it should log its own name or not (in the manner that
+ existing log messages often do.) The functions all return their C++
+ name so that test can be substantial mechanized.
*/
std::string logFromGlobal(bool id)
{
- LL_INFOS() << (id ? "logFromGlobal: " : "") << "hi" << LL_ENDL;
- return "logFromGlobal";
+ LL_INFOS() << (id ? "logFromGlobal: " : "") << "hi" << LL_ENDL;
+ return "logFromGlobal";
}
static std::string logFromStatic(bool id)
{
- LL_INFOS() << (id ? "logFromStatic: " : "") << "hi" << LL_ENDL;
- return "logFromStatic";
+ LL_INFOS() << (id ? "logFromStatic: " : "") << "hi" << LL_ENDL;
+ return "logFromStatic";
}
namespace
{
- std::string logFromAnon(bool id)
- {
- LL_INFOS() << (id ? "logFromAnon: " : "") << "hi" << LL_ENDL;
- return "logFromAnon";
- }
+ std::string logFromAnon(bool id)
+ {
+ LL_INFOS() << (id ? "logFromAnon: " : "") << "hi" << LL_ENDL;
+ return "logFromAnon";
+ }
}
namespace Foo {
- std::string logFromNamespace(bool id)
- {
- LL_INFOS() << (id ? "Foo::logFromNamespace: " : "") << "hi" << LL_ENDL;
- //return "Foo::logFromNamespace";
- // there is no standard way to get the namespace name, hence
- // we won't be testing for it
- return "logFromNamespace";
- }
+ std::string logFromNamespace(bool id)
+ {
+ LL_INFOS() << (id ? "Foo::logFromNamespace: " : "") << "hi" << LL_ENDL;
+ //return "Foo::logFromNamespace";
+ // there is no standard way to get the namespace name, hence
+ // we won't be testing for it
+ return "logFromNamespace";
+ }
}
namespace
{
- class ClassWithNoLogType {
- public:
- std::string logFromMember(bool id)
- {
- LL_INFOS() << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << LL_ENDL;
- return "ClassWithNoLogType::logFromMember";
- }
- static std::string logFromStatic(bool id)
- {
- LL_INFOS() << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
- return "ClassWithNoLogType::logFromStatic";
- }
- };
-
- class ClassWithLogType {
- LOG_CLASS(ClassWithLogType);
- public:
- std::string logFromMember(bool id)
- {
- LL_INFOS() << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << LL_ENDL;
- return "ClassWithLogType::logFromMember";
- }
- static std::string logFromStatic(bool id)
- {
- LL_INFOS() << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
- return "ClassWithLogType::logFromStatic";
- }
- };
-
- std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); }
- std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); }
- std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); }
-
- void ensure_has(const std::string& message,
- const std::string& actual, const std::string& expected)
- {
- std::string::size_type n1 = actual.find(expected);
- if (n1 == std::string::npos)
- {
- std::stringstream ss;
- ss << message << ": " << "expected to find a copy of '" << expected
- << "' in actual '" << actual << "'";
- throw tut::failure(ss.str().c_str());
- }
- }
-
- typedef std::string (*LogFromFunction)(bool);
- void testLogName(LLError::RecorderPtr recorder, LogFromFunction f,
- const std::string& class_name = "")
- {
- std::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages();
- std::string name = f(false);
- f(true);
-
- std::string messageWithoutName = std::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0);
- std::string messageWithName = std::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1);
-
- ensure_has(name + " logged without name",
- messageWithoutName, name);
- ensure_has(name + " logged with name",
- messageWithName, name);
-
- if (!class_name.empty())
- {
- ensure_has(name + "logged without name",
- messageWithoutName, class_name);
- ensure_has(name + "logged with name",
- messageWithName, class_name);
- }
- }
+ class ClassWithNoLogType {
+ public:
+ std::string logFromMember(bool id)
+ {
+ LL_INFOS() << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << LL_ENDL;
+ return "ClassWithNoLogType::logFromMember";
+ }
+ static std::string logFromStatic(bool id)
+ {
+ LL_INFOS() << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
+ return "ClassWithNoLogType::logFromStatic";
+ }
+ };
+
+ class ClassWithLogType {
+ LOG_CLASS(ClassWithLogType);
+ public:
+ std::string logFromMember(bool id)
+ {
+ LL_INFOS() << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << LL_ENDL;
+ return "ClassWithLogType::logFromMember";
+ }
+ static std::string logFromStatic(bool id)
+ {
+ LL_INFOS() << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
+ return "ClassWithLogType::logFromStatic";
+ }
+ };
+
+ std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); }
+ std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); }
+ std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); }
+
+ void ensure_has(const std::string& message,
+ const std::string& actual, const std::string& expected)
+ {
+ std::string::size_type n1 = actual.find(expected);
+ if (n1 == std::string::npos)
+ {
+ std::stringstream ss;
+ ss << message << ": " << "expected to find a copy of '" << expected
+ << "' in actual '" << actual << "'";
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ typedef std::string (*LogFromFunction)(bool);
+ void testLogName(LLError::RecorderPtr recorder, LogFromFunction f,
+ const std::string& class_name = "")
+ {
+ std::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages();
+ std::string name = f(false);
+ f(true);
+
+ std::string messageWithoutName = std::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0);
+ std::string messageWithName = std::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1);
+
+ ensure_has(name + " logged without name",
+ messageWithoutName, name);
+ ensure_has(name + " logged with name",
+ messageWithName, name);
+
+ if (!class_name.empty())
+ {
+ ensure_has(name + "logged without name",
+ messageWithoutName, class_name);
+ ensure_has(name + "logged with name",
+ messageWithName, class_name);
+ }
+ }
}
namespace
@@ -578,7 +578,7 @@ namespace tut
// backslash, return, and newline are not escaped with backslashes
{
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- setWantsMultiline(true);
+ setWantsMultiline(true);
writeMsgNeedsEscaping(); // but should not be now
ensure_message_field_equals(0, MSG_FIELD, "backslash\\");
ensure_message_field_equals(1, MSG_FIELD, "newline\nafternewline");
@@ -592,329 +592,329 @@ namespace tut
namespace tut
{
- template<> template<>
- // class/function information in output
- void ErrorTestObject::test<6>()
- {
- testLogName(mRecorder, logFromGlobal);
- testLogName(mRecorder, logFromStatic);
- testLogName(mRecorder, logFromAnon);
- testLogName(mRecorder, logFromNamespace);
- testLogName(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType");
- testLogName(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType");
- }
+ template<> template<>
+ // class/function information in output
+ void ErrorTestObject::test<6>()
+ {
+ testLogName(mRecorder, logFromGlobal);
+ testLogName(mRecorder, logFromStatic);
+ testLogName(mRecorder, logFromAnon);
+ testLogName(mRecorder, logFromNamespace);
+ testLogName(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType");
+ testLogName(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType");
+ }
}
namespace
{
- std::string innerLogger()
- {
- LL_INFOS() << "inside" << LL_ENDL;
- return "moo";
- }
-
- std::string outerLogger()
- {
- LL_INFOS() << "outside(" << innerLogger() << ")" << LL_ENDL;
- return "bar";
- }
-
- class LogWhileLogging
- {
- public:
- void print(std::ostream& out) const
- {
- LL_INFOS() << "logging" << LL_ENDL;
- out << "baz";
- }
- };
-
- std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l)
- { l.print(out); return out; }
-
- void metaLogger()
- {
- LogWhileLogging l;
- LL_INFOS() << "meta(" << l << ")" << LL_ENDL;
- }
+ std::string innerLogger()
+ {
+ LL_INFOS() << "inside" << LL_ENDL;
+ return "moo";
+ }
+
+ std::string outerLogger()
+ {
+ LL_INFOS() << "outside(" << innerLogger() << ")" << LL_ENDL;
+ return "bar";
+ }
+
+ class LogWhileLogging
+ {
+ public:
+ void print(std::ostream& out) const
+ {
+ LL_INFOS() << "logging" << LL_ENDL;
+ out << "baz";
+ }
+ };
+
+ std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l)
+ { l.print(out); return out; }
+
+ void metaLogger()
+ {
+ LogWhileLogging l;
+ LL_INFOS() << "meta(" << l << ")" << LL_ENDL;
+ }
}
namespace tut
{
- template<> template<>
- // handle nested logging
- void ErrorTestObject::test<7>()
- {
- outerLogger();
- ensure_message_field_equals(0, MSG_FIELD, "inside");
- ensure_message_field_equals(1, MSG_FIELD, "outside(moo)");
- ensure_message_count(2);
-
- metaLogger();
- ensure_message_field_equals(2, MSG_FIELD, "logging");
- ensure_message_field_equals(3, MSG_FIELD, "meta(baz)");
- ensure_message_count(4);
- }
-
- template<> template<>
- // special handling of LL_ERRS() calls
- void ErrorTestObject::test<8>()
- {
- std::string location = errorReturningLocation();
-
- ensure_message_field_equals(0, LOCATION_FIELD, location);
- ensure_message_field_equals(0, MSG_FIELD, "die");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(2);
-
- ensure("fatal callback called", fatalWasCalled);
- }
+ template<> template<>
+ // handle nested logging
+ void ErrorTestObject::test<7>()
+ {
+ outerLogger();
+ ensure_message_field_equals(0, MSG_FIELD, "inside");
+ ensure_message_field_equals(1, MSG_FIELD, "outside(moo)");
+ ensure_message_count(2);
+
+ metaLogger();
+ ensure_message_field_equals(2, MSG_FIELD, "logging");
+ ensure_message_field_equals(3, MSG_FIELD, "meta(baz)");
+ ensure_message_count(4);
+ }
+
+ template<> template<>
+ // special handling of LL_ERRS() calls
+ void ErrorTestObject::test<8>()
+ {
+ std::string location = errorReturningLocation();
+
+ ensure_message_field_equals(0, LOCATION_FIELD, location);
+ ensure_message_field_equals(0, MSG_FIELD, "die");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(2);
+
+ ensure("fatal callback called", fatalWasCalled);
+ }
}
namespace
{
- std::string roswell()
- {
- return "1947-07-08T03:04:05Z";
- }
-
- void ufoSighting()
- {
- LL_INFOS() << "ufo" << LL_ENDL;
- }
+ std::string roswell()
+ {
+ return "1947-07-08T03:04:05Z";
+ }
+
+ void ufoSighting()
+ {
+ LL_INFOS() << "ufo" << LL_ENDL;
+ }
}
namespace tut
{
- template<> template<>
- // time in output (for recorders that need it)
- void ErrorTestObject::test<9>()
- {
- LLError::setTimeFunction(roswell);
-
- setWantsTime(false);
- ufoSighting();
- ensure_message_field_equals(0, MSG_FIELD, "ufo");
- ensure_message_does_not_contain(0, roswell());
-
- setWantsTime(true);
- ufoSighting();
- ensure_message_field_equals(1, MSG_FIELD, "ufo");
- ensure_message_field_equals(1, TIME_FIELD, roswell());
- }
-
- template<> template<>
- // output order
- void ErrorTestObject::test<10>()
- {
- LLError::setTimeFunction(roswell);
- setWantsTime(true);
-
- std::string location,
- function;
- writeReturningLocationAndFunction(location, function);
-
- ensure_equals("order is time level tags location function message",
+ template<> template<>
+ // time in output (for recorders that need it)
+ void ErrorTestObject::test<9>()
+ {
+ LLError::setTimeFunction(roswell);
+
+ setWantsTime(false);
+ ufoSighting();
+ ensure_message_field_equals(0, MSG_FIELD, "ufo");
+ ensure_message_does_not_contain(0, roswell());
+
+ setWantsTime(true);
+ ufoSighting();
+ ensure_message_field_equals(1, MSG_FIELD, "ufo");
+ ensure_message_field_equals(1, TIME_FIELD, roswell());
+ }
+
+ template<> template<>
+ // output order
+ void ErrorTestObject::test<10>()
+ {
+ LLError::setTimeFunction(roswell);
+ setWantsTime(true);
+
+ std::string location,
+ function;
+ writeReturningLocationAndFunction(location, function);
+
+ ensure_equals("order is time level tags location function message",
message(0),
roswell() + " INFO " + "# " /* no tag */ + location + " " + function + " : " + "apple");
- }
+ }
- template<> template<>
- // multiple recorders
- void ErrorTestObject::test<11>()
- {
- LLError::RecorderPtr altRecorder(new TestRecorder());
- LLError::addRecorder(altRecorder);
+ template<> template<>
+ // multiple recorders
+ void ErrorTestObject::test<11>()
+ {
+ LLError::RecorderPtr altRecorder(new TestRecorder());
+ LLError::addRecorder(altRecorder);
- LL_INFOS() << "boo" << LL_ENDL;
+ LL_INFOS() << "boo" << LL_ENDL;
- ensure_message_field_equals(0, MSG_FIELD, "boo");
- ensure_equals("alt recorder count", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1);
- ensure_contains("alt recorder message 0", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");
+ ensure_message_field_equals(0, MSG_FIELD, "boo");
+ ensure_equals("alt recorder count", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1);
+ ensure_contains("alt recorder message 0", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");
- LLError::setTimeFunction(roswell);
+ LLError::setTimeFunction(roswell);
- LLError::RecorderPtr anotherRecorder(new TestRecorder());
- std::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->showTime(true);
- LLError::addRecorder(anotherRecorder);
+ LLError::RecorderPtr anotherRecorder(new TestRecorder());
+ std::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->showTime(true);
+ LLError::addRecorder(anotherRecorder);
- LL_INFOS() << "baz" << LL_ENDL;
+ LL_INFOS() << "baz" << LL_ENDL;
- std::string when = roswell();
+ std::string when = roswell();
- ensure_message_does_not_contain(1, when);
- ensure_equals("alt recorder count", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2);
- ensure_does_not_contain("alt recorder message 1", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when);
- ensure_equals("another recorder count", std::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1);
- ensure_contains("another recorder message 0", std::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when);
+ ensure_message_does_not_contain(1, when);
+ ensure_equals("alt recorder count", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2);
+ ensure_does_not_contain("alt recorder message 1", std::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when);
+ ensure_equals("another recorder count", std::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1);
+ ensure_contains("another recorder message 0", std::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when);
- LLError::removeRecorder(altRecorder);
- LLError::removeRecorder(anotherRecorder);
- }
+ LLError::removeRecorder(altRecorder);
+ LLError::removeRecorder(anotherRecorder);
+ }
}
class TestAlpha
{
- LOG_CLASS(TestAlpha);
+ LOG_CLASS(TestAlpha);
public:
- static void doDebug() { LL_DEBUGS() << "add dice" << LL_ENDL; }
- static void doInfo() { LL_INFOS() << "any idea" << LL_ENDL; }
- static void doWarn() { LL_WARNS() << "aim west" << LL_ENDL; }
- static void doError() { CATCH(LL_ERRS(), "ate eels"); }
- static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
+ static void doDebug() { LL_DEBUGS() << "add dice" << LL_ENDL; }
+ static void doInfo() { LL_INFOS() << "any idea" << LL_ENDL; }
+ static void doWarn() { LL_WARNS() << "aim west" << LL_ENDL; }
+ static void doError() { CATCH(LL_ERRS(), "ate eels"); }
+ static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
};
class TestBeta
{
- LOG_CLASS(TestBeta);
+ LOG_CLASS(TestBeta);
public:
- static void doDebug() { LL_DEBUGS() << "bed down" << LL_ENDL; }
- static void doInfo() { LL_INFOS() << "buy iron" << LL_ENDL; }
- static void doWarn() { LL_WARNS() << "bad word" << LL_ENDL; }
- static void doError() { CATCH(LL_ERRS(), "big easy"); }
- static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
+ static void doDebug() { LL_DEBUGS() << "bed down" << LL_ENDL; }
+ static void doInfo() { LL_INFOS() << "buy iron" << LL_ENDL; }
+ static void doWarn() { LL_WARNS() << "bad word" << LL_ENDL; }
+ static void doError() { CATCH(LL_ERRS(), "big easy"); }
+ static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
};
namespace tut
{
- template<> template<>
- // filtering by class
- void ErrorTestObject::test<12>()
- {
- LLError::setDefaultLevel(LLError::LEVEL_WARN);
- LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO);
-
- TestAlpha::doAll();
- TestBeta::doAll();
-
- ensure_message_field_equals(0, MSG_FIELD, "aim west");
- ensure_message_field_equals(1, MSG_FIELD, "ate eels");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_field_equals(3, MSG_FIELD, "buy iron");
- ensure_message_field_equals(4, MSG_FIELD, "bad word");
- ensure_message_field_equals(5, MSG_FIELD, "big easy");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(7);
- }
-
- template<> template<>
- // filtering by function, and that it will override class filtering
- void ErrorTestObject::test<13>()
- {
- LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN);
- LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG);
- LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
-
- TestBeta::doAll();
- ensure_message_field_equals(0, MSG_FIELD, "buy iron");
- ensure_message_field_equals(1, MSG_FIELD, "bad word");
- ensure_message_count(2);
- }
-
- template<> template<>
- // filtering by file
- // and that it is overridden by both class and function filtering
- void ErrorTestObject::test<14>()
- {
- LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- LLError::setFileLevel(LLError::abbreviateFile(__FILE__),
- LLError::LEVEL_WARN);
- LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO);
- LLError::setFunctionLevel("TestAlpha::doError",
- LLError::LEVEL_NONE);
- LLError::setFunctionLevel("TestBeta::doError",
- LLError::LEVEL_NONE);
-
- TestAlpha::doAll();
- TestBeta::doAll();
- ensure_message_field_equals(0, MSG_FIELD, "any idea");
- ensure_message_field_equals(1, MSG_FIELD, "aim west");
- ensure_message_field_equals(2, MSG_FIELD, "bad word");
- ensure_message_count(3);
- }
-
- template<> template<>
- // proper cached, efficient lookup of filtering
- void ErrorTestObject::test<15>()
- {
- LLError::setDefaultLevel(LLError::LEVEL_NONE);
-
- TestAlpha::doInfo();
- ensure_message_count(0);
- ensure_equals("first check", LLError::shouldLogCallCount(), 1);
- TestAlpha::doInfo();
- ensure_message_count(0);
- ensure_equals("second check", LLError::shouldLogCallCount(), 1);
-
- LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
- TestAlpha::doInfo();
- ensure_message_count(1);
- ensure_equals("third check", LLError::shouldLogCallCount(), 2);
- TestAlpha::doInfo();
- ensure_message_count(2);
- ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
-
- LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
- TestAlpha::doInfo();
- ensure_message_count(2);
- ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
- TestAlpha::doInfo();
- ensure_message_count(2);
- ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
- }
-
- template<> template<>
- // configuration from LLSD
- void ErrorTestObject::test<16>()
- {
- LLSD config;
- config["print-location"] = true;
- config["default-level"] = "DEBUG";
-
- LLSD set1;
- set1["level"] = "WARN";
+ template<> template<>
+ // filtering by class
+ void ErrorTestObject::test<12>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_WARN);
+ LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+
+ ensure_message_field_equals(0, MSG_FIELD, "aim west");
+ ensure_message_field_equals(1, MSG_FIELD, "ate eels");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_field_equals(3, MSG_FIELD, "buy iron");
+ ensure_message_field_equals(4, MSG_FIELD, "bad word");
+ ensure_message_field_equals(5, MSG_FIELD, "big easy");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(7);
+ }
+
+ template<> template<>
+ // filtering by function, and that it will override class filtering
+ void ErrorTestObject::test<13>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN);
+ LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG);
+ LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
+
+ TestBeta::doAll();
+ ensure_message_field_equals(0, MSG_FIELD, "buy iron");
+ ensure_message_field_equals(1, MSG_FIELD, "bad word");
+ ensure_message_count(2);
+ }
+
+ template<> template<>
+ // filtering by file
+ // and that it is overridden by both class and function filtering
+ void ErrorTestObject::test<14>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ LLError::setFileLevel(LLError::abbreviateFile(__FILE__),
+ LLError::LEVEL_WARN);
+ LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO);
+ LLError::setFunctionLevel("TestAlpha::doError",
+ LLError::LEVEL_NONE);
+ LLError::setFunctionLevel("TestBeta::doError",
+ LLError::LEVEL_NONE);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+ ensure_message_field_equals(0, MSG_FIELD, "any idea");
+ ensure_message_field_equals(1, MSG_FIELD, "aim west");
+ ensure_message_field_equals(2, MSG_FIELD, "bad word");
+ ensure_message_count(3);
+ }
+
+ template<> template<>
+ // proper cached, efficient lookup of filtering
+ void ErrorTestObject::test<15>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+
+ TestAlpha::doInfo();
+ ensure_message_count(0);
+ ensure_equals("first check", LLError::shouldLogCallCount(), 1);
+ TestAlpha::doInfo();
+ ensure_message_count(0);
+ ensure_equals("second check", LLError::shouldLogCallCount(), 1);
+
+ LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
+ TestAlpha::doInfo();
+ ensure_message_count(1);
+ ensure_equals("third check", LLError::shouldLogCallCount(), 2);
+ TestAlpha::doInfo();
+ ensure_message_count(2);
+ ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
+
+ LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
+ TestAlpha::doInfo();
+ ensure_message_count(2);
+ ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
+ TestAlpha::doInfo();
+ ensure_message_count(2);
+ ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
+ }
+
+ template<> template<>
+ // configuration from LLSD
+ void ErrorTestObject::test<16>()
+ {
+ LLSD config;
+ config["print-location"] = true;
+ config["default-level"] = "DEBUG";
+
+ LLSD set1;
+ set1["level"] = "WARN";
set1["files"][0] = LLError::abbreviateFile(__FILE__);
- LLSD set2;
- set2["level"] = "INFO";
- set2["classes"][0] = "TestAlpha";
-
- LLSD set3;
- set3["level"] = "NONE";
- set3["functions"][0] = "TestAlpha::doError";
- set3["functions"][1] = "TestBeta::doError";
-
- config["settings"][0] = set1;
- config["settings"][1] = set2;
- config["settings"][2] = set3;
-
- LLError::configure(config);
-
- TestAlpha::doAll();
- TestBeta::doAll();
- ensure_message_field_equals(0, MSG_FIELD, "any idea");
- ensure_message_field_equals(1, MSG_FIELD, "aim west");
- ensure_message_field_equals(2, MSG_FIELD, "bad word");
- ensure_message_count(3);
-
- // make sure reconfiguring works
- LLSD config2;
- config2["default-level"] = "WARN";
-
- LLError::configure(config2);
-
- TestAlpha::doAll();
- TestBeta::doAll();
- ensure_message_field_equals(3, MSG_FIELD, "aim west");
- ensure_message_field_equals(4, MSG_FIELD, "ate eels");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_field_equals(6, MSG_FIELD, "bad word");
- ensure_message_field_equals(7, MSG_FIELD, "big easy");
- // LL_ERRS() produces 2 recordMessage() calls
- ensure_message_count(9);
- }
+ LLSD set2;
+ set2["level"] = "INFO";
+ set2["classes"][0] = "TestAlpha";
+
+ LLSD set3;
+ set3["level"] = "NONE";
+ set3["functions"][0] = "TestAlpha::doError";
+ set3["functions"][1] = "TestBeta::doError";
+
+ config["settings"][0] = set1;
+ config["settings"][1] = set2;
+ config["settings"][2] = set3;
+
+ LLError::configure(config);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+ ensure_message_field_equals(0, MSG_FIELD, "any idea");
+ ensure_message_field_equals(1, MSG_FIELD, "aim west");
+ ensure_message_field_equals(2, MSG_FIELD, "bad word");
+ ensure_message_count(3);
+
+ // make sure reconfiguring works
+ LLSD config2;
+ config2["default-level"] = "WARN";
+
+ LLError::configure(config2);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+ ensure_message_field_equals(3, MSG_FIELD, "aim west");
+ ensure_message_field_equals(4, MSG_FIELD, "ate eels");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_field_equals(6, MSG_FIELD, "bad word");
+ ensure_message_field_equals(7, MSG_FIELD, "big easy");
+ // LL_ERRS() produces 2 recordMessage() calls
+ ensure_message_count(9);
+ }
}
namespace tut
@@ -962,16 +962,16 @@ namespace tut
}
/* Tests left:
- handling of classes without LOG_CLASS
+ handling of classes without LOG_CLASS
- live update of filtering from file
+ live update of filtering from file
- syslog recorder
- file recorder
- cerr/stderr recorder
- fixed buffer recorder
- windows recorder
+ syslog recorder
+ file recorder
+ cerr/stderr recorder
+ fixed buffer recorder
+ windows recorder
- mutex use when logging (?)
- strange careful about to crash handling (?)
+ mutex use when logging (?)
+ strange careful about to crash handling (?)
*/
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index bff647cbe8..01c4dd96ac 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdserialize_test.cpp
* @date 2006-04
* @brief LLSDSerialize unit tests
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -62,313 +62,313 @@ typedef std::function<bool(std::istream& istr, LLSD& data, llssize max_bytes)> P
std::vector<U8> string_to_vector(const std::string& str)
{
- return std::vector<U8>(str.begin(), str.end());
+ return std::vector<U8>(str.begin(), str.end());
}
namespace tut
{
- struct sd_xml_data
- {
- sd_xml_data()
- {
- mFormatter = new LLSDXMLFormatter;
- }
- LLSD mSD;
- LLPointer<LLSDXMLFormatter> mFormatter;
- void xml_test(const char* name, const std::string& expected)
- {
- std::ostringstream ostr;
- mFormatter->format(mSD, ostr);
- ensure_equals(name, ostr.str(), expected);
- }
- };
-
- typedef test_group<sd_xml_data> sd_xml_test;
- typedef sd_xml_test::object sd_xml_object;
- tut::sd_xml_test sd_xml_stream("LLSDXMLFormatter");
-
- template<> template<>
- void sd_xml_object::test<1>()
- {
- // random atomic tests
- std::string expected;
-
- expected = "<llsd><undef /></llsd>\n";
- xml_test("undef", expected);
-
- mSD = 3463;
- expected = "<llsd><integer>3463</integer></llsd>\n";
- xml_test("integer", expected);
-
- mSD = "";
- expected = "<llsd><string /></llsd>\n";
- xml_test("empty string", expected);
-
- mSD = "foobar";
- expected = "<llsd><string>foobar</string></llsd>\n";
- xml_test("string", expected);
-
- mSD = LLUUID::null;
- expected = "<llsd><uuid /></llsd>\n";
- xml_test("null uuid", expected);
-
- mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
- expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
- xml_test("uuid", expected);
-
- mSD = LLURI("https://secondlife.com/login");
- expected = "<llsd><uri>https://secondlife.com/login</uri></llsd>\n";
- xml_test("uri", expected);
-
- mSD = LLDate("2006-04-24T16:11:33Z");
- expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
- xml_test("date", expected);
-
- // Generated by: echo -n 'hello' | openssl enc -e -base64
- std::vector<U8> hello;
- hello.push_back('h');
- hello.push_back('e');
- hello.push_back('l');
- hello.push_back('l');
- hello.push_back('o');
- mSD = hello;
- expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
- xml_test("binary", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<2>()
- {
- // tests with boolean values.
- std::string expected;
-
- mFormatter->boolalpha(true);
- mSD = true;
- expected = "<llsd><boolean>true</boolean></llsd>\n";
- xml_test("bool alpha true", expected);
- mSD = false;
- expected = "<llsd><boolean>false</boolean></llsd>\n";
- xml_test("bool alpha false", expected);
-
- mFormatter->boolalpha(false);
- mSD = true;
- expected = "<llsd><boolean>1</boolean></llsd>\n";
- xml_test("bool true", expected);
- mSD = false;
- expected = "<llsd><boolean>0</boolean></llsd>\n";
- xml_test("bool false", expected);
- }
-
-
- template<> template<>
- void sd_xml_object::test<3>()
- {
- // tests with real values.
- std::string expected;
-
- mFormatter->realFormat("%.2f");
- mSD = 1.0;
- expected = "<llsd><real>1.00</real></llsd>\n";
- xml_test("real 1", expected);
-
- mSD = -34379.0438;
- expected = "<llsd><real>-34379.04</real></llsd>\n";
- xml_test("real reduced precision", expected);
- mFormatter->realFormat("%.4f");
- expected = "<llsd><real>-34379.0438</real></llsd>\n";
- xml_test("higher precision", expected);
-
- mFormatter->realFormat("%.0f");
- mSD = 0.0;
- expected = "<llsd><real>0</real></llsd>\n";
- xml_test("no decimal 0", expected);
- mSD = 3287.4387;
- expected = "<llsd><real>3287</real></llsd>\n";
- xml_test("no decimal real number", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<4>()
- {
- // tests with arrays
- std::string expected;
-
- mSD = LLSD::emptyArray();
- expected = "<llsd><array /></llsd>\n";
- xml_test("empty array", expected);
-
- mSD.append(LLSD());
- expected = "<llsd><array><undef /></array></llsd>\n";
- xml_test("1 element array", expected);
-
- mSD.append(1);
- expected = "<llsd><array><undef /><integer>1</integer></array></llsd>\n";
- xml_test("2 element array", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<5>()
- {
- // tests with arrays
- std::string expected;
-
- mSD = LLSD::emptyMap();
- expected = "<llsd><map /></llsd>\n";
- xml_test("empty map", expected);
-
- mSD["foo"] = "bar";
- expected = "<llsd><map><key>foo</key><string>bar</string></map></llsd>\n";
- xml_test("1 element map", expected);
-
- mSD["baz"] = LLSD();
- expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
- xml_test("2 element map", expected);
- }
-
- template<> template<>
- void sd_xml_object::test<6>()
- {
- // tests with binary
- std::string expected;
-
- // Generated by: echo -n 'hello' | openssl enc -e -base64
- mSD = string_to_vector("hello");
- expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
- xml_test("binary", expected);
-
- mSD = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
- expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
- xml_test("binary", expected);
- }
-
- class TestLLSDSerializeData
- {
- public:
- TestLLSDSerializeData();
- ~TestLLSDSerializeData();
-
- void doRoundTripTests(const std::string&);
- void checkRoundTrip(const std::string&, const LLSD& v);
-
- void setFormatterParser(LLPointer<LLSDFormatter> formatter, LLPointer<LLSDParser> parser)
- {
- mFormatter = [formatter](const LLSD& data, std::ostream& str)
- {
- formatter->format(data, str);
- };
- // this lambda must be mutable since otherwise the bound 'parser'
- // is assumed to point to a const LLSDParser
- mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable
- {
- // reset() call is needed since test code re-uses parser object
- parser->reset();
- return (parser->parse(istr, data, max_bytes) > 0);
- };
- }
-
- void setParser(bool (*parser)(LLSD&, std::istream&, llssize))
- {
- // why does LLSDSerialize::deserialize() reverse the parse() params??
- mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes)
- {
- return parser(data, istr, max_bytes);
- };
- }
-
- FormatterFunction mFormatter;
- ParserFunction mParser;
- };
-
- TestLLSDSerializeData::TestLLSDSerializeData()
- {
- }
-
- TestLLSDSerializeData::~TestLLSDSerializeData()
- {
- }
-
- void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
- {
- std::stringstream stream;
- mFormatter(v, stream);
- //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
- LLSD w;
- mParser(stream, w, stream.str().size());
-
- try
- {
- ensure_equals(msg, w, v);
- }
- catch (...)
- {
- std::cerr << "the serialized string was:" << std::endl;
- std::cerr << stream.str() << std::endl;
- throw;
- }
- }
-
- static void fillmap(LLSD& root, U32 width, U32 depth)
- {
- if(depth == 0)
- {
- root["foo"] = "bar";
- return;
- }
-
- for(U32 i = 0; i < width; ++i)
- {
- std::string key = llformat("child %d", i);
- root[key] = LLSD::emptyMap();
- fillmap(root[key], width, depth - 1);
- }
- }
-
- void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
- {
- LLSD v;
- checkRoundTrip(msg + " undefined", v);
-
- v = true;
- checkRoundTrip(msg + " true bool", v);
-
- v = false;
- checkRoundTrip(msg + " false bool", v);
-
- v = 1;
- checkRoundTrip(msg + " positive int", v);
-
- v = 0;
- checkRoundTrip(msg + " zero int", v);
-
- v = -1;
- checkRoundTrip(msg + " negative int", v);
-
- v = 1234.5f;
- checkRoundTrip(msg + " positive float", v);
-
- v = 0.0f;
- checkRoundTrip(msg + " zero float", v);
-
- v = -1234.5f;
- checkRoundTrip(msg + " negative float", v);
-
- // FIXME: need a NaN test
-
- v = LLUUID::null;
- checkRoundTrip(msg + " null uuid", v);
-
- LLUUID newUUID;
- newUUID.generate();
- v = newUUID;
- checkRoundTrip(msg + " new uuid", v);
-
- v = "";
- checkRoundTrip(msg + " empty string", v);
-
- v = "some string";
- checkRoundTrip(msg + " non-empty string", v);
-
- v =
+ struct sd_xml_data
+ {
+ sd_xml_data()
+ {
+ mFormatter = new LLSDXMLFormatter;
+ }
+ LLSD mSD;
+ LLPointer<LLSDXMLFormatter> mFormatter;
+ void xml_test(const char* name, const std::string& expected)
+ {
+ std::ostringstream ostr;
+ mFormatter->format(mSD, ostr);
+ ensure_equals(name, ostr.str(), expected);
+ }
+ };
+
+ typedef test_group<sd_xml_data> sd_xml_test;
+ typedef sd_xml_test::object sd_xml_object;
+ tut::sd_xml_test sd_xml_stream("LLSDXMLFormatter");
+
+ template<> template<>
+ void sd_xml_object::test<1>()
+ {
+ // random atomic tests
+ std::string expected;
+
+ expected = "<llsd><undef /></llsd>\n";
+ xml_test("undef", expected);
+
+ mSD = 3463;
+ expected = "<llsd><integer>3463</integer></llsd>\n";
+ xml_test("integer", expected);
+
+ mSD = "";
+ expected = "<llsd><string /></llsd>\n";
+ xml_test("empty string", expected);
+
+ mSD = "foobar";
+ expected = "<llsd><string>foobar</string></llsd>\n";
+ xml_test("string", expected);
+
+ mSD = LLUUID::null;
+ expected = "<llsd><uuid /></llsd>\n";
+ xml_test("null uuid", expected);
+
+ mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
+ expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
+ xml_test("uuid", expected);
+
+ mSD = LLURI("https://secondlife.com/login");
+ expected = "<llsd><uri>https://secondlife.com/login</uri></llsd>\n";
+ xml_test("uri", expected);
+
+ mSD = LLDate("2006-04-24T16:11:33Z");
+ expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
+ xml_test("date", expected);
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ std::vector<U8> hello;
+ hello.push_back('h');
+ hello.push_back('e');
+ hello.push_back('l');
+ hello.push_back('l');
+ hello.push_back('o');
+ mSD = hello;
+ expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ xml_test("binary", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<2>()
+ {
+ // tests with boolean values.
+ std::string expected;
+
+ mFormatter->boolalpha(true);
+ mSD = true;
+ expected = "<llsd><boolean>true</boolean></llsd>\n";
+ xml_test("bool alpha true", expected);
+ mSD = false;
+ expected = "<llsd><boolean>false</boolean></llsd>\n";
+ xml_test("bool alpha false", expected);
+
+ mFormatter->boolalpha(false);
+ mSD = true;
+ expected = "<llsd><boolean>1</boolean></llsd>\n";
+ xml_test("bool true", expected);
+ mSD = false;
+ expected = "<llsd><boolean>0</boolean></llsd>\n";
+ xml_test("bool false", expected);
+ }
+
+
+ template<> template<>
+ void sd_xml_object::test<3>()
+ {
+ // tests with real values.
+ std::string expected;
+
+ mFormatter->realFormat("%.2f");
+ mSD = 1.0;
+ expected = "<llsd><real>1.00</real></llsd>\n";
+ xml_test("real 1", expected);
+
+ mSD = -34379.0438;
+ expected = "<llsd><real>-34379.04</real></llsd>\n";
+ xml_test("real reduced precision", expected);
+ mFormatter->realFormat("%.4f");
+ expected = "<llsd><real>-34379.0438</real></llsd>\n";
+ xml_test("higher precision", expected);
+
+ mFormatter->realFormat("%.0f");
+ mSD = 0.0;
+ expected = "<llsd><real>0</real></llsd>\n";
+ xml_test("no decimal 0", expected);
+ mSD = 3287.4387;
+ expected = "<llsd><real>3287</real></llsd>\n";
+ xml_test("no decimal real number", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<4>()
+ {
+ // tests with arrays
+ std::string expected;
+
+ mSD = LLSD::emptyArray();
+ expected = "<llsd><array /></llsd>\n";
+ xml_test("empty array", expected);
+
+ mSD.append(LLSD());
+ expected = "<llsd><array><undef /></array></llsd>\n";
+ xml_test("1 element array", expected);
+
+ mSD.append(1);
+ expected = "<llsd><array><undef /><integer>1</integer></array></llsd>\n";
+ xml_test("2 element array", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<5>()
+ {
+ // tests with arrays
+ std::string expected;
+
+ mSD = LLSD::emptyMap();
+ expected = "<llsd><map /></llsd>\n";
+ xml_test("empty map", expected);
+
+ mSD["foo"] = "bar";
+ expected = "<llsd><map><key>foo</key><string>bar</string></map></llsd>\n";
+ xml_test("1 element map", expected);
+
+ mSD["baz"] = LLSD();
+ expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
+ xml_test("2 element map", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<6>()
+ {
+ // tests with binary
+ std::string expected;
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ mSD = string_to_vector("hello");
+ expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ xml_test("binary", expected);
+
+ mSD = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ xml_test("binary", expected);
+ }
+
+ class TestLLSDSerializeData
+ {
+ public:
+ TestLLSDSerializeData();
+ ~TestLLSDSerializeData();
+
+ void doRoundTripTests(const std::string&);
+ void checkRoundTrip(const std::string&, const LLSD& v);
+
+ void setFormatterParser(LLPointer<LLSDFormatter> formatter, LLPointer<LLSDParser> parser)
+ {
+ mFormatter = [formatter](const LLSD& data, std::ostream& str)
+ {
+ formatter->format(data, str);
+ };
+ // this lambda must be mutable since otherwise the bound 'parser'
+ // is assumed to point to a const LLSDParser
+ mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable
+ {
+ // reset() call is needed since test code re-uses parser object
+ parser->reset();
+ return (parser->parse(istr, data, max_bytes) > 0);
+ };
+ }
+
+ void setParser(bool (*parser)(LLSD&, std::istream&, llssize))
+ {
+ // why does LLSDSerialize::deserialize() reverse the parse() params??
+ mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes)
+ {
+ return parser(data, istr, max_bytes);
+ };
+ }
+
+ FormatterFunction mFormatter;
+ ParserFunction mParser;
+ };
+
+ TestLLSDSerializeData::TestLLSDSerializeData()
+ {
+ }
+
+ TestLLSDSerializeData::~TestLLSDSerializeData()
+ {
+ }
+
+ void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
+ {
+ std::stringstream stream;
+ mFormatter(v, stream);
+ //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
+ LLSD w;
+ mParser(stream, w, stream.str().size());
+
+ try
+ {
+ ensure_equals(msg, w, v);
+ }
+ catch (...)
+ {
+ std::cerr << "the serialized string was:" << std::endl;
+ std::cerr << stream.str() << std::endl;
+ throw;
+ }
+ }
+
+ static void fillmap(LLSD& root, U32 width, U32 depth)
+ {
+ if(depth == 0)
+ {
+ root["foo"] = "bar";
+ return;
+ }
+
+ for(U32 i = 0; i < width; ++i)
+ {
+ std::string key = llformat("child %d", i);
+ root[key] = LLSD::emptyMap();
+ fillmap(root[key], width, depth - 1);
+ }
+ }
+
+ void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
+ {
+ LLSD v;
+ checkRoundTrip(msg + " undefined", v);
+
+ v = true;
+ checkRoundTrip(msg + " true bool", v);
+
+ v = false;
+ checkRoundTrip(msg + " false bool", v);
+
+ v = 1;
+ checkRoundTrip(msg + " positive int", v);
+
+ v = 0;
+ checkRoundTrip(msg + " zero int", v);
+
+ v = -1;
+ checkRoundTrip(msg + " negative int", v);
+
+ v = 1234.5f;
+ checkRoundTrip(msg + " positive float", v);
+
+ v = 0.0f;
+ checkRoundTrip(msg + " zero float", v);
+
+ v = -1234.5f;
+ checkRoundTrip(msg + " negative float", v);
+
+ // FIXME: need a NaN test
+
+ v = LLUUID::null;
+ checkRoundTrip(msg + " null uuid", v);
+
+ LLUUID newUUID;
+ newUUID.generate();
+ v = newUUID;
+ checkRoundTrip(msg + " new uuid", v);
+
+ v = "";
+ checkRoundTrip(msg + " empty string", v);
+
+ v = "some string";
+ checkRoundTrip(msg + " non-empty string", v);
+
+ v =
"Second Life is a 3-D virtual world entirely built and owned by its residents. "
"Since opening to the public in 2003, it has grown explosively and today is "
"inhabited by nearly 100,000 people from around the globe.\n"
@@ -388,437 +388,437 @@ namespace tut
"currency exchanges.\n"
"\n"
"Welcome to Second Life. We look forward to seeing you in-world!\n"
- ;
- checkRoundTrip(msg + " long string", v);
-
- static const U32 block_size = 0x000020;
- for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
- {
- std::ostringstream out;
-
- for (U32 c = block; c < block + block_size; ++c)
- {
- if (c <= 0x000001f
- && c != 0x000009
- && c != 0x00000a)
- {
- // see XML standard, sections 2.2 and 4.1
- continue;
- }
- if (0x00d800 <= c && c <= 0x00dfff) { continue; }
- if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
- if ((c & 0x00fffe) == 0x00fffe) { continue; }
- // see Unicode standard, section 15.8
-
- if (c <= 0x00007f)
- {
- out << (char)(c & 0x7f);
- }
- else if (c <= 0x0007ff)
- {
- out << (char)(0xc0 | ((c >> 6) & 0x1f));
- out << (char)(0x80 | ((c >> 0) & 0x3f));
- }
- else if (c <= 0x00ffff)
- {
- out << (char)(0xe0 | ((c >> 12) & 0x0f));
- out << (char)(0x80 | ((c >> 6) & 0x3f));
- out << (char)(0x80 | ((c >> 0) & 0x3f));
- }
- else
- {
- out << (char)(0xf0 | ((c >> 18) & 0x07));
- out << (char)(0x80 | ((c >> 12) & 0x3f));
- out << (char)(0x80 | ((c >> 6) & 0x3f));
- out << (char)(0x80 | ((c >> 0) & 0x3f));
- }
- }
-
- v = out.str();
-
- std::ostringstream blockmsg;
- blockmsg << msg << " unicode string block 0x" << std::hex << block;
- checkRoundTrip(blockmsg.str(), v);
- }
-
- LLDate epoch;
- v = epoch;
- checkRoundTrip(msg + " epoch date", v);
-
- LLDate aDay("2002-12-07T05:07:15.00Z");
- v = aDay;
- checkRoundTrip(msg + " date", v);
-
- LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
- v = path;
- checkRoundTrip(msg + " url", v);
-
- const char source[] = "it must be a blue moon again";
- std::vector<U8> data;
- // note, includes terminating '\0'
- copy(&source[0], &source[sizeof(source)], back_inserter(data));
-
- v = data;
- checkRoundTrip(msg + " binary", v);
-
- v = LLSD::emptyMap();
- checkRoundTrip(msg + " empty map", v);
-
- v = LLSD::emptyMap();
- v["name"] = "luke"; //v.insert("name", "luke");
- v["age"] = 3; //v.insert("age", 3);
- checkRoundTrip(msg + " map", v);
-
- v.clear();
- v["a"]["1"] = true;
- v["b"]["0"] = false;
- checkRoundTrip(msg + " nested maps", v);
-
- v = LLSD::emptyArray();
- checkRoundTrip(msg + " empty array", v);
-
- v = LLSD::emptyArray();
- v.append("ali");
- v.append(28);
- checkRoundTrip(msg + " array", v);
-
- v.clear();
- v[0][0] = true;
- v[1][0] = false;
- checkRoundTrip(msg + " nested arrays", v);
-
- v = LLSD::emptyMap();
- fillmap(v, 10, 3); // 10^6 maps
- checkRoundTrip(msg + " many nested maps", v);
- }
-
- typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerializeGroup;
- typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject;
- TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization");
-
- template<> template<>
- void TestLLSDSerializeObject::test<1>()
- {
- setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY),
- new LLSDNotationParser());
- doRoundTripTests("pretty binary notation serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<2>()
- {
- setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDNotationParser());
- doRoundTripTests("raw binary notation serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<3>()
- {
- setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser());
- doRoundTripTests("xml serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<4>()
- {
- setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser());
- doRoundTripTests("binary serialization");
- }
-
- template<> template<>
- void TestLLSDSerializeObject::test<5>()
- {
- mFormatter = [](const LLSD& sd, std::ostream& str)
- {
- LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY);
- };
- setParser(LLSDSerialize::deserialize);
- doRoundTripTests("serialize(LLSD_BINARY)");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<6>()
- {
- mFormatter = [](const LLSD& sd, std::ostream& str)
- {
- LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML);
- };
- setParser(LLSDSerialize::deserialize);
- doRoundTripTests("serialize(LLSD_XML)");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<7>()
- {
- mFormatter = [](const LLSD& sd, std::ostream& str)
- {
- LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION);
- };
- setParser(LLSDSerialize::deserialize);
- // In this test, serialize(LLSD_NOTATION) emits a header recognized by
- // deserialize().
- doRoundTripTests("serialize(LLSD_NOTATION)");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<8>()
- {
- setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDNotationParser());
- setParser(LLSDSerialize::deserialize);
- // This is an interesting test because LLSDNotationFormatter does not
- // emit an llsd/notation header.
- doRoundTripTests("LLSDNotationFormatter -> deserialize");
- };
-
- template<> template<>
- void TestLLSDSerializeObject::test<9>()
- {
- setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDXMLParser());
- setParser(LLSDSerialize::deserialize);
- // This is an interesting test because LLSDXMLFormatter does not
- // emit an LLSD/XML header.
- doRoundTripTests("LLSDXMLFormatter -> deserialize");
- };
+ ;
+ checkRoundTrip(msg + " long string", v);
+
+ static const U32 block_size = 0x000020;
+ for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
+ {
+ std::ostringstream out;
+
+ for (U32 c = block; c < block + block_size; ++c)
+ {
+ if (c <= 0x000001f
+ && c != 0x000009
+ && c != 0x00000a)
+ {
+ // see XML standard, sections 2.2 and 4.1
+ continue;
+ }
+ if (0x00d800 <= c && c <= 0x00dfff) { continue; }
+ if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
+ if ((c & 0x00fffe) == 0x00fffe) { continue; }
+ // see Unicode standard, section 15.8
+
+ if (c <= 0x00007f)
+ {
+ out << (char)(c & 0x7f);
+ }
+ else if (c <= 0x0007ff)
+ {
+ out << (char)(0xc0 | ((c >> 6) & 0x1f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ else if (c <= 0x00ffff)
+ {
+ out << (char)(0xe0 | ((c >> 12) & 0x0f));
+ out << (char)(0x80 | ((c >> 6) & 0x3f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ else
+ {
+ out << (char)(0xf0 | ((c >> 18) & 0x07));
+ out << (char)(0x80 | ((c >> 12) & 0x3f));
+ out << (char)(0x80 | ((c >> 6) & 0x3f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ }
+
+ v = out.str();
+
+ std::ostringstream blockmsg;
+ blockmsg << msg << " unicode string block 0x" << std::hex << block;
+ checkRoundTrip(blockmsg.str(), v);
+ }
+
+ LLDate epoch;
+ v = epoch;
+ checkRoundTrip(msg + " epoch date", v);
+
+ LLDate aDay("2002-12-07T05:07:15.00Z");
+ v = aDay;
+ checkRoundTrip(msg + " date", v);
+
+ LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
+ v = path;
+ checkRoundTrip(msg + " url", v);
+
+ const char source[] = "it must be a blue moon again";
+ std::vector<U8> data;
+ // note, includes terminating '\0'
+ copy(&source[0], &source[sizeof(source)], back_inserter(data));
+
+ v = data;
+ checkRoundTrip(msg + " binary", v);
+
+ v = LLSD::emptyMap();
+ checkRoundTrip(msg + " empty map", v);
+
+ v = LLSD::emptyMap();
+ v["name"] = "luke"; //v.insert("name", "luke");
+ v["age"] = 3; //v.insert("age", 3);
+ checkRoundTrip(msg + " map", v);
+
+ v.clear();
+ v["a"]["1"] = true;
+ v["b"]["0"] = false;
+ checkRoundTrip(msg + " nested maps", v);
+
+ v = LLSD::emptyArray();
+ checkRoundTrip(msg + " empty array", v);
+
+ v = LLSD::emptyArray();
+ v.append("ali");
+ v.append(28);
+ checkRoundTrip(msg + " array", v);
+
+ v.clear();
+ v[0][0] = true;
+ v[1][0] = false;
+ checkRoundTrip(msg + " nested arrays", v);
+
+ v = LLSD::emptyMap();
+ fillmap(v, 10, 3); // 10^6 maps
+ checkRoundTrip(msg + " many nested maps", v);
+ }
+
+ typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerializeGroup;
+ typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject;
+ TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization");
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<1>()
+ {
+ setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY),
+ new LLSDNotationParser());
+ doRoundTripTests("pretty binary notation serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<2>()
+ {
+ setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDNotationParser());
+ doRoundTripTests("raw binary notation serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<3>()
+ {
+ setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser());
+ doRoundTripTests("xml serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<4>()
+ {
+ setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser());
+ doRoundTripTests("binary serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<5>()
+ {
+ mFormatter = [](const LLSD& sd, std::ostream& str)
+ {
+ LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY);
+ };
+ setParser(LLSDSerialize::deserialize);
+ doRoundTripTests("serialize(LLSD_BINARY)");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<6>()
+ {
+ mFormatter = [](const LLSD& sd, std::ostream& str)
+ {
+ LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML);
+ };
+ setParser(LLSDSerialize::deserialize);
+ doRoundTripTests("serialize(LLSD_XML)");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<7>()
+ {
+ mFormatter = [](const LLSD& sd, std::ostream& str)
+ {
+ LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION);
+ };
+ setParser(LLSDSerialize::deserialize);
+ // In this test, serialize(LLSD_NOTATION) emits a header recognized by
+ // deserialize().
+ doRoundTripTests("serialize(LLSD_NOTATION)");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<8>()
+ {
+ setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDNotationParser());
+ setParser(LLSDSerialize::deserialize);
+ // This is an interesting test because LLSDNotationFormatter does not
+ // emit an llsd/notation header.
+ doRoundTripTests("LLSDNotationFormatter -> deserialize");
+ };
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<9>()
+ {
+ setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDXMLParser());
+ setParser(LLSDSerialize::deserialize);
+ // This is an interesting test because LLSDXMLFormatter does not
+ // emit an LLSD/XML header.
+ doRoundTripTests("LLSDXMLFormatter -> deserialize");
+ };
/*==========================================================================*|
- // We do not expect this test to succeed. Without a header, neither
- // notation LLSD nor binary LLSD reliably start with a distinct character,
- // the way XML LLSD starts with '<'. By convention, we default to notation
- // rather than binary.
- template<> template<>
- void TestLLSDSerializeObject::test<10>()
- {
- setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
- new LLSDBinaryParser());
- setParser(LLSDSerialize::deserialize);
- // This is an interesting test because LLSDBinaryFormatter does not
- // emit an LLSD/Binary header.
- doRoundTripTests("LLSDBinaryFormatter -> deserialize");
- };
+ // We do not expect this test to succeed. Without a header, neither
+ // notation LLSD nor binary LLSD reliably start with a distinct character,
+ // the way XML LLSD starts with '<'. By convention, we default to notation
+ // rather than binary.
+ template<> template<>
+ void TestLLSDSerializeObject::test<10>()
+ {
+ setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
+ new LLSDBinaryParser());
+ setParser(LLSDSerialize::deserialize);
+ // This is an interesting test because LLSDBinaryFormatter does not
+ // emit an LLSD/Binary header.
+ doRoundTripTests("LLSDBinaryFormatter -> deserialize");
+ };
|*==========================================================================*/
- /**
- * @class TestLLSDParsing
- * @brief Base class for of a parse tester.
- */
- template <class parser_t>
- class TestLLSDParsing
- {
- public:
- TestLLSDParsing()
- {
- mParser = new parser_t;
- }
-
- void ensureParse(
- const std::string& msg,
- const std::string& in,
- const LLSD& expected_value,
- S32 expected_count,
- S32 depth_limit = -1)
- {
- std::stringstream input;
- input.str(in);
-
- LLSD parsed_result;
- mParser->reset(); // reset() call is needed since test code re-uses mParser
- S32 parsed_count = mParser->parse(input, parsed_result, in.size(), depth_limit);
- ensure_equals(msg.c_str(), parsed_result, expected_value);
-
- // This count check is really only useful for expected
- // parse failures, since the ensures equal will already
- // require equality.
- std::string count_msg(msg);
- count_msg += " (count)";
- ensure_equals(count_msg, parsed_count, expected_count);
- }
-
- LLPointer<parser_t> mParser;
- };
-
-
- /**
- * @class TestLLSDXMLParsing
- * @brief Concrete instance of a parse tester.
- */
- class TestLLSDXMLParsing : public TestLLSDParsing<LLSDXMLParser>
- {
- public:
- TestLLSDXMLParsing() {}
- };
-
- typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
- typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
- TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<1>()
- {
- // test handling of xml not recognized as llsd results in an
- // LLSD Undefined
- ensureParse(
- "malformed xml",
- "<llsd><string>ha ha</string>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "not llsd",
- "<html><body><p>ha ha</p></body></html>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "value without llsd",
- "<string>ha ha</string>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "key without llsd",
- "<key>ha ha</key>",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<2>()
- {
- // test handling of unrecognized or unparseable llsd values
- LLSD v;
- v["amy"] = 23;
- v["bob"] = LLSD();
- v["cam"] = 1.23;
-
- ensureParse(
- "unknown data type",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<key>bob</key><bigint>99999999999999999</bigint>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
- }
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<3>()
- {
- // test handling of nested bad data
-
- LLSD v;
- v["amy"] = 23;
- v["cam"] = 1.23;
-
- ensureParse(
- "map with html",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<html><body>ha ha</body></html>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v["amy"] = 23;
- v["cam"] = 1.23;
- ensureParse(
- "map with value for key",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<string>ha ha</string>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v["amy"] = 23;
- v["bob"] = LLSD::emptyMap();
- v["cam"] = 1.23;
- ensureParse(
- "map with map of html",
- "<llsd><map>"
- "<key>amy</key><integer>23</integer>"
- "<key>bob</key>"
- "<map>"
- "<html><body>ha ha</body></html>"
- "</map>"
- "<key>cam</key><real>1.23</real>"
- "</map></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v[0] = 23;
- v[1] = LLSD();
- v[2] = 1.23;
-
- ensureParse(
- "array value of html",
- "<llsd><array>"
- "<integer>23</integer>"
- "<html><body>ha ha</body></html>"
- "<real>1.23</real>"
- "</array></llsd>",
- v,
- v.size() + 1);
-
- v.clear();
- v[0] = 23;
- v[1] = LLSD::emptyMap();
- v[2] = 1.23;
- ensureParse(
- "array with map of html",
- "<llsd><array>"
- "<integer>23</integer>"
- "<map>"
- "<html><body>ha ha</body></html>"
- "</map>"
- "<real>1.23</real>"
- "</array></llsd>",
- v,
- v.size() + 1);
- }
-
- template<> template<>
- void TestLLSDXMLParsingObject::test<4>()
- {
- // test handling of binary object in XML
- std::string xml;
- LLSD expected;
-
- // Generated by: echo -n 'hello' | openssl enc -e -base64
- expected = string_to_vector("hello");
- xml = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
- ensureParse(
- "the word 'hello' packed in binary encoded base64",
- xml,
- expected,
- 1);
-
- expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
- xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
- ensureParse(
- "a common binary blob for object -> agent offline inv transfer",
- xml,
- expected,
- 1);
-
- expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
- xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBl\n";
- xml += "NDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5\n";
- xml += "LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZm\n";
- xml += "ZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMy\n";
- xml += "OXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
- ensureParse(
- "a common binary blob for object -> agent offline inv transfer",
- xml,
- expected,
- 1);
- }
+ /**
+ * @class TestLLSDParsing
+ * @brief Base class for of a parse tester.
+ */
+ template <class parser_t>
+ class TestLLSDParsing
+ {
+ public:
+ TestLLSDParsing()
+ {
+ mParser = new parser_t;
+ }
+
+ void ensureParse(
+ const std::string& msg,
+ const std::string& in,
+ const LLSD& expected_value,
+ S32 expected_count,
+ S32 depth_limit = -1)
+ {
+ std::stringstream input;
+ input.str(in);
+
+ LLSD parsed_result;
+ mParser->reset(); // reset() call is needed since test code re-uses mParser
+ S32 parsed_count = mParser->parse(input, parsed_result, in.size(), depth_limit);
+ ensure_equals(msg.c_str(), parsed_result, expected_value);
+
+ // This count check is really only useful for expected
+ // parse failures, since the ensures equal will already
+ // require equality.
+ std::string count_msg(msg);
+ count_msg += " (count)";
+ ensure_equals(count_msg, parsed_count, expected_count);
+ }
+
+ LLPointer<parser_t> mParser;
+ };
+
+
+ /**
+ * @class TestLLSDXMLParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDXMLParsing : public TestLLSDParsing<LLSDXMLParser>
+ {
+ public:
+ TestLLSDXMLParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
+ typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
+ TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<1>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed xml",
+ "<llsd><string>ha ha</string>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "not llsd",
+ "<html><body><p>ha ha</p></body></html>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "value without llsd",
+ "<string>ha ha</string>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "key without llsd",
+ "<key>ha ha</key>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<2>()
+ {
+ // test handling of unrecognized or unparseable llsd values
+ LLSD v;
+ v["amy"] = 23;
+ v["bob"] = LLSD();
+ v["cam"] = 1.23;
+
+ ensureParse(
+ "unknown data type",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<key>bob</key><bigint>99999999999999999</bigint>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+ }
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<3>()
+ {
+ // test handling of nested bad data
+
+ LLSD v;
+ v["amy"] = 23;
+ v["cam"] = 1.23;
+
+ ensureParse(
+ "map with html",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<html><body>ha ha</body></html>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v["amy"] = 23;
+ v["cam"] = 1.23;
+ ensureParse(
+ "map with value for key",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<string>ha ha</string>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v["amy"] = 23;
+ v["bob"] = LLSD::emptyMap();
+ v["cam"] = 1.23;
+ ensureParse(
+ "map with map of html",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<key>bob</key>"
+ "<map>"
+ "<html><body>ha ha</body></html>"
+ "</map>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v[0] = 23;
+ v[1] = LLSD();
+ v[2] = 1.23;
+
+ ensureParse(
+ "array value of html",
+ "<llsd><array>"
+ "<integer>23</integer>"
+ "<html><body>ha ha</body></html>"
+ "<real>1.23</real>"
+ "</array></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v[0] = 23;
+ v[1] = LLSD::emptyMap();
+ v[2] = 1.23;
+ ensureParse(
+ "array with map of html",
+ "<llsd><array>"
+ "<integer>23</integer>"
+ "<map>"
+ "<html><body>ha ha</body></html>"
+ "</map>"
+ "<real>1.23</real>"
+ "</array></llsd>",
+ v,
+ v.size() + 1);
+ }
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<4>()
+ {
+ // test handling of binary object in XML
+ std::string xml;
+ LLSD expected;
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ expected = string_to_vector("hello");
+ xml = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ ensureParse(
+ "the word 'hello' packed in binary encoded base64",
+ xml,
+ expected,
+ 1);
+
+ expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ ensureParse(
+ "a common binary blob for object -> agent offline inv transfer",
+ xml,
+ expected,
+ 1);
+
+ expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBl\n";
+ xml += "NDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5\n";
+ xml += "LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZm\n";
+ xml += "ZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMy\n";
+ xml += "OXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ ensureParse(
+ "a common binary blob for object -> agent offline inv transfer",
+ xml,
+ expected,
+ 1);
+ }
template<> template<>
void TestLLSDXMLParsingObject::test<5>()
@@ -856,272 +856,272 @@ namespace tut
}
- /*
- TODO:
- test XML parsing
- binary with unrecognized encoding
- nested LLSD tags
- multiple values inside an LLSD
- */
-
-
- /**
- * @class TestLLSDNotationParsing
- * @brief Concrete instance of a parse tester.
- */
- class TestLLSDNotationParsing : public TestLLSDParsing<LLSDNotationParser>
- {
- public:
- TestLLSDNotationParsing() {}
- };
-
- typedef tut::test_group<TestLLSDNotationParsing> TestLLSDNotationParsingGroup;
- typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject;
- TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup(
- "llsd notation parsing");
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<1>()
- {
- // test handling of xml not recognized as llsd results in an
- // LLSD Undefined
- ensureParse(
- "malformed notation map",
- "{'ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed notation array",
- "['ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed notation string",
- "'ha ha",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "bad notation noise",
- "g48ejlnfr",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<2>()
- {
- ensureParse("valid undef", "!", LLSD(), 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<3>()
- {
- LLSD val = false;
- ensureParse("valid boolean false 0", "false", val, 1);
- ensureParse("valid boolean false 1", "f", val, 1);
- ensureParse("valid boolean false 2", "0", val, 1);
- ensureParse("valid boolean false 3", "F", val, 1);
- ensureParse("valid boolean false 4", "FALSE", val, 1);
- val = true;
- ensureParse("valid boolean true 0", "true", val, 1);
- ensureParse("valid boolean true 1", "t", val, 1);
- ensureParse("valid boolean true 2", "1", val, 1);
- ensureParse("valid boolean true 3", "T", val, 1);
- ensureParse("valid boolean true 4", "TRUE", val, 1);
-
- val.clear();
- ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE);
- ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<4>()
- {
- LLSD val = 123;
- ensureParse("valid integer", "i123", val, 1);
- val.clear();
- ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<5>()
- {
- LLSD val = 456.7;
- ensureParse("valid real", "r456.7", val, 1);
- val.clear();
- ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<6>()
- {
- LLUUID id;
- LLSD val = id;
- ensureParse(
- "unparseable uuid",
- "u123",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- id.generate();
- val = id;
- std::string uuid_str("u");
- uuid_str += id.asString();
- ensureParse("valid uuid", uuid_str.c_str(), val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<7>()
- {
- LLSD val = std::string("foolish");
- ensureParse("valid string 1", "\"foolish\"", val, 1);
- val = std::string("g'day");
- ensureParse("valid string 2", "\"g'day\"", val, 1);
- val = std::string("have a \"nice\" day");
- ensureParse("valid string 3", "'have a \"nice\" day'", val, 1);
- val = std::string("whatever");
- ensureParse("valid string 4", "s(8)\"whatever\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<8>()
- {
- ensureParse(
- "invalid string 1",
- "s(7)\"whatever\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "invalid string 2",
- "s(9)\"whatever\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<9>()
- {
- LLSD val = LLURI("http://www.google.com");
- ensureParse("valid uri", "l\"http://www.google.com\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<10>()
- {
- LLSD val = LLDate("2007-12-28T09:22:53.10Z");
- ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<11>()
- {
- std::vector<U8> vec;
- vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c');
- vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1');
- LLSD val = vec;
- ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1);
- ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1);
- ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<12>()
- {
- ensureParse(
- "invalid -- binary length specified too long",
- "b(7)\"abc321\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "invalid -- binary length specified way too long",
- "b(1000000)\"abc321\"",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<13>()
- {
- LLSD val;
- val["amy"] = 23;
- val["bob"] = LLSD();
- val["cam"] = 1.23;
- ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4);
-
- val["bob"] = LLSD::emptyMap();
- val["bob"]["vehicle"] = std::string("bicycle");
- ensureParse(
- "nested map",
- "{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}",
- val,
- 5);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<14>()
- {
- LLSD val;
- val.append(23);
- val.append(LLSD());
- val.append(1.23);
- ensureParse("simple array", "[i23,!,r1.23]", val, 4);
- val[1] = LLSD::emptyArray();
- val[1].append("bicycle");
- ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<15>()
- {
- LLSD val;
- val["amy"] = 23;
- val["bob"]["dogs"] = LLSD::emptyArray();
- val["bob"]["dogs"].append(LLSD::emptyMap());
- val["bob"]["dogs"][0]["name"] = std::string("groove");
- val["bob"]["dogs"][0]["breed"] = std::string("samoyed");
- val["bob"]["dogs"].append(LLSD::emptyMap());
- val["bob"]["dogs"][1]["name"] = std::string("greyley");
- val["bob"]["dogs"][1]["breed"] = std::string("chow/husky");
- val["cam"] = 1.23;
- ensureParse(
- "nested notation",
- "{'amy':i23,"
- " 'bob':{'dogs':["
- "{'name':'groove', 'breed':'samoyed'},"
- "{'name':'greyley', 'breed':'chow/husky'}]},"
- " 'cam':r1.23}",
- val,
- 11);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<16>()
- {
- // text to make sure that incorrect sizes bail because
- std::string bad_str("s(5)\"hi\"");
- ensureParse(
- "size longer than bytes left",
- bad_str,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDNotationParsingObject::test<17>()
- {
- // text to make sure that incorrect sizes bail because
- std::string bad_bin("b(5)\"hi\"");
- ensureParse(
- "size longer than bytes left",
- bad_bin,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
+ /*
+ TODO:
+ test XML parsing
+ binary with unrecognized encoding
+ nested LLSD tags
+ multiple values inside an LLSD
+ */
+
+
+ /**
+ * @class TestLLSDNotationParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDNotationParsing : public TestLLSDParsing<LLSDNotationParser>
+ {
+ public:
+ TestLLSDNotationParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDNotationParsing> TestLLSDNotationParsingGroup;
+ typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject;
+ TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup(
+ "llsd notation parsing");
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<1>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed notation map",
+ "{'ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed notation array",
+ "['ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed notation string",
+ "'ha ha",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "bad notation noise",
+ "g48ejlnfr",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<2>()
+ {
+ ensureParse("valid undef", "!", LLSD(), 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<3>()
+ {
+ LLSD val = false;
+ ensureParse("valid boolean false 0", "false", val, 1);
+ ensureParse("valid boolean false 1", "f", val, 1);
+ ensureParse("valid boolean false 2", "0", val, 1);
+ ensureParse("valid boolean false 3", "F", val, 1);
+ ensureParse("valid boolean false 4", "FALSE", val, 1);
+ val = true;
+ ensureParse("valid boolean true 0", "true", val, 1);
+ ensureParse("valid boolean true 1", "t", val, 1);
+ ensureParse("valid boolean true 2", "1", val, 1);
+ ensureParse("valid boolean true 3", "T", val, 1);
+ ensureParse("valid boolean true 4", "TRUE", val, 1);
+
+ val.clear();
+ ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE);
+ ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<4>()
+ {
+ LLSD val = 123;
+ ensureParse("valid integer", "i123", val, 1);
+ val.clear();
+ ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<5>()
+ {
+ LLSD val = 456.7;
+ ensureParse("valid real", "r456.7", val, 1);
+ val.clear();
+ ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<6>()
+ {
+ LLUUID id;
+ LLSD val = id;
+ ensureParse(
+ "unparseable uuid",
+ "u123",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ id.generate();
+ val = id;
+ std::string uuid_str("u");
+ uuid_str += id.asString();
+ ensureParse("valid uuid", uuid_str.c_str(), val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<7>()
+ {
+ LLSD val = std::string("foolish");
+ ensureParse("valid string 1", "\"foolish\"", val, 1);
+ val = std::string("g'day");
+ ensureParse("valid string 2", "\"g'day\"", val, 1);
+ val = std::string("have a \"nice\" day");
+ ensureParse("valid string 3", "'have a \"nice\" day'", val, 1);
+ val = std::string("whatever");
+ ensureParse("valid string 4", "s(8)\"whatever\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<8>()
+ {
+ ensureParse(
+ "invalid string 1",
+ "s(7)\"whatever\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "invalid string 2",
+ "s(9)\"whatever\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<9>()
+ {
+ LLSD val = LLURI("http://www.google.com");
+ ensureParse("valid uri", "l\"http://www.google.com\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<10>()
+ {
+ LLSD val = LLDate("2007-12-28T09:22:53.10Z");
+ ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<11>()
+ {
+ std::vector<U8> vec;
+ vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c');
+ vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1');
+ LLSD val = vec;
+ ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1);
+ ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1);
+ ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<12>()
+ {
+ ensureParse(
+ "invalid -- binary length specified too long",
+ "b(7)\"abc321\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "invalid -- binary length specified way too long",
+ "b(1000000)\"abc321\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<13>()
+ {
+ LLSD val;
+ val["amy"] = 23;
+ val["bob"] = LLSD();
+ val["cam"] = 1.23;
+ ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4);
+
+ val["bob"] = LLSD::emptyMap();
+ val["bob"]["vehicle"] = std::string("bicycle");
+ ensureParse(
+ "nested map",
+ "{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}",
+ val,
+ 5);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<14>()
+ {
+ LLSD val;
+ val.append(23);
+ val.append(LLSD());
+ val.append(1.23);
+ ensureParse("simple array", "[i23,!,r1.23]", val, 4);
+ val[1] = LLSD::emptyArray();
+ val[1].append("bicycle");
+ ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<15>()
+ {
+ LLSD val;
+ val["amy"] = 23;
+ val["bob"]["dogs"] = LLSD::emptyArray();
+ val["bob"]["dogs"].append(LLSD::emptyMap());
+ val["bob"]["dogs"][0]["name"] = std::string("groove");
+ val["bob"]["dogs"][0]["breed"] = std::string("samoyed");
+ val["bob"]["dogs"].append(LLSD::emptyMap());
+ val["bob"]["dogs"][1]["name"] = std::string("greyley");
+ val["bob"]["dogs"][1]["breed"] = std::string("chow/husky");
+ val["cam"] = 1.23;
+ ensureParse(
+ "nested notation",
+ "{'amy':i23,"
+ " 'bob':{'dogs':["
+ "{'name':'groove', 'breed':'samoyed'},"
+ "{'name':'greyley', 'breed':'chow/husky'}]},"
+ " 'cam':r1.23}",
+ val,
+ 11);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<16>()
+ {
+ // text to make sure that incorrect sizes bail because
+ std::string bad_str("s(5)\"hi\"");
+ ensureParse(
+ "size longer than bytes left",
+ bad_str,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<17>()
+ {
+ // text to make sure that incorrect sizes bail because
+ std::string bad_bin("b(5)\"hi\"");
+ ensureParse(
+ "size longer than bytes left",
+ bad_bin,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
template<> template<>
void TestLLSDNotationParsingObject::test<18>()
{
- LLSD level_1 = LLSD::emptyMap(); level_1["level_2"] = 99;
- LLSD level_0 = LLSD::emptyMap(); level_0["level_1"] = level_1;
+ LLSD level_1 = LLSD::emptyMap(); level_1["level_2"] = 99;
+ LLSD level_0 = LLSD::emptyMap(); level_0["level_1"] = level_1;
LLSD deep = LLSD::emptyMap();
deep["level_0"] = level_0;
@@ -1166,7 +1166,7 @@ namespace tut
template<> template<>
void TestLLSDNotationParsingObject::test<20>()
{
- LLSD end = LLSD::emptyMap(); end["end"] = (S32)99;
+ LLSD end = LLSD::emptyMap(); end["end"] = (S32)99;
LLSD level_49 = LLSD::emptyMap(); level_49["level_49"] = end;
LLSD level_48 = LLSD::emptyMap(); level_48["level_48"] = level_49;
@@ -1257,536 +1257,536 @@ namespace tut
9);
}
- /**
- * @class TestLLSDBinaryParsing
- * @brief Concrete instance of a parse tester.
- */
- class TestLLSDBinaryParsing : public TestLLSDParsing<LLSDBinaryParser>
- {
- public:
- TestLLSDBinaryParsing() {}
- };
-
- typedef tut::test_group<TestLLSDBinaryParsing> TestLLSDBinaryParsingGroup;
- typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject;
- TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup(
- "llsd binary parsing");
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<1>()
- {
- std::vector<U8> vec;
- vec.resize(6);
- vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
- vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
- std::string string_expected((char*)&vec[0], vec.size());
- LLSD value = string_expected;
-
- vec.resize(11);
- vec[0] = 's'; // for string
- vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
- vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
-
- uint32_t size = htonl(6);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse("correct string parse", str_good, value, 1);
-
- size = htonl(7);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size string parse",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- size = htonl(100000);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size string parse",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<2>()
- {
- std::vector<U8> vec;
- vec.resize(6);
- vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
- vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
- LLSD value = vec;
-
- vec.resize(11);
- vec[0] = 'b'; // for binary
- vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
- vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
-
- uint32_t size = htonl(6);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse("correct binary parse", str_good, value, 1);
-
- size = htonl(7);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size binary parse 1",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- size = htonl(100000);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "incorrect size binary parse 2",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<3>()
- {
- // test handling of xml not recognized as llsd results in an
- // LLSD Undefined
- ensureParse(
- "malformed binary map",
- "{'ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed binary array",
- "['ha ha'",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "malformed binary string",
- "'ha ha",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- ensureParse(
- "bad noise",
- "g48ejlnfr",
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
- template<> template<>
- void TestLLSDBinaryParsingObject::test<4>()
- {
- ensureParse("valid undef", "!", LLSD(), 1);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<5>()
- {
- LLSD val = false;
- ensureParse("valid boolean false 2", "0", val, 1);
- val = true;
- ensureParse("valid boolean true 2", "1", val, 1);
-
- val.clear();
- ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE);
- ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<6>()
- {
- std::vector<U8> vec;
- vec.push_back('{');
- vec.resize(vec.size() + 4);
- uint32_t size = htonl(1);
- memcpy(&vec[1], &size, sizeof(uint32_t));
- vec.push_back('k');
- int key_size_loc = vec.size();
- size = htonl(1); // 1 too short
- vec.resize(vec.size() + 4);
- memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
- vec.push_back('a'); vec.push_back('m'); vec.push_back('y');
- vec.push_back('i');
- int integer_loc = vec.size();
- vec.resize(vec.size() + 4);
- uint32_t val_int = htonl(23);
- memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "invalid key size",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check with correct size, but unterminated map (missing '}')
- size = htonl(3); // correct size
- memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "valid key size, unterminated map",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check w/ correct size and correct map termination
- LLSD val;
- val["amy"] = 23;
- vec.push_back('}');
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse(
- "valid map",
- str_good,
- val,
- 2);
-
- // check w/ incorrect sizes and correct map termination
- size = htonl(0); // 1 too few (for the map entry)
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_3((char*)&vec[0], vec.size());
- ensureParse(
- "invalid map too long",
- str_bad_3,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- size = htonl(2); // 1 too many
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_4((char*)&vec[0], vec.size());
- ensureParse(
- "invalid map too short",
- str_bad_4,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<7>()
- {
- std::vector<U8> vec;
- vec.push_back('[');
- vec.resize(vec.size() + 4);
- uint32_t size = htonl(1); // 1 too short
- memcpy(&vec[1], &size, sizeof(uint32_t));
- vec.push_back('"'); vec.push_back('a'); vec.push_back('m');
- vec.push_back('y'); vec.push_back('"'); vec.push_back('i');
- int integer_loc = vec.size();
- vec.resize(vec.size() + 4);
- uint32_t val_int = htonl(23);
- memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
-
- std::string str_bad_1((char*)&vec[0], vec.size());
- ensureParse(
- "invalid array size",
- str_bad_1,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check with correct size, but unterminated map (missing ']')
- size = htonl(2); // correct size
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_2((char*)&vec[0], vec.size());
- ensureParse(
- "unterminated array",
- str_bad_2,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- // check w/ correct size and correct map termination
- LLSD val;
- val.append("amy");
- val.append(23);
- vec.push_back(']');
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse(
- "valid array",
- str_good,
- val,
- 3);
-
- // check with too many elements
- size = htonl(3); // 1 too long
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_bad_3((char*)&vec[0], vec.size());
- ensureParse(
- "array too short",
- str_bad_3,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<8>()
- {
- std::vector<U8> vec;
- vec.push_back('{');
- vec.resize(vec.size() + 4);
- memset(&vec[1], 0, 4);
- vec.push_back('}');
- std::string str_good((char*)&vec[0], vec.size());
- LLSD val = LLSD::emptyMap();
- ensureParse(
- "empty map",
- str_good,
- val,
- 1);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<9>()
- {
- std::vector<U8> vec;
- vec.push_back('[');
- vec.resize(vec.size() + 4);
- memset(&vec[1], 0, 4);
- vec.push_back(']');
- std::string str_good((char*)&vec[0], vec.size());
- LLSD val = LLSD::emptyArray();
- ensureParse(
- "empty array",
- str_good,
- val,
- 1);
- }
-
- template<> template<>
- void TestLLSDBinaryParsingObject::test<10>()
- {
- std::vector<U8> vec;
- vec.push_back('l');
- vec.resize(vec.size() + 4);
- uint32_t size = htonl(14); // 1 too long
- memcpy(&vec[1], &size, sizeof(uint32_t));
- vec.push_back('h'); vec.push_back('t'); vec.push_back('t');
- vec.push_back('p'); vec.push_back(':'); vec.push_back('/');
- vec.push_back('/'); vec.push_back('s'); vec.push_back('l');
- vec.push_back('.'); vec.push_back('c'); vec.push_back('o');
- vec.push_back('m');
- std::string str_bad((char*)&vec[0], vec.size());
- ensureParse(
- "invalid uri length size",
- str_bad,
- LLSD(),
- LLSDParser::PARSE_FAILURE);
-
- LLSD val;
- val = LLURI("http://sl.com");
- size = htonl(13); // correct length
- memcpy(&vec[1], &size, sizeof(uint32_t));
- std::string str_good((char*)&vec[0], vec.size());
- ensureParse(
- "valid key size",
- str_good,
- val,
- 1);
- }
+ /**
+ * @class TestLLSDBinaryParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDBinaryParsing : public TestLLSDParsing<LLSDBinaryParser>
+ {
+ public:
+ TestLLSDBinaryParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDBinaryParsing> TestLLSDBinaryParsingGroup;
+ typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject;
+ TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup(
+ "llsd binary parsing");
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<1>()
+ {
+ std::vector<U8> vec;
+ vec.resize(6);
+ vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+ vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+ std::string string_expected((char*)&vec[0], vec.size());
+ LLSD value = string_expected;
+
+ vec.resize(11);
+ vec[0] = 's'; // for string
+ vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+ vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+ uint32_t size = htonl(6);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse("correct string parse", str_good, value, 1);
+
+ size = htonl(7);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size string parse",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(100000);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size string parse",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<2>()
+ {
+ std::vector<U8> vec;
+ vec.resize(6);
+ vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+ vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+ LLSD value = vec;
+
+ vec.resize(11);
+ vec[0] = 'b'; // for binary
+ vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+ vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+ uint32_t size = htonl(6);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse("correct binary parse", str_good, value, 1);
+
+ size = htonl(7);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size binary parse 1",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(100000);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size binary parse 2",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<3>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed binary map",
+ "{'ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed binary array",
+ "['ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed binary string",
+ "'ha ha",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "bad noise",
+ "g48ejlnfr",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<4>()
+ {
+ ensureParse("valid undef", "!", LLSD(), 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<5>()
+ {
+ LLSD val = false;
+ ensureParse("valid boolean false 2", "0", val, 1);
+ val = true;
+ ensureParse("valid boolean true 2", "1", val, 1);
+
+ val.clear();
+ ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE);
+ ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<6>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('{');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(1);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('k');
+ int key_size_loc = vec.size();
+ size = htonl(1); // 1 too short
+ vec.resize(vec.size() + 4);
+ memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+ vec.push_back('a'); vec.push_back('m'); vec.push_back('y');
+ vec.push_back('i');
+ int integer_loc = vec.size();
+ vec.resize(vec.size() + 4);
+ uint32_t val_int = htonl(23);
+ memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid key size",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check with correct size, but unterminated map (missing '}')
+ size = htonl(3); // correct size
+ memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid key size, unterminated map",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check w/ correct size and correct map termination
+ LLSD val;
+ val["amy"] = 23;
+ vec.push_back('}');
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid map",
+ str_good,
+ val,
+ 2);
+
+ // check w/ incorrect sizes and correct map termination
+ size = htonl(0); // 1 too few (for the map entry)
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_3((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid map too long",
+ str_bad_3,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(2); // 1 too many
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_4((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid map too short",
+ str_bad_4,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<7>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('[');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(1); // 1 too short
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('"'); vec.push_back('a'); vec.push_back('m');
+ vec.push_back('y'); vec.push_back('"'); vec.push_back('i');
+ int integer_loc = vec.size();
+ vec.resize(vec.size() + 4);
+ uint32_t val_int = htonl(23);
+ memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid array size",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check with correct size, but unterminated map (missing ']')
+ size = htonl(2); // correct size
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "unterminated array",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check w/ correct size and correct map termination
+ LLSD val;
+ val.append("amy");
+ val.append(23);
+ vec.push_back(']');
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid array",
+ str_good,
+ val,
+ 3);
+
+ // check with too many elements
+ size = htonl(3); // 1 too long
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_3((char*)&vec[0], vec.size());
+ ensureParse(
+ "array too short",
+ str_bad_3,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<8>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('{');
+ vec.resize(vec.size() + 4);
+ memset(&vec[1], 0, 4);
+ vec.push_back('}');
+ std::string str_good((char*)&vec[0], vec.size());
+ LLSD val = LLSD::emptyMap();
+ ensureParse(
+ "empty map",
+ str_good,
+ val,
+ 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<9>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('[');
+ vec.resize(vec.size() + 4);
+ memset(&vec[1], 0, 4);
+ vec.push_back(']');
+ std::string str_good((char*)&vec[0], vec.size());
+ LLSD val = LLSD::emptyArray();
+ ensureParse(
+ "empty array",
+ str_good,
+ val,
+ 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<10>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('l');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(14); // 1 too long
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('h'); vec.push_back('t'); vec.push_back('t');
+ vec.push_back('p'); vec.push_back(':'); vec.push_back('/');
+ vec.push_back('/'); vec.push_back('s'); vec.push_back('l');
+ vec.push_back('.'); vec.push_back('c'); vec.push_back('o');
+ vec.push_back('m');
+ std::string str_bad((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid uri length size",
+ str_bad,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ LLSD val;
+ val = LLURI("http://sl.com");
+ size = htonl(13); // correct length
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid key size",
+ str_good,
+ val,
+ 1);
+ }
/*
- template<> template<>
- void TestLLSDBinaryParsingObject::test<11>()
- {
- }
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<11>()
+ {
+ }
*/
/**
- * @class TestLLSDCrossCompatible
- * @brief Miscellaneous serialization and parsing tests
- */
- class TestLLSDCrossCompatible
- {
- public:
- TestLLSDCrossCompatible() {}
-
- void ensureBinaryAndNotation(
- const std::string& msg,
- const LLSD& input)
- {
- // to binary, and back again
- std::stringstream str1;
- S32 count1 = LLSDSerialize::toBinary(input, str1);
- LLSD actual_value_bin;
- S32 count2 = LLSDSerialize::fromBinary(
- actual_value_bin,
- str1,
- LLSDSerialize::SIZE_UNLIMITED);
- ensure_equals(
- "ensureBinaryAndNotation binary count",
- count2,
- count1);
-
- // to notation and back again
- std::stringstream str2;
- S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2);
- ensure_equals(
- "ensureBinaryAndNotation notation count1",
- count3,
- count2);
- LLSD actual_value_notation;
- S32 count4 = LLSDSerialize::fromNotation(
- actual_value_notation,
- str2,
- LLSDSerialize::SIZE_UNLIMITED);
- ensure_equals(
- "ensureBinaryAndNotation notation count2",
- count4,
- count3);
- ensure_equals(
- (msg + " (binaryandnotation)").c_str(),
- actual_value_notation,
- input);
- }
-
- void ensureBinaryAndXML(
- const std::string& msg,
- const LLSD& input)
- {
- // to binary, and back again
- std::stringstream str1;
- S32 count1 = LLSDSerialize::toBinary(input, str1);
- LLSD actual_value_bin;
- S32 count2 = LLSDSerialize::fromBinary(
- actual_value_bin,
- str1,
- LLSDSerialize::SIZE_UNLIMITED);
- ensure_equals(
- "ensureBinaryAndXML binary count",
- count2,
- count1);
-
- // to xml and back again
- std::stringstream str2;
- S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2);
- ensure_equals(
- "ensureBinaryAndXML xml count1",
- count3,
- count2);
- LLSD actual_value_xml;
- S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2);
- ensure_equals(
- "ensureBinaryAndXML xml count2",
- count4,
- count3);
- ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input);
- }
- };
-
- typedef tut::test_group<TestLLSDCrossCompatible> TestLLSDCompatibleGroup;
- typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject;
- TestLLSDCompatibleGroup gTestLLSDCompatibleGroup(
- "llsd serialize compatible");
-
- template<> template<>
- void TestLLSDCompatibleObject::test<1>()
- {
- LLSD test;
- ensureBinaryAndNotation("undef", test);
- ensureBinaryAndXML("undef", test);
- test = true;
- ensureBinaryAndNotation("boolean true", test);
- ensureBinaryAndXML("boolean true", test);
- test = false;
- ensureBinaryAndNotation("boolean false", test);
- ensureBinaryAndXML("boolean false", test);
- test = 0;
- ensureBinaryAndNotation("integer zero", test);
- ensureBinaryAndXML("integer zero", test);
- test = 1;
- ensureBinaryAndNotation("integer positive", test);
- ensureBinaryAndXML("integer positive", test);
- test = -234567;
- ensureBinaryAndNotation("integer negative", test);
- ensureBinaryAndXML("integer negative", test);
- test = 0.0;
- ensureBinaryAndNotation("real zero", test);
- ensureBinaryAndXML("real zero", test);
- test = 1.0;
- ensureBinaryAndNotation("real positive", test);
- ensureBinaryAndXML("real positive", test);
- test = -1.0;
- ensureBinaryAndNotation("real negative", test);
- ensureBinaryAndXML("real negative", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<2>()
- {
- LLSD test;
- test = "foobar";
- ensureBinaryAndNotation("string", test);
- ensureBinaryAndXML("string", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<3>()
- {
- LLSD test;
- LLUUID id;
- id.generate();
- test = id;
- ensureBinaryAndNotation("uuid", test);
- ensureBinaryAndXML("uuid", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<4>()
- {
- LLSD test;
- test = LLDate(12345.0);
- ensureBinaryAndNotation("date", test);
- ensureBinaryAndXML("date", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<5>()
- {
- LLSD test;
- test = LLURI("http://www.secondlife.com/");
- ensureBinaryAndNotation("uri", test);
- ensureBinaryAndXML("uri", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<6>()
- {
- LLSD test;
- typedef std::vector<U8> buf_t;
- buf_t val;
- for(int ii = 0; ii < 100; ++ii)
- {
- srand(ii); /* Flawfinder: ignore */
- S32 size = rand() % 100 + 10;
- std::generate_n(
- std::back_insert_iterator<buf_t>(val),
- size,
- rand);
- }
- test = val;
- ensureBinaryAndNotation("binary", test);
- ensureBinaryAndXML("binary", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<7>()
- {
- LLSD test;
- test = LLSD::emptyArray();
- test.append(1);
- test.append("hello");
- ensureBinaryAndNotation("array", test);
- ensureBinaryAndXML("array", test);
- }
-
- template<> template<>
- void TestLLSDCompatibleObject::test<8>()
- {
- LLSD test;
- test = LLSD::emptyArray();
- test["foo"] = "bar";
- test["baz"] = 100;
- ensureBinaryAndNotation("map", test);
- ensureBinaryAndXML("map", test);
- }
+ * @class TestLLSDCrossCompatible
+ * @brief Miscellaneous serialization and parsing tests
+ */
+ class TestLLSDCrossCompatible
+ {
+ public:
+ TestLLSDCrossCompatible() {}
+
+ void ensureBinaryAndNotation(
+ const std::string& msg,
+ const LLSD& input)
+ {
+ // to binary, and back again
+ std::stringstream str1;
+ S32 count1 = LLSDSerialize::toBinary(input, str1);
+ LLSD actual_value_bin;
+ S32 count2 = LLSDSerialize::fromBinary(
+ actual_value_bin,
+ str1,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndNotation binary count",
+ count2,
+ count1);
+
+ // to notation and back again
+ std::stringstream str2;
+ S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2);
+ ensure_equals(
+ "ensureBinaryAndNotation notation count1",
+ count3,
+ count2);
+ LLSD actual_value_notation;
+ S32 count4 = LLSDSerialize::fromNotation(
+ actual_value_notation,
+ str2,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndNotation notation count2",
+ count4,
+ count3);
+ ensure_equals(
+ (msg + " (binaryandnotation)").c_str(),
+ actual_value_notation,
+ input);
+ }
+
+ void ensureBinaryAndXML(
+ const std::string& msg,
+ const LLSD& input)
+ {
+ // to binary, and back again
+ std::stringstream str1;
+ S32 count1 = LLSDSerialize::toBinary(input, str1);
+ LLSD actual_value_bin;
+ S32 count2 = LLSDSerialize::fromBinary(
+ actual_value_bin,
+ str1,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndXML binary count",
+ count2,
+ count1);
+
+ // to xml and back again
+ std::stringstream str2;
+ S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2);
+ ensure_equals(
+ "ensureBinaryAndXML xml count1",
+ count3,
+ count2);
+ LLSD actual_value_xml;
+ S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2);
+ ensure_equals(
+ "ensureBinaryAndXML xml count2",
+ count4,
+ count3);
+ ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input);
+ }
+ };
+
+ typedef tut::test_group<TestLLSDCrossCompatible> TestLLSDCompatibleGroup;
+ typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject;
+ TestLLSDCompatibleGroup gTestLLSDCompatibleGroup(
+ "llsd serialize compatible");
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<1>()
+ {
+ LLSD test;
+ ensureBinaryAndNotation("undef", test);
+ ensureBinaryAndXML("undef", test);
+ test = true;
+ ensureBinaryAndNotation("boolean true", test);
+ ensureBinaryAndXML("boolean true", test);
+ test = false;
+ ensureBinaryAndNotation("boolean false", test);
+ ensureBinaryAndXML("boolean false", test);
+ test = 0;
+ ensureBinaryAndNotation("integer zero", test);
+ ensureBinaryAndXML("integer zero", test);
+ test = 1;
+ ensureBinaryAndNotation("integer positive", test);
+ ensureBinaryAndXML("integer positive", test);
+ test = -234567;
+ ensureBinaryAndNotation("integer negative", test);
+ ensureBinaryAndXML("integer negative", test);
+ test = 0.0;
+ ensureBinaryAndNotation("real zero", test);
+ ensureBinaryAndXML("real zero", test);
+ test = 1.0;
+ ensureBinaryAndNotation("real positive", test);
+ ensureBinaryAndXML("real positive", test);
+ test = -1.0;
+ ensureBinaryAndNotation("real negative", test);
+ ensureBinaryAndXML("real negative", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<2>()
+ {
+ LLSD test;
+ test = "foobar";
+ ensureBinaryAndNotation("string", test);
+ ensureBinaryAndXML("string", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<3>()
+ {
+ LLSD test;
+ LLUUID id;
+ id.generate();
+ test = id;
+ ensureBinaryAndNotation("uuid", test);
+ ensureBinaryAndXML("uuid", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<4>()
+ {
+ LLSD test;
+ test = LLDate(12345.0);
+ ensureBinaryAndNotation("date", test);
+ ensureBinaryAndXML("date", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<5>()
+ {
+ LLSD test;
+ test = LLURI("http://www.secondlife.com/");
+ ensureBinaryAndNotation("uri", test);
+ ensureBinaryAndXML("uri", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<6>()
+ {
+ LLSD test;
+ typedef std::vector<U8> buf_t;
+ buf_t val;
+ for(int ii = 0; ii < 100; ++ii)
+ {
+ srand(ii); /* Flawfinder: ignore */
+ S32 size = rand() % 100 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(val),
+ size,
+ rand);
+ }
+ test = val;
+ ensureBinaryAndNotation("binary", test);
+ ensureBinaryAndXML("binary", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<7>()
+ {
+ LLSD test;
+ test = LLSD::emptyArray();
+ test.append(1);
+ test.append("hello");
+ ensureBinaryAndNotation("array", test);
+ ensureBinaryAndXML("array", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<8>()
+ {
+ LLSD test;
+ test = LLSD::emptyArray();
+ test["foo"] = "bar";
+ test["baz"] = 100;
+ ensureBinaryAndNotation("map", test);
+ ensureBinaryAndXML("map", test);
+ }
// helper for TestPythonCompatible
static std::string import_llsd("import os.path\n"
@@ -2129,7 +2129,7 @@ namespace tut
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
ensure("Failed to read LLSD::String from Python",
itemFromStream(inf, item, parse));
- ensure_equals(item.asString(),
+ ensure_equals(item.asString(),
"This string\n"
"has several\n"
"lines.");