summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/StackWalker.cpp66
-rw-r--r--indra/llcommon/StackWalker.h80
-rw-r--r--indra/llcommon/always_return.h2
-rw-r--r--indra/llcommon/apply.cpp2
-rw-r--r--indra/llcommon/apply.h10
-rw-r--r--indra/llcommon/chrono.h2
-rw-r--r--indra/llcommon/classic_callback.cpp2
-rw-r--r--indra/llcommon/commoncontrol.cpp2
-rw-r--r--indra/llcommon/commoncontrol.h2
-rw-r--r--indra/llcommon/ctype_workaround.h18
-rw-r--r--indra/llcommon/fix_macros.h2
-rw-r--r--indra/llcommon/function_types.h2
-rw-r--r--indra/llcommon/hbxxh.cpp6
-rw-r--r--indra/llcommon/hbxxh.h6
-rw-r--r--indra/llcommon/indra_constants.cpp56
-rw-r--r--indra/llcommon/indra_constants.h338
-rw-r--r--indra/llcommon/is_approx_equal_fraction.h10
-rw-r--r--indra/llcommon/lazyeventapi.cpp2
-rw-r--r--indra/llcommon/lazyeventapi.h2
-rw-r--r--indra/llcommon/linden_common.h10
-rw-r--r--indra/llcommon/llalignedarray.h136
-rw-r--r--indra/llcommon/llallocator.cpp10
-rw-r--r--indra/llcommon/llallocator.h10
-rw-r--r--indra/llcommon/llallocator_heap_profile.cpp48
-rw-r--r--indra/llcommon/llallocator_heap_profile.h12
-rw-r--r--indra/llcommon/llapp.cpp960
-rw-r--r--indra/llcommon/llapp.h526
-rw-r--r--indra/llcommon/llapr.cpp902
-rw-r--r--indra/llcommon/llapr.h130
-rw-r--r--indra/llcommon/llassettype.cpp280
-rw-r--r--indra/llcommon/llassettype.h194
-rw-r--r--indra/llcommon/llatomic.cpp10
-rw-r--r--indra/llcommon/llatomic.h12
-rw-r--r--indra/llcommon/llbase32.cpp50
-rw-r--r--indra/llcommon/llbase32.h12
-rw-r--r--indra/llcommon/llbase64.cpp50
-rw-r--r--indra/llcommon/llbase64.h12
-rw-r--r--indra/llcommon/llbitpack.cpp10
-rw-r--r--indra/llcommon/llbitpack.h342
-rw-r--r--indra/llcommon/llboost.h40
-rw-r--r--indra/llcommon/llcallbacklist.cpp224
-rw-r--r--indra/llcommon/llcallbacklist.h42
-rw-r--r--indra/llcommon/llcallstack.cpp28
-rw-r--r--indra/llcommon/llcallstack.h10
-rw-r--r--indra/llcommon/llcleanup.cpp2
-rw-r--r--indra/llcommon/llcleanup.h2
-rw-r--r--indra/llcommon/llclickaction.h10
-rw-r--r--indra/llcommon/llcommon.cpp56
-rw-r--r--indra/llcommon/llcommon.h16
-rw-r--r--indra/llcommon/llcommonutils.cpp44
-rw-r--r--indra/llcommon/llcommonutils.h38
-rw-r--r--indra/llcommon/llcond.h2
-rw-r--r--indra/llcommon/llcoros.cpp12
-rw-r--r--indra/llcommon/llcoros.h12
-rw-r--r--indra/llcommon/llcrc.cpp116
-rw-r--r--indra/llcommon/llcrc.h30
-rw-r--r--indra/llcommon/llcriticaldamp.cpp100
-rw-r--r--indra/llcommon/llcriticaldamp.h60
-rw-r--r--indra/llcommon/lldate.cpp394
-rw-r--r--indra/llcommon/lldate.h192
-rw-r--r--indra/llcommon/lldeadmantimer.cpp226
-rw-r--r--indra/llcommon/lldeadmantimer.h258
-rw-r--r--indra/llcommon/lldefs.h202
-rw-r--r--indra/llcommon/lldependencies.cpp10
-rw-r--r--indra/llcommon/lldependencies.h16
-rw-r--r--indra/llcommon/lldepthstack.h116
-rw-r--r--indra/llcommon/lldictionary.cpp32
-rw-r--r--indra/llcommon/lldictionary.h108
-rw-r--r--indra/llcommon/lldoubledispatch.h22
-rw-r--r--indra/llcommon/llendianswizzle.h112
-rw-r--r--indra/llcommon/llerror.cpp1714
-rw-r--r--indra/llcommon/llerror.h416
-rw-r--r--indra/llcommon/llerrorcontrol.h322
-rw-r--r--indra/llcommon/llerrorlegacy.h10
-rw-r--r--indra/llcommon/llevent.cpp264
-rw-r--r--indra/llcommon/llevent.h180
-rw-r--r--indra/llcommon/lleventapi.cpp10
-rw-r--r--indra/llcommon/lleventapi.h10
-rw-r--r--indra/llcommon/lleventcoro.cpp10
-rw-r--r--indra/llcommon/lleventcoro.h12
-rw-r--r--indra/llcommon/lleventdispatcher.cpp12
-rw-r--r--indra/llcommon/lleventdispatcher.h28
-rw-r--r--indra/llcommon/lleventemitter.h96
-rw-r--r--indra/llcommon/lleventfilter.cpp10
-rw-r--r--indra/llcommon/lleventfilter.h22
-rw-r--r--indra/llcommon/llevents.cpp26
-rw-r--r--indra/llcommon/llevents.h42
-rw-r--r--indra/llcommon/lleventtimer.cpp42
-rw-r--r--indra/llcommon/lleventtimer.h68
-rw-r--r--indra/llcommon/llexception.cpp6
-rw-r--r--indra/llcommon/llexception.h2
-rw-r--r--indra/llcommon/llfasttimer.cpp506
-rw-r--r--indra/llcommon/llfasttimer.h408
-rw-r--r--indra/llcommon/llfile.cpp546
-rw-r--r--indra/llcommon/llfile.h148
-rw-r--r--indra/llcommon/llfindlocale.cpp10
-rw-r--r--indra/llcommon/llfindlocale.h10
-rw-r--r--indra/llcommon/llfixedbuffer.cpp80
-rw-r--r--indra/llcommon/llfixedbuffer.h38
-rw-r--r--indra/llcommon/llformat.cpp46
-rw-r--r--indra/llcommon/llformat.h10
-rw-r--r--indra/llcommon/llframetimer.cpp96
-rw-r--r--indra/llcommon/llframetimer.h218
-rw-r--r--indra/llcommon/llhandle.h240
-rw-r--r--indra/llcommon/llhash.h32
-rw-r--r--indra/llcommon/llheartbeat.cpp196
-rw-r--r--indra/llcommon/llheartbeat.h56
-rw-r--r--indra/llcommon/llheteromap.cpp4
-rw-r--r--indra/llcommon/llheteromap.h2
-rw-r--r--indra/llcommon/llindexedvector.h112
-rw-r--r--indra/llcommon/llinitdestroyclass.cpp12
-rw-r--r--indra/llcommon/llinitdestroyclass.h86
-rw-r--r--indra/llcommon/llinitparam.cpp870
-rw-r--r--indra/llcommon/llinitparam.h5580
-rw-r--r--indra/llcommon/llinstancetracker.cpp10
-rw-r--r--indra/llcommon/llinstancetracker.h28
-rw-r--r--indra/llcommon/llkeybind.cpp20
-rw-r--r--indra/llcommon/llkeybind.h12
-rw-r--r--indra/llcommon/llkeythrottle.h550
-rw-r--r--indra/llcommon/llkeyusetracker.h334
-rw-r--r--indra/llcommon/llleap.cpp2
-rw-r--r--indra/llcommon/llleap.h2
-rw-r--r--indra/llcommon/llleaplistener.cpp2
-rw-r--r--indra/llcommon/llleaplistener.h2
-rw-r--r--indra/llcommon/llliveappconfig.cpp70
-rw-r--r--indra/llcommon/llliveappconfig.h42
-rw-r--r--indra/llcommon/lllivefile.cpp152
-rw-r--r--indra/llcommon/lllivefile.h106
-rw-r--r--indra/llcommon/llmainthreadtask.cpp2
-rw-r--r--indra/llcommon/llmainthreadtask.h2
-rw-r--r--indra/llcommon/llmake.h2
-rw-r--r--indra/llcommon/llmd5.cpp150
-rw-r--r--indra/llcommon/llmd5.h30
-rw-r--r--indra/llcommon/llmemory.cpp304
-rw-r--r--indra/llcommon/llmemory.h350
-rw-r--r--indra/llcommon/llmemorystream.cpp32
-rw-r--r--indra/llcommon/llmemorystream.h32
-rw-r--r--indra/llcommon/llmetricperformancetester.cpp426
-rw-r--r--indra/llcommon/llmetricperformancetester.h324
-rw-r--r--indra/llcommon/llmetrics.cpp170
-rw-r--r--indra/llcommon/llmetrics.h34
-rw-r--r--indra/llcommon/llmortician.cpp56
-rw-r--r--indra/llcommon/llmortician.h36
-rw-r--r--indra/llcommon/llmutex.cpp162
-rw-r--r--indra/llcommon/llmutex.h102
-rw-r--r--indra/llcommon/llnametable.h118
-rw-r--r--indra/llcommon/llpointer.h544
-rw-r--r--indra/llcommon/llpredicate.cpp26
-rw-r--r--indra/llcommon/llpredicate.h346
-rw-r--r--indra/llcommon/llpreprocessor.h86
-rw-r--r--indra/llcommon/llpriqueuemap.h188
-rw-r--r--indra/llcommon/llprocess.cpp2022
-rw-r--r--indra/llcommon/llprocess.h994
-rw-r--r--indra/llcommon/llprocessor.cpp1428
-rw-r--r--indra/llcommon/llprocessor.h30
-rw-r--r--indra/llcommon/llprocinfo.cpp64
-rw-r--r--indra/llcommon/llprocinfo.h34
-rw-r--r--indra/llcommon/llptrto.cpp10
-rw-r--r--indra/llcommon/llptrto.h10
-rw-r--r--indra/llcommon/llqueuedthread.cpp550
-rw-r--r--indra/llcommon/llqueuedthread.h226
-rw-r--r--indra/llcommon/llrand.cpp74
-rw-r--r--indra/llcommon/llrand.h38
-rw-r--r--indra/llcommon/llrefcount.cpp26
-rw-r--r--indra/llcommon/llrefcount.h156
-rw-r--r--indra/llcommon/llregex.h90
-rw-r--r--indra/llcommon/llregistry.h580
-rw-r--r--indra/llcommon/llrun.cpp212
-rw-r--r--indra/llcommon/llrun.h204
-rw-r--r--indra/llcommon/llsafehandle.h270
-rw-r--r--indra/llcommon/llsd.cpp1524
-rw-r--r--indra/llcommon/llsd.h850
-rw-r--r--indra/llcommon/llsdjson.cpp10
-rw-r--r--indra/llcommon/llsdjson.h22
-rw-r--r--indra/llcommon/llsdparam.cpp366
-rw-r--r--indra/llcommon/llsdparam.h180
-rw-r--r--indra/llcommon/llsdserialize.cpp3982
-rw-r--r--indra/llcommon/llsdserialize.h1306
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp1470
-rw-r--r--indra/llcommon/llsdserialize_xml.h10
-rw-r--r--indra/llcommon/llsdutil.cpp720
-rw-r--r--indra/llcommon/llsdutil.h50
-rw-r--r--indra/llcommon/llsimplehash.h228
-rw-r--r--indra/llcommon/llsingleton.cpp14
-rw-r--r--indra/llcommon/llsingleton.h12
-rw-r--r--indra/llcommon/llsmoothstep.h22
-rw-r--r--indra/llcommon/llstacktrace.cpp194
-rw-r--r--indra/llcommon/llstacktrace.h10
-rw-r--r--indra/llcommon/llstatenums.h10
-rw-r--r--indra/llcommon/llstaticstringtable.h60
-rw-r--r--indra/llcommon/llstl.h346
-rw-r--r--indra/llcommon/llstreamqueue.cpp2
-rw-r--r--indra/llcommon/llstreamqueue.h2
-rw-r--r--indra/llcommon/llstreamtools.cpp760
-rw-r--r--indra/llcommon/llstreamtools.h36
-rw-r--r--indra/llcommon/llstrider.h60
-rw-r--r--indra/llcommon/llstring.cpp2246
-rw-r--r--indra/llcommon/llstring.h2459
-rw-r--r--indra/llcommon/llstringtable.cpp430
-rw-r--r--indra/llcommon/llstringtable.h264
-rw-r--r--indra/llcommon/llsys.cpp1614
-rw-r--r--indra/llcommon/llsys.h134
-rw-r--r--indra/llcommon/lltempredirect.cpp2
-rw-r--r--indra/llcommon/lltempredirect.h2
-rw-r--r--indra/llcommon/llthread.cpp28
-rw-r--r--indra/llcommon/llthread.h36
-rw-r--r--indra/llcommon/llthreadlocalstorage.h28
-rw-r--r--indra/llcommon/llthreadsafequeue.cpp10
-rw-r--r--indra/llcommon/llthreadsafequeue.h286
-rw-r--r--indra/llcommon/lltimer.cpp524
-rw-r--r--indra/llcommon/lltimer.h166
-rw-r--r--indra/llcommon/lltrace.cpp70
-rw-r--r--indra/llcommon/lltrace.h222
-rw-r--r--indra/llcommon/lltraceaccumulators.cpp350
-rw-r--r--indra/llcommon/lltraceaccumulators.h1018
-rw-r--r--indra/llcommon/lltracerecording.cpp1300
-rw-r--r--indra/llcommon/lltracerecording.h1306
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp326
-rw-r--r--indra/llcommon/lltracethreadrecorder.h100
-rw-r--r--indra/llcommon/lltreeiterators.h74
-rw-r--r--indra/llcommon/llunits.h36
-rw-r--r--indra/llcommon/llunittype.h1030
-rw-r--r--indra/llcommon/lluri.cpp1016
-rw-r--r--indra/llcommon/lluri.h266
-rw-r--r--indra/llcommon/lluriparser.cpp234
-rw-r--r--indra/llcommon/lluriparser.h78
-rw-r--r--indra/llcommon/lluuid.cpp54
-rw-r--r--indra/llcommon/lluuid.h218
-rw-r--r--indra/llcommon/llwin32headers.h10
-rw-r--r--indra/llcommon/llwin32headerslean.h10
-rw-r--r--indra/llcommon/llworkerthread.cpp488
-rw-r--r--indra/llcommon/llworkerthread.h216
-rw-r--r--indra/llcommon/lockstatic.h2
-rw-r--r--indra/llcommon/mutex.h2
-rw-r--r--indra/llcommon/stdtypes.h96
-rw-r--r--indra/llcommon/string_table.h10
-rw-r--r--indra/llcommon/stringize.h10
-rw-r--r--indra/llcommon/tests/StringVec.h2
-rw-r--r--indra/llcommon/tests/apply_test.cpp2
-rw-r--r--indra/llcommon/tests/bitpack_test.cpp170
-rw-r--r--indra/llcommon/tests/classic_callback_test.cpp2
-rw-r--r--indra/llcommon/tests/commonmisc_test.cpp1176
-rw-r--r--indra/llcommon/tests/lazyeventapi_test.cpp2
-rw-r--r--indra/llcommon/tests/listener.h10
-rw-r--r--indra/llcommon/tests/llallocator_heap_profile_test.cpp10
-rw-r--r--indra/llcommon/tests/llallocator_test.cpp12
-rw-r--r--indra/llcommon/tests/llbase64_test.cpp70
-rw-r--r--indra/llcommon/tests/llcond_test.cpp4
-rw-r--r--indra/llcommon/tests/lldate_test.cpp286
-rw-r--r--indra/llcommon/tests/lldeadmantimer_test.cpp1006
-rw-r--r--indra/llcommon/tests/lldependencies_test.cpp10
-rw-r--r--indra/llcommon/tests/llerror_test.cpp1178
-rw-r--r--indra/llcommon/tests/lleventcoro_test.cpp10
-rw-r--r--indra/llcommon/tests/lleventdispatcher_test.cpp4
-rw-r--r--indra/llcommon/tests/lleventfilter_test.cpp10
-rw-r--r--indra/llcommon/tests/llframetimer_test.cpp168
-rw-r--r--indra/llcommon/tests/llheteromap_test.cpp2
-rw-r--r--indra/llcommon/tests/llinstancetracker_test.cpp12
-rw-r--r--indra/llcommon/tests/lllazy_test.cpp10
-rw-r--r--indra/llcommon/tests/llleap_test.cpp2
-rw-r--r--indra/llcommon/tests/llmainthreadtask_test.cpp2
-rw-r--r--indra/llcommon/tests/llmemtype_test.cpp100
-rw-r--r--indra/llcommon/tests/llpounceable_test.cpp2
-rw-r--r--indra/llcommon/tests/llprocess_test.cpp4
-rw-r--r--indra/llcommon/tests/llprocessor_test.cpp62
-rw-r--r--indra/llcommon/tests/llprocinfo_test.cpp60
-rw-r--r--indra/llcommon/tests/llrand_test.cpp138
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp3048
-rw-r--r--indra/llcommon/tests/llsingleton_test.cpp2
-rw-r--r--indra/llcommon/tests/llstreamqueue_test.cpp2
-rw-r--r--indra/llcommon/tests/llstring_test.cpp1668
-rw-r--r--indra/llcommon/tests/lltrace_test.cpp186
-rw-r--r--indra/llcommon/tests/lltreeiterators_test.cpp14
-rw-r--r--indra/llcommon/tests/llunits_test.cpp674
-rw-r--r--indra/llcommon/tests/lluri_test.cpp704
-rw-r--r--indra/llcommon/tests/stringize_test.cpp12
-rw-r--r--indra/llcommon/tests/threadsafeschedule_test.cpp2
-rw-r--r--indra/llcommon/tests/tuple_test.cpp2
-rw-r--r--indra/llcommon/tests/workqueue_test.cpp2
-rw-r--r--indra/llcommon/tests/wrapllerrs.h16
-rw-r--r--indra/llcommon/threadpool.cpp2
-rw-r--r--indra/llcommon/threadpool.h2
-rw-r--r--indra/llcommon/threadpool_fwd.h2
-rw-r--r--indra/llcommon/threadsafeschedule.h4
-rw-r--r--indra/llcommon/timer.h10
-rw-r--r--indra/llcommon/tuple.h2
-rw-r--r--indra/llcommon/u64.cpp118
-rw-r--r--indra/llcommon/u64.h10
-rw-r--r--indra/llcommon/workqueue.cpp2
-rw-r--r--indra/llcommon/workqueue.h2
291 files changed, 35696 insertions, 35673 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index c947184dc8..5f4ed2fffa 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -3,7 +3,6 @@
project(llcommon)
include(00-Common)
-include(ICU4C)
include(LLCommon)
include(bugsplat)
include(Linking)
@@ -283,7 +282,6 @@ target_link_libraries(
ll::uriparser
ll::oslibraries
ll::tracy
- ll::icu4c
)
target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/indra/llcommon/StackWalker.cpp b/indra/llcommon/StackWalker.cpp
index 56defc6465..201eeed56b 100644
--- a/indra/llcommon/StackWalker.cpp
+++ b/indra/llcommon/StackWalker.cpp
@@ -1,5 +1,5 @@
/**********************************************************************
- *
+ *
* StackWalker.cpp
* http://stackwalker.codeplex.com/
*
@@ -13,14 +13,14 @@
* http://www.codeproject.com/threads/StackWalker.asp
* 2005-07-28 v2 - Changed the params of the constructor and ShowCallstack
* (to simplify the usage)
- * 2005-08-01 v3 - Changed to use 'CONTEXT_FULL' instead of CONTEXT_ALL
+ * 2005-08-01 v3 - Changed to use 'CONTEXT_FULL' instead of CONTEXT_ALL
* (should also be enough)
* - Changed to compile correctly with the PSDK of VC7.0
* (GetFileVersionInfoSizeA and GetFileVersionInfoA is wrongly defined:
* it uses LPSTR instead of LPCSTR as first paremeter)
* - Added declarations to support VC5/6 without using 'dbghelp.h'
- * - Added a 'pUserData' member to the ShowCallstack function and the
- * PReadProcessMemoryRoutine declaration (to pass some user-defined data,
+ * - Added a 'pUserData' member to the ShowCallstack function and the
+ * PReadProcessMemoryRoutine declaration (to pass some user-defined data,
* which can be used in the readMemoryFunction-callback)
* 2005-08-02 v4 - OnSymInit now also outputs the OS-Version by default
* - Added example for doing an exception-callstack-walking in main.cpp
@@ -60,26 +60,26 @@
* Copyright (c) 2005-2013, Jochen Kalmbach
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of Jochen Kalmbach nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Jochen Kalmbach nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**********************************************************************/
@@ -234,7 +234,7 @@ DWORD64
// Some missing defines (for VC5/6):
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
+#endif
// secure-CRT_functions are only available starting with VC8
@@ -396,7 +396,7 @@ public:
m_szSymPath = _strdup(szSymPath);
if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)
this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0);
-
+
DWORD symOptions = this->pSGO(); // SymGetOptions
symOptions |= SYMOPT_LOAD_LINES;
symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
@@ -512,11 +512,11 @@ struct IMAGEHLP_MODULE64_V2 {
tSSO pSSO;
// StackWalk64()
- typedef BOOL (__stdcall *tSW)(
- DWORD MachineType,
+ typedef BOOL (__stdcall *tSW)(
+ DWORD MachineType,
HANDLE hProcess,
- HANDLE hThread,
- LPSTACKFRAME64 StackFrame,
+ HANDLE hThread,
+ LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
@@ -1012,7 +1012,7 @@ BOOL StackWalker::LoadModules()
// The following is used to pass the "userData"-Pointer to the user-provided readMemoryFunction
// This has to be done due to a problem with the "hProcess"-parameter in x64...
-// Because this class is in no case multi-threading-enabled (because of the limitations
+// Because this class is in no case multi-threading-enabled (because of the limitations
// of dbghelp.dll) it is "safe" to use a static-variable
static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL;
static LPVOID s_readMemoryFunction_UserData = NULL;
@@ -1222,7 +1222,7 @@ BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con
csEntry.symTypeString = NULL;
break;
}
-
+
MyStrCpy(csEntry.moduleName, STACKWALK_MAX_NAMELEN, Module.ModuleName);
csEntry.baseOfImage = Module.BaseOfImage;
MyStrCpy(csEntry.loadedImageName, STACKWALK_MAX_NAMELEN, Module.LoadedImageName);
@@ -1243,7 +1243,7 @@ BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con
et = firstEntry;
bLastEntryCalled = false;
this->OnCallstackEntry(et, csEntry);
-
+
if (s.AddrReturn.Offset == 0)
{
bLastEntryCalled = true;
@@ -1358,7 +1358,7 @@ void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUser
ver.dwOSVersionInfoSize = sizeof(ver);
if (GetVersionExA(&ver) != FALSE)
{
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s)\n",
+ _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s)\n",
ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
ver.szCSDVersion);
if (m_verbose)
@@ -1372,7 +1372,7 @@ void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUser
ver.dwOSVersionInfoSize = sizeof(ver);
if (GetVersionExA( (OSVERSIONINFOA*) &ver) != FALSE)
{
- _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n",
+ _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n",
ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
ver.szCSDVersion, ver.wSuiteMask, ver.wProductType);
if (m_verbose)
diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h
index 4634765d0b..91cd55bbaf 100644
--- a/indra/llcommon/StackWalker.h
+++ b/indra/llcommon/StackWalker.h
@@ -1,5 +1,5 @@
/**********************************************************************
- *
+ *
* StackWalker.h
*
*
@@ -13,33 +13,33 @@
* Copyright (c) 2005-2009, Jochen Kalmbach
* All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification,
+ * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of Jochen Kalmbach nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of Jochen Kalmbach nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* **********************************************************************/
#if LL_WINDOWS
-// #pragma once is supported starting with _MCS_VER 1000,
+// #pragma once is supported starting with _MCS_VER 1000,
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
#pragma once
@@ -61,34 +61,34 @@ class StackWalker
public:
typedef enum StackWalkOptions
{
- // No addition info will be retrived
+ // No addition info will be retrived
// (only the address is available)
RetrieveNone = 0,
-
+
// Try to get the symbol-name
RetrieveSymbol = 1,
-
+
// Try to get the line for this symbol
RetrieveLine = 2,
-
+
// Try to retrieve the module-infos
RetrieveModuleInfo = 4,
-
+
// Also retrieve the version for the DLL/EXE
RetrieveFileVersion = 8,
-
+
// Contains all the abouve
RetrieveVerbose = 0xF,
-
+
// Generate a "good" symbol-search-path
SymBuildPath = 0x10,
-
+
// Also use the public Microsoft-Symbol-Server
SymUseSymSrv = 0x20,
-
+
// Contains all the abouve "Sym"-options
SymAll = 0x30,
-
+
// Contains all options (default)
OptionsAll = 0x3F
} StackWalkOptions;
@@ -96,8 +96,8 @@ public:
StackWalker(
bool verbose = true,
int options = OptionsAll, // 'int' is by design, to combine the enum-flags
- LPCSTR szSymPath = NULL,
- DWORD dwProcessId = GetCurrentProcessId(),
+ LPCSTR szSymPath = NULL,
+ DWORD dwProcessId = GetCurrentProcessId(),
HANDLE hProcess = GetCurrentProcess()
);
StackWalker(DWORD dwProcessId, HANDLE hProcess);
@@ -116,18 +116,18 @@ public:
BOOL ShowCallstack(
bool verbose,
- HANDLE hThread = GetCurrentThread(),
- const CONTEXT *context = NULL,
+ HANDLE hThread = GetCurrentThread(),
+ const CONTEXT *context = NULL,
PReadProcessMemoryRoutine readMemoryFunction = NULL,
LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
);
#if _MSC_VER >= 1300
-// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
+// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
protected:
#endif
- enum { STACKWALK_MAX_NAMELEN = 4096 }; // max name length for found symbols
+ enum { STACKWALK_MAX_NAMELEN = 4096 }; // max name length for found symbols
protected:
// Entry for each Callstack-Entry
@@ -173,10 +173,10 @@ protected:
// The "ugly" assembler-implementation is needed for systems before XP
-// If you have a new PSDK and you only compile for XP and later, then you can use
+// If you have a new PSDK and you only compile for XP and later, then you can use
// the "RtlCaptureContext"
-// Currently there is no define which determines the PSDK-Version...
-// So we just use the compiler-version (and assumes that the PSDK is
+// Currently there is no define which determines the PSDK-Version...
+// So we just use the compiler-version (and assumes that the PSDK is
// the one which was installed by the VS-IDE)
// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
@@ -185,7 +185,7 @@ protected:
#if defined(_M_IX86)
#ifdef CURRENT_THREAD_VIA_EXCEPTION
-// TODO: The following is not a "good" implementation,
+// TODO: The following is not a "good" implementation,
// because the callstack is only valid in the "__except" block...
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
do { \
diff --git a/indra/llcommon/always_return.h b/indra/llcommon/always_return.h
index 6b9f1fdeaf..a206471da5 100644
--- a/indra/llcommon/always_return.h
+++ b/indra/llcommon/always_return.h
@@ -4,7 +4,7 @@
* @date 2023-01-20
* @brief Call specified callable with arbitrary arguments, but always return
* specified type.
- *
+ *
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Copyright (c) 2023, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/apply.cpp b/indra/llcommon/apply.cpp
index 417e23d3b4..805b1234ac 100644
--- a/indra/llcommon/apply.cpp
+++ b/indra/llcommon/apply.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-12-21
* @brief Implementation for apply.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/apply.h b/indra/llcommon/apply.h
index cf6161ed50..ec1a39f7b0 100644
--- a/indra/llcommon/apply.h
+++ b/indra/llcommon/apply.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-06-18
* @brief C++14 version of std::apply()
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
@@ -69,7 +69,7 @@ using std::invoke;
// Use invoke() to handle pointer-to-method:
// derived from https://stackoverflow.com/a/38288251
-template<typename Fn, typename... Args,
+template<typename Fn, typename... Args,
typename std::enable_if<std::is_member_pointer<typename std::decay<Fn>::type>::value,
int>::type = 0 >
auto invoke(Fn&& f, Args&&... args)
@@ -77,7 +77,7 @@ auto invoke(Fn&& f, Args&&... args)
return std::mem_fn(std::forward<Fn>(f))(std::forward<Args>(args)...);
}
-template<typename Fn, typename... Args,
+template<typename Fn, typename... Args,
typename std::enable_if<!std::is_member_pointer<typename std::decay<Fn>::type>::value,
int>::type = 0 >
auto invoke(Fn&& f, Args&&... args)
@@ -154,7 +154,7 @@ using std::bind_front;
#else // no std::bind_front()
-template<typename Fn, typename... Args,
+template<typename Fn, typename... Args,
typename std::enable_if<!std::is_member_pointer<typename std::decay<Fn>::type>::value,
int>::type = 0 >
auto bind_front(Fn&& f, Args&&... args)
@@ -172,7 +172,7 @@ auto bind_front(Fn&& f, Args&&... args)
};
}
-template<typename Fn, typename... Args,
+template<typename Fn, typename... Args,
typename std::enable_if<std::is_member_pointer<typename std::decay<Fn>::type>::value,
int>::type = 0 >
auto bind_front(Fn&& f, Args&&... args)
diff --git a/indra/llcommon/chrono.h b/indra/llcommon/chrono.h
index 806e871892..d121b9adf6 100644
--- a/indra/llcommon/chrono.h
+++ b/indra/llcommon/chrono.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-05
* @brief supplement <chrono> with utility functions
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/classic_callback.cpp b/indra/llcommon/classic_callback.cpp
index 5674e0a44d..b2d0e7b303 100644
--- a/indra/llcommon/classic_callback.cpp
+++ b/indra/llcommon/classic_callback.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-09-23
* @brief Implementation for classic_callback.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/commoncontrol.cpp b/indra/llcommon/commoncontrol.cpp
index 81e66baf8c..d8bdcd5aa5 100644
--- a/indra/llcommon/commoncontrol.cpp
+++ b/indra/llcommon/commoncontrol.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-06-08
* @brief Implementation for commoncontrol.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/commoncontrol.h b/indra/llcommon/commoncontrol.h
index 07d4a45ac5..13aa983a99 100644
--- a/indra/llcommon/commoncontrol.h
+++ b/indra/llcommon/commoncontrol.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-06-08
* @brief Access LLViewerControl LLEventAPI, if process has one.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/ctype_workaround.h b/indra/llcommon/ctype_workaround.h
index 552be9fb90..89a47fe3db 100644
--- a/indra/llcommon/ctype_workaround.h
+++ b/indra/llcommon/ctype_workaround.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file ctype_workaround.h
* @brief The workaround is to create some legacy symbols that point
* to the correct symbols, which avoids link errors.
@@ -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$
*/
@@ -42,12 +42,12 @@ __const unsigned short int *__ctype_b;
__const __int32_t *__ctype_tolower;
__const __int32_t *__ctype_toupper;
-// call this function at the beginning of main()
+// call this function at the beginning of main()
void ctype_workaround()
{
- __ctype_b = *(__ctype_b_loc());
- __ctype_toupper = *(__ctype_toupper_loc());
- __ctype_tolower = *(__ctype_tolower_loc());
+ __ctype_b = *(__ctype_b_loc());
+ __ctype_toupper = *(__ctype_toupper_loc());
+ __ctype_tolower = *(__ctype_tolower_loc());
}
#endif
diff --git a/indra/llcommon/fix_macros.h b/indra/llcommon/fix_macros.h
index 43c09c54bc..ed6c26a371 100644
--- a/indra/llcommon/fix_macros.h
+++ b/indra/llcommon/fix_macros.h
@@ -6,7 +6,7 @@
* generic names, preventing any library from using those names. We've
* had to fix these in so many places that it's worth making a header
* file to handle it.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/function_types.h b/indra/llcommon/function_types.h
index 3f42f6d640..7e15895a7e 100644
--- a/indra/llcommon/function_types.h
+++ b/indra/llcommon/function_types.h
@@ -4,7 +4,7 @@
* @date 2023-01-20
* @brief Extend boost::function_types to examine boost::function and
* std::function
- *
+ *
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Copyright (c) 2023, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/hbxxh.cpp b/indra/llcommon/hbxxh.cpp
index 388269d6c8..41d797a7e3 100644
--- a/indra/llcommon/hbxxh.cpp
+++ b/indra/llcommon/hbxxh.cpp
@@ -10,16 +10,16 @@
* 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$
*/
diff --git a/indra/llcommon/hbxxh.h b/indra/llcommon/hbxxh.h
index 9c0e9cf172..142e140cf3 100644
--- a/indra/llcommon/hbxxh.h
+++ b/indra/llcommon/hbxxh.h
@@ -10,16 +10,16 @@
* 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$
*/
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index 9a0c565b06..d24a221671 100644
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file indra_constants.cpp
* @brief some useful short term constants for Indra
*
* $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$
*/
@@ -38,39 +38,39 @@ const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
// Maintenance's group id.
const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd");
// Grass Images
-const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
+const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
-const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
+const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
-const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
-const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
-const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
-const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
-const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
+const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
+const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
+const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
+const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
+const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
-const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
+const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
const LLUUID IMG_WHITE ("5748decc-f629-461c-9a36-a35a221fe21f"); // dataserver
-const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
-const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
-const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
-const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
-const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
+const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
+const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
+const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
+const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
+const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
-const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
-const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
+const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
+const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
-const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER
-const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER
-const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER
+const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER
+const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER
+const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER
-const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
-const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
-const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
-const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
+const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
+const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
+const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
+const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
-const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
+const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
const LLUUID DEFAULT_OBJECT_TEXTURE ("89556747-24cb-43ed-920b-47caed15465f"); // On dataserver
const LLUUID DEFAULT_OBJECT_SPECULAR ("87e0e8f7-8729-1ea8-cfc9-8915773009db"); // On dataserver
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index a16cfac2b9..811313e56e 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file indra_constants.h
* @brief some useful short term constants for Indra
*
* $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$
*/
@@ -37,21 +37,21 @@ static const U32 REGION_WIDTH_U32 = 256;
const F32 REGION_HEIGHT_METERS = 4096.f;
-const F32 DEFAULT_AGENT_DEPTH = 0.45f;
-const F32 DEFAULT_AGENT_WIDTH = 0.60f;
-const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
+const F32 DEFAULT_AGENT_DEPTH = 0.45f;
+const F32 DEFAULT_AGENT_WIDTH = 0.60f;
+const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
enum ETerrainBrushType
{
- // the valid brush numbers cannot be reordered, because they
- // are used in the binary LSL format as arguments to llModifyLand()
- E_LANDBRUSH_LEVEL = 0,
- E_LANDBRUSH_RAISE = 1,
- E_LANDBRUSH_LOWER = 2,
- E_LANDBRUSH_SMOOTH = 3,
- E_LANDBRUSH_NOISE = 4,
- E_LANDBRUSH_REVERT = 5,
- E_LANDBRUSH_INVALID = 6
+ // the valid brush numbers cannot be reordered, because they
+ // are used in the binary LSL format as arguments to llModifyLand()
+ E_LANDBRUSH_LEVEL = 0,
+ E_LANDBRUSH_RAISE = 1,
+ E_LANDBRUSH_LOWER = 2,
+ E_LANDBRUSH_SMOOTH = 3,
+ E_LANDBRUSH_NOISE = 4,
+ E_LANDBRUSH_REVERT = 5,
+ E_LANDBRUSH_INVALID = 6
};
enum EMouseClickType{
@@ -67,101 +67,101 @@ enum EMouseClickType{
// keys
// Bit masks for various keyboard modifier keys.
-const MASK MASK_NONE = 0x0000;
-const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
-const MASK MASK_ALT = 0x0002;
-const MASK MASK_SHIFT = 0x0004;
+const MASK MASK_NONE = 0x0000;
+const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
+const MASK MASK_ALT = 0x0002;
+const MASK MASK_SHIFT = 0x0004;
const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
-const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
-const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
+const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
+const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
// Special keys go into >128
-const KEY KEY_SPECIAL = 0x80; // special keys start here
-const KEY KEY_RETURN = 0x81;
-const KEY KEY_LEFT = 0x82;
-const KEY KEY_RIGHT = 0x83;
-const KEY KEY_UP = 0x84;
-const KEY KEY_DOWN = 0x85;
-const KEY KEY_ESCAPE = 0x86;
+const KEY KEY_SPECIAL = 0x80; // special keys start here
+const KEY KEY_RETURN = 0x81;
+const KEY KEY_LEFT = 0x82;
+const KEY KEY_RIGHT = 0x83;
+const KEY KEY_UP = 0x84;
+const KEY KEY_DOWN = 0x85;
+const KEY KEY_ESCAPE = 0x86;
const KEY KEY_BACKSPACE =0x87;
-const KEY KEY_DELETE = 0x88;
-const KEY KEY_SHIFT = 0x89;
-const KEY KEY_CONTROL = 0x8A;
-const KEY KEY_ALT = 0x8B;
-const KEY KEY_HOME = 0x8C;
-const KEY KEY_END = 0x8D;
+const KEY KEY_DELETE = 0x88;
+const KEY KEY_SHIFT = 0x89;
+const KEY KEY_CONTROL = 0x8A;
+const KEY KEY_ALT = 0x8B;
+const KEY KEY_HOME = 0x8C;
+const KEY KEY_END = 0x8D;
const KEY KEY_PAGE_UP = 0x8E;
const KEY KEY_PAGE_DOWN = 0x8F;
const KEY KEY_HYPHEN = 0x90;
const KEY KEY_EQUALS = 0x91;
const KEY KEY_INSERT = 0x92;
const KEY KEY_CAPSLOCK = 0x93;
-const KEY KEY_TAB = 0x94;
-const KEY KEY_ADD = 0x95;
+const KEY KEY_TAB = 0x94;
+const KEY KEY_ADD = 0x95;
const KEY KEY_SUBTRACT =0x96;
const KEY KEY_MULTIPLY =0x97;
-const KEY KEY_DIVIDE = 0x98;
-const KEY KEY_F1 = 0xA1;
-const KEY KEY_F2 = 0xA2;
-const KEY KEY_F3 = 0xA3;
-const KEY KEY_F4 = 0xA4;
-const KEY KEY_F5 = 0xA5;
-const KEY KEY_F6 = 0xA6;
-const KEY KEY_F7 = 0xA7;
-const KEY KEY_F8 = 0xA8;
-const KEY KEY_F9 = 0xA9;
-const KEY KEY_F10 = 0xAA;
-const KEY KEY_F11 = 0xAB;
-const KEY KEY_F12 = 0xAC;
-
-const KEY KEY_PAD_UP = 0xC0;
-const KEY KEY_PAD_DOWN = 0xC1;
-const KEY KEY_PAD_LEFT = 0xC2;
-const KEY KEY_PAD_RIGHT = 0xC3;
-const KEY KEY_PAD_HOME = 0xC4;
-const KEY KEY_PAD_END = 0xC5;
-const KEY KEY_PAD_PGUP = 0xC6;
-const KEY KEY_PAD_PGDN = 0xC7;
-const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
-const KEY KEY_PAD_INS = 0xC9;
-const KEY KEY_PAD_DEL = 0xCA;
-const KEY KEY_PAD_RETURN = 0xCB;
-const KEY KEY_PAD_ADD = 0xCC; // not used
-const KEY KEY_PAD_SUBTRACT = 0xCD; // not used
+const KEY KEY_DIVIDE = 0x98;
+const KEY KEY_F1 = 0xA1;
+const KEY KEY_F2 = 0xA2;
+const KEY KEY_F3 = 0xA3;
+const KEY KEY_F4 = 0xA4;
+const KEY KEY_F5 = 0xA5;
+const KEY KEY_F6 = 0xA6;
+const KEY KEY_F7 = 0xA7;
+const KEY KEY_F8 = 0xA8;
+const KEY KEY_F9 = 0xA9;
+const KEY KEY_F10 = 0xAA;
+const KEY KEY_F11 = 0xAB;
+const KEY KEY_F12 = 0xAC;
+
+const KEY KEY_PAD_UP = 0xC0;
+const KEY KEY_PAD_DOWN = 0xC1;
+const KEY KEY_PAD_LEFT = 0xC2;
+const KEY KEY_PAD_RIGHT = 0xC3;
+const KEY KEY_PAD_HOME = 0xC4;
+const KEY KEY_PAD_END = 0xC5;
+const KEY KEY_PAD_PGUP = 0xC6;
+const KEY KEY_PAD_PGDN = 0xC7;
+const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
+const KEY KEY_PAD_INS = 0xC9;
+const KEY KEY_PAD_DEL = 0xCA;
+const KEY KEY_PAD_RETURN = 0xCB;
+const KEY KEY_PAD_ADD = 0xCC; // not used
+const KEY KEY_PAD_SUBTRACT = 0xCD; // not used
const KEY KEY_PAD_MULTIPLY = 0xCE; // not used
-const KEY KEY_PAD_DIVIDE = 0xCF; // not used
-
-const KEY KEY_BUTTON0 = 0xD0;
-const KEY KEY_BUTTON1 = 0xD1;
-const KEY KEY_BUTTON2 = 0xD2;
-const KEY KEY_BUTTON3 = 0xD3;
-const KEY KEY_BUTTON4 = 0xD4;
-const KEY KEY_BUTTON5 = 0xD5;
-const KEY KEY_BUTTON6 = 0xD6;
-const KEY KEY_BUTTON7 = 0xD7;
-const KEY KEY_BUTTON8 = 0xD8;
-const KEY KEY_BUTTON9 = 0xD9;
-const KEY KEY_BUTTON10 = 0xDA;
-const KEY KEY_BUTTON11 = 0xDB;
-const KEY KEY_BUTTON12 = 0xDC;
-const KEY KEY_BUTTON13 = 0xDD;
-const KEY KEY_BUTTON14 = 0xDE;
-const KEY KEY_BUTTON15 = 0xDF;
-
-const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
+const KEY KEY_PAD_DIVIDE = 0xCF; // not used
+
+const KEY KEY_BUTTON0 = 0xD0;
+const KEY KEY_BUTTON1 = 0xD1;
+const KEY KEY_BUTTON2 = 0xD2;
+const KEY KEY_BUTTON3 = 0xD3;
+const KEY KEY_BUTTON4 = 0xD4;
+const KEY KEY_BUTTON5 = 0xD5;
+const KEY KEY_BUTTON6 = 0xD6;
+const KEY KEY_BUTTON7 = 0xD7;
+const KEY KEY_BUTTON8 = 0xD8;
+const KEY KEY_BUTTON9 = 0xD9;
+const KEY KEY_BUTTON10 = 0xDA;
+const KEY KEY_BUTTON11 = 0xDB;
+const KEY KEY_BUTTON12 = 0xDC;
+const KEY KEY_BUTTON13 = 0xDD;
+const KEY KEY_BUTTON14 = 0xDE;
+const KEY KEY_BUTTON15 = 0xDF;
+
+const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
const S32 KEY_COUNT = 256;
-const F32 DEFAULT_WATER_HEIGHT = 20.0f;
+const F32 DEFAULT_WATER_HEIGHT = 20.0f;
// Maturity ratings for simulators
-const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
-const U8 SIM_ACCESS_PG = 13;
-const U8 SIM_ACCESS_MATURE = 21;
-const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
-const U8 SIM_ACCESS_DOWN = 254;
-const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
+const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
+const U8 SIM_ACCESS_PG = 13;
+const U8 SIM_ACCESS_MATURE = 21;
+const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
+const U8 SIM_ACCESS_DOWN = 254;
+const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
// attachment constants
const U8 ATTACHMENT_ADD = 0x80;
@@ -258,84 +258,84 @@ const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
const S32 CHAT_CHANNEL_DEBUG = S32_MAX;
// agent constants
-const U32 CONTROL_AT_POS_INDEX = 0;
-const U32 CONTROL_AT_NEG_INDEX = 1;
-const U32 CONTROL_LEFT_POS_INDEX = 2;
-const U32 CONTROL_LEFT_NEG_INDEX = 3;
-const U32 CONTROL_UP_POS_INDEX = 4;
-const U32 CONTROL_UP_NEG_INDEX = 5;
-const U32 CONTROL_PITCH_POS_INDEX = 6;
-const U32 CONTROL_PITCH_NEG_INDEX = 7;
-const U32 CONTROL_YAW_POS_INDEX = 8;
-const U32 CONTROL_YAW_NEG_INDEX = 9;
-const U32 CONTROL_FAST_AT_INDEX = 10;
-const U32 CONTROL_FAST_LEFT_INDEX = 11;
-const U32 CONTROL_FAST_UP_INDEX = 12;
-const U32 CONTROL_FLY_INDEX = 13;
-const U32 CONTROL_STOP_INDEX = 14;
-const U32 CONTROL_FINISH_ANIM_INDEX = 15;
-const U32 CONTROL_STAND_UP_INDEX = 16;
-const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
-const U32 CONTROL_MOUSELOOK_INDEX = 18;
-const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
-const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
-const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
-const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
-const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
-const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
-const U32 CONTROL_TURN_LEFT_INDEX = 25;
-const U32 CONTROL_TURN_RIGHT_INDEX = 26;
-const U32 CONTROL_AWAY_INDEX = 27;
-const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
-const U32 CONTROL_LBUTTON_UP_INDEX = 29;
-const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
-const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
-const U32 TOTAL_CONTROLS = 32;
-
-const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
-const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
-const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
-const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
-const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
-const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
-const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
-const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
-const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
-const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
-
-const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
-const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
-const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
-
-const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
-const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
-const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
-const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
-const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
-const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
-
-const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
-const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
-const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
-const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
-const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
-const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
-const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
-const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
-
-const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
-
-const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
-const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
-const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
-const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
-
-// move these up so that we can hide them in "State" for object updates
+const U32 CONTROL_AT_POS_INDEX = 0;
+const U32 CONTROL_AT_NEG_INDEX = 1;
+const U32 CONTROL_LEFT_POS_INDEX = 2;
+const U32 CONTROL_LEFT_NEG_INDEX = 3;
+const U32 CONTROL_UP_POS_INDEX = 4;
+const U32 CONTROL_UP_NEG_INDEX = 5;
+const U32 CONTROL_PITCH_POS_INDEX = 6;
+const U32 CONTROL_PITCH_NEG_INDEX = 7;
+const U32 CONTROL_YAW_POS_INDEX = 8;
+const U32 CONTROL_YAW_NEG_INDEX = 9;
+const U32 CONTROL_FAST_AT_INDEX = 10;
+const U32 CONTROL_FAST_LEFT_INDEX = 11;
+const U32 CONTROL_FAST_UP_INDEX = 12;
+const U32 CONTROL_FLY_INDEX = 13;
+const U32 CONTROL_STOP_INDEX = 14;
+const U32 CONTROL_FINISH_ANIM_INDEX = 15;
+const U32 CONTROL_STAND_UP_INDEX = 16;
+const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
+const U32 CONTROL_MOUSELOOK_INDEX = 18;
+const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
+const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
+const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
+const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
+const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
+const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
+const U32 CONTROL_TURN_LEFT_INDEX = 25;
+const U32 CONTROL_TURN_RIGHT_INDEX = 26;
+const U32 CONTROL_AWAY_INDEX = 27;
+const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
+const U32 CONTROL_LBUTTON_UP_INDEX = 29;
+const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
+const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
+const U32 TOTAL_CONTROLS = 32;
+
+const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
+const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
+const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
+const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
+const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
+const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
+const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
+const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
+const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
+const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
+
+const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
+const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
+const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
+
+const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
+const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
+const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
+const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
+const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
+const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
+
+const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
+const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
+const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
+const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
+const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
+const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
+const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
+const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
+
+const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
+
+const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
+const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
+const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
+const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
+
+// move these up so that we can hide them in "State" for object updates
// (for now)
-const U32 AGENT_ATTACH_OFFSET = 4;
-const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
+const U32 AGENT_ATTACH_OFFSET = 4;
+const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
-// RN: this method swaps the upper and lower nibbles to maintain backward
+// RN: this method swaps the upper and lower nibbles to maintain backward
// compatibility with old objects that only used the upper nibble
#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
diff --git a/indra/llcommon/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h
index 4a9b2e2725..79f4f5ebbd 100644
--- a/indra/llcommon/is_approx_equal_fraction.h
+++ b/indra/llcommon/is_approx_equal_fraction.h
@@ -5,25 +5,25 @@
* @brief lltut.h uses is_approx_equal_fraction(). Moved to this header
* file in llcommon so we can use lltut.h for llcommon tests without
* making llcommon depend on llmath.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/lazyeventapi.cpp b/indra/llcommon/lazyeventapi.cpp
index 028af9f33f..91db0ee4a6 100644
--- a/indra/llcommon/lazyeventapi.cpp
+++ b/indra/llcommon/lazyeventapi.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-06-17
* @brief Implementation for lazyeventapi.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/lazyeventapi.h b/indra/llcommon/lazyeventapi.h
index e36831270b..0e5df4e6f4 100644
--- a/indra/llcommon/lazyeventapi.h
+++ b/indra/llcommon/lazyeventapi.h
@@ -4,7 +4,7 @@
* @date 2022-06-16
* @brief Declaring a static module-scope LazyEventAPI registers a specific
* LLEventAPI for future on-demand instantiation.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index a228fd22be..a918caa2e8 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file linden_common.h
* @brief Includes common headers that are always safe to include
*
* $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$
*/
diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h
index da9d98c16c..0ba8b34cb6 100644
--- a/indra/llcommon/llalignedarray.h
+++ b/indra/llcommon/llalignedarray.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llalignedarray.h
* @brief A static array which obeys alignment restrictions and mimics std::vector accessors.
*
* $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$
*/
@@ -33,94 +33,94 @@ template <class T, U32 alignment>
class LLAlignedArray
{
public:
- T* mArray;
- U32 mElementCount;
- U32 mCapacity;
-
- LLAlignedArray();
- ~LLAlignedArray();
-
- void push_back(const T& elem);
- U32 size() const { return mElementCount; }
- void resize(U32 size);
- T* append(S32 N);
- T& operator[](int idx);
- const T& operator[](int idx) const;
+ T* mArray;
+ U32 mElementCount;
+ U32 mCapacity;
+
+ LLAlignedArray();
+ ~LLAlignedArray();
+
+ void push_back(const T& elem);
+ U32 size() const { return mElementCount; }
+ void resize(U32 size);
+ T* append(S32 N);
+ T& operator[](int idx);
+ const T& operator[](int idx) const;
};
template <class T, U32 alignment>
LLAlignedArray<T, alignment>::LLAlignedArray()
{
- llassert(alignment >= 16);
- mArray = NULL;
- mElementCount = 0;
- mCapacity = 0;
+ llassert(alignment >= 16);
+ mArray = NULL;
+ mElementCount = 0;
+ mCapacity = 0;
}
template <class T, U32 alignment>
LLAlignedArray<T, alignment>::~LLAlignedArray()
{
- ll_aligned_free<alignment>(mArray);
- mArray = NULL;
- mElementCount = 0;
- mCapacity = 0;
+ ll_aligned_free<alignment>(mArray);
+ mArray = NULL;
+ mElementCount = 0;
+ mCapacity = 0;
}
template <class T, U32 alignment>
void LLAlignedArray<T, alignment>::push_back(const T& elem)
{
- T* old_buf = NULL;
- if (mCapacity <= mElementCount)
- {
- mCapacity++;
- mCapacity *= 2;
- T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
- if (mArray)
- {
- ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
- }
- old_buf = mArray;
- mArray = new_buf;
- }
-
- mArray[mElementCount++] = elem;
-
- //delete old array here to prevent error on a.push_back(a[0])
- ll_aligned_free<alignment>(old_buf);
+ T* old_buf = NULL;
+ if (mCapacity <= mElementCount)
+ {
+ mCapacity++;
+ mCapacity *= 2;
+ T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
+ if (mArray)
+ {
+ ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
+ }
+ old_buf = mArray;
+ mArray = new_buf;
+ }
+
+ mArray[mElementCount++] = elem;
+
+ //delete old array here to prevent error on a.push_back(a[0])
+ ll_aligned_free<alignment>(old_buf);
}
template <class T, U32 alignment>
void LLAlignedArray<T, alignment>::resize(U32 size)
{
- if (mCapacity < size)
- {
- mCapacity = size+mCapacity*2;
- T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
- if (mArray)
- {
- ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
- ll_aligned_free<alignment>(mArray);
- }
-
- /*for (U32 i = mElementCount; i < mCapacity; ++i)
- {
- new(new_buf+i) T();
- }*/
- mArray = new_buf;
- }
-
- mElementCount = size;
+ if (mCapacity < size)
+ {
+ mCapacity = size+mCapacity*2;
+ T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
+ if (mArray)
+ {
+ ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
+ ll_aligned_free<alignment>(mArray);
+ }
+
+ /*for (U32 i = mElementCount; i < mCapacity; ++i)
+ {
+ new(new_buf+i) T();
+ }*/
+ mArray = new_buf;
+ }
+
+ mElementCount = size;
}
template <class T, U32 alignment>
T& LLAlignedArray<T, alignment>::operator[](int idx)
{
- if(idx >= mElementCount || idx < 0)
+ if(idx >= mElementCount || idx < 0)
{
LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL;
}
- return mArray[idx];
+ return mArray[idx];
}
template <class T, U32 alignment>
@@ -130,15 +130,15 @@ const T& LLAlignedArray<T, alignment>::operator[](int idx) const
{
LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL;
}
- return mArray[idx];
+ return mArray[idx];
}
template <class T, U32 alignment>
T* LLAlignedArray<T, alignment>::append(S32 N)
{
- U32 sz = size();
- resize(sz+N);
- return &((*this)[sz]);
+ U32 sz = size();
+ resize(sz+N);
+ return &((*this)[sz]);
}
#endif
diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp
index ac97fb71dd..abe3779b85 100644
--- a/indra/llcommon/llallocator.cpp
+++ b/indra/llcommon/llallocator.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llallocator.cpp
* @brief Implementation of the LLAllocator class.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h
index d26ad73c5b..aa3eead546 100644
--- a/indra/llcommon/llallocator.h
+++ b/indra/llcommon/llallocator.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llallocator.h
* @brief Declaration of the LLAllocator class.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp
index c6d9542b42..85e56b4db4 100644
--- a/indra/llcommon/llallocator_heap_profile.cpp
+++ b/indra/llcommon/llallocator_heap_profile.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llallocator_heap_profile.cpp
* @brief Implementation of the parser for tcmalloc heap profile data.
* @author Brad Kittenbrink
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -67,7 +67,7 @@ void LLAllocatorHeapProfile::parse(std::string const & prof_text)
std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length();
- range_t prof_range(prof_begin, prof_text.end());
+ range_t prof_range(prof_begin, prof_text.end());
boost::algorithm::split(prof_lines,
prof_range,
boost::bind(std::equal_to<llwchar>(), '\n', _1));
@@ -107,34 +107,34 @@ void LLAllocatorHeapProfile::parse(std::string const & prof_text)
++j;
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
- llassert(j != line_elems.end());
+ llassert(j != line_elems.end());
if (j != line_elems.end())
- {
- ++j; // skip the '@'
-
- mLines.push_back(line(live_count, live_size, tot_count, tot_size));
- line & current_line = mLines.back();
-
- for(; j != line_elems.end(); ++j)
- {
- if(!j->empty())
- {
- U32 marker = boost::lexical_cast<U32>(*j);
- current_line.mTrace.push_back(marker);
- }
- }
- }
+ {
+ ++j; // skip the '@'
+
+ mLines.push_back(line(live_count, live_size, tot_count, tot_size));
+ line & current_line = mLines.back();
+
+ for(; j != line_elems.end(); ++j)
+ {
+ if(!j->empty())
+ {
+ U32 marker = boost::lexical_cast<U32>(*j);
+ current_line.mTrace.push_back(marker);
+ }
+ }
+ }
}
// *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it
}
void LLAllocatorHeapProfile::dump(std::ostream & out) const
{
- for (const LLAllocatorHeapProfile::line& line : mLines)
+ for (const LLAllocatorHeapProfile::line& line : mLines)
{
out << line.mLiveCount << ": " << line.mLiveSize << '[' << line.mTotalCount << ": " << line.mTotalSize << "] @";
- for (const stack_marker marker : line.mTrace)
+ for (const stack_marker marker : line.mTrace)
{
out << ' ' << marker;
}
diff --git a/indra/llcommon/llallocator_heap_profile.h b/indra/llcommon/llallocator_heap_profile.h
index 69300b829b..22f284b703 100644
--- a/indra/llcommon/llallocator_heap_profile.h
+++ b/indra/llcommon/llallocator_heap_profile.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llallocator_heap_profile.h
* @brief Declaration of the parser for tcmalloc heap profile data.
* @author Brad Kittenbrink
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -59,7 +59,7 @@ public:
{
}
- void parse(std::string const & prof_text);
+ void parse(std::string const & prof_text);
void dump(std::ostream & out) const;
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 90d0c28eb1..9729f68d23 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();
- LLEventTimer::updateClass();
- mRunner.run();
+ LLFrameTimer::updateFrameTime();
+ LLFrameTimer::updateFrameCount();
+ LLEventTimer::updateClass();
+ 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/llapp.h b/indra/llcommon/llapp.h
index a892bfeb1e..93bf4dd929 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llapp.h
* @brief Declaration 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$
*/
@@ -53,290 +53,290 @@ void clear_signals();
class LL_COMMON_API LLApp
{
public:
- typedef enum e_app_status
- {
- APP_STATUS_RUNNING, // The application is currently running - the default status
- APP_STATUS_QUITTING, // The application is currently quitting - threads should listen for this and clean up
- APP_STATUS_STOPPED, // The application is no longer running - tells the error thread it can exit
- APP_STATUS_ERROR // The application had a fatal error occur - tells the error thread to run
- } EAppStatus;
-
-
- LLApp();
- virtual ~LLApp();
-
- /**
- * @brief Return the static app instance if one was created.
- */
- static LLApp* instance();
-
- /** @name Runtime options */
- //@{
- /**
- * @brief Enumeration to specify option priorities in highest to
- * lowest order.
- */
- enum OptionPriority
- {
- PRIORITY_RUNTIME_OVERRIDE,
- PRIORITY_COMMAND_LINE,
- PRIORITY_SPECIFIC_CONFIGURATION,
- PRIORITY_GENERAL_CONFIGURATION,
- PRIORITY_DEFAULT,
- PRIORITY_COUNT
- };
-
- /**
- * @brief Get the application option at the highest priority.
- *
- * If the return value is undefined, the option does not exist.
- * @param name The name of the option.
- * @return Returns the option data.
- */
- LLSD getOption(const std::string& name) const;
-
- /**
- * @brief Parse ASCII command line options and insert them into
- * application command line options.
- *
- * The name inserted into the option will have leading option
- * identifiers (a minus or double minus) stripped. All options
- * with values will be stored as a string, while all options
- * without values will be stored as true.
- * @param argc The argc passed into main().
- * @param argv The argv passed into main().
- * @return Returns true if the parse succeeded.
- */
- bool parseCommandOptions(int argc, char** argv);
-
- /**
- * @brief Parse Unicode command line options and insert them into
- * application command line options.
- *
- * The name inserted into the option will have leading option
- * identifiers (a minus or double minus) stripped. All options
- * with values will be stored as a string, while all options
- * without values will be stored as true.
- * @param argc The argc passed into main().
- * @param wargv The wargv passed into main().
- * @return Returns true if the parse succeeded.
- */
- bool parseCommandOptions(int argc, wchar_t** wargv);
-
- /**
- * @brief Keep track of live files automatically.
- *
- * *TODO: it currently uses the <code>addToEventTimer()</code> API
- * instead of the runner. I should probalby use the runner.
- *
- * *NOTE: DO NOT add the livefile instance to any kind of check loop.
- *
- * @param livefile A valid instance of an LLLiveFile. This LLApp
- * instance will delete the livefile instance.
- */
- void manageLiveFile(LLLiveFile* livefile);
-
- /**
- * @brief Set the options at the specified priority.
- *
- * This function completely replaces the options at the priority
- * level with the data specified. This function will make sure
- * level and data might be valid before doing the replace.
- * @param level The priority level of the data.
- * @param data The data to set.
- * @return Returns true if the option was set.
- */
- bool setOptionData(OptionPriority level, LLSD data);
-
- /**
- * @brief Get the option data at the specified priority.
- *
- * This method is probably not so useful except when merging
- * information.
- * @param level The priority level of the data.
- * @return Returns The data (if any) at the level priority.
- */
- LLSD getOptionData(OptionPriority level);
- //@}
-
-
-
- //
- // Main application logic
- //
- virtual bool init() = 0; // Override to do application initialization
-
- //
- // cleanup()
- //
- // It's currently assumed that the cleanup() method will only get
- // called from the main thread or the error handling thread, as it will
- // likely do thread shutdown, among other things.
- //
- virtual bool cleanup() = 0; // Override to do application cleanup
-
- //
- // frame()
- //
- // Pass control to the application for a single frame. Returns 'done'
- // flag: if frame() returns false, it expects to be called again.
- //
- virtual bool frame() = 0; // Override for application body logic
-
- //
- // Crash logging
- //
- void disableCrashlogger(); // Let the OS handle the crashes
- static bool isCrashloggerDisabled(); // Get the here above set value
-
- //
- // Application status
- //
- static void setQuitting(); // Set status to QUITTING, the app is now shutting down
- static void setStopped(); // Set status to STOPPED, the app is done running and should exit
- static void setError(); // Set status to ERROR, the error handler should run
- static bool isStopped();
- static bool isRunning();
- static bool isQuitting();
- static bool isError();
- static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
- static int getPid();
-
- //
- // Sleep for specified time while still running
- //
- // For use by a coroutine or thread that performs some maintenance on a
- // periodic basis. (See also LLEventTimer.) This method supports the
- // pattern of an "infinite" loop that sleeps for some time, performs some
- // action, then sleeps again. The trouble with literally sleeping a worker
- // thread is that it could potentially sleep right through attempted
- // application shutdown. This method avoids that by returning false as
- // soon as the application status changes away from APP_STATUS_RUNNING
- // (isRunning()).
- //
- // sleep() returns true if it sleeps undisturbed for the entire specified
- // duration. The idea is that you can code 'while sleep(duration) ...',
- // which will break the loop once shutdown begins.
- //
- // Since any time-based LLUnit should be implicitly convertible to
- // F32Milliseconds, accept that specific type as a proxy.
- static bool sleep(F32Milliseconds duration);
- // Allow any duration defined in terms of <chrono>.
- // One can imagine a wonderfully general bidirectional conversion system
- // between any type derived from LLUnits::LLUnit<T, LLUnits::Seconds> and
- // any std::chrono::duration -- but that doesn't yet exist.
- template <typename Rep, typename Period>
- bool sleep(const std::chrono::duration<Rep, Period>& duration)
- {
- // wait_for_unequal() has the opposite bool return convention
- return ! sStatus.wait_for_unequal(duration, APP_STATUS_RUNNING);
- }
-
- /** @name Error handling methods */
- //@{
- /**
- * @brief Do our generic platform-specific error-handling setup --
- * signals on unix, structured exceptions on windows.
- *
- * DO call this method if your app will either spawn children or be
- * spawned by a launcher.
- * Call just after app object construction.
- * (Otherwise your app will crash when getting signals,
- * and will not core dump.)
- *
- * DO NOT call this method if your application has specialized
- * error handling code.
- */
- void setupErrorHandling(bool mSecondInstance=false);
-
- void setErrorHandler(LLAppErrorHandler handler);
- static void runErrorHandler(); // run shortly after we detect an error
- //@}
-
- // the maximum length of the minidump filename returned by getMiniDumpFilename()
- static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
-
- // change the directory where Breakpad minidump files are written to
- void setDebugFileNames(const std::string &path);
-
- // Return the Google Breakpad minidump filename after a crash.
- char *getMiniDumpFilename() { return mMinidumpPath; }
- std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
- std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
-
- // Write out a Google Breakpad minidump file.
- void writeMiniDump();
-
-
- /**
- * @brief Get a reference to the application runner
- *
- * Please use the runner with caution. Since the Runner usage
- * pattern is not yet clear, this method just gives access to it
- * to add and remove runnables.
- * @return Returns the application runner. Do not save the
- * pointer past the caller's stack frame.
- */
- LLRunner& getRunner() { return mRunner; }
+ typedef enum e_app_status
+ {
+ APP_STATUS_RUNNING, // The application is currently running - the default status
+ APP_STATUS_QUITTING, // The application is currently quitting - threads should listen for this and clean up
+ APP_STATUS_STOPPED, // The application is no longer running - tells the error thread it can exit
+ APP_STATUS_ERROR // The application had a fatal error occur - tells the error thread to run
+ } EAppStatus;
+
+
+ LLApp();
+ virtual ~LLApp();
+
+ /**
+ * @brief Return the static app instance if one was created.
+ */
+ static LLApp* instance();
+
+ /** @name Runtime options */
+ //@{
+ /**
+ * @brief Enumeration to specify option priorities in highest to
+ * lowest order.
+ */
+ enum OptionPriority
+ {
+ PRIORITY_RUNTIME_OVERRIDE,
+ PRIORITY_COMMAND_LINE,
+ PRIORITY_SPECIFIC_CONFIGURATION,
+ PRIORITY_GENERAL_CONFIGURATION,
+ PRIORITY_DEFAULT,
+ PRIORITY_COUNT
+ };
+
+ /**
+ * @brief Get the application option at the highest priority.
+ *
+ * If the return value is undefined, the option does not exist.
+ * @param name The name of the option.
+ * @return Returns the option data.
+ */
+ LLSD getOption(const std::string& name) const;
+
+ /**
+ * @brief Parse ASCII command line options and insert them into
+ * application command line options.
+ *
+ * The name inserted into the option will have leading option
+ * identifiers (a minus or double minus) stripped. All options
+ * with values will be stored as a string, while all options
+ * without values will be stored as true.
+ * @param argc The argc passed into main().
+ * @param argv The argv passed into main().
+ * @return Returns true if the parse succeeded.
+ */
+ bool parseCommandOptions(int argc, char** argv);
+
+ /**
+ * @brief Parse Unicode command line options and insert them into
+ * application command line options.
+ *
+ * The name inserted into the option will have leading option
+ * identifiers (a minus or double minus) stripped. All options
+ * with values will be stored as a string, while all options
+ * without values will be stored as true.
+ * @param argc The argc passed into main().
+ * @param wargv The wargv passed into main().
+ * @return Returns true if the parse succeeded.
+ */
+ bool parseCommandOptions(int argc, wchar_t** wargv);
+
+ /**
+ * @brief Keep track of live files automatically.
+ *
+ * *TODO: it currently uses the <code>addToEventTimer()</code> API
+ * instead of the runner. I should probalby use the runner.
+ *
+ * *NOTE: DO NOT add the livefile instance to any kind of check loop.
+ *
+ * @param livefile A valid instance of an LLLiveFile. This LLApp
+ * instance will delete the livefile instance.
+ */
+ void manageLiveFile(LLLiveFile* livefile);
+
+ /**
+ * @brief Set the options at the specified priority.
+ *
+ * This function completely replaces the options at the priority
+ * level with the data specified. This function will make sure
+ * level and data might be valid before doing the replace.
+ * @param level The priority level of the data.
+ * @param data The data to set.
+ * @return Returns true if the option was set.
+ */
+ bool setOptionData(OptionPriority level, LLSD data);
+
+ /**
+ * @brief Get the option data at the specified priority.
+ *
+ * This method is probably not so useful except when merging
+ * information.
+ * @param level The priority level of the data.
+ * @return Returns The data (if any) at the level priority.
+ */
+ LLSD getOptionData(OptionPriority level);
+ //@}
+
+
+
+ //
+ // Main application logic
+ //
+ virtual bool init() = 0; // Override to do application initialization
+
+ //
+ // cleanup()
+ //
+ // It's currently assumed that the cleanup() method will only get
+ // called from the main thread or the error handling thread, as it will
+ // likely do thread shutdown, among other things.
+ //
+ virtual bool cleanup() = 0; // Override to do application cleanup
+
+ //
+ // frame()
+ //
+ // Pass control to the application for a single frame. Returns 'done'
+ // flag: if frame() returns false, it expects to be called again.
+ //
+ virtual bool frame() = 0; // Override for application body logic
+
+ //
+ // Crash logging
+ //
+ void disableCrashlogger(); // Let the OS handle the crashes
+ static bool isCrashloggerDisabled(); // Get the here above set value
+
+ //
+ // Application status
+ //
+ static void setQuitting(); // Set status to QUITTING, the app is now shutting down
+ static void setStopped(); // Set status to STOPPED, the app is done running and should exit
+ static void setError(); // Set status to ERROR, the error handler should run
+ static bool isStopped();
+ static bool isRunning();
+ static bool isQuitting();
+ static bool isError();
+ static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
+ static int getPid();
+
+ //
+ // Sleep for specified time while still running
+ //
+ // For use by a coroutine or thread that performs some maintenance on a
+ // periodic basis. (See also LLEventTimer.) This method supports the
+ // pattern of an "infinite" loop that sleeps for some time, performs some
+ // action, then sleeps again. The trouble with literally sleeping a worker
+ // thread is that it could potentially sleep right through attempted
+ // application shutdown. This method avoids that by returning false as
+ // soon as the application status changes away from APP_STATUS_RUNNING
+ // (isRunning()).
+ //
+ // sleep() returns true if it sleeps undisturbed for the entire specified
+ // duration. The idea is that you can code 'while sleep(duration) ...',
+ // which will break the loop once shutdown begins.
+ //
+ // Since any time-based LLUnit should be implicitly convertible to
+ // F32Milliseconds, accept that specific type as a proxy.
+ static bool sleep(F32Milliseconds duration);
+ // Allow any duration defined in terms of <chrono>.
+ // One can imagine a wonderfully general bidirectional conversion system
+ // between any type derived from LLUnits::LLUnit<T, LLUnits::Seconds> and
+ // any std::chrono::duration -- but that doesn't yet exist.
+ template <typename Rep, typename Period>
+ bool sleep(const std::chrono::duration<Rep, Period>& duration)
+ {
+ // wait_for_unequal() has the opposite bool return convention
+ return ! sStatus.wait_for_unequal(duration, APP_STATUS_RUNNING);
+ }
+
+ /** @name Error handling methods */
+ //@{
+ /**
+ * @brief Do our generic platform-specific error-handling setup --
+ * signals on unix, structured exceptions on windows.
+ *
+ * DO call this method if your app will either spawn children or be
+ * spawned by a launcher.
+ * Call just after app object construction.
+ * (Otherwise your app will crash when getting signals,
+ * and will not core dump.)
+ *
+ * DO NOT call this method if your application has specialized
+ * error handling code.
+ */
+ void setupErrorHandling(bool mSecondInstance=false);
+
+ void setErrorHandler(LLAppErrorHandler handler);
+ static void runErrorHandler(); // run shortly after we detect an error
+ //@}
+
+ // the maximum length of the minidump filename returned by getMiniDumpFilename()
+ static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
+
+ // change the directory where Breakpad minidump files are written to
+ void setDebugFileNames(const std::string &path);
+
+ // Return the Google Breakpad minidump filename after a crash.
+ char *getMiniDumpFilename() { return mMinidumpPath; }
+ std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
+ std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
+
+ // Write out a Google Breakpad minidump file.
+ void writeMiniDump();
+
+
+ /**
+ * @brief Get a reference to the application runner
+ *
+ * Please use the runner with caution. Since the Runner usage
+ * pattern is not yet clear, this method just gives access to it
+ * to add and remove runnables.
+ * @return Returns the application runner. Do not save the
+ * pointer past the caller's stack frame.
+ */
+ LLRunner& getRunner() { return mRunner; }
#ifdef LL_WINDOWS
virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { }
#endif
public:
- typedef std::map<std::string, std::string> string_map;
- string_map mOptionMap; // Contains all command-line options and arguments in a map
+ typedef std::map<std::string, std::string> string_map;
+ string_map mOptionMap; // Contains all command-line options and arguments in a map
protected:
- static void setStatus(EAppStatus status); // Use this to change the application status.
- static LLScalarCond<EAppStatus> sStatus; // Reflects current application status
- static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
- std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.
+ static void setStatus(EAppStatus status); // Use this to change the application status.
+ static LLScalarCond<EAppStatus> sStatus; // Reflects current application status
+ static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
+ std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.
std::string mDumpPath; //output path for google breakpad. Dependency workaround.
- /**
- * @brief This method is called once a frame to do once a frame tasks.
- */
- void stepFrame();
+ /**
+ * @brief This method is called once a frame to do once a frame tasks.
+ */
+ void stepFrame();
private:
- // Contains the filename of the minidump file after a crash.
- char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
-
- std::string mStaticDebugFileName;
- std::string mDynamicDebugFileName;
+ // Contains the filename of the minidump file after a crash.
+ char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
+
+ std::string mStaticDebugFileName;
+ std::string mDynamicDebugFileName;
- // *NOTE: On Windows, we need a routine to reset the structured
- // exception handler when some evil driver has taken it over for
- // their own purposes
- typedef int(*signal_handler_func)(int signum);
- static LLAppErrorHandler sErrorHandler;
+ // *NOTE: On Windows, we need a routine to reset the structured
+ // exception handler when some evil driver has taken it over for
+ // their own purposes
+ typedef int(*signal_handler_func)(int signum);
+ static LLAppErrorHandler sErrorHandler;
- // This is the application level runnable scheduler.
- LLRunner mRunner;
+ // This is the application level runnable scheduler.
+ LLRunner mRunner;
- /** @name Runtime option implementation */
- //@{
+ /** @name Runtime option implementation */
+ //@{
- // The application options.
- LLSD mOptions;
+ // The application options.
+ LLSD mOptions;
- // The live files for this application
- std::vector<LLLiveFile*> mLiveFiles;
- //@}
+ // The live files for this application
+ std::vector<LLLiveFile*> mLiveFiles;
+ //@}
private:
- // the static application instance if it was created.
- static LLApp* sApplication;
+ // the static application instance if it was created.
+ static LLApp* sApplication;
#if !LL_WINDOWS
- friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
+ friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
#endif
public:
- static BOOL sLogInSignal;
+ static BOOL sLogInSignal;
};
#endif // LL_LLAPP_H
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 575c524219..c907a8c073 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llapr.cpp
* @author Phoenix
* @date 2004-11-28
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2004&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$
*/
@@ -46,200 +46,200 @@ int abortfunc(int retcode)
void ll_init_apr()
{
- // Initialize APR and create the global pool
- apr_initialize();
-
- if (!gAPRPoolp)
- {
- apr_pool_create_ex(&gAPRPoolp, NULL, abortfunc, NULL);
- }
+ // Initialize APR and create the global pool
+ apr_initialize();
+
+ if (!gAPRPoolp)
+ {
+ apr_pool_create_ex(&gAPRPoolp, NULL, abortfunc, NULL);
+ }
- if(!LLAPRFile::sAPRFilePoolp)
- {
- LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
- }
+ if(!LLAPRFile::sAPRFilePoolp)
+ {
+ LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
+ }
- gAPRInitialized = true;
+ gAPRInitialized = true;
}
bool ll_apr_is_initialized()
{
- return gAPRInitialized;
+ return gAPRInitialized;
}
void ll_cleanup_apr()
{
- gAPRInitialized = false;
+ gAPRInitialized = false;
- LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL;
+ LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL;
- if (gAPRPoolp)
- {
- apr_pool_destroy(gAPRPoolp);
- gAPRPoolp = NULL;
- }
- if (LLAPRFile::sAPRFilePoolp)
- {
- delete LLAPRFile::sAPRFilePoolp ;
- LLAPRFile::sAPRFilePoolp = NULL ;
- }
- apr_terminate();
+ if (gAPRPoolp)
+ {
+ apr_pool_destroy(gAPRPoolp);
+ gAPRPoolp = NULL;
+ }
+ if (LLAPRFile::sAPRFilePoolp)
+ {
+ delete LLAPRFile::sAPRFilePoolp ;
+ LLAPRFile::sAPRFilePoolp = NULL ;
+ }
+ apr_terminate();
}
//
//
//LLAPRPool
//
-LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
- : mParent(parent),
- mReleasePoolFlag(releasePoolFlag),
- mMaxSize(size),
- mPool(NULL)
-{
- createAPRPool() ;
+LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
+ : mParent(parent),
+ mReleasePoolFlag(releasePoolFlag),
+ mMaxSize(size),
+ mPool(NULL)
+{
+ createAPRPool() ;
}
-LLAPRPool::~LLAPRPool()
+LLAPRPool::~LLAPRPool()
{
- releaseAPRPool() ;
+ releaseAPRPool() ;
}
void LLAPRPool::createAPRPool()
{
- if(mPool)
- {
- return ;
- }
+ if(mPool)
+ {
+ return ;
+ }
- mStatus = apr_pool_create(&mPool, mParent);
- ll_apr_warn_status(mStatus) ;
+ mStatus = apr_pool_create(&mPool, mParent);
+ ll_apr_warn_status(mStatus) ;
- if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
- {
- apr_allocator_t *allocator = apr_pool_allocator_get(mPool);
- if (allocator)
- {
- apr_allocator_max_free_set(allocator, mMaxSize) ;
- }
- }
+ if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
+ {
+ apr_allocator_t *allocator = apr_pool_allocator_get(mPool);
+ if (allocator)
+ {
+ apr_allocator_max_free_set(allocator, mMaxSize) ;
+ }
+ }
}
void LLAPRPool::releaseAPRPool()
{
- if(!mPool)
- {
- return ;
- }
+ if(!mPool)
+ {
+ return ;
+ }
- if(!mParent || mReleasePoolFlag)
- {
- apr_pool_destroy(mPool) ;
- mPool = NULL ;
- }
+ if(!mParent || mReleasePoolFlag)
+ {
+ apr_pool_destroy(mPool) ;
+ mPool = NULL ;
+ }
}
//virtual
-apr_pool_t* LLAPRPool::getAPRPool()
-{
- return mPool ;
+apr_pool_t* LLAPRPool::getAPRPool()
+{
+ return mPool ;
}
-LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
- : LLAPRPool(parent, size, releasePoolFlag),
- mNumActiveRef(0),
- mNumTotalRef(0)
+LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
+ : LLAPRPool(parent, size, releasePoolFlag),
+ mNumActiveRef(0),
+ mNumTotalRef(0)
{
- //create mutex
- if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
- {
- mMutexp.reset(new std::mutex());
- }
+ //create mutex
+ if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
+ {
+ mMutexp.reset(new std::mutex());
+ }
}
LLVolatileAPRPool::~LLVolatileAPRPool()
{
- //delete mutex
+ //delete mutex
mMutexp.reset();
}
//
//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
//
-//virtual
-apr_pool_t* LLVolatileAPRPool::getAPRPool()
+//virtual
+apr_pool_t* LLVolatileAPRPool::getAPRPool()
{
- return LLVolatileAPRPool::getVolatileAPRPool() ;
+ return LLVolatileAPRPool::getVolatileAPRPool() ;
}
-apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
-{
- LLScopedLock lock(mMutexp.get()) ;
+apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
+{
+ LLScopedLock lock(mMutexp.get()) ;
- mNumTotalRef++ ;
- mNumActiveRef++ ;
+ mNumTotalRef++ ;
+ mNumActiveRef++ ;
- if(!mPool)
- {
- createAPRPool() ;
- }
-
- return mPool ;
+ if(!mPool)
+ {
+ createAPRPool() ;
+ }
+
+ return mPool ;
}
-void LLVolatileAPRPool::clearVolatileAPRPool()
+void LLVolatileAPRPool::clearVolatileAPRPool()
{
LLScopedLock lock(mMutexp.get());
- if(mNumActiveRef > 0)
- {
- mNumActiveRef--;
- if(mNumActiveRef < 1)
- {
- if(isFull())
- {
- mNumTotalRef = 0 ;
-
- //destroy the apr_pool.
- releaseAPRPool() ;
- }
- else
- {
- //This does not actually free the memory,
- //it just allows the pool to re-use this memory for the next allocation.
- apr_pool_clear(mPool) ;
- }
- }
- }
- else
- {
- llassert_always(mNumActiveRef > 0) ;
- }
-
- llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ;
+ if(mNumActiveRef > 0)
+ {
+ mNumActiveRef--;
+ if(mNumActiveRef < 1)
+ {
+ if(isFull())
+ {
+ mNumTotalRef = 0 ;
+
+ //destroy the apr_pool.
+ releaseAPRPool() ;
+ }
+ else
+ {
+ //This does not actually free the memory,
+ //it just allows the pool to re-use this memory for the next allocation.
+ apr_pool_clear(mPool) ;
+ }
+ }
+ }
+ else
+ {
+ llassert_always(mNumActiveRef > 0) ;
+ }
+
+ llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ;
}
BOOL LLVolatileAPRPool::isFull()
{
- return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
+ return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
}
//---------------------------------------------------------------------
bool _ll_apr_warn_status(apr_status_t status, const char* file, int line)
{
- if(APR_SUCCESS == status) return false;
+ if(APR_SUCCESS == status) return false;
#if !LL_LINUX
- char buf[MAX_STRING]; /* Flawfinder: ignore */
- apr_strerror(status, buf, sizeof(buf));
- LL_WARNS("APR") << "APR: " << file << ":" << line << " " << buf << LL_ENDL;
+ char buf[MAX_STRING]; /* Flawfinder: ignore */
+ apr_strerror(status, buf, sizeof(buf));
+ LL_WARNS("APR") << "APR: " << file << ":" << line << " " << buf << LL_ENDL;
#endif
- return true;
+ return true;
}
void _ll_apr_assert_status(apr_status_t status, const char* file, int line)
{
- llassert(! _ll_apr_warn_status(status, file, line));
+ llassert(! _ll_apr_warn_status(status, file, line));
}
//---------------------------------------------------------------------
@@ -253,7 +253,7 @@ class LLAPRFilePoolScope
public:
LLAPRFilePoolScope() : pPool(NULL), mInitialized(false) {}
LLAPRFilePoolScope(LLVolatileAPRPool* poolp) : mInitialized(false)
- {
+ {
setFilePool(poolp);
}
~LLAPRFilePoolScope()
@@ -305,154 +305,154 @@ private:
// LLAPRFile functions
//
LLAPRFile::LLAPRFile()
- : mFile(NULL),
- mCurrentFilePoolp(NULL)
+ : mFile(NULL),
+ mCurrentFilePoolp(NULL)
{
}
LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
- : mFile(NULL),
- mCurrentFilePoolp(NULL)
+ : mFile(NULL),
+ mCurrentFilePoolp(NULL)
{
- open(filename, flags, pool);
+ open(filename, flags, pool);
}
LLAPRFile::~LLAPRFile()
{
- close() ;
+ close() ;
}
-apr_status_t LLAPRFile::close()
+apr_status_t LLAPRFile::close()
{
- apr_status_t ret = APR_SUCCESS ;
- if(mFile)
- {
- ret = apr_file_close(mFile);
- mFile = NULL ;
- }
+ apr_status_t ret = APR_SUCCESS ;
+ if(mFile)
+ {
+ ret = apr_file_close(mFile);
+ mFile = NULL ;
+ }
- if(mCurrentFilePoolp)
- {
- mCurrentFilePoolp->clearVolatileAPRPool() ;
- mCurrentFilePoolp = NULL ;
- }
+ if(mCurrentFilePoolp)
+ {
+ mCurrentFilePoolp->clearVolatileAPRPool() ;
+ mCurrentFilePoolp = NULL ;
+ }
- return ret ;
+ return ret ;
}
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
{
- apr_status_t s ;
-
- //check if already open some file
- llassert_always(!mFile) ;
- llassert_always(!mCurrentFilePoolp) ;
-
- mCurrentFilePoolp = pool ? pool : sAPRFilePoolp;
- apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close()
- s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
-
- if (s != APR_SUCCESS || !mFile)
- {
- mFile = NULL ;
-
- if (sizep)
- {
- *sizep = 0;
- }
- }
- else if (sizep)
- {
- S32 file_size = 0;
- apr_off_t offset = 0;
- if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
- {
- llassert_always(offset <= 0x7fffffff);
- file_size = (S32)offset;
- offset = 0;
- apr_file_seek(mFile, APR_SET, &offset);
- }
- *sizep = file_size;
- }
-
- if (!mFile)
- {
- // It will clean pool
- close() ;
- }
-
- return s ;
+ apr_status_t s ;
+
+ //check if already open some file
+ llassert_always(!mFile) ;
+ llassert_always(!mCurrentFilePoolp) ;
+
+ mCurrentFilePoolp = pool ? pool : sAPRFilePoolp;
+ apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close()
+ s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
+
+ if (s != APR_SUCCESS || !mFile)
+ {
+ mFile = NULL ;
+
+ if (sizep)
+ {
+ *sizep = 0;
+ }
+ }
+ else if (sizep)
+ {
+ S32 file_size = 0;
+ apr_off_t offset = 0;
+ if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
+ {
+ llassert_always(offset <= 0x7fffffff);
+ file_size = (S32)offset;
+ offset = 0;
+ apr_file_seek(mFile, APR_SET, &offset);
+ }
+ *sizep = file_size;
+ }
+
+ if (!mFile)
+ {
+ // It will clean pool
+ close() ;
+ }
+
+ return s ;
}
//use gAPRPoolp.
apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool)
{
- apr_status_t s;
+ apr_status_t s;
- //check if already open some file
- llassert_always(!mFile) ;
- llassert_always(!mCurrentFilePoolp) ;
- llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
-
- s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
- if (s != APR_SUCCESS || !mFile)
- {
- mFile = NULL ;
- close() ;
- return s;
- }
+ //check if already open some file
+ llassert_always(!mFile) ;
+ llassert_always(!mCurrentFilePoolp) ;
+ llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
- return s;
+ s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
+ if (s != APR_SUCCESS || !mFile)
+ {
+ mFile = NULL ;
+ close() ;
+ return s;
+ }
+
+ return s;
}
// File I/O
S32 LLAPRFile::read(void *buf, S32 nbytes)
{
- if(!mFile)
- {
- LL_WARNS() << "apr mFile is removed by somebody else. Can not read." << LL_ENDL ;
- return 0;
- }
-
- apr_size_t sz = nbytes;
- apr_status_t s = apr_file_read(mFile, buf, &sz);
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- return 0;
- }
- else
- {
- llassert_always(sz <= 0x7fffffff);
- return (S32)sz;
- }
+ if(!mFile)
+ {
+ LL_WARNS() << "apr mFile is removed by somebody else. Can not read." << LL_ENDL ;
+ return 0;
+ }
+
+ apr_size_t sz = nbytes;
+ apr_status_t s = apr_file_read(mFile, buf, &sz);
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ return 0;
+ }
+ else
+ {
+ llassert_always(sz <= 0x7fffffff);
+ return (S32)sz;
+ }
}
S32 LLAPRFile::write(const void *buf, S32 nbytes)
{
- if(!mFile)
- {
- LL_WARNS() << "apr mFile is removed by somebody else. Can not write." << LL_ENDL ;
- return 0;
- }
-
- apr_size_t sz = nbytes;
- apr_status_t s = apr_file_write(mFile, buf, &sz);
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- return 0;
- }
- else
- {
- llassert_always(sz <= 0x7fffffff);
- return (S32)sz;
- }
+ if(!mFile)
+ {
+ LL_WARNS() << "apr mFile is removed by somebody else. Can not write." << LL_ENDL ;
+ return 0;
+ }
+
+ apr_size_t sz = nbytes;
+ apr_status_t s = apr_file_write(mFile, buf, &sz);
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ return 0;
+ }
+ else
+ {
+ llassert_always(sz <= 0x7fffffff);
+ return (S32)sz;
+ }
}
S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
{
- return LLAPRFile::seek(mFile, where, offset) ;
+ return LLAPRFile::seek(mFile, where, offset) ;
}
//
@@ -461,285 +461,285 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
//
//static
-apr_status_t LLAPRFile::close(apr_file_t* file_handle)
+apr_status_t LLAPRFile::close(apr_file_t* file_handle)
{
- apr_status_t ret = APR_SUCCESS ;
- if(file_handle)
- {
- ret = apr_file_close(file_handle);
- file_handle = NULL ;
- }
+ apr_status_t ret = APR_SUCCESS ;
+ if(file_handle)
+ {
+ ret = apr_file_close(file_handle);
+ file_handle = NULL ;
+ }
- return ret ;
+ return ret ;
}
//static
apr_file_t* LLAPRFile::open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags)
{
- apr_status_t s;
- apr_file_t* file_handle ;
+ apr_status_t s;
+ apr_file_t* file_handle ;
- s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
- if (s != APR_SUCCESS || !file_handle)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
- file_handle = NULL ;
- close(file_handle) ;
- return NULL;
- }
+ s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
+ if (s != APR_SUCCESS || !file_handle)
+ {
+ ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
+ file_handle = NULL ;
+ close(file_handle) ;
+ return NULL;
+ }
- return file_handle ;
+ return file_handle ;
}
//static
S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
{
- if(!file_handle)
- {
- return -1 ;
- }
-
- apr_status_t s;
- apr_off_t apr_offset;
- if (offset >= 0)
- {
- apr_offset = (apr_off_t)offset;
- s = apr_file_seek(file_handle, where, &apr_offset);
- }
- else
- {
- apr_offset = 0;
- s = apr_file_seek(file_handle, APR_END, &apr_offset);
- }
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- return -1;
- }
- else
- {
- llassert_always(apr_offset <= 0x7fffffff);
- return (S32)apr_offset;
- }
+ if(!file_handle)
+ {
+ return -1 ;
+ }
+
+ apr_status_t s;
+ apr_off_t apr_offset;
+ if (offset >= 0)
+ {
+ apr_offset = (apr_off_t)offset;
+ s = apr_file_seek(file_handle, where, &apr_offset);
+ }
+ else
+ {
+ apr_offset = 0;
+ s = apr_file_seek(file_handle, APR_END, &apr_offset);
+ }
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ return -1;
+ }
+ else
+ {
+ llassert_always(apr_offset <= 0x7fffffff);
+ return (S32)apr_offset;
+ }
}
//static
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
LL_PROFILE_ZONE_SCOPED;
- //*****************************************
- LLAPRFilePoolScope scope(pool);
- apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
- //*****************************************
- if (!file_handle)
- {
- return 0;
- }
-
- llassert(offset >= 0);
-
- if (offset > 0)
- offset = LLAPRFile::seek(file_handle, APR_SET, offset);
-
- apr_size_t bytes_read;
- if (offset < 0)
- {
- bytes_read = 0;
- }
- else
- {
- bytes_read = nbytes ;
- apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
- if (s != APR_SUCCESS)
- {
- LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
- ll_apr_warn_status(s);
- bytes_read = 0;
- }
- else
- {
- llassert_always(bytes_read <= 0x7fffffff);
- }
- }
-
- //*****************************************
- close(file_handle) ;
- //*****************************************
- return (S32)bytes_read;
+ //*****************************************
+ LLAPRFilePoolScope scope(pool);
+ apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
+ //*****************************************
+ if (!file_handle)
+ {
+ return 0;
+ }
+
+ llassert(offset >= 0);
+
+ if (offset > 0)
+ offset = LLAPRFile::seek(file_handle, APR_SET, offset);
+
+ apr_size_t bytes_read;
+ if (offset < 0)
+ {
+ bytes_read = 0;
+ }
+ else
+ {
+ bytes_read = nbytes ;
+ apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
+ if (s != APR_SUCCESS)
+ {
+ LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
+ ll_apr_warn_status(s);
+ bytes_read = 0;
+ }
+ else
+ {
+ llassert_always(bytes_read <= 0x7fffffff);
+ }
+ }
+
+ //*****************************************
+ close(file_handle) ;
+ //*****************************************
+ return (S32)bytes_read;
}
//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
LL_PROFILE_ZONE_SCOPED;
- apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
- if (offset < 0)
- {
- flags |= APR_APPEND;
- offset = 0;
- }
-
- //*****************************************
- LLAPRFilePoolScope scope(pool);
- apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);
- //*****************************************
- if (!file_handle)
- {
- return 0;
- }
-
- if (offset > 0)
- {
- offset = LLAPRFile::seek(file_handle, APR_SET, offset);
- }
-
- apr_size_t bytes_written;
- if (offset < 0)
- {
- bytes_written = 0;
- }
- else
- {
- bytes_written = nbytes ;
- apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
- if (s != APR_SUCCESS)
- {
- LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
- ll_apr_warn_status(s);
- bytes_written = 0;
- }
- else
- {
- llassert_always(bytes_written <= 0x7fffffff);
- }
- }
-
- //*****************************************
- LLAPRFile::close(file_handle);
- //*****************************************
-
- return (S32)bytes_written;
+ apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
+ if (offset < 0)
+ {
+ flags |= APR_APPEND;
+ offset = 0;
+ }
+
+ //*****************************************
+ LLAPRFilePoolScope scope(pool);
+ apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);
+ //*****************************************
+ if (!file_handle)
+ {
+ return 0;
+ }
+
+ if (offset > 0)
+ {
+ offset = LLAPRFile::seek(file_handle, APR_SET, offset);
+ }
+
+ apr_size_t bytes_written;
+ if (offset < 0)
+ {
+ bytes_written = 0;
+ }
+ else
+ {
+ bytes_written = nbytes ;
+ apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
+ if (s != APR_SUCCESS)
+ {
+ LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
+ ll_apr_warn_status(s);
+ bytes_written = 0;
+ }
+ else
+ {
+ llassert_always(bytes_written <= 0x7fffffff);
+ }
+ }
+
+ //*****************************************
+ LLAPRFile::close(file_handle);
+ //*****************************************
+
+ return (S32)bytes_written;
}
//static
bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
{
- apr_status_t s;
+ apr_status_t s;
- LLAPRFilePoolScope scope(pool);
- s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
- return false;
- }
- return true;
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
+ return false;
+ }
+ return true;
}
//static
bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
{
- apr_status_t s;
+ apr_status_t s;
+
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());
- LLAPRFilePoolScope scope(pool);
- s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
- return false;
- }
- return true;
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
+ return false;
+ }
+ return true;
}
//static
bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
{
- apr_file_t* apr_file;
- apr_status_t s;
+ apr_file_t* apr_file;
+ apr_status_t s;
- LLAPRFilePoolScope scope(pool);
- s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());
- if (s != APR_SUCCESS || !apr_file)
- {
- return false;
- }
- else
- {
- apr_file_close(apr_file) ;
- return true;
- }
+ if (s != APR_SUCCESS || !apr_file)
+ {
+ return false;
+ }
+ else
+ {
+ apr_file_close(apr_file) ;
+ return true;
+ }
}
//static
S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
{
- apr_file_t* apr_file;
- apr_finfo_t info;
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS || !apr_file)
- {
- return 0;
- }
- else
- {
- apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
-
- apr_file_close(apr_file) ;
-
- if (s == APR_SUCCESS)
- {
- return (S32)info.size;
- }
- else
- {
- return 0;
- }
- }
+ apr_file_t* apr_file;
+ apr_finfo_t info;
+ apr_status_t s;
+
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());
+
+ if (s != APR_SUCCESS || !apr_file)
+ {
+ return 0;
+ }
+ else
+ {
+ apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
+
+ apr_file_close(apr_file) ;
+
+ if (s == APR_SUCCESS)
+ {
+ return (S32)info.size;
+ }
+ else
+ {
+ return 0;
+ }
+ }
}
//static
bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
{
- apr_status_t s;
+ apr_status_t s;
+
+ LLAPRFilePoolScope scope(pool);
+ s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());
- LLAPRFilePoolScope scope(pool);
- s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
- return false;
- }
- return true;
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
+ return false;
+ }
+ return true;
}
//static
bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
- return false;
- }
- return true;
+ apr_status_t s;
+
+ LLAPRFilePoolScope scope(pool);
+ s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());
+
+ if (s != APR_SUCCESS)
+ {
+ ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
+ return false;
+ }
+ return true;
}
//
//end of static components of LLAPRFile
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 565d7cfb63..2f88fdcd59 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llapr.h
* @author Phoenix
* @date 2004-11-28
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2004&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$
*/
@@ -57,13 +57,13 @@ void LL_COMMON_API _ll_apr_assert_status(apr_status_t status, const char* file,
extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
-/**
+/**
* @brief initialize the common apr constructs -- apr itself, the
* global pool, and a mutex.
*/
void LL_COMMON_API ll_init_apr();
-/**
+/**
* @brief Cleanup those common apr constructs.
*/
void LL_COMMON_API ll_cleanup_apr();
@@ -78,22 +78,22 @@ bool LL_COMMON_API ll_apr_is_initialized();
class LL_COMMON_API LLAPRPool
{
public:
- LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
- virtual ~LLAPRPool() ;
+ LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
+ virtual ~LLAPRPool() ;
- virtual apr_pool_t* getAPRPool() ;
- apr_status_t getStatus() {return mStatus ; }
+ virtual apr_pool_t* getAPRPool() ;
+ apr_status_t getStatus() {return mStatus ; }
protected:
- void releaseAPRPool() ;
- void createAPRPool() ;
+ void releaseAPRPool() ;
+ void createAPRPool() ;
protected:
- apr_pool_t* mPool ; //pointing to an apr_pool
- apr_pool_t* mParent ; //parent pool
- apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
- apr_status_t mStatus ; //status when creating the pool
- BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
+ apr_pool_t* mPool ; //pointing to an apr_pool
+ apr_pool_t* mParent ; //parent pool
+ apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
+ apr_status_t mStatus ; //status when creating the pool
+ BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
};
//
@@ -104,20 +104,20 @@ protected:
class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
{
public:
- LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
- virtual ~LLVolatileAPRPool();
+ LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
+ virtual ~LLVolatileAPRPool();
- /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
- apr_pool_t* getVolatileAPRPool() ;
- void clearVolatileAPRPool() ;
+ /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
+ apr_pool_t* getVolatileAPRPool() ;
+ void clearVolatileAPRPool() ;
+
+ BOOL isFull() ;
- BOOL isFull() ;
-
private:
- S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
- S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
+ S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
+ S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
- std::unique_ptr<std::mutex> mMutexp;
+ std::unique_ptr<std::mutex> mMutexp;
} ;
// File IO convenience functions.
@@ -137,7 +137,7 @@ private:
//which: 1)only keeps one file open;
// 2)closes the open file in the destruction function
// 3)informs the apr_pool to clean the memory when the file is closed.
-//Note: please close an open file at the earliest convenience.
+//Note: please close an open file at the earliest convenience.
// especially do not put some time-costly operations between open() and close().
// otherwise it might lock the APRFilePool.
//there are two different apr_pools the APRFile can use:
@@ -147,53 +147,53 @@ private:
class LL_COMMON_API LLAPRFile : boost::noncopyable
{
- // make this non copyable since a copy closes the file
+ // make this non copyable since a copy closes the file
private:
- apr_file_t* mFile ;
- LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
+ apr_file_t* mFile ;
+ LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
public:
- LLAPRFile() ;
- LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
- ~LLAPRFile() ;
-
- apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL);
- apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp.
- apr_status_t close() ;
-
- // Returns actual offset, -1 if seek fails
- S32 seek(apr_seek_where_t where, S32 offset);
- apr_status_t eof() { return apr_file_eof(mFile);}
-
- // Returns bytes read/written, 0 if read/write fails:
- S32 read(void* buf, S32 nbytes);
- S32 write(const void* buf, S32 nbytes);
-
- apr_file_t* getFileHandle() {return mFile;}
-
+ LLAPRFile() ;
+ LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
+ ~LLAPRFile() ;
+
+ apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL);
+ apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp.
+ apr_status_t close() ;
+
+ // Returns actual offset, -1 if seek fails
+ S32 seek(apr_seek_where_t where, S32 offset);
+ apr_status_t eof() { return apr_file_eof(mFile);}
+
+ // Returns bytes read/written, 0 if read/write fails:
+ S32 read(void* buf, S32 nbytes);
+ S32 write(const void* buf, S32 nbytes);
+
+ apr_file_t* getFileHandle() {return mFile;}
+
//
//*******************************************************************************************************************************
//static components
//
public:
- static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
+ static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
private:
- static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags);
- static apr_status_t close(apr_file_t* file) ;
- static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
+ static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags);
+ static apr_status_t close(apr_file_t* file) ;
+ static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
public:
- // returns false if failure:
- static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
- static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
- static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
- static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
- static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
- static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
-
- // Returns bytes read/written, 0 if read/write fails:
- static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
- static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
+ // returns false if failure:
+ static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
+ static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
+ static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
+ static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
+ static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
+ static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
+
+ // Returns bytes read/written, 0 if read/write fails:
+ static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
+ static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
//*******************************************************************************************************************************
};
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 6492d888c1..3e46bde954 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llassettype.cpp
* @brief Implementatino of LLAssetType functionality.
*
* $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$
*/
@@ -36,69 +36,69 @@
///----------------------------------------------------------------------------
struct AssetEntry : public LLDictionaryEntry
{
- AssetEntry(const char *desc_name,
- const char *type_name, // 8 character limit!
- const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one
- bool can_link, // can you create a link to this type?
- bool can_fetch, // can you fetch this asset by ID?
- bool can_know) // can you see this asset's ID?
- :
- LLDictionaryEntry(desc_name),
- mTypeName(type_name),
- mHumanName(human_name),
- mCanLink(can_link),
- mCanFetch(can_fetch),
- mCanKnow(can_know)
- {
- llassert(strlen(mTypeName) <= 8);
- }
-
- const char *mTypeName;
- const char *mHumanName;
- bool mCanLink;
- bool mCanFetch;
- bool mCanKnow;
+ AssetEntry(const char *desc_name,
+ const char *type_name, // 8 character limit!
+ const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one
+ bool can_link, // can you create a link to this type?
+ bool can_fetch, // can you fetch this asset by ID?
+ bool can_know) // can you see this asset's ID?
+ :
+ LLDictionaryEntry(desc_name),
+ mTypeName(type_name),
+ mHumanName(human_name),
+ mCanLink(can_link),
+ mCanFetch(can_fetch),
+ mCanKnow(can_know)
+ {
+ llassert(strlen(mTypeName) <= 8);
+ }
+
+ const char *mTypeName;
+ const char *mHumanName;
+ bool mCanLink;
+ bool mCanFetch;
+ bool mCanKnow;
};
class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
- public LLDictionary<LLAssetType::EType, AssetEntry>
+ public LLDictionary<LLAssetType::EType, AssetEntry>
{
- LLSINGLETON(LLAssetDictionary);
+ LLSINGLETON(LLAssetDictionary);
};
LLAssetDictionary::LLAssetDictionary()
{
- // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW?
- // |--------------------|-----------|-------------------|-----------|-----------|---------|
- addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true));
- addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true));
- addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false));
- addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true));
- addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false));
- addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true));
- addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false));
- addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true));
- addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false));
- addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false));
- addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false));
- addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false));
- addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true));
- addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false));
- addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false));
- addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false));
- addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true));
- addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true));
- addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false));
-
- addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true));
- addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true));
- addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
- addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
- addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
- addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true));
- addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true));
- addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
- addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
+ // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW?
+ // |--------------------|-----------|-------------------|-----------|-----------|---------|
+ addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true));
+ addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true));
+ addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false));
+ addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true));
+ addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false));
+ addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true));
+ addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false));
+ addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true));
+ addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false));
+ addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false));
+ addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false));
+ addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false));
+ addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true));
+ addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false));
+ addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false));
+ addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false));
+ addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true));
+ addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true));
+ addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false));
+
+ addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true));
+ addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true));
+ addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
+ addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
+ addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
+ addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true));
+ addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true));
+ addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
+ addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
};
@@ -107,140 +107,140 @@ const std::string LLAssetType::BADLOOKUP("llassettype_bad_lookup");
// static
LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
{
- std::string s = desc_name;
- LLStringUtil::toUpper(s);
- return LLAssetDictionary::getInstance()->lookup(s);
+ std::string s = desc_name;
+ LLStringUtil::toUpper(s);
+ return LLAssetDictionary::getInstance()->lookup(s);
}
// static
const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
{
- const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type);
- if (entry)
- {
- return entry->mName;
- }
- else
- {
- return BADLOOKUP;
- }
+ const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mName;
+ }
+ else
+ {
+ return BADLOOKUP;
+ }
}
// static
const char *LLAssetType::lookup(LLAssetType::EType asset_type)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mTypeName;
- }
- else
- {
- return BADLOOKUP.c_str();
- }
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mTypeName;
+ }
+ else
+ {
+ return BADLOOKUP.c_str();
+ }
}
// static
LLAssetType::EType LLAssetType::lookup(const char* name)
{
- return lookup(ll_safe_string(name));
+ return lookup(ll_safe_string(name));
}
// static
LLAssetType::EType LLAssetType::lookup(const std::string& type_name)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- for (const LLAssetDictionary::value_type& pair : *dict)
- {
- const AssetEntry *entry = pair.second;
- if (type_name == entry->mTypeName)
- {
- return pair.first;
- }
- }
- return AT_UNKNOWN;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (const LLAssetDictionary::value_type& pair : *dict)
+ {
+ const AssetEntry *entry = pair.second;
+ if (type_name == entry->mTypeName)
+ {
+ return pair.first;
+ }
+ }
+ return AT_UNKNOWN;
}
// static
const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mHumanName;
- }
- else
- {
- return BADLOOKUP.c_str();
- }
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mHumanName;
+ }
+ else
+ {
+ return BADLOOKUP.c_str();
+ }
}
// static
LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name)
{
- return lookupHumanReadable(ll_safe_string(name));
+ return lookupHumanReadable(ll_safe_string(name));
}
// static
LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- for (const LLAssetDictionary::value_type& pair : *dict)
- {
- const AssetEntry *entry = pair.second;
- if (entry->mHumanName && (readable_name == entry->mHumanName))
- {
- return pair.first;
- }
- }
- return AT_NONE;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (const LLAssetDictionary::value_type& pair : *dict)
+ {
+ const AssetEntry *entry = pair.second;
+ if (entry->mHumanName && (readable_name == entry->mHumanName))
+ {
+ return pair.first;
+ }
+ }
+ return AT_NONE;
}
// static
bool LLAssetType::lookupCanLink(EType asset_type)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mCanLink;
- }
- return false;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mCanLink;
+ }
+ return false;
}
// static
// Not adding this to dictionary since we probably will only have these two types
bool LLAssetType::lookupIsLinkType(EType asset_type)
{
- if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER)
- {
- return true;
- }
- return false;
+ if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER)
+ {
+ return true;
+ }
+ return false;
}
// static
bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mCanFetch;
- }
- return false;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mCanFetch;
+ }
+ return false;
}
// static
bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type)
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mCanKnow;
- }
- return false;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mCanKnow;
+ }
+ return false;
}
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index e8df8574f7..1989155550 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llassettype.h
* @brief Declaration of LLAssetType.
*
* $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$
*/
@@ -32,89 +32,89 @@
class LL_COMMON_API LLAssetType
{
public:
- enum EType
- {
- AT_TEXTURE = 0,
- // Used for painting the faces of geometry.
- // Stored in typical j2c stream format.
+ enum EType
+ {
+ AT_TEXTURE = 0,
+ // Used for painting the faces of geometry.
+ // Stored in typical j2c stream format.
- AT_SOUND = 1,
- // Used to fill the aural spectrum.
+ AT_SOUND = 1,
+ // Used to fill the aural spectrum.
- AT_CALLINGCARD = 2,
- // Links instant message access to the user on the card.
- // : E.G. A card for yourself, for linden support, for
- // : the guy you were talking to in the coliseum.
+ AT_CALLINGCARD = 2,
+ // Links instant message access to the user on the card.
+ // : E.G. A card for yourself, for linden support, for
+ // : the guy you were talking to in the coliseum.
- AT_LANDMARK = 3,
- // Links to places in the world with location and a screen shot or image saved.
- // : E.G. Home, linden headquarters, the coliseum, destinations where
- // : we want to increase traffic.
+ AT_LANDMARK = 3,
+ // Links to places in the world with location and a screen shot or image saved.
+ // : E.G. Home, linden headquarters, the coliseum, destinations where
+ // : we want to increase traffic.
- AT_SCRIPT = 4,
- // Valid scripts that can be attached to an object.
- // : E.G. Open a door, jump into the air.
+ AT_SCRIPT = 4,
+ // Valid scripts that can be attached to an object.
+ // : E.G. Open a door, jump into the air.
- AT_CLOTHING = 5,
- // A collection of textures and parameters that can be worn by an avatar.
+ AT_CLOTHING = 5,
+ // A collection of textures and parameters that can be worn by an avatar.
- AT_OBJECT = 6,
- // Any combination of textures, sounds, and scripts that are
- // associated with a fixed piece of geometry.
- // : E.G. A hot tub, a house with working door.
+ AT_OBJECT = 6,
+ // Any combination of textures, sounds, and scripts that are
+ // associated with a fixed piece of geometry.
+ // : E.G. A hot tub, a house with working door.
- AT_NOTECARD = 7,
- // Just text.
+ AT_NOTECARD = 7,
+ // Just text.
- AT_CATEGORY = 8,
- // Holds a collection of inventory items.
- // It's treated as an item in the inventory and therefore needs a type.
+ AT_CATEGORY = 8,
+ // Holds a collection of inventory items.
+ // It's treated as an item in the inventory and therefore needs a type.
- AT_LSL_TEXT = 10,
- AT_LSL_BYTECODE = 11,
- // The LSL is the scripting language.
- // We've split it into a text and bytecode representation.
-
- AT_TEXTURE_TGA = 12,
- // Uncompressed TGA texture.
+ AT_LSL_TEXT = 10,
+ AT_LSL_BYTECODE = 11,
+ // The LSL is the scripting language.
+ // We've split it into a text and bytecode representation.
- AT_BODYPART = 13,
- // A collection of textures and parameters that can be worn by an avatar.
+ AT_TEXTURE_TGA = 12,
+ // Uncompressed TGA texture.
- AT_SOUND_WAV = 17,
- // Uncompressed sound.
+ AT_BODYPART = 13,
+ // A collection of textures and parameters that can be worn by an avatar.
- AT_IMAGE_TGA = 18,
- // Uncompressed image, non-square.
- // Not appropriate for use as a texture.
+ AT_SOUND_WAV = 17,
+ // Uncompressed sound.
- AT_IMAGE_JPEG = 19,
- // Compressed image, non-square.
- // Not appropriate for use as a texture.
+ AT_IMAGE_TGA = 18,
+ // Uncompressed image, non-square.
+ // Not appropriate for use as a texture.
- AT_ANIMATION = 20,
- // Animation.
+ AT_IMAGE_JPEG = 19,
+ // Compressed image, non-square.
+ // Not appropriate for use as a texture.
- AT_GESTURE = 21,
- // Gesture, sequence of animations, sounds, chat, wait steps.
+ AT_ANIMATION = 20,
+ // Animation.
- AT_SIMSTATE = 22,
- // Simstate file.
+ AT_GESTURE = 21,
+ // Gesture, sequence of animations, sounds, chat, wait steps.
- AT_LINK = 24,
- // Inventory symbolic link
+ AT_SIMSTATE = 22,
+ // Simstate file.
+
+ AT_LINK = 24,
+ // Inventory symbolic link
+
+ AT_LINK_FOLDER = 25,
+ // Inventory folder link
- AT_LINK_FOLDER = 25,
- // Inventory folder link
-
AT_MARKETPLACE_FOLDER = 26,
// Marketplace folder. Same as an AT_CATEGORY but different display methods.
-
- AT_WIDGET = 40,
- // UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...)
-
- AT_PERSON = 45,
- // A user uuid which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop.
+
+ AT_WIDGET = 40,
+ // UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...)
+
+ AT_PERSON = 45,
+ // A user uuid which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop.
AT_MESH = 49,
// Mesh data in our proprietary SLM format
@@ -129,45 +129,45 @@ public:
AT_SETTINGS = 56, // Collection of settings
AT_MATERIAL = 57, // Render Material
- AT_COUNT = 58,
+ AT_COUNT = 58,
- // +*********************************************************+
- // | TO ADD AN ELEMENT TO THIS ENUM: |
- // +*********************************************************+
- // | 1. INSERT BEFORE AT_COUNT |
- // | 2. INCREMENT AT_COUNT BY 1 |
- // | 3. ADD TO LLAssetType.cpp |
- // | 4. ADD TO LLViewerAssetType.cpp |
- // | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
- // +*********************************************************+
- AT_UNKNOWN = 255,
- AT_NONE = -1
- };
+ // +*********************************************************+
+ // | TO ADD AN ELEMENT TO THIS ENUM: |
+ // +*********************************************************+
+ // | 1. INSERT BEFORE AT_COUNT |
+ // | 2. INCREMENT AT_COUNT BY 1 |
+ // | 3. ADD TO LLAssetType.cpp |
+ // | 4. ADD TO LLViewerAssetType.cpp |
+ // | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
+ // +*********************************************************+
+ AT_UNKNOWN = 255,
+ AT_NONE = -1
+ };
- // machine transation between type and strings
- static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
- static EType lookup(const std::string& type_name);
- static const char* lookup(EType asset_type);
+ // machine transation between type and strings
+ static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
+ static EType lookup(const std::string& type_name);
+ static const char* lookup(EType asset_type);
- // translation from a type to a human readable form.
- static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate
- static EType lookupHumanReadable(const std::string& readable_name);
- static const char* lookupHumanReadable(EType asset_type);
+ // translation from a type to a human readable form.
+ static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate
+ static EType lookupHumanReadable(const std::string& readable_name);
+ static const char* lookupHumanReadable(EType asset_type);
- static EType getType(const std::string& desc_name);
- static const std::string& getDesc(EType asset_type);
+ static EType getType(const std::string& desc_name);
+ static const std::string& getDesc(EType asset_type);
- static bool lookupCanLink(EType asset_type);
- static bool lookupIsLinkType(EType asset_type);
+ static bool lookupCanLink(EType asset_type);
+ static bool lookupIsLinkType(EType asset_type);
- static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
- static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
+ static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
+ static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
static const std::string BADLOOKUP;
protected:
- LLAssetType() {}
- ~LLAssetType() {}
+ LLAssetType() {}
+ ~LLAssetType() {}
};
#endif // LL_LLASSETTYPE_H
diff --git a/indra/llcommon/llatomic.cpp b/indra/llcommon/llatomic.cpp
index 93aba1f460..d200bb0406 100644
--- a/indra/llcommon/llatomic.cpp
+++ b/indra/llcommon/llatomic.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llatomic.cpp
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2018, 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$
*/
diff --git a/indra/llcommon/llatomic.h b/indra/llcommon/llatomic.h
index 8de773846c..c5304637cc 100644
--- a/indra/llcommon/llatomic.h
+++ b/indra/llcommon/llatomic.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llatomic.h
* @brief Base classes for atomic.
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2018, 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$
*/
@@ -40,7 +40,7 @@ public:
operator const Type() { return mData; }
- Type CurrentValue() const { return mData; }
+ Type CurrentValue() const { return mData; }
Type operator =(const Type& x) { mData.store(x); return mData; }
void operator -=(Type x) { mData -= x; }
diff --git a/indra/llcommon/llbase32.cpp b/indra/llcommon/llbase32.cpp
index 349567c90b..979114fe86 100644
--- a/indra/llcommon/llbase32.cpp
+++ b/indra/llcommon/llbase32.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbase32.cpp
* @brief base32 encoding that returns a std::string
* @author James Cook
@@ -10,21 +10,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -118,9 +118,9 @@ base32_encode(char *dst, size_t size, const void *data, size_t len)
| 6 | 1 0 7 6 5 | 3-4 |
| 7 | 4 3 2 1 0 | 4 |
+-------+-----------+--------+
-
+
*/
-
+
s[0] = (x[0] >> 3);
s[1] = ((x[0] & 0x07) << 2) | (x[1] >> 6);
s[2] = (x[1] >> 1) & 0x1f;
@@ -167,12 +167,12 @@ base32_decode(char *dst, size_t size, const void *data, size_t len)
if (0 == base32_map[0]) {
for (i = 0; i < LL_ARRAY_SIZE(base32_map); i++) {
const char *x;
-
+
x = memchr(base32_alphabet, ascii_toupper(i), sizeof base32_alphabet);
base32_map[i] = x ? (x - base32_alphabet) : (unsigned char) -1;
}
}
-
+
for (i = 0; i < len && max_pad > 0; i++) {
unsigned char c;
char s[8];
@@ -219,20 +219,20 @@ base32_decode(char *dst, size_t size, const void *data, size_t len)
// static
std::string LLBase32::encode(const U8* input, size_t input_size)
{
- std::string output;
- if (input)
- {
- // Each 5 byte chunk of input is represented by an
- // 8 byte chunk of output.
- size_t input_chunks = (input_size + 4) / 5;
- size_t output_size = input_chunks * 8;
-
- output.resize(output_size);
-
- size_t encoded = base32_encode(&output[0], output_size, input, input_size);
-
- LL_INFOS() << "encoded " << encoded << " into buffer of size "
- << output_size << LL_ENDL;
- }
- return output;
+ std::string output;
+ if (input)
+ {
+ // Each 5 byte chunk of input is represented by an
+ // 8 byte chunk of output.
+ size_t input_chunks = (input_size + 4) / 5;
+ size_t output_size = input_chunks * 8;
+
+ output.resize(output_size);
+
+ size_t encoded = base32_encode(&output[0], output_size, input, input_size);
+
+ LL_INFOS() << "encoded " << encoded << " into buffer of size "
+ << output_size << LL_ENDL;
+ }
+ return output;
}
diff --git a/indra/llcommon/llbase32.h b/indra/llcommon/llbase32.h
index eeb96d789d..8cfbd7ef53 100644
--- a/indra/llcommon/llbase32.h
+++ b/indra/llcommon/llbase32.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbase32.h
* @brief base32 encoding that returns a std::string
* @author James Cook
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -31,7 +31,7 @@
class LL_COMMON_API LLBase32
{
public:
- static std::string encode(const U8* input, size_t input_size);
+ static std::string encode(const U8* input, size_t input_size);
};
#endif
diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp
index 433b54f6f8..dbbbec9813 100644
--- a/indra/llcommon/llbase64.cpp
+++ b/indra/llcommon/llbase64.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbase64.cpp
* @brief Wrapper for apr base64 encoding that returns a std::string
* @author James Cook
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -37,25 +37,25 @@
// static
std::string LLBase64::encode(const U8* input, size_t input_size)
{
- std::string output;
- if (input
- && input_size > 0)
- {
- // Yes, it returns int.
- int b64_buffer_length = apr_base64_encode_len(narrow<size_t>(input_size));
- char* b64_buffer = new char[b64_buffer_length];
-
- // This is faster than apr_base64_encode() if you know
- // you're not on an EBCDIC machine. Also, the output is
- // null terminated, even though the documentation doesn't
- // specify. See apr_base64.c for details. JC
- b64_buffer_length = apr_base64_encode_binary(
- b64_buffer,
- input,
- narrow<size_t>(input_size));
- output.assign(b64_buffer);
- delete[] b64_buffer;
- }
- return output;
+ std::string output;
+ if (input
+ && input_size > 0)
+ {
+ // Yes, it returns int.
+ int b64_buffer_length = apr_base64_encode_len(narrow<size_t>(input_size));
+ char* b64_buffer = new char[b64_buffer_length];
+
+ // This is faster than apr_base64_encode() if you know
+ // you're not on an EBCDIC machine. Also, the output is
+ // null terminated, even though the documentation doesn't
+ // specify. See apr_base64.c for details. JC
+ b64_buffer_length = apr_base64_encode_binary(
+ b64_buffer,
+ input,
+ narrow<size_t>(input_size));
+ output.assign(b64_buffer);
+ delete[] b64_buffer;
+ }
+ return output;
}
diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h
index 16d2c217d0..d4e9d97ea4 100644
--- a/indra/llcommon/llbase64.h
+++ b/indra/llcommon/llbase64.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbase64.h
* @brief Wrapper for apr base64 encoding that returns a std::string
* @author James Cook
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -31,7 +31,7 @@
class LL_COMMON_API LLBase64
{
public:
- static std::string encode(const U8* input, size_t input_size);
+ static std::string encode(const U8* input, size_t input_size);
};
#endif
diff --git a/indra/llcommon/llbitpack.cpp b/indra/llcommon/llbitpack.cpp
index 622a099945..011b310f40 100644
--- a/indra/llcommon/llbitpack.cpp
+++ b/indra/llcommon/llbitpack.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file bitpack.cpp
* @brief LLBitPack class implementation
*
* $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$
*/
diff --git a/indra/llcommon/llbitpack.h b/indra/llcommon/llbitpack.h
index f99a354cd4..f7eb57a4f0 100644
--- a/indra/llcommon/llbitpack.h
+++ b/indra/llcommon/llbitpack.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llbitpack.h
* @brief Convert data to packed bit stream
*
* $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$
*/
@@ -35,174 +35,174 @@ const U32 MAX_DATA_BITS = 8;
class LLBitPack
{
public:
- LLBitPack(U8 *buffer, U32 max_size) : mBuffer(buffer), mBufferSize(0), mLoad(0), mLoadSize(0), mTotalBits(0), mMaxSize(max_size)
- {
- }
-
- ~LLBitPack()
- {
- }
-
- void resetBitPacking()
- {
- mLoad = 0;
- mLoadSize = 0;
- mTotalBits = 0;
- mBufferSize = 0;
- }
-
- U32 bitPack(U8 *total_data, U32 total_dsize)
- {
- U32 dsize;
- U8 data;
-
- while (total_dsize > 0)
- {
- if (total_dsize > MAX_DATA_BITS)
- {
- dsize = MAX_DATA_BITS;
- total_dsize -= MAX_DATA_BITS;
- }
- else
- {
- dsize = total_dsize;
- total_dsize = 0;
- }
-
- data = *total_data++;
-
- data <<= (MAX_DATA_BITS - dsize);
- while (dsize > 0)
- {
- if (mLoadSize == MAX_DATA_BITS)
- {
- *(mBuffer + mBufferSize++) = mLoad;
- if (mBufferSize > mMaxSize)
- {
- LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
- }
- mLoadSize = 0;
- mLoad = 0x00;
- }
- mLoad <<= 1;
- mLoad |= (data >> (MAX_DATA_BITS - 1));
- data <<= 1;
- mLoadSize++;
- mTotalBits++;
- dsize--;
- }
- }
- return mBufferSize;
- }
-
- U32 bitCopy(U8 *total_data, U32 total_dsize)
- {
- U32 dsize;
- U8 data;
-
- while (total_dsize > 0)
- {
- if (total_dsize > MAX_DATA_BITS)
- {
- dsize = MAX_DATA_BITS;
- total_dsize -= MAX_DATA_BITS;
- }
- else
- {
- dsize = total_dsize;
- total_dsize = 0;
- }
-
- data = *total_data++;
-
- while (dsize > 0)
- {
- if (mLoadSize == MAX_DATA_BITS)
- {
- *(mBuffer + mBufferSize++) = mLoad;
- if (mBufferSize > mMaxSize)
- {
- LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
- }
- mLoadSize = 0;
- mLoad = 0x00;
- }
- mLoad <<= 1;
- mLoad |= (data >> (MAX_DATA_BITS - 1));
- data <<= 1;
- mLoadSize++;
- mTotalBits++;
- dsize--;
- }
- }
- return mBufferSize;
- }
-
- U32 bitUnpack(U8 *total_retval, U32 total_dsize)
- {
- U32 dsize;
- U8 *retval;
-
- while (total_dsize > 0)
- {
- if (total_dsize > MAX_DATA_BITS)
- {
- dsize = MAX_DATA_BITS;
- total_dsize -= MAX_DATA_BITS;
- }
- else
- {
- dsize = total_dsize;
- total_dsize = 0;
- }
-
- retval = total_retval++;
- *retval = 0x00;
- while (dsize > 0)
- {
- if (mLoadSize == 0)
- {
+ LLBitPack(U8 *buffer, U32 max_size) : mBuffer(buffer), mBufferSize(0), mLoad(0), mLoadSize(0), mTotalBits(0), mMaxSize(max_size)
+ {
+ }
+
+ ~LLBitPack()
+ {
+ }
+
+ void resetBitPacking()
+ {
+ mLoad = 0;
+ mLoadSize = 0;
+ mTotalBits = 0;
+ mBufferSize = 0;
+ }
+
+ U32 bitPack(U8 *total_data, U32 total_dsize)
+ {
+ U32 dsize;
+ U8 data;
+
+ while (total_dsize > 0)
+ {
+ if (total_dsize > MAX_DATA_BITS)
+ {
+ dsize = MAX_DATA_BITS;
+ total_dsize -= MAX_DATA_BITS;
+ }
+ else
+ {
+ dsize = total_dsize;
+ total_dsize = 0;
+ }
+
+ data = *total_data++;
+
+ data <<= (MAX_DATA_BITS - dsize);
+ while (dsize > 0)
+ {
+ if (mLoadSize == MAX_DATA_BITS)
+ {
+ *(mBuffer + mBufferSize++) = mLoad;
+ if (mBufferSize > mMaxSize)
+ {
+ LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
+ }
+ mLoadSize = 0;
+ mLoad = 0x00;
+ }
+ mLoad <<= 1;
+ mLoad |= (data >> (MAX_DATA_BITS - 1));
+ data <<= 1;
+ mLoadSize++;
+ mTotalBits++;
+ dsize--;
+ }
+ }
+ return mBufferSize;
+ }
+
+ U32 bitCopy(U8 *total_data, U32 total_dsize)
+ {
+ U32 dsize;
+ U8 data;
+
+ while (total_dsize > 0)
+ {
+ if (total_dsize > MAX_DATA_BITS)
+ {
+ dsize = MAX_DATA_BITS;
+ total_dsize -= MAX_DATA_BITS;
+ }
+ else
+ {
+ dsize = total_dsize;
+ total_dsize = 0;
+ }
+
+ data = *total_data++;
+
+ while (dsize > 0)
+ {
+ if (mLoadSize == MAX_DATA_BITS)
+ {
+ *(mBuffer + mBufferSize++) = mLoad;
+ if (mBufferSize > mMaxSize)
+ {
+ LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
+ }
+ mLoadSize = 0;
+ mLoad = 0x00;
+ }
+ mLoad <<= 1;
+ mLoad |= (data >> (MAX_DATA_BITS - 1));
+ data <<= 1;
+ mLoadSize++;
+ mTotalBits++;
+ dsize--;
+ }
+ }
+ return mBufferSize;
+ }
+
+ U32 bitUnpack(U8 *total_retval, U32 total_dsize)
+ {
+ U32 dsize;
+ U8 *retval;
+
+ while (total_dsize > 0)
+ {
+ if (total_dsize > MAX_DATA_BITS)
+ {
+ dsize = MAX_DATA_BITS;
+ total_dsize -= MAX_DATA_BITS;
+ }
+ else
+ {
+ dsize = total_dsize;
+ total_dsize = 0;
+ }
+
+ retval = total_retval++;
+ *retval = 0x00;
+ while (dsize > 0)
+ {
+ if (mLoadSize == 0)
+ {
#ifdef _DEBUG
- if (mBufferSize > mMaxSize)
- {
- LL_ERRS() << "mBufferSize exceeding mMaxSize" << LL_ENDL;
- LL_ERRS() << mBufferSize << " > " << mMaxSize << LL_ENDL;
- }
+ if (mBufferSize > mMaxSize)
+ {
+ LL_ERRS() << "mBufferSize exceeding mMaxSize" << LL_ENDL;
+ LL_ERRS() << mBufferSize << " > " << mMaxSize << LL_ENDL;
+ }
#endif
- mLoad = *(mBuffer + mBufferSize++);
- mLoadSize = MAX_DATA_BITS;
- }
- *retval <<= 1;
- *retval |= (mLoad >> (MAX_DATA_BITS - 1));
- mLoadSize--;
- mLoad <<= 1;
- dsize--;
- }
- }
- return mBufferSize;
- }
-
- U32 flushBitPack()
- {
- if (mLoadSize)
- {
- mLoad <<= (MAX_DATA_BITS - mLoadSize);
- *(mBuffer + mBufferSize++) = mLoad;
- if (mBufferSize > mMaxSize)
- {
- LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
- }
- mLoadSize = 0;
- }
- return mBufferSize;
- }
-
- U8 *mBuffer;
- U32 mBufferSize;
- U8 mLoad;
- U32 mLoadSize;
- U32 mTotalBits;
- U32 mMaxSize;
+ mLoad = *(mBuffer + mBufferSize++);
+ mLoadSize = MAX_DATA_BITS;
+ }
+ *retval <<= 1;
+ *retval |= (mLoad >> (MAX_DATA_BITS - 1));
+ mLoadSize--;
+ mLoad <<= 1;
+ dsize--;
+ }
+ }
+ return mBufferSize;
+ }
+
+ U32 flushBitPack()
+ {
+ if (mLoadSize)
+ {
+ mLoad <<= (MAX_DATA_BITS - mLoadSize);
+ *(mBuffer + mBufferSize++) = mLoad;
+ if (mBufferSize > mMaxSize)
+ {
+ LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
+ }
+ mLoadSize = 0;
+ }
+ return mBufferSize;
+ }
+
+ U8 *mBuffer;
+ U32 mBufferSize;
+ U8 mLoad;
+ U32 mLoadSize;
+ U32 mTotalBits;
+ U32 mMaxSize;
};
#endif
diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h
index 57d958a51a..980fc9e1c4 100644
--- a/indra/llcommon/llboost.h
+++ b/indra/llcommon/llboost.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llboost.h
* @brief helper object & functions for use with boost
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -31,12 +31,12 @@
// boost_tokenizer typedef
/* example usage:
- boost_tokenizer tokens(input_string, boost::char_separator<char>(" \t\n"));
- for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- std::string tok = *token_iter;
- process_token_string( tok );
- }
+ boost_tokenizer tokens(input_string, boost::char_separator<char>(" \t\n"));
+ for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ {
+ std::string tok = *token_iter;
+ process_token_string( tok );
+ }
*/
typedef boost::tokenizer<boost::char_separator<char> > boost_tokenizer;
@@ -44,15 +44,15 @@ typedef boost::tokenizer<boost::char_separator<char> > boost_tokenizer;
// returns false if any of the callbacks return false
struct boost_boolean_combiner
{
- typedef bool result_type;
- template<typename InputIterator>
- bool operator()(InputIterator first, InputIterator last) const
- {
- bool res = true;
- while (first != last)
- res &= *first++;
- return res;
- }
+ typedef bool result_type;
+ template<typename InputIterator>
+ bool operator()(InputIterator first, InputIterator last) const
+ {
+ bool res = true;
+ while (first != last)
+ res &= *first++;
+ return res;
+ }
};
#endif // LL_LLBOOST_H
diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp
index 9f23ce5317..b5a58e90b3 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$
*/
@@ -38,7 +38,7 @@ LLCallbackList gIdleCallbacks;
LLCallbackList::LLCallbackList()
{
- // nothing
+ // nothing
}
LLCallbackList::~LLCallbackList()
@@ -48,72 +48,72 @@ LLCallbackList::~LLCallbackList()
void LLCallbackList::addFunction( callback_t func, void *data)
{
- if (!func)
- {
- return;
- }
-
- // only add one callback per func/data pair
- //
- if (containsFunction(func, data))
- {
- return;
- }
-
- callback_pair_t t(func, data);
- mCallbackList.push_back(t);
+ if (!func)
+ {
+ return;
+ }
+
+ // only add one callback per func/data pair
+ //
+ if (containsFunction(func, data))
+ {
+ return;
+ }
+
+ callback_pair_t t(func, data);
+ mCallbackList.push_back(t);
}
bool LLCallbackList::containsFunction( callback_t func, void *data)
{
- callback_pair_t t(func, data);
- callback_list_t::iterator iter = find(func,data);
- if (iter != mCallbackList.end())
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ callback_pair_t t(func, data);
+ callback_list_t::iterator iter = find(func,data);
+ if (iter != mCallbackList.end())
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
bool LLCallbackList::deleteFunction( callback_t func, void *data)
{
- callback_list_t::iterator iter = find(func,data);
- if (iter != mCallbackList.end())
- {
- mCallbackList.erase(iter);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ callback_list_t::iterator iter = find(func,data);
+ if (iter != mCallbackList.end())
+ {
+ mCallbackList.erase(iter);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
-inline
+inline
LLCallbackList::callback_list_t::iterator
LLCallbackList::find(callback_t func, void *data)
{
- callback_pair_t t(func, data);
- return std::find(mCallbackList.begin(), mCallbackList.end(), t);
+ callback_pair_t t(func, data);
+ return std::find(mCallbackList.begin(), mCallbackList.end(), t);
}
void LLCallbackList::deleteAllFunctions()
{
- mCallbackList.clear();
+ mCallbackList.clear();
}
void LLCallbackList::callFunctions()
{
- for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
- {
- callback_list_t::iterator curiter = iter++;
- curiter->first(curiter->second);
- }
+ for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
+ {
+ callback_list_t::iterator curiter = iter++;
+ curiter->first(curiter->second);
+ }
}
// Shim class to allow arbitrary boost::bind
@@ -121,29 +121,29 @@ void LLCallbackList::callFunctions()
class OnIdleCallbackOneTime
{
public:
- OnIdleCallbackOneTime(nullary_func_t callable):
- mCallable(callable)
- {
- }
- static void onIdle(void *data)
- {
- gIdleCallbacks.deleteFunction(onIdle, data);
- OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
- self->call();
- delete self;
- }
- void call()
- {
- mCallable();
- }
+ OnIdleCallbackOneTime(nullary_func_t callable):
+ mCallable(callable)
+ {
+ }
+ static void onIdle(void *data)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
+ self->call();
+ delete self;
+ }
+ void call()
+ {
+ mCallable();
+ }
private:
- nullary_func_t mCallable;
+ nullary_func_t mCallable;
};
void doOnIdleOneTime(nullary_func_t callable)
{
- OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
- gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
+ OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
}
// Shim class to allow generic boost functions to be run as
@@ -152,79 +152,79 @@ void doOnIdleOneTime(nullary_func_t callable)
class OnIdleCallbackRepeating
{
public:
- OnIdleCallbackRepeating(bool_func_t callable):
- mCallable(callable)
- {
- }
- // Will keep getting called until the callable returns true.
- static void onIdle(void *data)
- {
- OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
- bool done = self->call();
- if (done)
- {
- gIdleCallbacks.deleteFunction(onIdle, data);
- delete self;
- }
- }
- bool call()
- {
- return mCallable();
- }
+ OnIdleCallbackRepeating(bool_func_t callable):
+ mCallable(callable)
+ {
+ }
+ // Will keep getting called until the callable returns true.
+ static void onIdle(void *data)
+ {
+ OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
+ bool done = self->call();
+ if (done)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ delete self;
+ }
+ }
+ bool call()
+ {
+ return mCallable();
+ }
private:
- bool_func_t mCallable;
+ bool_func_t mCallable;
};
void doOnIdleRepeating(bool_func_t callable)
{
- OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
- gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
+ OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
}
class NullaryFuncEventTimer: public LLEventTimer
{
public:
- NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
- LLEventTimer(seconds),
- mCallable(callable)
- {
- }
+ NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
+ LLEventTimer(seconds),
+ mCallable(callable)
+ {
+ }
private:
- BOOL tick()
- {
- mCallable();
- return TRUE;
- }
+ BOOL tick()
+ {
+ mCallable();
+ return TRUE;
+ }
- nullary_func_t mCallable;
+ nullary_func_t mCallable;
};
// Call a given callable once after specified interval.
void doAfterInterval(nullary_func_t callable, F32 seconds)
{
- new NullaryFuncEventTimer(callable, seconds);
+ new NullaryFuncEventTimer(callable, seconds);
}
class BoolFuncEventTimer: public LLEventTimer
{
public:
- BoolFuncEventTimer(bool_func_t callable, F32 seconds):
- LLEventTimer(seconds),
- mCallable(callable)
- {
- }
+ BoolFuncEventTimer(bool_func_t callable, F32 seconds):
+ LLEventTimer(seconds),
+ mCallable(callable)
+ {
+ }
private:
- BOOL tick()
- {
- return mCallable();
- }
+ BOOL tick()
+ {
+ return mCallable();
+ }
- bool_func_t mCallable;
+ bool_func_t mCallable;
};
// Call a given callable every specified number of seconds, until it returns true.
void doPeriodically(bool_func_t callable, F32 seconds)
{
- new BoolFuncEventTimer(callable, seconds);
+ new BoolFuncEventTimer(callable, seconds);
}
diff --git a/indra/llcommon/llcallbacklist.h b/indra/llcommon/llcallbacklist.h
index 89716cd74c..d6c415f7c5 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$
*/
@@ -34,29 +34,29 @@
class LLCallbackList
{
public:
- typedef void (*callback_t)(void*);
+ typedef void (*callback_t)(void*);
+
+ typedef std::pair< callback_t,void* > callback_pair_t;
+ // NOTE: It is confirmed that we DEPEND on the order provided by using a list :(
+ //
+ typedef std::list< callback_pair_t > callback_list_t;
- typedef std::pair< callback_t,void* > callback_pair_t;
- // NOTE: It is confirmed that we DEPEND on the order provided by using a list :(
- //
- typedef std::list< callback_pair_t > callback_list_t;
-
- LLCallbackList();
- ~LLCallbackList();
+ LLCallbackList();
+ ~LLCallbackList();
- void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
- 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 callFunctions(); // calls all functions
- void deleteAllFunctions();
+ void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
+ 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 callFunctions(); // calls all functions
+ void deleteAllFunctions();
- static void test();
+ static void test();
protected:
- inline callback_list_t::iterator find(callback_t func, void *data);
+ inline callback_list_t::iterator find(callback_t func, void *data);
- callback_list_t mCallbackList;
+ callback_list_t mCallbackList;
};
typedef boost::function<void ()> nullary_func_t;
diff --git a/indra/llcommon/llcallstack.cpp b/indra/llcommon/llcallstack.cpp
index 83d5ae2a63..c0be4f598e 100644
--- a/indra/llcommon/llcallstack.cpp
+++ b/indra/llcommon/llcallstack.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcallstack.cpp
* @brief run-time extraction of the current callstack
*
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2016, 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$
*/
@@ -91,7 +91,7 @@ LLCallStack::LLCallStack(S32 skip_count, bool verbose):
bool LLCallStack::contains(const std::string& str)
{
- for (const std::string& src_str : m_strings)
+ for (const std::string& src_str : m_strings)
{
if (src_str.find(str) != std::string::npos)
{
@@ -104,7 +104,7 @@ bool LLCallStack::contains(const std::string& str)
std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack)
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
- for (const std::string& str : call_stack.m_strings)
+ for (const std::string& str : call_stack.m_strings)
{
s << str;
}
@@ -121,27 +121,27 @@ LLContextStrings::LLContextStrings()
// static
LLContextStrings* LLContextStrings::getThreadLocalInstance()
{
- LLContextStrings *cons = LLThreadLocalSingletonPointer<LLContextStrings>::getInstance();
+ LLContextStrings *cons = LLThreadLocalSingletonPointer<LLContextStrings>::getInstance();
if (!cons)
{
LLThreadLocalSingletonPointer<LLContextStrings>::setInstance(new LLContextStrings);
}
- return LLThreadLocalSingletonPointer<LLContextStrings>::getInstance();
+ return LLThreadLocalSingletonPointer<LLContextStrings>::getInstance();
}
// static
void LLContextStrings::addContextString(const std::string& str)
{
- LLContextStrings *cons = getThreadLocalInstance();
+ LLContextStrings *cons = getThreadLocalInstance();
//LL_INFOS() << "CTX " << (S32)cons << " ADD " << str << " CNT " << cons->m_contextStrings[str] << LL_ENDL;
- cons->m_contextStrings[str]++;
+ cons->m_contextStrings[str]++;
}
// static
void LLContextStrings::removeContextString(const std::string& str)
{
- LLContextStrings *cons = getThreadLocalInstance();
- cons->m_contextStrings[str]--;
+ LLContextStrings *cons = getThreadLocalInstance();
+ cons->m_contextStrings[str]--;
//LL_INFOS() << "CTX " << (S32)cons << " REMOVE " << str << " CNT " << cons->m_contextStrings[str] << LL_ENDL;
if (cons->m_contextStrings[str] == 0)
{
@@ -175,7 +175,7 @@ void LLContextStrings::output(std::ostream& os)
}
}
-// static
+// static
std::ostream& operator<<(std::ostream& s, const LLContextStatus& context_status)
{
LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->output(s);
diff --git a/indra/llcommon/llcallstack.h b/indra/llcommon/llcallstack.h
index d5a2b7b157..ad10a9dbf7 100644
--- a/indra/llcommon/llcallstack.h
+++ b/indra/llcommon/llcallstack.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcallstack.h
* @brief run-time extraction of the current callstack
*
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2016, 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$
*/
diff --git a/indra/llcommon/llcleanup.cpp b/indra/llcommon/llcleanup.cpp
index 1f34c2036a..38b2ccbeff 100644
--- a/indra/llcommon/llcleanup.cpp
+++ b/indra/llcommon/llcleanup.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-08-30
* @brief Implementation for llcleanup.
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h
index 0f567ed5f6..b120a5c4fe 100644
--- a/indra/llcommon/llcleanup.h
+++ b/indra/llcommon/llcleanup.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2015-05-20
* @brief Mechanism for cleaning up subsystem resources
- *
+ *
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Copyright (c) 2015, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llclickaction.h b/indra/llcommon/llclickaction.h
index 2f83113af9..daa4e88f80 100644
--- a/indra/llcommon/llclickaction.h
+++ b/indra/llcommon/llclickaction.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llclickaction.h
* @author James Cook
* @brief Constants for single-click actions on objects
@@ -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$
*/
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 6e988260a9..14bdeb5c60 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llcommon.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$
*/
@@ -122,32 +122,32 @@ static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
//static
void LLCommon::initClass()
{
- if (!sAprInitialized)
- {
- ll_init_apr();
- sAprInitialized = TRUE;
- }
- LLTimer::initClass();
- LLThreadSafeRefCount::initThreadSafeRefCount();
- assert_main_thread(); // Make sure we record the main thread
- if (!sMasterThreadRecorder)
- {
- sMasterThreadRecorder = new LLTrace::ThreadRecorder();
- LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
- }
+ if (!sAprInitialized)
+ {
+ ll_init_apr();
+ sAprInitialized = TRUE;
+ }
+ LLTimer::initClass();
+ LLThreadSafeRefCount::initThreadSafeRefCount();
+ assert_main_thread(); // Make sure we record the main thread
+ if (!sMasterThreadRecorder)
+ {
+ sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+ LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+ }
}
//static
void LLCommon::cleanupClass()
{
- delete sMasterThreadRecorder;
- sMasterThreadRecorder = NULL;
- LLTrace::set_master_thread_recorder(NULL);
- LLThreadSafeRefCount::cleanupThreadSafeRefCount();
- SUBSYSTEM_CLEANUP_DBG(LLTimer);
- if (sAprInitialized)
- {
- ll_cleanup_apr();
- sAprInitialized = FALSE;
- }
+ delete sMasterThreadRecorder;
+ sMasterThreadRecorder = NULL;
+ LLTrace::set_master_thread_recorder(NULL);
+ LLThreadSafeRefCount::cleanupThreadSafeRefCount();
+ SUBSYSTEM_CLEANUP_DBG(LLTimer);
+ if (sAprInitialized)
+ {
+ ll_cleanup_apr();
+ sAprInitialized = FALSE;
+ }
}
diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h
index ca9cad5d05..129e71f703 100644
--- a/indra/llcommon/llcommon.h
+++ b/indra/llcommon/llcommon.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llcommon.h
*
* $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$
*/
@@ -33,10 +33,10 @@
class LL_COMMON_API LLCommon
{
public:
- static void initClass();
- static void cleanupClass();
+ static void initClass();
+ static void cleanupClass();
private:
- static BOOL sAprInitialized;
+ static BOOL sAprInitialized;
};
#endif
diff --git a/indra/llcommon/llcommonutils.cpp b/indra/llcommon/llcommonutils.cpp
index d82554c202..a38879c89f 100644
--- a/indra/llcommon/llcommonutils.cpp
+++ b/indra/llcommon/llcommonutils.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2010&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$
*/
@@ -28,29 +28,29 @@
#include "llcommonutils.h"
void LLCommonUtils::computeDifference(
- const uuid_vec_t& vnew,
- const uuid_vec_t& vcur,
- uuid_vec_t& vadded,
- uuid_vec_t& vremoved)
+ const uuid_vec_t& vnew,
+ const uuid_vec_t& vcur,
+ uuid_vec_t& vadded,
+ uuid_vec_t& vremoved)
{
- uuid_vec_t vnew_copy(vnew);
- uuid_vec_t vcur_copy(vcur);
+ uuid_vec_t vnew_copy(vnew);
+ uuid_vec_t vcur_copy(vcur);
- std::sort(vnew_copy.begin(), vnew_copy.end());
- std::sort(vcur_copy.begin(), vcur_copy.end());
+ std::sort(vnew_copy.begin(), vnew_copy.end());
+ std::sort(vcur_copy.begin(), vcur_copy.end());
- size_t maxsize = llmax(vnew_copy.size(), vcur_copy.size());
- vadded.resize(maxsize);
- vremoved.resize(maxsize);
+ size_t maxsize = llmax(vnew_copy.size(), vcur_copy.size());
+ vadded.resize(maxsize);
+ vremoved.resize(maxsize);
- uuid_vec_t::iterator it;
- // what was removed
- it = set_difference(vcur_copy.begin(), vcur_copy.end(), vnew_copy.begin(), vnew_copy.end(), vremoved.begin());
- vremoved.erase(it, vremoved.end());
+ uuid_vec_t::iterator it;
+ // what was removed
+ it = set_difference(vcur_copy.begin(), vcur_copy.end(), vnew_copy.begin(), vnew_copy.end(), vremoved.begin());
+ vremoved.erase(it, vremoved.end());
- // what was added
- it = set_difference(vnew_copy.begin(), vnew_copy.end(), vcur_copy.begin(), vcur_copy.end(), vadded.begin());
- vadded.erase(it, vadded.end());
+ // what was added
+ it = set_difference(vnew_copy.begin(), vnew_copy.end(), vcur_copy.begin(), vcur_copy.end(), vadded.begin());
+ vadded.erase(it, vadded.end());
}
// EOF
diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h
index 20ada27830..5f6fd41aa3 100644
--- a/indra/llcommon/llcommonutils.h
+++ b/indra/llcommon/llcommonutils.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2010&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$
*/
@@ -31,21 +31,21 @@
namespace LLCommonUtils
{
- /**
- * Computes difference between 'vnew' and 'vcur' vectors.
- * Items present in 'vnew' and missing in 'vcur' are treated as added and are copied into 'vadded'
- * Items missing in 'vnew' and present in 'vcur' are treated as removed and are copied into 'vremoved'
- *
- * @param vnew[in] - incoming IDs
- * @param vcur[in] - current IDs
- * @param vadded[out] - difference between incoming and current IDS - added IDs
- * @param vremoved[out] - difference between incoming and current IDS - removed IDs
- */
- LL_COMMON_API void computeDifference(
- const uuid_vec_t& vnew,
- const uuid_vec_t& vcur,
- uuid_vec_t& vadded,
- uuid_vec_t& vremoved);
+ /**
+ * Computes difference between 'vnew' and 'vcur' vectors.
+ * Items present in 'vnew' and missing in 'vcur' are treated as added and are copied into 'vadded'
+ * Items missing in 'vnew' and present in 'vcur' are treated as removed and are copied into 'vremoved'
+ *
+ * @param vnew[in] - incoming IDs
+ * @param vcur[in] - current IDs
+ * @param vadded[out] - difference between incoming and current IDS - added IDs
+ * @param vremoved[out] - difference between incoming and current IDS - removed IDs
+ */
+ LL_COMMON_API void computeDifference(
+ const uuid_vec_t& vnew,
+ const uuid_vec_t& vcur,
+ uuid_vec_t& vadded,
+ uuid_vec_t& vremoved);
};
#endif //LL_LLCOMMONUTILS_H
diff --git a/indra/llcommon/llcond.h b/indra/llcommon/llcond.h
index da6e6affe1..2df1719941 100644
--- a/indra/llcommon/llcond.h
+++ b/indra/llcommon/llcond.h
@@ -5,7 +5,7 @@
* @brief LLCond is a wrapper around condition_variable to encapsulate the
* obligatory condition_variable usage pattern. We also provide
* simplified versions LLScalarCond, LLBoolCond and LLOneShotCond.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index c13900f74a..aa8eca7d90 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-06-03
* @brief Implementation for llcoros.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -123,7 +123,7 @@ LLCoros::LLCoros():
// Previously we used
// boost::context::guarded_stack_allocator::default_stacksize();
// empirically this is insufficient.
- mStackSize(900*1024),
+ mStackSize(1024*1024),
// mCurrent does NOT own the current CoroData instance -- it simply
// points to it. So initialize it with a no-op deleter.
mCurrent{ [](CoroData*){} }
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index fd878f20ad..71c1c1c443 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-06-02
* @brief Manage running boost::coroutine instances
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -158,7 +158,7 @@ public:
* LLCoros::launch()).
*/
static std::string getName();
-
+
/**
* rethrow() is called by the thread's main fiber to propagate an
* exception from any coroutine into the main fiber, where it can engage
diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp
index 626bb1e564..34aa7b46e8 100644
--- a/indra/llcommon/llcrc.cpp
+++ b/indra/llcommon/llcrc.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcrc.cpp
* @brief implementation of the crc class.
*
* $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$
*/
@@ -142,77 +142,77 @@ LLCRC::LLCRC() : mCurrent(0xffffffff)
U32 LLCRC::getCRC() const
{
- return ~mCurrent;
+ return ~mCurrent;
}
void LLCRC::update(U8 next_byte)
{
- mCurrent = UPDC32(next_byte, mCurrent);
+ mCurrent = UPDC32(next_byte, mCurrent);
}
void LLCRC::update(const U8* buffer, size_t buffer_size)
{
- for (size_t i = 0; i < buffer_size; i++)
- {
- mCurrent = UPDC32(buffer[i], mCurrent);
- }
+ for (size_t i = 0; i < buffer_size; i++)
+ {
+ mCurrent = UPDC32(buffer[i], mCurrent);
+ }
}
void LLCRC::update(const std::string& filename)
{
- if (filename.empty())
- {
- LL_ERRS() << "No filename specified" << LL_ENDL;
- return;
- }
-
- FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
-
- if (fp)
- {
- fseek(fp, 0, SEEK_END);
- long size = ftell(fp);
-
- fseek(fp, 0, SEEK_SET);
-
- if (size > 0)
- {
- U8* data = new U8[size];
- size_t nread;
-
- nread = fread(data, 1, size, fp);
- fclose(fp);
-
- if (nread < (size_t) size)
- {
- LL_WARNS() << "Short read on " << filename << LL_ENDL;
- }
-
- update(data, nread);
- delete[] data;
- }
- else
- {
- fclose(fp);
- }
- }
+ if (filename.empty())
+ {
+ LL_ERRS() << "No filename specified" << LL_ENDL;
+ return;
+ }
+
+ FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
+
+ if (fp)
+ {
+ fseek(fp, 0, SEEK_END);
+ long size = ftell(fp);
+
+ fseek(fp, 0, SEEK_SET);
+
+ if (size > 0)
+ {
+ U8* data = new U8[size];
+ size_t nread;
+
+ nread = fread(data, 1, size, fp);
+ fclose(fp);
+
+ if (nread < (size_t) size)
+ {
+ LL_WARNS() << "Short read on " << filename << LL_ENDL;
+ }
+
+ update(data, nread);
+ delete[] data;
+ }
+ else
+ {
+ fclose(fp);
+ }
+ }
}
#ifdef _DEBUG
BOOL LLCRC::testHarness()
{
- const S32 TEST_BUFFER_SIZE = 16;
- const char TEST_BUFFER[TEST_BUFFER_SIZE] = "hello &#$)$&Nd0"; /* Flawfinder: ignore */
- LLCRC c1, c2;
- c1.update((U8*)TEST_BUFFER, TEST_BUFFER_SIZE - 1);
- char* rh = (char*)TEST_BUFFER;
- while(*rh != '\0')
- {
- c2.update(*rh);
- ++rh;
- }
- return(c1.getCRC() == c2.getCRC());
+ const S32 TEST_BUFFER_SIZE = 16;
+ const char TEST_BUFFER[TEST_BUFFER_SIZE] = "hello &#$)$&Nd0"; /* Flawfinder: ignore */
+ LLCRC c1, c2;
+ c1.update((U8*)TEST_BUFFER, TEST_BUFFER_SIZE - 1);
+ char* rh = (char*)TEST_BUFFER;
+ while(*rh != '\0')
+ {
+ c2.update(*rh);
+ ++rh;
+ }
+ return(c1.getCRC() == c2.getCRC());
}
#endif
diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h
index 3f41b28ffa..3b48b778ff 100644
--- a/indra/llcommon/llcrc.h
+++ b/indra/llcommon/llcrc.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcrc.h
* @brief LLCRC class header file.
*
* $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$
*/
@@ -47,20 +47,20 @@
class LL_COMMON_API LLCRC
{
protected:
- U32 mCurrent;
-
+ U32 mCurrent;
+
public:
- LLCRC();
+ LLCRC();
- U32 getCRC() const;
- void update(U8 next_byte);
- void update(const U8* buffer, size_t buffer_size);
- void update(const std::string& filename);
+ U32 getCRC() const;
+ void update(U8 next_byte);
+ void update(const U8* buffer, size_t buffer_size);
+ void update(const std::string& filename);
#ifdef _DEBUG
- // This function runs tests to make sure the crc is
- // working. Returns TRUE if it is.
- static BOOL testHarness();
+ // This function runs tests to make sure the crc is
+ // working. Returns TRUE if it is.
+ static BOOL testHarness();
#endif
};
diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index 54be855f67..bb5f2b647a 100644
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcriticaldamp.cpp
* @brief Implementation of the critical damping functionality.
*
* $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$
*/
@@ -39,20 +39,20 @@ F32 LLSmoothInterpolation::sTimeDelta;
// helper functors
struct LLSmoothInterpolation::CompareTimeConstants
{
- bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const
- {
- return a < b.mTimeScale;
- }
+ bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const
+ {
+ return a < b.mTimeScale;
+ }
- bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const
- {
- return a.mTimeScale < b; // bottom of a is higher than bottom of b
- }
+ bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const
+ {
+ return a.mTimeScale < b; // bottom of a is higher than bottom of b
+ }
- bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const
- {
- return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b
- }
+ bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const
+ {
+ return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b
+ }
};
//-----------------------------------------------------------------------------
@@ -60,7 +60,7 @@ struct LLSmoothInterpolation::CompareTimeConstants
//-----------------------------------------------------------------------------
LLSmoothInterpolation::LLSmoothInterpolation()
{
- sTimeDelta = 0.f;
+ sTimeDelta = 0.f;
}
// static
@@ -69,46 +69,46 @@ LLSmoothInterpolation::LLSmoothInterpolation()
//-----------------------------------------------------------------------------
void LLSmoothInterpolation::updateInterpolants()
{
- sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32();
+ sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32();
- for (S32 i = 0; i < sInterpolants.size(); i++)
- {
- Interpolant& interp = sInterpolants[i];
- interp.mInterpolant = calcInterpolant(interp.mTimeScale);
- }
-}
+ for (S32 i = 0; i < sInterpolants.size(); i++)
+ {
+ Interpolant& interp = sInterpolants[i];
+ interp.mInterpolant = calcInterpolant(interp.mTimeScale);
+ }
+}
//-----------------------------------------------------------------------------
// getInterpolant()
//-----------------------------------------------------------------------------
F32 LLSmoothInterpolation::getInterpolant(F32SecondsImplicit time_constant, bool use_cache)
{
- if (time_constant == 0.f)
- {
- return 1.f;
- }
+ if (time_constant == 0.f)
+ {
+ return 1.f;
+ }
- if (use_cache)
- {
- interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants());
- if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant)
- {
- return find_it->mInterpolant;
- }
- else
- {
- Interpolant interp;
- interp.mTimeScale = time_constant.value();
- interp.mInterpolant = calcInterpolant(time_constant.value());
- sInterpolants.insert(find_it, interp);
- return interp.mInterpolant;
- }
- }
- else
- {
- return calcInterpolant(time_constant.value());
+ if (use_cache)
+ {
+ interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants());
+ if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant)
+ {
+ return find_it->mInterpolant;
+ }
+ else
+ {
+ Interpolant interp;
+ interp.mTimeScale = time_constant.value();
+ interp.mInterpolant = calcInterpolant(time_constant.value());
+ sInterpolants.insert(find_it, interp);
+ return interp.mInterpolant;
+ }
+ }
+ else
+ {
+ return calcInterpolant(time_constant.value());
- }
+ }
}
//-----------------------------------------------------------------------------
@@ -116,6 +116,6 @@ F32 LLSmoothInterpolation::getInterpolant(F32SecondsImplicit time_constant, bool
//-----------------------------------------------------------------------------
F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant)
{
- return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f);
+ return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f);
}
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index 1fb6a1af29..2c37d276c4 100644
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -1,26 +1,26 @@
-/**
+/**
* @file llcriticaldamp.h
* @brief A lightweight class that calculates critical damping constants once
- * per frame.
+ * per frame.
*
* $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$
*/
@@ -33,39 +33,39 @@
#include "llframetimer.h"
#include "llunits.h"
-class LL_COMMON_API LLSmoothInterpolation
+class LL_COMMON_API LLSmoothInterpolation
{
public:
- LLSmoothInterpolation();
+ LLSmoothInterpolation();
- // MANIPULATORS
- static void updateInterpolants();
+ // MANIPULATORS
+ static void updateInterpolants();
- // ACCESSORS
- static F32 getInterpolant(F32SecondsImplicit time_constant, bool use_cache = true);
+ // ACCESSORS
+ static F32 getInterpolant(F32SecondsImplicit time_constant, bool use_cache = true);
- template<typename T>
- static T lerp(T a, T b, F32SecondsImplicit time_constant, bool use_cache = true)
- {
- F32 interpolant = getInterpolant(time_constant, use_cache);
- return ((a * (1.f - interpolant))
- + (b * interpolant));
- }
+ template<typename T>
+ static T lerp(T a, T b, F32SecondsImplicit time_constant, bool use_cache = true)
+ {
+ F32 interpolant = getInterpolant(time_constant, use_cache);
+ return ((a * (1.f - interpolant))
+ + (b * interpolant));
+ }
protected:
- static F32 calcInterpolant(F32 time_constant);
+ static F32 calcInterpolant(F32 time_constant);
- struct CompareTimeConstants;
- static LLFrameTimer sInternalTimer; // frame timer for calculating deltas
+ struct CompareTimeConstants;
+ static LLFrameTimer sInternalTimer; // frame timer for calculating deltas
- struct Interpolant
- {
- F32 mTimeScale;
- F32 mInterpolant;
- };
- typedef std::vector<Interpolant> interpolant_vec_t;
- static interpolant_vec_t sInterpolants;
- static F32 sTimeDelta;
+ struct Interpolant
+ {
+ F32 mTimeScale;
+ F32 mInterpolant;
+ };
+ typedef std::vector<Interpolant> interpolant_vec_t;
+ static interpolant_vec_t sInterpolants;
+ static F32 sTimeDelta;
};
typedef LLSmoothInterpolation LLCriticalDamp;
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 2ddcf40895..c63c7012d1 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 F64 DATE_EPOCH = 0.0;
static const F64 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;
- }
-
- F64 seconds_since_epoch = time / LL_APR_USEC_PER_SEC;
-
- // check for fractional
- c = s.peek();
- if(c == '.')
- {
- F64 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;
+ }
+
+ F64 seconds_since_epoch = time / LL_APR_USEC_PER_SEC;
+
+ // check for fractional
+ c = s.peek();
+ if(c == '.')
+ {
+ F64 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;
}
F64 LLDate::secondsSinceEpoch() const
{
- return mSecondsSinceEpoch;
+ return mSecondsSinceEpoch;
}
void LLDate::secondsSinceEpoch(F64 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 be2cd2d051..81f2dd0d1c 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,110 +44,110 @@
class LL_COMMON_API LLDate
{
public:
- /**
- * @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.
- */
- F64 secondsSinceEpoch() const;
-
- /**
- * @brief Set the date in seconds since epoch.
- *
- * @param seconds The number of seconds since epoch UTC.
- */
- void secondsSinceEpoch(F64 seconds);
-
+ /**
+ * @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.
+ */
+ F64 secondsSinceEpoch() const;
+
+ /**
+ * @brief Set the date in seconds since epoch.
+ *
+ * @param seconds The number of seconds since epoch UTC.
+ */
+ void secondsSinceEpoch(F64 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:
- F64 mSecondsSinceEpoch;
+ F64 mSecondsSinceEpoch;
};
// Helper function to stream out a date
diff --git a/indra/llcommon/lldeadmantimer.cpp b/indra/llcommon/lldeadmantimer.cpp
index 830443b956..f9c14d7c24 100644
--- a/indra/llcommon/lldeadmantimer.cpp
+++ b/indra/llcommon/lldeadmantimer.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lldeadmantimer.cpp
* @brief Simple deadman-switch timer.
* @author monty@lindenlab.com
@@ -43,146 +43,146 @@
// true true Not allowed
//
LLDeadmanTimer::LLDeadmanTimer(F64 horizon, bool inc_cpu)
- : mHorizon(time_type(llmax(horizon, F64(0.0)) * get_timer_info().mClockFrequency)),
- mActive(false), // If true, a timer is running.
- mDone(false), // If true, timer has completed and can be read (once)
- mStarted(U64L(0)),
- mExpires(U64L(0)),
- mStopped(U64L(0)),
- mCount(U64L(0)),
- mIncCPU(inc_cpu),
- mUStartCPU(LLProcInfo::time_type(U64L(0))),
- mUEndCPU(LLProcInfo::time_type(U64L(0))),
- mSStartCPU(LLProcInfo::time_type(U64L(0))),
- mSEndCPU(LLProcInfo::time_type(U64L(0)))
+ : mHorizon(time_type(llmax(horizon, F64(0.0)) * get_timer_info().mClockFrequency)),
+ mActive(false), // If true, a timer is running.
+ mDone(false), // If true, timer has completed and can be read (once)
+ mStarted(U64L(0)),
+ mExpires(U64L(0)),
+ mStopped(U64L(0)),
+ mCount(U64L(0)),
+ mIncCPU(inc_cpu),
+ mUStartCPU(LLProcInfo::time_type(U64L(0))),
+ mUEndCPU(LLProcInfo::time_type(U64L(0))),
+ mSStartCPU(LLProcInfo::time_type(U64L(0))),
+ mSEndCPU(LLProcInfo::time_type(U64L(0)))
{}
// static
LLDeadmanTimer::time_type LLDeadmanTimer::getNow()
{
- return LLTimer::getCurrentClockCount();
+ return LLTimer::getCurrentClockCount();
}
void LLDeadmanTimer::start(time_type now)
{
- // *TODO: If active, let's complete an existing timer and save
- // the result to the side. I think this will be useful later.
- // For now, wipe out anything in progress, start fresh.
-
- if (! now)
- {
- now = LLTimer::getCurrentClockCount();
- }
- mActive = true;
- mDone = false;
- mStarted = now;
- mExpires = now + mHorizon;
- mStopped = now;
- mCount = U64L(0);
- if (mIncCPU)
- {
- LLProcInfo::getCPUUsage(mUStartCPU, mSStartCPU);
- }
+ // *TODO: If active, let's complete an existing timer and save
+ // the result to the side. I think this will be useful later.
+ // For now, wipe out anything in progress, start fresh.
+
+ if (! now)
+ {
+ now = LLTimer::getCurrentClockCount();
+ }
+ mActive = true;
+ mDone = false;
+ mStarted = now;
+ mExpires = now + mHorizon;
+ mStopped = now;
+ mCount = U64L(0);
+ if (mIncCPU)
+ {
+ LLProcInfo::getCPUUsage(mUStartCPU, mSStartCPU);
+ }
}
void LLDeadmanTimer::stop(time_type now)
{
- if (! mActive)
- {
- return;
- }
-
- if (! now)
- {
- now = getNow();
- }
- mStopped = now;
- mActive = false;
- mDone = true;
- if (mIncCPU)
- {
- LLProcInfo::getCPUUsage(mUEndCPU, mSEndCPU);
- }
+ if (! mActive)
+ {
+ return;
+ }
+
+ if (! now)
+ {
+ now = getNow();
+ }
+ mStopped = now;
+ mActive = false;
+ mDone = true;
+ if (mIncCPU)
+ {
+ LLProcInfo::getCPUUsage(mUEndCPU, mSEndCPU);
+ }
}
bool LLDeadmanTimer::isExpired(time_type now, F64 & started, F64 & stopped, U64 & count,
- U64 & user_cpu, U64 & sys_cpu)
+ U64 & user_cpu, U64 & sys_cpu)
{
- const bool status(isExpired(now, started, stopped, count));
- if (status)
- {
- user_cpu = U64(mUEndCPU - mUStartCPU);
- sys_cpu = U64(mSEndCPU - mSStartCPU);
- }
- return status;
+ const bool status(isExpired(now, started, stopped, count));
+ if (status)
+ {
+ user_cpu = U64(mUEndCPU - mUStartCPU);
+ sys_cpu = U64(mSEndCPU - mSStartCPU);
+ }
+ return status;
}
-
+
bool LLDeadmanTimer::isExpired(time_type now, F64 & started, F64 & stopped, U64 & count)
{
- if (mActive && ! mDone)
- {
- if (! now)
- {
- now = getNow();
- }
-
- if (now >= mExpires)
- {
- // mStopped from ringBell() is the value we want
- mActive = false;
- mDone = true;
- }
- }
-
- if (! mDone)
- {
- return false;
- }
-
- started = mStarted * get_timer_info().mClockFrequencyInv;
- stopped = mStopped * get_timer_info().mClockFrequencyInv;
- count = mCount;
- mDone = false;
-
- return true;
+ if (mActive && ! mDone)
+ {
+ if (! now)
+ {
+ now = getNow();
+ }
+
+ if (now >= mExpires)
+ {
+ // mStopped from ringBell() is the value we want
+ mActive = false;
+ mDone = true;
+ }
+ }
+
+ if (! mDone)
+ {
+ return false;
+ }
+
+ started = mStarted * get_timer_info().mClockFrequencyInv;
+ stopped = mStopped * get_timer_info().mClockFrequencyInv;
+ count = mCount;
+ mDone = false;
+
+ return true;
}
-
+
void LLDeadmanTimer::ringBell(time_type now, unsigned int count)
{
- if (! mActive)
- {
- return;
- }
-
- if (! now)
- {
- now = getNow();
- }
-
- if (now >= mExpires)
- {
- // Timer has expired, this event will be dropped
- mActive = false;
- mDone = true;
- }
- else
- {
- // Timer renewed, keep going
- mStopped = now;
- mExpires = now + mHorizon;
- mCount += count;
- if (mIncCPU)
- {
- LLProcInfo::getCPUUsage(mUEndCPU, mSEndCPU);
- }
- }
-
- return;
+ if (! mActive)
+ {
+ return;
+ }
+
+ if (! now)
+ {
+ now = getNow();
+ }
+
+ if (now >= mExpires)
+ {
+ // Timer has expired, this event will be dropped
+ mActive = false;
+ mDone = true;
+ }
+ else
+ {
+ // Timer renewed, keep going
+ mStopped = now;
+ mExpires = now + mHorizon;
+ mCount += count;
+ if (mIncCPU)
+ {
+ LLProcInfo::getCPUUsage(mUEndCPU, mSEndCPU);
+ }
+ }
+
+ return;
}
diff --git a/indra/llcommon/lldeadmantimer.h b/indra/llcommon/lldeadmantimer.h
index 980976e176..3f10420d41 100644
--- a/indra/llcommon/lldeadmantimer.h
+++ b/indra/llcommon/lldeadmantimer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lldeadmantimer.h
* @brief Interface to a simple event timer with a deadman's switch
* @author monty@lindenlab.com
@@ -25,8 +25,8 @@
* $/LicenseInfo$
*/
-#ifndef LL_DEADMANTIMER_H
-#define LL_DEADMANTIMER_H
+#ifndef LL_DEADMANTIMER_H
+#define LL_DEADMANTIMER_H
#include "linden_common.h"
@@ -78,137 +78,137 @@
class LL_COMMON_API LLDeadmanTimer
{
public:
- /// Public types
-
- /// Low-level time type chosen for compatibility with
- /// LLTimer::getCurrentClockCount() which is the basis
- /// of time operations in this class. This is likely
- /// to change in a future version in a move to TSC-based
- /// timing.
- typedef U64 time_type;
-
+ /// Public types
+
+ /// Low-level time type chosen for compatibility with
+ /// LLTimer::getCurrentClockCount() which is the basis
+ /// of time operations in this class. This is likely
+ /// to change in a future version in a move to TSC-based
+ /// timing.
+ typedef U64 time_type;
+
public:
- /// Construct and initialize an LLDeadmanTimer
- ///
- /// @param horizon Time, in seconds, after the last @see ringBell()
- /// call at which point the timer will consider itself
- /// expired.
- ///
- /// @param inc_cpu If true, gather system and user cpu stats while
- /// running the timer. This does require more syscalls
- /// during updates. If false, cpu usage data isn't
- /// collected and will be zero if queried.
- LLDeadmanTimer(F64 horizon, bool inc_cpu);
-
- ~LLDeadmanTimer()
- {}
-
+ /// Construct and initialize an LLDeadmanTimer
+ ///
+ /// @param horizon Time, in seconds, after the last @see ringBell()
+ /// call at which point the timer will consider itself
+ /// expired.
+ ///
+ /// @param inc_cpu If true, gather system and user cpu stats while
+ /// running the timer. This does require more syscalls
+ /// during updates. If false, cpu usage data isn't
+ /// collected and will be zero if queried.
+ LLDeadmanTimer(F64 horizon, bool inc_cpu);
+
+ ~LLDeadmanTimer()
+ {}
+
private:
- LLDeadmanTimer(const LLDeadmanTimer &); // Not defined
- void operator=(const LLDeadmanTimer &); // Not defined
+ LLDeadmanTimer(const LLDeadmanTimer &); // Not defined
+ void operator=(const LLDeadmanTimer &); // Not defined
public:
- /// Get the current time. Zero-basis for this time
- /// representation is not defined and is different on
- /// different platforms. Do not attempt to compute
- /// negative times relative to the first value returned,
- /// there may not be enough 'front porch' on the range
- /// to prevent wraparound.
- ///
- /// Note: Implementation is expected to change in a
- /// future release as well.
- ///
- static time_type getNow();
-
- /// Begin timing. If the timer is already active, it is reset
- /// and timing begins now.
- ///
- /// @param now Current time as returned by @see
- /// LLTimer::getCurrentClockCount(). If zero,
- /// method will lookup current time.
- ///
- void start(time_type now);
-
- /// End timing. Actively declare the end of the event independent
- /// of the deadman's switch operation. @see isExpired() will return
- /// true and appropriate values will be returned.
- ///
- /// @param now Current time as returned by @see
- /// LLTimer::getCurrentClockCount(). If zero,
- /// method will lookup current time.
- ///
- void stop(time_type now);
-
- /// Declare that something interesting happened. This has two
- /// effects on an unexpired-timer. 1) The expiration time
- /// is extended for 'horizon' seconds after the 'now' value.
- /// 2) An internal counter associated with the event is incremented
- /// by the @ref count parameter. This count is returned via the
- /// @see isExpired() method.
- ///
- /// @param now Current time as returned by @see
- /// LLTimer::getCurrentClockCount(). If zero,
- /// method will lookup current time.
- ///
- /// @param count Count of events to be associated with
- /// this bell ringing.
- ///
- void ringBell(time_type now, unsigned int count);
-
- /// Checks the status of the timer. If the timer has expired,
- /// also returns various timer-related stats. Unlike ringBell(),
- /// does not extend the horizon, it only checks for expiration.
- ///
- /// @param now Current time as returned by @see
- /// LLTimer::getCurrentClockCount(). If zero,
- /// method will lookup current time.
- ///
- /// @param started If expired, the starting time of the event is
- /// returned to the caller via this reference.
- ///
- /// @param stopped If expired, the ending time of the event is
- /// returned to the caller via this reference.
- /// Ending time will be that provided in the
- /// stop() method or the last ringBell() call
- /// leading to expiration, whichever (stop() call
- /// or notice of expiration) happened first.
- ///
- /// @param count If expired, the number of ringBell() calls
- /// made prior to expiration.
- ///
- /// @param user_cpu Amount of CPU spent in user mode by the process
- /// during the event. Value in microseconds and will
- /// read zero if not enabled by the constructor.
- ///
- /// @param sys_cpu Amount of CPU spent in system mode by the process.
- ///
- /// @return true if the timer has expired, false otherwise.
- /// If true, it also returns the started,
- /// stopped and count values otherwise these are
- /// left unchanged.
- ///
- bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count,
- U64 & user_cpu, U64 & sys_cpu);
-
- /// Identical to the six-arugment form except it does without the
- /// CPU time return if the caller isn't interested in it.
- bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count);
+ /// Get the current time. Zero-basis for this time
+ /// representation is not defined and is different on
+ /// different platforms. Do not attempt to compute
+ /// negative times relative to the first value returned,
+ /// there may not be enough 'front porch' on the range
+ /// to prevent wraparound.
+ ///
+ /// Note: Implementation is expected to change in a
+ /// future release as well.
+ ///
+ static time_type getNow();
+
+ /// Begin timing. If the timer is already active, it is reset
+ /// and timing begins now.
+ ///
+ /// @param now Current time as returned by @see
+ /// LLTimer::getCurrentClockCount(). If zero,
+ /// method will lookup current time.
+ ///
+ void start(time_type now);
+
+ /// End timing. Actively declare the end of the event independent
+ /// of the deadman's switch operation. @see isExpired() will return
+ /// true and appropriate values will be returned.
+ ///
+ /// @param now Current time as returned by @see
+ /// LLTimer::getCurrentClockCount(). If zero,
+ /// method will lookup current time.
+ ///
+ void stop(time_type now);
+
+ /// Declare that something interesting happened. This has two
+ /// effects on an unexpired-timer. 1) The expiration time
+ /// is extended for 'horizon' seconds after the 'now' value.
+ /// 2) An internal counter associated with the event is incremented
+ /// by the @ref count parameter. This count is returned via the
+ /// @see isExpired() method.
+ ///
+ /// @param now Current time as returned by @see
+ /// LLTimer::getCurrentClockCount(). If zero,
+ /// method will lookup current time.
+ ///
+ /// @param count Count of events to be associated with
+ /// this bell ringing.
+ ///
+ void ringBell(time_type now, unsigned int count);
+
+ /// Checks the status of the timer. If the timer has expired,
+ /// also returns various timer-related stats. Unlike ringBell(),
+ /// does not extend the horizon, it only checks for expiration.
+ ///
+ /// @param now Current time as returned by @see
+ /// LLTimer::getCurrentClockCount(). If zero,
+ /// method will lookup current time.
+ ///
+ /// @param started If expired, the starting time of the event is
+ /// returned to the caller via this reference.
+ ///
+ /// @param stopped If expired, the ending time of the event is
+ /// returned to the caller via this reference.
+ /// Ending time will be that provided in the
+ /// stop() method or the last ringBell() call
+ /// leading to expiration, whichever (stop() call
+ /// or notice of expiration) happened first.
+ ///
+ /// @param count If expired, the number of ringBell() calls
+ /// made prior to expiration.
+ ///
+ /// @param user_cpu Amount of CPU spent in user mode by the process
+ /// during the event. Value in microseconds and will
+ /// read zero if not enabled by the constructor.
+ ///
+ /// @param sys_cpu Amount of CPU spent in system mode by the process.
+ ///
+ /// @return true if the timer has expired, false otherwise.
+ /// If true, it also returns the started,
+ /// stopped and count values otherwise these are
+ /// left unchanged.
+ ///
+ bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count,
+ U64 & user_cpu, U64 & sys_cpu);
+
+ /// Identical to the six-arugment form except it does without the
+ /// CPU time return if the caller isn't interested in it.
+ bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count);
protected:
- time_type mHorizon;
- bool mActive;
- bool mDone;
- time_type mStarted;
- time_type mExpires;
- time_type mStopped;
- time_type mCount;
-
- const bool mIncCPU; // Include CPU metrics in timer
- LLProcInfo::time_type mUStartCPU;
- LLProcInfo::time_type mUEndCPU;
- LLProcInfo::time_type mSStartCPU;
- LLProcInfo::time_type mSEndCPU;
+ time_type mHorizon;
+ bool mActive;
+ bool mDone;
+ time_type mStarted;
+ time_type mExpires;
+ time_type mStopped;
+ time_type mCount;
+
+ const bool mIncCPU; // Include CPU metrics in timer
+ LLProcInfo::time_type mUStartCPU;
+ LLProcInfo::time_type mUEndCPU;
+ LLProcInfo::time_type mSStartCPU;
+ LLProcInfo::time_type mSEndCPU;
};
-
-#endif // LL_DEADMANTIMER_H
+
+#endif // LL_DEADMANTIMER_H
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 4e25001fff..0ba756d472 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldefs.h
* @brief Various generic constant definitions.
*
* $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$
*/
@@ -31,73 +31,73 @@
#include <type_traits>
// Often used array indices
-const U32 VX = 0;
-const U32 VY = 1;
-const U32 VZ = 2;
-const U32 VW = 3;
-const U32 VS = 3;
-
-const U32 VRED = 0;
-const U32 VGREEN = 1;
-const U32 VBLUE = 2;
-const U32 VALPHA = 3;
-
-const U32 INVALID_DIRECTION = 0xFFFFFFFF;
-const U32 EAST = 0;
-const U32 NORTH = 1;
-const U32 WEST = 2;
-const U32 SOUTH = 3;
-
-const U32 NORTHEAST = 4;
-const U32 NORTHWEST = 5;
-const U32 SOUTHWEST = 6;
-const U32 SOUTHEAST = 7;
-const U32 MIDDLE = 8;
-
-const U8 EAST_MASK = 0x1<<EAST;
-const U8 NORTH_MASK = 0x1<<NORTH;
-const U8 WEST_MASK = 0x1<<WEST;
-const U8 SOUTH_MASK = 0x1<<SOUTH;
-
-const U8 NORTHEAST_MASK = NORTH_MASK | EAST_MASK;
-const U8 NORTHWEST_MASK = NORTH_MASK | WEST_MASK;
-const U8 SOUTHWEST_MASK = SOUTH_MASK | WEST_MASK;
-const U8 SOUTHEAST_MASK = SOUTH_MASK | EAST_MASK;
+const U32 VX = 0;
+const U32 VY = 1;
+const U32 VZ = 2;
+const U32 VW = 3;
+const U32 VS = 3;
+
+const U32 VRED = 0;
+const U32 VGREEN = 1;
+const U32 VBLUE = 2;
+const U32 VALPHA = 3;
+
+const U32 INVALID_DIRECTION = 0xFFFFFFFF;
+const U32 EAST = 0;
+const U32 NORTH = 1;
+const U32 WEST = 2;
+const U32 SOUTH = 3;
+
+const U32 NORTHEAST = 4;
+const U32 NORTHWEST = 5;
+const U32 SOUTHWEST = 6;
+const U32 SOUTHEAST = 7;
+const U32 MIDDLE = 8;
+
+const U8 EAST_MASK = 0x1<<EAST;
+const U8 NORTH_MASK = 0x1<<NORTH;
+const U8 WEST_MASK = 0x1<<WEST;
+const U8 SOUTH_MASK = 0x1<<SOUTH;
+
+const U8 NORTHEAST_MASK = NORTH_MASK | EAST_MASK;
+const U8 NORTHWEST_MASK = NORTH_MASK | WEST_MASK;
+const U8 SOUTHWEST_MASK = SOUTH_MASK | WEST_MASK;
+const U8 SOUTHEAST_MASK = SOUTH_MASK | EAST_MASK;
const U32 gDirOpposite[8] = {2, 3, 0, 1, 6, 7, 4, 5};
const U32 gDirAdjacent[8][2] = {
- {4, 7},
- {4, 5},
- {5, 6},
- {6, 7},
- {0, 1},
- {1, 2},
- {2, 3},
- {0, 3}
- };
+ {4, 7},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {0, 3}
+ };
// Magnitude along the x and y axis
const S32 gDirAxes[8][2] = {
- { 1, 0}, // east
- { 0, 1}, // north
- {-1, 0}, // west
- { 0,-1}, // south
- { 1, 1}, // ne
- {-1, 1}, // nw
- {-1,-1}, // sw
- { 1,-1}, // se
- };
-
-const S32 gDirMasks[8] = {
- EAST_MASK,
- NORTH_MASK,
- WEST_MASK,
- SOUTH_MASK,
- NORTHEAST_MASK,
- NORTHWEST_MASK,
- SOUTHWEST_MASK,
- SOUTHEAST_MASK
- };
+ { 1, 0}, // east
+ { 0, 1}, // north
+ {-1, 0}, // west
+ { 0,-1}, // south
+ { 1, 1}, // ne
+ {-1, 1}, // nw
+ {-1,-1}, // sw
+ { 1,-1}, // se
+ };
+
+const S32 gDirMasks[8] = {
+ EAST_MASK,
+ NORTH_MASK,
+ WEST_MASK,
+ SOUTH_MASK,
+ NORTHEAST_MASK,
+ NORTHWEST_MASK,
+ SOUTHWEST_MASK,
+ SOUTHEAST_MASK
+ };
// Sides of a box...
// . Z __.Y
@@ -109,21 +109,21 @@ const S32 gDirMasks[8] = {
// / | /| -3- / | 5 = TOP_SIDE = +z
// +------------------+ | 6 = BOTTOM_SIDE = -z
// | | | / | |
-// | |/| | / | |/|
-// | 2 | | *-------|-1--------> X
-// |/| | -4- |/| |
+// | |/| | / | |/|
+// | 2 | | *-------|-1--------> X
+// |/| | -4- |/| |
// | +----|---------|---+
// | / / | /
// | / -6- | /
-// |/ / |/
+// |/ / |/
// +------------------+
-const U32 NO_SIDE = 0;
-const U32 FRONT_SIDE = 1;
-const U32 BACK_SIDE = 2;
-const U32 LEFT_SIDE = 3;
-const U32 RIGHT_SIDE = 4;
-const U32 TOP_SIDE = 5;
-const U32 BOTTOM_SIDE = 6;
+const U32 NO_SIDE = 0;
+const U32 FRONT_SIDE = 1;
+const U32 BACK_SIDE = 2;
+const U32 LEFT_SIDE = 3;
+const U32 RIGHT_SIDE = 4;
+const U32 TOP_SIDE = 5;
+const U32 BOTTOM_SIDE = 6;
const U8 LL_SOUND_FLAG_NONE = 0x0;
const U8 LL_SOUND_FLAG_LOOP = 1<<0;
@@ -141,17 +141,17 @@ const U8 LL_SOUND_FLAG_SYNC_MASK = LL_SOUND_FLAG_SYNC_MASTER | LL_SOUND_FLAG_SYN
// DO NOT CHANGE.
// --------------
//
-const U32 LL_MAX_PATH = 1024; // buffer size of maximum path + filename string length
+const U32 LL_MAX_PATH = 1024; // buffer size of maximum path + filename string length
// For strings we send in messages
-const U32 STD_STRING_BUF_SIZE = 255; // Buffer size
-const U32 STD_STRING_STR_LEN = 254; // Length of the string (not including \0)
+const U32 STD_STRING_BUF_SIZE = 255; // Buffer size
+const U32 STD_STRING_STR_LEN = 254; // Length of the string (not including \0)
// *NOTE: This value is used as hard-coded numbers in scanf() variants.
// DO NOT CHANGE.
-const U32 MAX_STRING = STD_STRING_BUF_SIZE; // Buffer size
+const U32 MAX_STRING = STD_STRING_BUF_SIZE; // Buffer size
-const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luck
+const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luck
// C++ is our friend. . . use template functions to make life easier!
@@ -176,7 +176,7 @@ inline auto llmax(T data)
return data;
}
-template <typename T0, typename T1, typename... Ts>
+template <typename T0, typename T1, typename... Ts>
inline auto llmax(T0 d0, T1 d1, Ts... rest)
{
auto maxrest = llmax(d1, rest...);
@@ -190,44 +190,44 @@ inline auto llmin(T data)
return data;
}
-template <typename T0, typename T1, typename... Ts>
+template <typename T0, typename T1, typename... Ts>
inline auto llmin(T0 d0, T1 d1, Ts... rest)
{
auto minrest = llmin(d1, rest...);
return (d0 < minrest) ? d0 : minrest;
}
-template <typename A, typename MIN, typename MAX>
+template <typename A, typename MIN, typename MAX>
inline A llclamp(A a, MIN minval, MAX maxval)
{
- A aminval{ static_cast<A>(minval) }, amaxval{ static_cast<A>(maxval) };
- if ( a < aminval )
- {
- return aminval;
- }
- else if ( a > amaxval )
- {
- return amaxval;
- }
- return a;
+ A aminval{ static_cast<A>(minval) }, amaxval{ static_cast<A>(maxval) };
+ if ( a < aminval )
+ {
+ return aminval;
+ }
+ else if ( a > amaxval )
+ {
+ return amaxval;
+ }
+ return a;
}
-template <class LLDATATYPE>
+template <class LLDATATYPE>
inline LLDATATYPE llclampf(LLDATATYPE a)
{
- return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
+ return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
}
-template <class LLDATATYPE>
+template <class LLDATATYPE>
inline LLDATATYPE llclampb(LLDATATYPE a)
{
- return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
+ return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
}
-template <class LLDATATYPE>
+template <class LLDATATYPE>
inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs)
{
- std::swap(lhs, rhs);
+ std::swap(lhs, rhs);
}
#endif // LL_LLDEFS_H
diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp
index db546c5c3b..dec0748374 100644
--- a/indra/llcommon/lldependencies.cpp
+++ b/indra/llcommon/lldependencies.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-09-17
* @brief Implementation for lldependencies.
- *
+ *
* $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$
*/
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
index 950af4a4ad..47b6fedc7d 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$
*/
@@ -177,7 +177,7 @@ struct LLDependenciesEmpty
* values such as NULL or 0 rather than having to write
* LLDependenciesEmpty().
*/
- LLDependenciesEmpty(void*) {}
+ LLDependenciesEmpty(void*) {}
};
/**
@@ -209,7 +209,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;
@@ -239,7 +239,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
@@ -598,7 +598,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/lldepthstack.h b/indra/llcommon/lldepthstack.h
index b65840d342..66a7a4ce15 100644
--- a/indra/llcommon/lldepthstack.h
+++ b/indra/llcommon/lldepthstack.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldepthstack.h
* @brief Declaration of the LLDepthStack 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$
*/
@@ -32,65 +32,65 @@
template <class DATA_TYPE> class LLDepthStack
{
private:
- std::deque<DATA_TYPE*> mStack;
- U32 mCurrentDepth;
- U32 mMaxDepth;
+ std::deque<DATA_TYPE*> mStack;
+ U32 mCurrentDepth;
+ U32 mMaxDepth;
public:
- LLDepthStack()
- : mCurrentDepth(0), mMaxDepth(0)
- {}
+ LLDepthStack()
+ : mCurrentDepth(0), mMaxDepth(0)
+ {}
+
+ void setDepth(U32 depth)
+ {
+ mMaxDepth = depth;
+ }
+
+ U32 getDepth(void) const
+ {
+ return mCurrentDepth;
+ }
- void setDepth(U32 depth)
- {
- mMaxDepth = depth;
- }
+ void push(DATA_TYPE *data)
+ {
+ if (mCurrentDepth < mMaxDepth)
+ {
+ mStack.push_back(data);
+ mCurrentDepth++;
+ }
+ else
+ {
+ // the last item falls off stack and is deleted
+ if (!mStack.empty())
+ {
+ mStack.pop_front();
+ }
+ mStack.push_back(data);
+ }
+ }
- U32 getDepth(void) const
- {
- return mCurrentDepth;
- }
+ DATA_TYPE *pop()
+ {
+ DATA_TYPE *tempp = NULL;
+ if (!mStack.empty())
+ {
+ tempp = mStack.back();
+ mStack.pop_back();
+ mCurrentDepth--;
+ }
+ return tempp;
+ }
- void push(DATA_TYPE *data)
- {
- if (mCurrentDepth < mMaxDepth)
- {
- mStack.push_back(data);
- mCurrentDepth++;
- }
- else
- {
- // the last item falls off stack and is deleted
- if (!mStack.empty())
- {
- mStack.pop_front();
- }
- mStack.push_back(data);
- }
- }
-
- DATA_TYPE *pop()
- {
- DATA_TYPE *tempp = NULL;
- if (!mStack.empty())
- {
- tempp = mStack.back();
- mStack.pop_back();
- mCurrentDepth--;
- }
- return tempp;
- }
-
- DATA_TYPE *check()
- {
- return mStack.empty() ? NULL : mStack.back();
- }
+ DATA_TYPE *check()
+ {
+ return mStack.empty() ? NULL : mStack.back();
+ }
- void removeAllNodes()
- {
- mCurrentDepth = 0;
- mStack.clear();
- }
+ void removeAllNodes()
+ {
+ mCurrentDepth = 0;
+ mStack.clear();
+ }
};
#endif
diff --git a/indra/llcommon/lldictionary.cpp b/indra/llcommon/lldictionary.cpp
index e16c35ed6a..1970aa58f2 100644
--- a/indra/llcommon/lldictionary.cpp
+++ b/indra/llcommon/lldictionary.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldictionary.cpp
* @brief Lldictionary class header file
*
* $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$
*/
@@ -32,16 +32,16 @@
// Define in .cpp file to prevent header include of llstring.h
LLDictionaryEntry::LLDictionaryEntry(const std::string &name)
-: mName(name)
+: mName(name)
{
- mNameCapitalized = mName;
- LLStringUtil::replaceChar(mNameCapitalized, '-', ' ');
- LLStringUtil::replaceChar(mNameCapitalized, '_', ' ');
- for (U32 i=0; i < mNameCapitalized.size(); i++)
- {
- if (i == 0 || mNameCapitalized[i-1] == ' ') // don't change ordering of this statement or crash
- {
- mNameCapitalized[i] = toupper(mNameCapitalized[i]);
- }
- }
+ mNameCapitalized = mName;
+ LLStringUtil::replaceChar(mNameCapitalized, '-', ' ');
+ LLStringUtil::replaceChar(mNameCapitalized, '_', ' ');
+ for (U32 i=0; i < mNameCapitalized.size(); i++)
+ {
+ if (i == 0 || mNameCapitalized[i-1] == ' ') // don't change ordering of this statement or crash
+ {
+ mNameCapitalized[i] = toupper(mNameCapitalized[i]);
+ }
+ }
}
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
index 18664e340e..9c399057ae 100644
--- a/indra/llcommon/lldictionary.h
+++ b/indra/llcommon/lldictionary.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldictionary.h
* @brief Lldictionary class header file
*
* $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$
*/
@@ -34,64 +34,64 @@
struct LL_COMMON_API LLDictionaryEntry
{
- LLDictionaryEntry(const std::string &name);
- virtual ~LLDictionaryEntry() {}
- const std::string mName;
- std::string mNameCapitalized;
+ LLDictionaryEntry(const std::string &name);
+ virtual ~LLDictionaryEntry() {}
+ const std::string mName;
+ std::string mNameCapitalized;
};
template <class Index, class Entry>
class LLDictionary : public std::map<Index, Entry *>
{
public:
- typedef std::map<Index, Entry *> map_t;
- typedef typename map_t::iterator iterator_t;
- typedef typename map_t::const_iterator const_iterator_t;
-
- LLDictionary() {}
- virtual ~LLDictionary()
- {
- for (iterator_t iter = map_t::begin(); iter != map_t::end(); ++iter)
- delete (iter->second);
- }
+ typedef std::map<Index, Entry *> map_t;
+ typedef typename map_t::iterator iterator_t;
+ typedef typename map_t::const_iterator const_iterator_t;
+
+ LLDictionary() {}
+ virtual ~LLDictionary()
+ {
+ for (iterator_t iter = map_t::begin(); iter != map_t::end(); ++iter)
+ delete (iter->second);
+ }
- const Entry *lookup(Index index) const
- {
- const_iterator_t dictionary_iter = map_t::find(index);
- if (dictionary_iter == map_t::end()) return NULL;
- return dictionary_iter->second;
- }
- const Index lookup(const std::string &name) const
- {
- for (const_iterator_t dictionary_iter = map_t::begin();
- dictionary_iter != map_t::end();
- dictionary_iter++)
- {
- const Entry *entry = dictionary_iter->second;
- if (entry->mName == name)
- {
- return dictionary_iter->first;
- }
- }
- return notFound();
- }
+ const Entry *lookup(Index index) const
+ {
+ const_iterator_t dictionary_iter = map_t::find(index);
+ if (dictionary_iter == map_t::end()) return NULL;
+ return dictionary_iter->second;
+ }
+ const Index lookup(const std::string &name) const
+ {
+ for (const_iterator_t dictionary_iter = map_t::begin();
+ dictionary_iter != map_t::end();
+ dictionary_iter++)
+ {
+ const Entry *entry = dictionary_iter->second;
+ if (entry->mName == name)
+ {
+ return dictionary_iter->first;
+ }
+ }
+ return notFound();
+ }
protected:
- virtual Index notFound() const
- {
- // default is to assert
- // don't assert -- makes it impossible to work on mesh-development and viewer-development simultaneously
- // -- davep 2010.10.29
- //llassert(false);
- return Index(-1);
- }
- void addEntry(Index index, Entry *entry)
- {
- if (!this->emplace(index, entry).second)
- {
- LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL;
- }
- }
+ virtual Index notFound() const
+ {
+ // default is to assert
+ // don't assert -- makes it impossible to work on mesh-development and viewer-development simultaneously
+ // -- davep 2010.10.29
+ //llassert(false);
+ return Index(-1);
+ }
+ void addEntry(Index index, Entry *entry)
+ {
+ if (!this->emplace(index, entry).second)
+ {
+ LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL;
+ }
+ }
};
#endif // LL_LLDICTIONARY_H
diff --git a/indra/llcommon/lldoubledispatch.h b/indra/llcommon/lldoubledispatch.h
index ce6731e864..c8c566205a 100644
--- a/indra/llcommon/lldoubledispatch.h
+++ b/indra/llcommon/lldoubledispatch.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-11-11
* @brief function calls virtual on more than one parameter
- *
+ *
* $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$
*/
@@ -41,7 +41,7 @@
* subset of that problem: function calls which accept two parameters, and
* select which particular function to call depending on the dynamic type of
* both.
- *
+ *
* Scott Meyers, in More Effective C++ (Item 31), talks about some of the perils
* and pitfalls lurking down this pathway. He discusses and dismisses the
* straightforward approaches of using single-dispatch virtual functions twice,
@@ -50,17 +50,17 @@
* look up the actual types of both parameters (he uses the classes' string names,
* via typeid(param).name()) to obtain a pointer to a free (non-member) function
* that will accept this pair of parameters.
- *
+ *
* He does point out that his approach doesn't handle inheritance. If you have a
* registry entry for SpaceShip, and you have in hand a MilitaryShip (subclass of
* SpaceShip) and an Asteroid, you'd like to call the function appropriate for
* SpaceShips and Asteroids -- but alas, his lookup fails because the class name
* for your MilitaryShip subclass isn't in the registry.
- *
+ *
* This class extends his idea to build a registry whose entries can examine the
* dynamic type of the parameter in a more flexible way -- using dynamic_cast<>
* -- thereby supporting inheritance relationships.
- *
+ *
* Of course we must allow for the ambiguity this permits. We choose to use a
* sequence container rather than a map, and require that the client code
* specify the order in which dispatch-table entries should be searched. The
@@ -69,7 +69,7 @@
* you catch ErrorBaseClass before you catch ErrorSubclass, then any
* ErrorSubclass exceptions thrown by the protected code will always match
* ErrorBaseClass, and you will never reach your catch(ErrorSubclass) clause.
- *
+ *
* So, in a similar way, if you have a specific routine to process
* MilitaryShip and Asteroid, you'd better place that in the table @em before
* your more general routine that processes SpaceShip and Asteroid, or else
@@ -279,7 +279,7 @@ private:
/// Look up the first matching entry.
EntryPtr lookup(const ParamBaseType& param1, const ParamBaseType& param2) const
{
- typename DispatchTable::const_iterator found = find(param1, param2);
+ typename DispatchTable::const_iterator found = find(param1, param2);
if (found != mDispatch.end())
{
// Dereferencing the list iterator gets us an EntryPtr
diff --git a/indra/llcommon/llendianswizzle.h b/indra/llcommon/llendianswizzle.h
index 4c08074a9c..d56eb7be2e 100644
--- a/indra/llcommon/llendianswizzle.h
+++ b/indra/llcommon/llendianswizzle.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llendianswizzle.h
* @brief Functions for in-place bit swizzling
*
* $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$
*/
@@ -28,63 +28,63 @@
#define LL_LLENDIANSWIZZLE_H
/* This function is intended to be used for in-place swizzling, particularly after fread() of
- binary values from a file. Such as:
-
- numRead = fread(scale.mV, sizeof(float), 3, fp);
- llendianswizzle(scale.mV, sizeof(float), 3);
-
- It assumes that the values in the file are LITTLE endian, so it's a no-op on a little endian machine.
-
- It keys off of typesize to do the correct swizzle, so make sure that typesize is the size of the native type.
-
- 64-bit types are not yet handled.
+ binary values from a file. Such as:
+
+ numRead = fread(scale.mV, sizeof(float), 3, fp);
+ llendianswizzle(scale.mV, sizeof(float), 3);
+
+ It assumes that the values in the file are LITTLE endian, so it's a no-op on a little endian machine.
+
+ It keys off of typesize to do the correct swizzle, so make sure that typesize is the size of the native type.
+
+ 64-bit types are not yet handled.
*/
#ifdef LL_LITTLE_ENDIAN
- // little endian is native for most things.
- inline void llendianswizzle(void *,int,int)
- {
- // Nothing to do
- }
+ // little endian is native for most things.
+ inline void llendianswizzle(void *,int,int)
+ {
+ // Nothing to do
+ }
#endif
#ifdef LL_BIG_ENDIAN
- // big endian requires a bit of work.
- inline void llendianswizzle(void *p,int typesize, int count)
- {
- int i;
- switch(typesize)
- {
- case 2:
- {
- U16 temp;
- for(i=count ;i!=0 ;i--)
- {
- temp = ((U16*)p)[0];
- ((U16*)p)[0] = ((temp >> 8) & 0x000000FF) | ((temp << 8) & 0x0000FF00);
- p = (void*)(((U16*)p) + 1);
- }
- }
- break;
-
- case 4:
- {
- U32 temp;
- for(i=count; i!=0; i--)
- {
- temp = ((U32*)p)[0];
- ((U32*)p)[0] =
- ((temp >> 24) & 0x000000FF) |
- ((temp >> 8) & 0x0000FF00) |
- ((temp << 8) & 0x00FF0000) |
- ((temp << 24) & 0xFF000000);
- p = (void*)(((U32*)p) + 1);
- }
- }
- break;
- }
-
- }
+ // big endian requires a bit of work.
+ inline void llendianswizzle(void *p,int typesize, int count)
+ {
+ int i;
+ switch(typesize)
+ {
+ case 2:
+ {
+ U16 temp;
+ for(i=count ;i!=0 ;i--)
+ {
+ temp = ((U16*)p)[0];
+ ((U16*)p)[0] = ((temp >> 8) & 0x000000FF) | ((temp << 8) & 0x0000FF00);
+ p = (void*)(((U16*)p) + 1);
+ }
+ }
+ break;
+
+ case 4:
+ {
+ U32 temp;
+ for(i=count; i!=0; i--)
+ {
+ temp = ((U32*)p)[0];
+ ((U32*)p)[0] =
+ ((temp >> 24) & 0x000000FF) |
+ ((temp >> 8) & 0x0000FF00) |
+ ((temp << 8) & 0x00FF0000) |
+ ((temp << 24) & 0xFF000000);
+ p = (void*)(((U32*)p) + 1);
+ }
+ }
+ break;
+ }
+
+ }
#endif
// Use this when working with a single integral value you want swizzled
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 0f48ce16b2..e4843a88eb 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,250 +1274,250 @@ 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)
- {
- g->mFatalMessage = 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)
+ {
+ 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
@@ -1576,7 +1576,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/llerror.h b/indra/llcommon/llerror.h
index a70b5cef3a..7353a36c5f 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -79,16 +79,16 @@ const int LL_ERR_NOERR = 0;
#define llassert_always_msg(func, msg) if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << msg << ")" << LL_ENDL
-#define llassert_always(func) llassert_always_msg(func, #func)
+#define llassert_always(func) llassert_always_msg(func, #func)
#ifdef SHOW_ASSERT
-#define llassert(func) llassert_always_msg(func, #func)
-#define llassert_msg(func, msg) llassert_always_msg(func, msg)
-#define llverify(func) llassert_always_msg(func, #func)
+#define llassert(func) llassert_always_msg(func, #func)
+#define llassert_msg(func, msg) llassert_always_msg(func, msg)
+#define llverify(func) llassert_always_msg(func, #func)
#else
#define llassert(func)
#define llassert_msg(func, msg)
-#define llverify(func) do {if (func) {}} while(0)
+#define llverify(func) do {if (func) {}} while(0)
#endif
#ifdef LL_WINDOWS
@@ -107,58 +107,58 @@ const int LL_ERR_NOERR = 0;
/** Error Logging Facility
- Information for most users:
+ Information for most users:
- Code can log messages with constructions like this:
+ Code can log messages with constructions like this:
- LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id
- << " denied due to timeout" << LL_ENDL;
+ LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id
+ << " denied due to timeout" << LL_ENDL;
- Messages can be logged to one of four increasing levels of concern,
- using one of four "streams":
+ Messages can be logged to one of four increasing levels of concern,
+ using one of four "streams":
- LL_DEBUGS("StringTag") - debug messages that are normally suppressed
- LL_INFOS("StringTag") - informational messages that are normal shown
- LL_WARNS("StringTag") - warning messages that signal a problem
- LL_ERRS("StringTag") - error messages that are major, unrecoverable failures
+ LL_DEBUGS("StringTag") - debug messages that are normally suppressed
+ LL_INFOS("StringTag") - informational messages that are normal shown
+ LL_WARNS("StringTag") - warning messages that signal a problem
+ LL_ERRS("StringTag") - error messages that are major, unrecoverable failures
- The later (LL_ERRS("StringTag")) automatically crashes the process after the message
- is logged.
+ The later (LL_ERRS("StringTag")) automatically crashes the process after the message
+ is logged.
- Note that these "streams" are actually #define magic. Rules for use:
- * they cannot be used as normal streams, only to start a message
- * messages written to them MUST be terminated with LL_ENDL
- * between the opening and closing, the << operator is indeed
- writing onto a std::ostream, so all conversions and stream
- formating are available
+ Note that these "streams" are actually #define magic. Rules for use:
+ * they cannot be used as normal streams, only to start a message
+ * messages written to them MUST be terminated with LL_ENDL
+ * between the opening and closing, the << operator is indeed
+ writing onto a std::ostream, so all conversions and stream
+ formating are available
- These messages are automatically logged with function name, and (if enabled)
- file and line of the message. (Note: Existing messages that already include
- the function name don't get name printed twice.)
+ These messages are automatically logged with function name, and (if enabled)
+ file and line of the message. (Note: Existing messages that already include
+ the function name don't get name printed twice.)
- If you have a class, adding LOG_CLASS line to the declaration will cause
- all messages emitted from member functions (normal and static) to be tagged
- with the proper class name as well as the function name:
+ If you have a class, adding LOG_CLASS line to the declaration will cause
+ all messages emitted from member functions (normal and static) to be tagged
+ with the proper class name as well as the function name:
- class LLFoo
- {
- LOG_CLASS(LLFoo);
- public:
- ...
- };
+ class LLFoo
+ {
+ LOG_CLASS(LLFoo);
+ public:
+ ...
+ };
- void LLFoo::doSomething(int i)
- {
- if (i > 100)
- {
- LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL;
- }
- ...
- }
+ void LLFoo::doSomething(int i)
+ {
+ if (i > 100)
+ {
+ LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL;
+ }
+ ...
+ }
- will result in messages like:
+ will result in messages like:
- WARN #FooBarTag# llcommon/llfoo(100) LLFoo::doSomething : called with a big value for i: 283
+ WARN #FooBarTag# llcommon/llfoo(100) LLFoo::doSomething : called with a big value for i: 283
the syntax is:
<timestamp> SPACE <level> SPACE <tags> SPACE <location> SPACE <function> SPACE COLON SPACE <message>
@@ -169,117 +169,117 @@ const int LL_ERR_NOERR = 0;
The tags must be a single word (may not contain a space); if more than one tag is specified,
they are all surrounded by '#' ( #FooTag#BarTag# ).
- Which messages are logged and which are suppressed can be controlled at run
- time from the configuration file. The default configuration is in newview/app_settings/logcontrol.xml
+ Which messages are logged and which are suppressed can be controlled at run
+ time from the configuration file. The default configuration is in newview/app_settings/logcontrol.xml
A copy of that file named logcontrol-dev.xml can be made in the users personal settings
directory; that will override the installed default file. See the logcontrol.xml
file or http://wiki.secondlife.com/wiki/Logging_System_Overview for configuration details.
- Lastly, logging is now very efficient in both compiled code and execution
- when skipped. There is no need to wrap messages, even debugging ones, in
- #ifdef _DEBUG constructs. LL_DEBUGS("StringTag") messages are compiled into all builds,
- even release. Which means you can use them to help debug even when deployed
- to a real grid.
+ Lastly, logging is now very efficient in both compiled code and execution
+ when skipped. There is no need to wrap messages, even debugging ones, in
+ #ifdef _DEBUG constructs. LL_DEBUGS("StringTag") messages are compiled into all builds,
+ even release. Which means you can use them to help debug even when deployed
+ to a real grid.
*/
namespace LLError
{
- enum ELevel
- {
- LEVEL_ALL = 0,
- // used to indicate that all messages should be logged
-
- LEVEL_DEBUG = 0,
- LEVEL_INFO = 1,
- LEVEL_WARN = 2,
- LEVEL_ERROR = 3, // used to be called FATAL
-
- LEVEL_NONE = 4
- // not really a level
- // used to indicate that no messages should be logged
- };
- // If you change ELevel, please update llvlog() macro below.
-
- /* Macro support
- The classes CallSite and Log are used by the logging macros below.
- They are not intended for general use.
- */
-
- struct CallSite;
-
- class LL_COMMON_API Log
- {
- public:
- static bool shouldLog(CallSite&);
- static void flush(const std::ostringstream&, const CallSite&);
- static std::string demangle(const char* mangled);
- /// classname<TYPE>()
- template <typename T>
- static std::string classname() { return demangle(typeid(T).name()); }
- /// classname(some_pointer)
- template <typename T>
- static std::string classname(T* const ptr) { return ptr? demangle(typeid(*ptr).name()) : "nullptr"; }
- /// classname(some_reference)
- template <typename T>
- static std::string classname(const T& obj) { return demangle(typeid(obj).name()); }
- };
-
- struct LL_COMMON_API CallSite
- {
- // Represents a specific place in the code where a message is logged
- // This is public because it is used by the macros below. It is not
- // intended for public use.
- CallSite(ELevel level,
- const char* file,
- int line,
- const std::type_info& class_info,
- const char* function,
- bool print_once,
- const char** tags,
- size_t tag_count);
-
- ~CallSite();
+ enum ELevel
+ {
+ LEVEL_ALL = 0,
+ // used to indicate that all messages should be logged
+
+ LEVEL_DEBUG = 0,
+ LEVEL_INFO = 1,
+ LEVEL_WARN = 2,
+ LEVEL_ERROR = 3, // used to be called FATAL
+
+ LEVEL_NONE = 4
+ // not really a level
+ // used to indicate that no messages should be logged
+ };
+ // If you change ELevel, please update llvlog() macro below.
+
+ /* Macro support
+ The classes CallSite and Log are used by the logging macros below.
+ They are not intended for general use.
+ */
+
+ struct CallSite;
+
+ class LL_COMMON_API Log
+ {
+ public:
+ static bool shouldLog(CallSite&);
+ static void flush(const std::ostringstream&, const CallSite&);
+ static std::string demangle(const char* mangled);
+ /// classname<TYPE>()
+ template <typename T>
+ static std::string classname() { return demangle(typeid(T).name()); }
+ /// classname(some_pointer)
+ template <typename T>
+ static std::string classname(T* const ptr) { return ptr? demangle(typeid(*ptr).name()) : "nullptr"; }
+ /// classname(some_reference)
+ template <typename T>
+ static std::string classname(const T& obj) { return demangle(typeid(obj).name()); }
+ };
+
+ struct LL_COMMON_API CallSite
+ {
+ // Represents a specific place in the code where a message is logged
+ // This is public because it is used by the macros below. It is not
+ // intended for public use.
+ CallSite(ELevel level,
+ const char* file,
+ int line,
+ const std::type_info& class_info,
+ const char* function,
+ bool print_once,
+ const char** tags,
+ size_t tag_count);
+
+ ~CallSite();
#ifdef LL_LIBRARY_INCLUDE
- bool shouldLog();
+ bool shouldLog();
#else // LL_LIBRARY_INCLUDE
- bool shouldLog()
- {
- return mCached
- ? mShouldLog
- : Log::shouldLog(*this);
- }
- // this member function needs to be in-line for efficiency
+ bool shouldLog()
+ {
+ return mCached
+ ? mShouldLog
+ : Log::shouldLog(*this);
+ }
+ // this member function needs to be in-line for efficiency
#endif // LL_LIBRARY_INCLUDE
- void invalidate();
-
- // these describe the call site and never change
- const ELevel mLevel;
- const char* const mFile;
- const int mLine;
- const std::type_info& mClassInfo;
- const char* const mFunction;
- const char** mTags;
- size_t mTagCount;
- const bool mPrintOnce;
- const char* mLevelString;
- std::string mLocationString,
- mFunctionString,
- mTagString;
- bool mCached,
- mShouldLog;
-
- friend class Log;
- };
+ void invalidate();
+
+ // these describe the call site and never change
+ const ELevel mLevel;
+ const char* const mFile;
+ const int mLine;
+ const std::type_info& mClassInfo;
+ const char* const mFunction;
+ const char** mTags;
+ size_t mTagCount;
+ const bool mPrintOnce;
+ const char* mLevelString;
+ std::string mLocationString,
+ mFunctionString,
+ mTagString;
+ bool mCached,
+ mShouldLog;
+
+ friend class Log;
+ };
- class End { };
- inline std::ostream& operator<<(std::ostream& s, const End&)
- { return s; }
- // used to indicate the end of a message
+ class End { };
+ inline std::ostream& operator<<(std::ostream& s, const End&)
+ { return s; }
+ // used to indicate the end of a message
- class LL_COMMON_API NoClassInfo { };
- // used to indicate no class info known for logging
+ class LL_COMMON_API NoClassInfo { };
+ // used to indicate no class info known for logging
//LLCallStacks keeps track of call stacks and output the call stacks to log file
//
@@ -335,30 +335,30 @@ namespace LLError
#define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
#define llcallstacks \
- { \
- std::ostringstream _out; \
- LLError::LLCallStacks::insert(_out, __FUNCTION__, __LINE__) ; \
- _out
+ { \
+ std::ostringstream _out; \
+ LLError::LLCallStacks::insert(_out, __FUNCTION__, __LINE__) ; \
+ _out
#define llcallstacksendl \
- LLError::End(); \
- LLError::LLCallStacks::end(_out) ; \
- }
+ LLError::End(); \
+ LLError::LLCallStacks::end(_out) ; \
+ }
#define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear()
#define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print()
/*
- Class type information for logging
+ Class type information for logging
*/
-#define LOG_CLASS(s) typedef s _LL_CLASS_TO_LOG
- // Declares class to tag logged messages with.
- // See top of file for example of how to use this
+#define LOG_CLASS(s) typedef s _LL_CLASS_TO_LOG
+ // Declares class to tag logged messages with.
+ // See top of file for example of how to use this
typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
- // Outside a class declaration, or in class without LOG_CLASS(), this
- // typedef causes the messages to not be associated with any class.
+ // Outside a class declaration, or in class without LOG_CLASS(), this
+ // typedef causes the messages to not be associated with any class.
/////////////////////////////////
// Error Logging Macros
@@ -381,34 +381,34 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define lllog(level, once, ...) \
do { \
LL_PROFILE_ZONE_NAMED("lllog"); \
- const char* tags[] = {"", ##__VA_ARGS__}; \
- static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
- lllog_test_()
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
+ lllog_test_()
#define lllog_test_() \
- if (LL_UNLIKELY(_site.shouldLog())) \
- { \
- std::ostringstream _out; \
- _out
+ if (LL_UNLIKELY(_site.shouldLog())) \
+ { \
+ std::ostringstream _out; \
+ _out
#define lllog_site_args_(level, once, tags) \
- level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
- __FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
+ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
+ __FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
//Use this construct if you need to do computation in the middle of a
//message:
//
-// LL_INFOS("AgentGesture") << "the agent " << agend_id;
-// switch (f)
-// {
-// case FOP_SHRUGS: LL_CONT << "shrugs"; break;
-// case FOP_TAPS: LL_CONT << "points at " << who; break;
-// case FOP_SAYS: LL_CONT << "says " << message; break;
-// }
-// LL_CONT << " for " << t << " seconds" << LL_ENDL;
+// LL_INFOS("AgentGesture") << "the agent " << agend_id;
+// switch (f)
+// {
+// case FOP_SHRUGS: LL_CONT << "shrugs"; break;
+// case FOP_TAPS: LL_CONT << "points at " << who; break;
+// case FOP_SAYS: LL_CONT << "says " << message; break;
+// }
+// LL_CONT << " for " << t << " seconds" << LL_ENDL;
//
//Such computation is done iff the message will be logged.
-#define LL_CONT _out
+#define LL_CONT _out
#define LL_NEWLINE '\n'
@@ -437,24 +437,24 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
// NEW Macros for debugging, allow the passing of a string tag
// Pass comma separated list of tags (currently only supports up to 0, 1, or 2)
-#define LL_DEBUGS(...) lllog(LLError::LEVEL_DEBUG, false, ##__VA_ARGS__)
-#define LL_INFOS(...) lllog(LLError::LEVEL_INFO, false, ##__VA_ARGS__)
-#define LL_WARNS(...) lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
-#define LL_ERRS(...) lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
+#define LL_DEBUGS(...) lllog(LLError::LEVEL_DEBUG, false, ##__VA_ARGS__)
+#define LL_INFOS(...) lllog(LLError::LEVEL_INFO, false, ##__VA_ARGS__)
+#define LL_WARNS(...) lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
+#define LL_ERRS(...) lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
// alternative to llassert_always that prints explanatory message
// note ## token paste operator hack used above will only work in gcc following
// a comma and is completely unnecessary in VS since the comma is automatically
// suppressed
// https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
// https://docs.microsoft.com/en-us/cpp/preprocessor/variadic-macros?view=vs-2015
-#define LL_WARNS_IF(exp, ...) if (exp) LL_WARNS(__VA_ARGS__) << "(" #exp ")"
-#define LL_ERRS_IF(exp, ...) if (exp) LL_ERRS(__VA_ARGS__) << "(" #exp ")"
+#define LL_WARNS_IF(exp, ...) if (exp) LL_WARNS(__VA_ARGS__) << "(" #exp ")"
+#define LL_ERRS_IF(exp, ...) if (exp) LL_ERRS(__VA_ARGS__) << "(" #exp ")"
// Only print the log message once (good for warnings or infos that would otherwise
// spam the log file over and over, such as tighter loops).
-#define LL_DEBUGS_ONCE(...) lllog(LLError::LEVEL_DEBUG, true, ##__VA_ARGS__)
-#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
-#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
+#define LL_DEBUGS_ONCE(...) lllog(LLError::LEVEL_DEBUG, true, ##__VA_ARGS__)
+#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
+#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
// Use this if you need to pass LLError::ELevel as a variable.
#define LL_VLOGS(level, ...) llvlog(level, false, ##__VA_ARGS__)
@@ -470,33 +470,33 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
// instance for the passed level value.
// Compare implementation to lllog() above.
#define llvlog(level, once, ...) \
- do { \
- const char* tags[] = {"", ##__VA_ARGS__}; \
- /* Need a static CallSite instance per expected ELevel value. */ \
- /* Since we intend to index this array with the ELevel, */ \
- /* _sites[0] should be ELevel(0), and so on -- avoid using */ \
- /* ELevel symbolic names when initializing -- except for */ \
- /* the last entry, which handles anything beyond the end. */ \
- /* (Commented ELevel value names are from 2016-09-01.) */ \
- /* Passing an ELevel past the end of this array is itself */ \
- /* a fatal error, so ensure the last is LEVEL_ERROR. */ \
- static LLError::CallSite _sites[] = \
- { \
- /* LEVEL_DEBUG */ \
- LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
- /* LEVEL_INFO */ \
- LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
- /* LEVEL_WARN */ \
- LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
- /* LEVEL_ERROR */ \
- LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
- }; \
- /* Clamp the passed 'level' to at most last entry */ \
- std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
- (LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
- /* selected CallSite *must* be named _site for LL_ENDL */ \
- LLError::CallSite& _site(_sites[which]); \
- lllog_test_()
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ /* Need a static CallSite instance per expected ELevel value. */ \
+ /* Since we intend to index this array with the ELevel, */ \
+ /* _sites[0] should be ELevel(0), and so on -- avoid using */ \
+ /* ELevel symbolic names when initializing -- except for */ \
+ /* the last entry, which handles anything beyond the end. */ \
+ /* (Commented ELevel value names are from 2016-09-01.) */ \
+ /* Passing an ELevel past the end of this array is itself */ \
+ /* a fatal error, so ensure the last is LEVEL_ERROR. */ \
+ static LLError::CallSite _sites[] = \
+ { \
+ /* LEVEL_DEBUG */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
+ /* LEVEL_INFO */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
+ /* LEVEL_WARN */ \
+ LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
+ /* LEVEL_ERROR */ \
+ LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
+ }; \
+ /* Clamp the passed 'level' to at most last entry */ \
+ std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
+ (LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
+ /* selected CallSite *must* be named _site for LL_ENDL */ \
+ LLError::CallSite& _site(_sites[which]); \
+ lllog_test_()
/*
// Check at run-time whether logging is enabled, without generating output.
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 77b187a80f..bf5a6df556 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -38,143 +38,143 @@
class LLSD;
/*
- This is the part of the LLError namespace that manages the messages
- produced by the logging. The logging support is defined in llerror.h.
- Most files do not need to include this.
+ This is the part of the LLError namespace that manages the messages
+ produced by the logging. The logging support is defined in llerror.h.
+ Most files do not need to include this.
- These implementations are in llerror.cpp.
+ These implementations are in llerror.cpp.
*/
// Line buffer interface
class LLLineBuffer
{
public:
- LLLineBuffer() {};
- virtual ~LLLineBuffer() {};
+ LLLineBuffer() {};
+ virtual ~LLLineBuffer() {};
- virtual void clear() = 0; // Clear the buffer, and reset it.
+ virtual void clear() = 0; // Clear the buffer, and reset it.
- virtual void addLine(const std::string& utf8line) = 0;
+ virtual void addLine(const std::string& utf8line) = 0;
};
namespace LLError
{
- LL_COMMON_API void initForApplication(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true);
- // resets all logging settings to defaults needed by applicaitons
- // logs to stderr and windows debug log
- // sets up log configuration from the file logcontrol.xml in dir
+ LL_COMMON_API void initForApplication(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true);
+ // resets all logging settings to defaults needed by applicaitons
+ // logs to stderr and windows debug log
+ // sets up log configuration from the file logcontrol.xml in dir
- /*
- Settings that control what is logged.
- Setting a level means log messages at that level or above.
- */
+ /*
+ Settings that control what is logged.
+ Setting a level means log messages at that level or above.
+ */
- LL_COMMON_API void setPrintLocation(bool);
- LL_COMMON_API void setDefaultLevel(LLError::ELevel);
- LL_COMMON_API ELevel getDefaultLevel();
- LL_COMMON_API void setAlwaysFlush(bool flush);
+ LL_COMMON_API void setPrintLocation(bool);
+ LL_COMMON_API void setDefaultLevel(LLError::ELevel);
+ LL_COMMON_API ELevel getDefaultLevel();
+ LL_COMMON_API void setAlwaysFlush(bool flush);
LL_COMMON_API bool getAlwaysFlush();
- LL_COMMON_API void setEnabledLogTypesMask(U32 mask);
- LL_COMMON_API U32 getEnabledLogTypesMask();
- LL_COMMON_API void setFunctionLevel(const std::string& function_name, LLError::ELevel);
- LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
- LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
- LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel);
-
- LL_COMMON_API LLError::ELevel decodeLevel(std::string name);
- LL_COMMON_API void configure(const LLSD&);
- // the LLSD can configure all of the settings
- // usually read automatically from the live errorlog.xml file
-
-
- /*
- Control functions.
- */
-
- typedef boost::function<void(const std::string&)> FatalFunction;
-
- LL_COMMON_API void setFatalFunction(const FatalFunction&);
- // The fatal function will be called after an message of LEVEL_ERROR
- // is logged. Note: supressing a LEVEL_ERROR message from being logged
- // (by, for example, setting a class level to LEVEL_NONE), will keep
- // that message from causing the fatal function to be invoked.
- // The passed FatalFunction will be the LAST log function called
- // before LL_ERRS crashes its caller. A FatalFunction can throw an
- // exception, or call exit(), to bypass the crash. It MUST disrupt the
- // flow of control because no caller expects LL_ERRS to return.
-
- LL_COMMON_API FatalFunction getFatalFunction();
- // Retrieve the previously-set FatalFunction
-
- LL_COMMON_API std::string getFatalMessage();
- // Retrieve the message last passed to FatalFunction, if any
-
- /// temporarily override the FatalFunction for the duration of a
- /// particular scope, e.g. for unit tests
- class LL_COMMON_API OverrideFatalFunction
- {
- public:
- OverrideFatalFunction(const FatalFunction& func):
- mPrev(getFatalFunction())
- {
- setFatalFunction(func);
- }
- ~OverrideFatalFunction()
- {
- setFatalFunction(mPrev);
- }
-
- private:
- FatalFunction mPrev;
- };
-
- typedef std::string (*TimeFunction)();
- LL_COMMON_API std::string utcTime();
-
- LL_COMMON_API void setTimeFunction(TimeFunction);
- // The function is use to return the current time, formatted for
- // display by those error recorders that want the time included.
-
-
-
- class LL_COMMON_API Recorder
- {
- // An object that handles the actual output or error messages.
- public:
- Recorder();
- virtual ~Recorder();
-
- virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
- // use the level for better display, not for filtering
-
- virtual bool enabled() { return true; }
-
- bool wantsTime();
- bool wantsTags();
- bool wantsLevel();
- bool wantsLocation();
- bool wantsFunctionName();
- bool wantsMultiline();
-
- void showTime(bool show);
- void showTags(bool show);
- void showLevel(bool show);
- void showLocation(bool show);
- void showFunctionName(bool show);
- void showMultiline(bool show);
-
- protected:
- bool mWantsTime;
- bool mWantsTags;
- bool mWantsLevel;
- bool mWantsLocation;
- bool mWantsFunctionName;
- bool mWantsMultiline;
- };
-
- typedef std::shared_ptr<Recorder> RecorderPtr;
+ LL_COMMON_API void setEnabledLogTypesMask(U32 mask);
+ LL_COMMON_API U32 getEnabledLogTypesMask();
+ LL_COMMON_API void setFunctionLevel(const std::string& function_name, LLError::ELevel);
+ LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
+ LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
+ LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel);
+
+ LL_COMMON_API LLError::ELevel decodeLevel(std::string name);
+ LL_COMMON_API void configure(const LLSD&);
+ // the LLSD can configure all of the settings
+ // usually read automatically from the live errorlog.xml file
+
+
+ /*
+ Control functions.
+ */
+
+ typedef boost::function<void(const std::string&)> FatalFunction;
+
+ LL_COMMON_API void setFatalFunction(const FatalFunction&);
+ // The fatal function will be called after an message of LEVEL_ERROR
+ // is logged. Note: supressing a LEVEL_ERROR message from being logged
+ // (by, for example, setting a class level to LEVEL_NONE), will keep
+ // that message from causing the fatal function to be invoked.
+ // The passed FatalFunction will be the LAST log function called
+ // before LL_ERRS crashes its caller. A FatalFunction can throw an
+ // exception, or call exit(), to bypass the crash. It MUST disrupt the
+ // flow of control because no caller expects LL_ERRS to return.
+
+ LL_COMMON_API FatalFunction getFatalFunction();
+ // Retrieve the previously-set FatalFunction
+
+ LL_COMMON_API std::string getFatalMessage();
+ // Retrieve the message last passed to FatalFunction, if any
+
+ /// temporarily override the FatalFunction for the duration of a
+ /// particular scope, e.g. for unit tests
+ class LL_COMMON_API OverrideFatalFunction
+ {
+ public:
+ OverrideFatalFunction(const FatalFunction& func):
+ mPrev(getFatalFunction())
+ {
+ setFatalFunction(func);
+ }
+ ~OverrideFatalFunction()
+ {
+ setFatalFunction(mPrev);
+ }
+
+ private:
+ FatalFunction mPrev;
+ };
+
+ typedef std::string (*TimeFunction)();
+ LL_COMMON_API std::string utcTime();
+
+ LL_COMMON_API void setTimeFunction(TimeFunction);
+ // The function is use to return the current time, formatted for
+ // display by those error recorders that want the time included.
+
+
+
+ class LL_COMMON_API Recorder
+ {
+ // An object that handles the actual output or error messages.
+ public:
+ Recorder();
+ virtual ~Recorder();
+
+ virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
+ // use the level for better display, not for filtering
+
+ virtual bool enabled() { return true; }
+
+ bool wantsTime();
+ bool wantsTags();
+ bool wantsLevel();
+ bool wantsLocation();
+ bool wantsFunctionName();
+ bool wantsMultiline();
+
+ void showTime(bool show);
+ void showTags(bool show);
+ void showLevel(bool show);
+ void showLocation(bool show);
+ void showFunctionName(bool show);
+ void showMultiline(bool show);
+
+ protected:
+ bool mWantsTime;
+ bool mWantsTags;
+ bool mWantsLevel;
+ bool mWantsLocation;
+ bool mWantsFunctionName;
+ bool mWantsMultiline;
+ };
+
+ typedef std::shared_ptr<Recorder> RecorderPtr;
/**
* Instantiate GenericRecorder with a callable(level, message) to get
@@ -197,48 +197,48 @@ namespace LLError
CALLABLE mCallable;
};
- /**
- * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership
- * while still ensuring that the allocated memory is eventually freed
- */
- LL_COMMON_API void addRecorder(RecorderPtr);
- LL_COMMON_API void removeRecorder(RecorderPtr);
- // each error message is passed to each recorder via recordMessage()
- /**
- * Call addGenericRecorder() with a callable(level, message) to get
- * control on every log message without having to code an explicit
- * Recorder subclass. Save the returned RecorderPtr if you later want to
- * call removeRecorder().
- */
- template <typename CALLABLE>
- RecorderPtr addGenericRecorder(const CALLABLE& callable)
- {
- RecorderPtr ptr{ new GenericRecorder<CALLABLE>(callable) };
- addRecorder(ptr);
- return ptr;
- }
-
- LL_COMMON_API void logToFile(const std::string& filename);
- LL_COMMON_API void logToStderr();
- LL_COMMON_API void logToFixedBuffer(LLLineBuffer*);
- // Utilities to add recorders for logging to a file or a fixed buffer
- // A second call to the same function will remove the logger added
- // with the first.
- // Passing the empty string or NULL to just removes any prior.
- LL_COMMON_API std::string logFileName();
- // returns name of current logging file, empty string if none
-
-
- /*
- Utilities for use by the unit tests of LLError itself.
- */
-
- typedef LLPointer<LLRefCount> SettingsStoragePtr;
- LL_COMMON_API SettingsStoragePtr saveAndResetSettings();
- LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage);
-
- LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
- LL_COMMON_API int shouldLogCallCount();
+ /**
+ * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership
+ * while still ensuring that the allocated memory is eventually freed
+ */
+ LL_COMMON_API void addRecorder(RecorderPtr);
+ LL_COMMON_API void removeRecorder(RecorderPtr);
+ // each error message is passed to each recorder via recordMessage()
+ /**
+ * Call addGenericRecorder() with a callable(level, message) to get
+ * control on every log message without having to code an explicit
+ * Recorder subclass. Save the returned RecorderPtr if you later want to
+ * call removeRecorder().
+ */
+ template <typename CALLABLE>
+ RecorderPtr addGenericRecorder(const CALLABLE& callable)
+ {
+ RecorderPtr ptr{ new GenericRecorder<CALLABLE>(callable) };
+ addRecorder(ptr);
+ return ptr;
+ }
+
+ LL_COMMON_API void logToFile(const std::string& filename);
+ LL_COMMON_API void logToStderr();
+ LL_COMMON_API void logToFixedBuffer(LLLineBuffer*);
+ // Utilities to add recorders for logging to a file or a fixed buffer
+ // A second call to the same function will remove the logger added
+ // with the first.
+ // Passing the empty string or NULL to just removes any prior.
+ LL_COMMON_API std::string logFileName();
+ // returns name of current logging file, empty string if none
+
+
+ /*
+ Utilities for use by the unit tests of LLError itself.
+ */
+
+ typedef LLPointer<LLRefCount> SettingsStoragePtr;
+ LL_COMMON_API SettingsStoragePtr saveAndResetSettings();
+ LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage);
+
+ LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
+ LL_COMMON_API int shouldLogCallCount();
};
#endif // LL_LLERRORCONTROL_H
diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 31dd207008..693e1501d5 100644
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llerrorlegacy.h
* @date January 2007
* @brief old things from the older error system
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
diff --git a/indra/llcommon/llevent.cpp b/indra/llcommon/llevent.cpp
index 501d06e3cd..305ab8144a 100644
--- a/indra/llcommon/llevent.cpp
+++ b/indra/llcommon/llevent.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llevent.cpp
* @brief LLEvent and LLEventListener base classes.
*
* $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$
*/
@@ -42,13 +42,13 @@ LLEvent::~LLEvent()
// virtual
bool LLEvent::accept(LLEventListener* listener)
{
- return true;
+ return true;
}
// virtual
const std::string& LLEvent::desc()
{
- return mDesc;
+ return mDesc;
}
/************************************************
@@ -56,50 +56,50 @@ const std::string& LLEvent::desc()
************************************************/
LLObservable::LLObservable()
- : mDispatcher(new LLEventDispatcher())
+ : mDispatcher(new LLEventDispatcher())
{
}
// virtual
LLObservable::~LLObservable()
{
- if (mDispatcher.notNull())
- {
- mDispatcher->disengage(this);
- mDispatcher = NULL;
- }
+ if (mDispatcher.notNull())
+ {
+ mDispatcher->disengage(this);
+ mDispatcher = NULL;
+ }
}
// virtual
bool LLObservable::setDispatcher(LLPointer<LLEventDispatcher> dispatcher)
{
- if (mDispatcher.notNull())
- {
- mDispatcher->disengage(this);
- mDispatcher = NULL;
- }
- if (dispatcher.notNull() || dispatcher->engage(this))
- {
- mDispatcher = dispatcher;
- return true;
- }
- return false;
+ if (mDispatcher.notNull())
+ {
+ mDispatcher->disengage(this);
+ mDispatcher = NULL;
+ }
+ if (dispatcher.notNull() || dispatcher->engage(this))
+ {
+ mDispatcher = dispatcher;
+ return true;
+ }
+ return false;
}
// Returns the current dispatcher pointer.
// virtual
LLEventDispatcher* LLObservable::getDispatcher()
{
- return mDispatcher;
+ return mDispatcher;
}
// Notifies the dispatcher of an event being fired.
void LLObservable::fireEvent(LLPointer<LLEvent> event, LLSD filter)
{
- if (mDispatcher.notNull())
- {
- mDispatcher->fireEvent(event, filter);
- }
+ if (mDispatcher.notNull())
+ {
+ mDispatcher->fireEvent(event, filter);
+ }
}
/************************************************
@@ -109,134 +109,134 @@ void LLObservable::fireEvent(LLPointer<LLEvent> event, LLSD filter)
class LLEventDispatcher::Impl
{
public:
- virtual ~Impl() { }
- virtual bool engage(LLObservable* observable) { return true; }
- virtual void disengage(LLObservable* observable) { }
-
- virtual void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata) = 0;
- virtual void removeListener(LLEventListener *listener) = 0;
- virtual std::vector<LLListenerEntry> getListeners() const = 0;
- virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter) = 0;
+ virtual ~Impl() { }
+ virtual bool engage(LLObservable* observable) { return true; }
+ virtual void disengage(LLObservable* observable) { }
+
+ virtual void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata) = 0;
+ virtual void removeListener(LLEventListener *listener) = 0;
+ virtual std::vector<LLListenerEntry> getListeners() const = 0;
+ virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter) = 0;
};
bool LLEventDispatcher::engage(LLObservable* observable)
{
- return impl->engage(observable);
+ return impl->engage(observable);
}
void LLEventDispatcher::disengage(LLObservable* observable)
{
- impl->disengage(observable);
+ impl->disengage(observable);
}
void LLEventDispatcher::addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata)
{
- impl->addListener(listener, filter, userdata);
+ impl->addListener(listener, filter, userdata);
}
void LLEventDispatcher::removeListener(LLEventListener *listener)
{
- impl->removeListener(listener);
+ impl->removeListener(listener);
}
std::vector<LLListenerEntry> LLEventDispatcher::getListeners() const
{
- return impl->getListeners();
+ return impl->getListeners();
}
bool LLEventDispatcher::fireEvent(LLPointer<LLEvent> event, LLSD filter)
{
- return impl->fireEvent(event, filter);
+ return impl->fireEvent(event, filter);
}
class LLSimpleDispatcher : public LLEventDispatcher::Impl
{
public:
- LLSimpleDispatcher(LLEventDispatcher *parent) : mParent(parent) { }
- virtual ~LLSimpleDispatcher();
- virtual void addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata);
- virtual void removeListener(LLEventListener* listener);
- virtual std::vector<LLListenerEntry> getListeners() const;
- virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter);
+ LLSimpleDispatcher(LLEventDispatcher *parent) : mParent(parent) { }
+ virtual ~LLSimpleDispatcher();
+ virtual void addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata);
+ virtual void removeListener(LLEventListener* listener);
+ virtual std::vector<LLListenerEntry> getListeners() const;
+ virtual bool fireEvent(LLPointer<LLEvent> event, LLSD filter);
protected:
- std::vector<LLListenerEntry> mListeners;
- LLEventDispatcher *mParent;
+ std::vector<LLListenerEntry> mListeners;
+ LLEventDispatcher *mParent;
};
LLSimpleDispatcher::~LLSimpleDispatcher()
{
- while (mListeners.size() > 0)
- {
- removeListener(mListeners.begin()->listener);
- }
+ while (mListeners.size() > 0)
+ {
+ removeListener(mListeners.begin()->listener);
+ }
}
void LLSimpleDispatcher::addListener(LLEventListener* listener, LLSD filter, const LLSD& userdata)
{
- if (listener == NULL) return;
- removeListener(listener);
- LLListenerEntry new_entry;
- new_entry.listener = listener;
- new_entry.filter = filter;
- new_entry.userdata = userdata;
- mListeners.push_back(new_entry);
- listener->handleAttach(mParent);
+ if (listener == NULL) return;
+ removeListener(listener);
+ LLListenerEntry new_entry;
+ new_entry.listener = listener;
+ new_entry.filter = filter;
+ new_entry.userdata = userdata;
+ mListeners.push_back(new_entry);
+ listener->handleAttach(mParent);
}
void LLSimpleDispatcher::removeListener(LLEventListener* listener)
{
- std::vector<LLListenerEntry>::iterator itor = mListeners.begin();
- std::vector<LLListenerEntry>::iterator end = mListeners.end();
- for (; itor != end; ++itor)
- {
- if ((*itor).listener == listener)
- {
- mListeners.erase(itor);
- break;
- }
- }
- listener->handleDetach(mParent);
+ std::vector<LLListenerEntry>::iterator itor = mListeners.begin();
+ std::vector<LLListenerEntry>::iterator end = mListeners.end();
+ for (; itor != end; ++itor)
+ {
+ if ((*itor).listener == listener)
+ {
+ mListeners.erase(itor);
+ break;
+ }
+ }
+ listener->handleDetach(mParent);
}
std::vector<LLListenerEntry> LLSimpleDispatcher::getListeners() const
{
- std::vector<LLListenerEntry> ret;
- for (const LLListenerEntry& entry : mListeners)
- {
- ret.push_back(entry);
- }
-
- return ret;
+ std::vector<LLListenerEntry> ret;
+ for (const LLListenerEntry& entry : mListeners)
+ {
+ ret.push_back(entry);
+ }
+
+ return ret;
}
// virtual
bool LLSimpleDispatcher::fireEvent(LLPointer<LLEvent> event, LLSD filter)
{
- std::string filter_string = filter.asString();
- for (LLListenerEntry& entry : mListeners)
- {
- if (filter_string == "" || entry.filter.asString() == filter_string)
- {
- (entry.listener)->handleEvent(event, entry.userdata);
- }
- }
- return true;
+ std::string filter_string = filter.asString();
+ for (LLListenerEntry& entry : mListeners)
+ {
+ if (filter_string == "" || entry.filter.asString() == filter_string)
+ {
+ (entry.listener)->handleEvent(event, entry.userdata);
+ }
+ }
+ return true;
}
LLEventDispatcher::LLEventDispatcher()
{
- impl = new LLSimpleDispatcher(this);
+ impl = new LLSimpleDispatcher(this);
}
LLEventDispatcher::~LLEventDispatcher()
{
- if (impl)
- {
- delete impl;
- impl = NULL;
- }
+ if (impl)
+ {
+ delete impl;
+ impl = NULL;
+ }
}
/************************************************
@@ -249,52 +249,52 @@ LLEventListener::~LLEventListener()
LLSimpleListener::~LLSimpleListener()
{
- clearDispatchers();
+ clearDispatchers();
}
void LLSimpleListener::clearDispatchers()
{
- // Remove myself from all listening dispatchers
- std::vector<LLEventDispatcher *>::iterator itor;
- while (mDispatchers.size() > 0)
- {
- itor = mDispatchers.begin();
- LLEventDispatcher *dispatcher = *itor;
- dispatcher->removeListener(this);
- itor = mDispatchers.begin();
- if (itor != mDispatchers.end() && (*itor) == dispatcher)
- {
- // Somehow, the dispatcher was not removed. Remove it forcibly
- mDispatchers.erase(itor);
- }
- }
+ // Remove myself from all listening dispatchers
+ std::vector<LLEventDispatcher *>::iterator itor;
+ while (mDispatchers.size() > 0)
+ {
+ itor = mDispatchers.begin();
+ LLEventDispatcher *dispatcher = *itor;
+ dispatcher->removeListener(this);
+ itor = mDispatchers.begin();
+ if (itor != mDispatchers.end() && (*itor) == dispatcher)
+ {
+ // Somehow, the dispatcher was not removed. Remove it forcibly
+ mDispatchers.erase(itor);
+ }
+ }
}
bool LLSimpleListener::handleAttach(LLEventDispatcher *dispatcher)
{
- // Add dispatcher if it doesn't already exist
- for (LLEventDispatcher* disp : mDispatchers)
- {
- if (disp == dispatcher) return true;
- }
- mDispatchers.push_back(dispatcher);
- return true;
+ // Add dispatcher if it doesn't already exist
+ for (LLEventDispatcher* disp : mDispatchers)
+ {
+ if (disp == dispatcher) return true;
+ }
+ mDispatchers.push_back(dispatcher);
+ return true;
}
bool LLSimpleListener::handleDetach(LLEventDispatcher *dispatcher)
{
- // Remove dispatcher from list
- std::vector<LLEventDispatcher *>::iterator itor;
- for (itor = mDispatchers.begin(); itor != mDispatchers.end(); )
- {
- if ((*itor) == dispatcher)
- {
- itor = mDispatchers.erase(itor);
- }
- else
- {
- ++itor;
- }
- }
- return true;
+ // Remove dispatcher from list
+ std::vector<LLEventDispatcher *>::iterator itor;
+ for (itor = mDispatchers.begin(); itor != mDispatchers.end(); )
+ {
+ if ((*itor) == dispatcher)
+ {
+ itor = mDispatchers.erase(itor);
+ }
+ else
+ {
+ ++itor;
+ }
+ }
+ return true;
}
diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 28ce7de102..4933f8d607 100644
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llevent.h
* @author Tom Yedwab
* @brief LLEvent and LLEventListener base classes.
@@ -6,21 +6,21 @@
* $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$
*/
@@ -44,58 +44,58 @@ class LLObservable;
class LL_COMMON_API LLEvent : public LLThreadSafeRefCount
{
protected:
- virtual ~LLEvent();
-
+ virtual ~LLEvent();
+
public:
- LLEvent(LLObservable* source, const std::string& desc = "") : mSource(source), mDesc(desc) { }
-
- LLObservable* getSource() { return mSource; }
- virtual LLSD getValue() { return LLSD(); }
- // Determines whether this particular listener
- // should be notified of this event.
- // If this function returns true, handleEvent is
- // called on the listener with this event as the
- // argument.
- // Defaults to handling all events. Override this
- // if associated with an Observable with many different listeners
- virtual bool accept(LLEventListener* listener);
-
- // return a string describing the event
- virtual const std::string& desc();
+ LLEvent(LLObservable* source, const std::string& desc = "") : mSource(source), mDesc(desc) { }
+
+ LLObservable* getSource() { return mSource; }
+ virtual LLSD getValue() { return LLSD(); }
+ // Determines whether this particular listener
+ // should be notified of this event.
+ // If this function returns true, handleEvent is
+ // called on the listener with this event as the
+ // argument.
+ // Defaults to handling all events. Override this
+ // if associated with an Observable with many different listeners
+ virtual bool accept(LLEventListener* listener);
+
+ // return a string describing the event
+ virtual const std::string& desc();
private:
- LLObservable* mSource;
- std::string mDesc;
+ LLObservable* mSource;
+ std::string mDesc;
};
// Abstract listener. All listeners derive from LLEventListener
class LL_COMMON_API LLEventListener : public LLThreadSafeRefCount
{
protected:
- virtual ~LLEventListener();
-
+ virtual ~LLEventListener();
+
public:
- // Processes the event.
- // TODO: Make the return value less ambiguous?
- virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) = 0;
+ // Processes the event.
+ // TODO: Make the return value less ambiguous?
+ virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) = 0;
- // Called when an dispatcher starts/stops listening
- virtual bool handleAttach(LLEventDispatcher *dispatcher) = 0;
- virtual bool handleDetach(LLEventDispatcher *dispatcher) = 0;
+ // Called when an dispatcher starts/stops listening
+ virtual bool handleAttach(LLEventDispatcher *dispatcher) = 0;
+ virtual bool handleDetach(LLEventDispatcher *dispatcher) = 0;
};
// A listener which tracks references to it and cleans up when it's deallocated
class LL_COMMON_API LLSimpleListener : public LLEventListener
{
public:
- void clearDispatchers();
- virtual bool handleAttach(LLEventDispatcher *dispatcher);
- virtual bool handleDetach(LLEventDispatcher *dispatcher);
+ void clearDispatchers();
+ virtual bool handleAttach(LLEventDispatcher *dispatcher);
+ virtual bool handleDetach(LLEventDispatcher *dispatcher);
protected:
- ~LLSimpleListener();
- std::vector<LLEventDispatcher *> mDispatchers;
+ ~LLSimpleListener();
+ std::vector<LLEventDispatcher *> mDispatchers;
};
class LLObservable; // defined below
@@ -103,9 +103,9 @@ class LLObservable; // defined below
// A structure which stores a Listener and its metadata
struct LLListenerEntry
{
- LLEventListener* listener;
- LLSD filter;
- LLSD userdata;
+ LLEventListener* listener;
+ LLSD filter;
+ LLSD userdata;
};
// Base class for a dispatcher - an object which listens
@@ -114,40 +114,40 @@ struct LLListenerEntry
class LL_COMMON_API LLEventDispatcher : public LLThreadSafeRefCount
{
protected:
- virtual ~LLEventDispatcher();
-
+ virtual ~LLEventDispatcher();
+
public:
- // The default constructor creates a default simple dispatcher implementation.
- // The simple implementation has an array of listeners and fires every event to
- // all of them.
- LLEventDispatcher();
-
- // This dispatcher is being attached to an observable object.
- // If we return false, the attach fails.
- bool engage(LLObservable* observable);
+ // The default constructor creates a default simple dispatcher implementation.
+ // The simple implementation has an array of listeners and fires every event to
+ // all of them.
+ LLEventDispatcher();
+
+ // This dispatcher is being attached to an observable object.
+ // If we return false, the attach fails.
+ bool engage(LLObservable* observable);
- // This dispatcher is being detached from an observable object.
- void disengage(LLObservable* observable);
+ // This dispatcher is being detached from an observable object.
+ void disengage(LLObservable* observable);
- // Adds a listener to this dispatcher, with a given user data
- // that will be passed to the listener when an event is fired.
- // Duplicate pointers are removed on addtion.
- void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata);
+ // Adds a listener to this dispatcher, with a given user data
+ // that will be passed to the listener when an event is fired.
+ // Duplicate pointers are removed on addtion.
+ void addListener(LLEventListener *listener, LLSD filter, const LLSD& userdata);
- // Removes a listener from this dispatcher
- void removeListener(LLEventListener *listener);
+ // Removes a listener from this dispatcher
+ void removeListener(LLEventListener *listener);
- // Gets a list of interested listeners
- std::vector<LLListenerEntry> getListeners() const;
+ // Gets a list of interested listeners
+ std::vector<LLListenerEntry> getListeners() const;
- // Handle an event that has just been fired by communicating it
- // to listeners, passing it across a network, etc.
- bool fireEvent(LLPointer<LLEvent> event, LLSD filter);
+ // Handle an event that has just been fired by communicating it
+ // to listeners, passing it across a network, etc.
+ bool fireEvent(LLPointer<LLEvent> event, LLSD filter);
public:
- class Impl;
+ class Impl;
private:
- Impl* impl;
+ Impl* impl;
};
// Interface for observable data (data that fires events)
@@ -157,38 +157,38 @@ private:
class LL_COMMON_API LLObservable
{
public:
- // Initialize with the default Dispatcher
- LLObservable();
- virtual ~LLObservable();
-
- // Replaces the existing dispatcher pointer to the new one,
- // informing the dispatcher of the change.
- virtual bool setDispatcher(LLPointer<LLEventDispatcher> dispatcher);
-
- // Returns the current dispatcher pointer.
- virtual LLEventDispatcher* getDispatcher();
-
- void addListener(LLEventListener *listener, LLSD filter = "", const LLSD& userdata = "")
- {
- if (mDispatcher.notNull()) mDispatcher->addListener(listener, filter, userdata);
- }
- void removeListener(LLEventListener *listener)
- {
- if (mDispatcher.notNull()) mDispatcher->removeListener(listener);
- }
- // Notifies the dispatcher of an event being fired.
- void fireEvent(LLPointer<LLEvent> event, LLSD filter = LLSD());
+ // Initialize with the default Dispatcher
+ LLObservable();
+ virtual ~LLObservable();
+
+ // Replaces the existing dispatcher pointer to the new one,
+ // informing the dispatcher of the change.
+ virtual bool setDispatcher(LLPointer<LLEventDispatcher> dispatcher);
+
+ // Returns the current dispatcher pointer.
+ virtual LLEventDispatcher* getDispatcher();
+
+ void addListener(LLEventListener *listener, LLSD filter = "", const LLSD& userdata = "")
+ {
+ if (mDispatcher.notNull()) mDispatcher->addListener(listener, filter, userdata);
+ }
+ void removeListener(LLEventListener *listener)
+ {
+ if (mDispatcher.notNull()) mDispatcher->removeListener(listener);
+ }
+ // Notifies the dispatcher of an event being fired.
+ void fireEvent(LLPointer<LLEvent> event, LLSD filter = LLSD());
protected:
- LLPointer<LLEventDispatcher> mDispatcher;
+ LLPointer<LLEventDispatcher> mDispatcher;
};
class LLValueChangedEvent : public LLEvent
{
public:
- LLValueChangedEvent(LLObservable* source, LLSD value) : LLEvent(source, "value_changed"), mValue(value) { }
- LLSD getValue() { return mValue; }
- LLSD mValue;
+ LLValueChangedEvent(LLObservable* source, LLSD value) : LLEvent(source, "value_changed"), mValue(value) { }
+ LLSD getValue() { return mValue; }
+ LLSD mValue;
};
} // LLOldEvents
diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp
index 3d46ef1034..8b724256b8 100644
--- a/indra/llcommon/lleventapi.cpp
+++ b/indra/llcommon/lleventapi.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-11-10
* @brief Implementation for lleventapi.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h
index 25f6becd8b..3ae820db51 100644
--- a/indra/llcommon/lleventapi.h
+++ b/indra/llcommon/lleventapi.h
@@ -5,25 +5,25 @@
* @brief LLEventAPI is the base class for every class that wraps a C++ API
* in an event API
* (see https://wiki.lindenlab.com/wiki/Incremental_Viewer_Automation/Event_API).
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 067b5e6fbc..e1fc4764f6 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-04-29
* @brief Implementation for lleventcoro.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index c0fe8b094f..492563bb98 100644
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-04-29
* @brief Utilities to interface between coroutines and events.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -152,7 +152,7 @@ LLSD postAndSuspendWithTimeout(const LLSD& event,
F32 timeout, const LLSD& timeoutResult);
/// Suspend the coroutine until an event is fired on the identified pump
-/// or the timeout duration has elapsed. If the timeout duration
+/// or the timeout duration has elapsed. If the timeout duration
/// elapses the specified LLSD is returned.
inline
LLSD suspendUntilEventOnWithTimeout(const LLEventPumpOrPumpName& suspendPumpOrName,
diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp
index da96de18f7..9dd6864cff 100644
--- a/indra/llcommon/lleventdispatcher.cpp
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-06-18
* @brief Implementation for lleventdispatcher.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -755,7 +755,7 @@ std::string LLEventDispatcher::getState() const
bool LLEventDispatcher::setState(SetState&, const std::string& state) const
{
- // If SetState is instantiated at multiple levels of function call, ignore
+ // If SetState is instantiated at multiple levels of function call, ignore
// the lower-level call because the outer call presumably provides more
// context.
if (mState.get())
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h
index a82bc7a69b..4c3c0f3414 100644
--- a/indra/llcommon/lleventdispatcher.h
+++ b/indra/llcommon/lleventdispatcher.h
@@ -6,25 +6,25 @@
* useful when you have a single LLEventPump listener on which you can
* request different operations, vs. instantiating a different
* LLEventPump for each such operation.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -201,7 +201,7 @@ public:
template <typename R, class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG))
@@ -213,7 +213,7 @@ public:
template <typename R, class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG) const)
@@ -226,7 +226,7 @@ public:
template <class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG))
@@ -238,7 +238,7 @@ public:
template <class CLASS, typename ARG,
typename = typename std::enable_if<
! std::is_same<typename std::decay<ARG>::type, LLSD>::value
- >::type>
+ >::type>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG) const)
@@ -247,7 +247,7 @@ public:
}
// non-const binary (or more) method
- template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG0, ARG1, ARGS...))
@@ -256,7 +256,7 @@ public:
}
// const binary (or more) method
- template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <typename R, class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
R (CLASS::*method)(ARG0, ARG1, ARGS...) const)
@@ -265,7 +265,7 @@ public:
}
// non-const binary (or more) method returning void
- template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG0, ARG1, ARGS...))
@@ -274,7 +274,7 @@ public:
}
// const binary (or more) method returning void
- template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
+ template <class CLASS, typename ARG0, typename ARG1, typename... ARGS>
void add(const std::string& name,
const std::string& desc,
void (CLASS::*method)(ARG0, ARG1, ARGS...) const)
@@ -371,7 +371,7 @@ public:
const InstanceGetter& getter, const LLSD& params,
const LLSD& defaults=LLSD());
- //@}
+ //@}
/// Unregister a callable
bool remove(const std::string& name);
diff --git a/indra/llcommon/lleventemitter.h b/indra/llcommon/lleventemitter.h
index cd82fc56f9..14160e1e76 100644
--- a/indra/llcommon/lleventemitter.h
+++ b/indra/llcommon/lleventemitter.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lleventemitter.h
* @brief General event emitter class
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -38,65 +38,65 @@
#include "stdtypes.h"
///////////////////////////////////////////////////////////////////////////////
-// templatized emitter class
+// templatized emitter class
template < class T >
class eventEmitter
{
- public:
- typedef typename T::EventType EventType;
- typedef std::list< T* > ObserverContainer;
- typedef void ( T::*observerMethod )( const EventType& );
+ public:
+ typedef typename T::EventType EventType;
+ typedef std::list< T* > ObserverContainer;
+ typedef void ( T::*observerMethod )( const EventType& );
- protected:
- ObserverContainer observers;
+ protected:
+ ObserverContainer observers;
- public:
- eventEmitter () { };
+ public:
+ eventEmitter () { };
- ~eventEmitter () { };
+ ~eventEmitter () { };
- ///////////////////////////////////////////////////////////////////////////////
- //
- BOOL addObserver ( T* observerIn )
- {
- if ( ! observerIn )
- return FALSE;
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ BOOL addObserver ( T* observerIn )
+ {
+ if ( ! observerIn )
+ return FALSE;
- // check if observer already exists
- if ( std::find ( observers.begin (), observers.end (), observerIn ) != observers.end () )
- return FALSE;
+ // check if observer already exists
+ if ( std::find ( observers.begin (), observers.end (), observerIn ) != observers.end () )
+ return FALSE;
- // save it
- observers.push_back ( observerIn );
+ // save it
+ observers.push_back ( observerIn );
- return true;
- };
+ return true;
+ };
- ///////////////////////////////////////////////////////////////////////////////
- //
- BOOL remObserver ( T* observerIn )
- {
- if ( ! observerIn )
- return FALSE;
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ BOOL remObserver ( T* observerIn )
+ {
+ if ( ! observerIn )
+ return FALSE;
- observers.remove ( observerIn );
+ observers.remove ( observerIn );
- return TRUE;
- };
+ return TRUE;
+ };
- ///////////////////////////////////////////////////////////////////////////////
- //
- void update ( observerMethod method, const EventType& msgIn )
- {
- typename std::list< T* >::iterator iter = observers.begin ();
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ void update ( observerMethod method, const EventType& msgIn )
+ {
+ typename std::list< T* >::iterator iter = observers.begin ();
- while ( iter != observers.end () )
- {
- ( ( *iter )->*method ) ( msgIn );
+ while ( iter != observers.end () )
+ {
+ ( ( *iter )->*method ) ( msgIn );
- ++iter;
- };
- };
+ ++iter;
+ };
+ };
};
#endif // lleventemitter_h
diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp
index 4cded7f88e..604ee8a42d 100644
--- a/indra/llcommon/lleventfilter.cpp
+++ b/indra/llcommon/lleventfilter.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-03-05
* @brief Implementation for lleventfilter.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
index 1fb41e0297..5c45144fad 100644
--- a/indra/llcommon/lleventfilter.h
+++ b/indra/llcommon/lleventfilter.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-03-05
* @brief Define LLEventFilter: LLEventStream subclass with conditions
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -149,11 +149,11 @@ public:
/**
* Like actionAfter(), but where the desired Action is a particular event
* for all listeners. Pass the timeout time and the desired @a event data.
- *
+ *
* Suppose the timeout should only be satisfied by a particular event, but
* the ultimate listener must see all other incoming events as well, plus
* the timeout @a event if any:
- *
+ *
* @code
* some LLEventMatching LLEventMatching
* event ---> for particular ---> LLEventTimeout ---> for timeout
@@ -161,7 +161,7 @@ public:
* \ \ ultimate
* `-----------------------------------------------------> listener
* @endcode
- *
+ *
* Since a given listener can listen on more than one LLEventPump, we can
* set things up so it sees the set union of events from LLEventTimeout
* and the original event source. However, as LLEventTimeout passes
@@ -197,8 +197,8 @@ private:
/**
* Production implementation of LLEventTimoutBase.
- *
- * @NOTE: Caution should be taken when using the LLEventTimeout(LLEventPump &)
+ *
+ * @NOTE: Caution should be taken when using the LLEventTimeout(LLEventPump &)
* constructor to ensure that the upstream event pump is not an LLEventMaildrop
* or any other kind of store and forward pump which may have events outstanding.
* Using this constructor will cause the upstream event pump to fire any pending
@@ -207,7 +207,7 @@ private:
* from the event pump and attached using the listen method.
* See llcoro::suspendUntilEventOnWithTimeout() for an example.
*/
-
+
class LL_COMMON_API LLEventTimeout: public LLEventTimeoutBase
{
public:
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 70931f3a65..5b4e69659d 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-09-12
* @brief Implementation for llevents.
- *
+ *
* $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$
*/
@@ -423,8 +423,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
float nodePosition = 1.0;
- // if the supplied name is empty we are not interested in the ordering mechanism
- // and can bypass attempting to find the optimal location to insert the new
+ // if the supplied name is empty we are not interested in the ordering mechanism
+ // and can bypass attempting to find the optimal location to insert the new
// listener. We'll just tack it on to the end.
if (!name.empty()) // should be the same as testing against ANONYMOUS
{
@@ -569,12 +569,12 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.
LLBoundListener bound = mSignal->connect(nodePosition, listener);
-
+
if (!name.empty())
{ // note that we are not tracking anonymous listeners here either.
- // This means that it is the caller's responsibility to either assign
- // to a TempBoundListerer (scoped_connection) or manually disconnect
- // when done.
+ // This means that it is the caller's responsibility to either assign
+ // to a TempBoundListerer (scoped_connection) or manually disconnect
+ // when done.
mConnections[name] = bound;
}
return bound;
@@ -641,9 +641,9 @@ bool LLEventMailDrop::post(const LLSD& event)
{
// forward the call to our base class
bool posted = LLEventStream::post(event);
-
+
if (!posted)
- { // if the event was not handled we will save it for later so that it can
+ { // if the event was not handled we will save it for later so that it can
// be posted to any future listeners when they attach.
mEventHistory.push_back(event);
}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index bebcfacdcb..9a0a6863f0 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/bind.hpp>
@@ -310,9 +310,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.
*/
@@ -541,10 +541,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.
*/
@@ -607,7 +607,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;
@@ -660,21 +660,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 f575a7b6bf..33fafffefd 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$
*/
@@ -33,20 +33,20 @@
//////////////////////////////////////////////////////////////////////////////
//
-// LLEventTimer Implementation
+// LLEventTimer Implementation
//
//////////////////////////////////////////////////////////////////////////////
LLEventTimer::LLEventTimer(F32 period)
: mEventTimer()
{
- mPeriod = period;
+ mPeriod = period;
}
LLEventTimer::LLEventTimer(const LLDate& time)
: mEventTimer()
{
- mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
+ mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
}
@@ -55,19 +55,19 @@ LLEventTimer::~LLEventTimer()
}
//static
-void LLEventTimer::updateClass()
+void LLEventTimer::updateClass()
{
- for (auto& timer : instance_snapshot())
- {
- F32 et = timer.mEventTimer.getElapsedTimeF32();
- if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
- timer.mEventTimer.reset();
- if ( timer.tick() )
- {
- delete &timer;
- }
- }
- }
+ for (auto& timer : instance_snapshot())
+ {
+ F32 et = timer.mEventTimer.getElapsedTimeF32();
+ if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
+ timer.mEventTimer.reset();
+ if ( timer.tick() )
+ {
+ delete &timer;
+ }
+ }
+ }
}
diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h
index dbbfe0c6e6..ed6f10d5e1 100644
--- a/indra/llcommon/lleventtimer.h
+++ b/indra/llcommon/lleventtimer.h
@@ -1,30 +1,30 @@
-/**
+/**
* @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$
*/
-#ifndef LL_EVENTTIMER_H
+#ifndef LL_EVENTTIMER_H
#define LL_EVENTTIMER_H
#include "stdtypes.h"
@@ -37,42 +37,42 @@ class LL_COMMON_API LLEventTimer : public LLInstanceTracker<LLEventTimer>
{
public:
- LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
- LLEventTimer(const LLDate& time);
- virtual ~LLEventTimer();
+ LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
+ LLEventTimer(const LLDate& time);
+ virtual ~LLEventTimer();
- //function to be called at the supplied frequency
- // Normally return FALSE; TRUE will delete the timer after the function returns.
- virtual BOOL tick() = 0;
+ //function to be called at the supplied frequency
+ // Normally return FALSE; TRUE will delete the timer after the function returns.
+ virtual BOOL tick() = 0;
- static void updateClass();
+ static void updateClass();
- /// Schedule recurring calls to generic callable every period seconds.
- /// Returns a pointer; if you delete it, cancels the recurring calls.
- template <typename CALLABLE>
- static LLEventTimer* run_every(F32 period, const CALLABLE& callable);
+ /// Schedule recurring calls to generic callable every period seconds.
+ /// Returns a pointer; if you delete it, cancels the recurring calls.
+ template <typename CALLABLE>
+ static LLEventTimer* run_every(F32 period, const CALLABLE& callable);
- /// Schedule a future call to generic callable. Returns a pointer.
- /// CAUTION: The object referenced by that pointer WILL BE DELETED once
- /// the callback has been called! LLEventTimer::getInstance(pointer) (NOT
- /// pointer->getInstance(pointer)!) can be used to test whether the
- /// pointer is still valid. If it is, deleting it will cancel the
- /// callback.
- template <typename CALLABLE>
- static LLEventTimer* run_at(const LLDate& time, const CALLABLE& callable);
+ /// Schedule a future call to generic callable. Returns a pointer.
+ /// CAUTION: The object referenced by that pointer WILL BE DELETED once
+ /// the callback has been called! LLEventTimer::getInstance(pointer) (NOT
+ /// pointer->getInstance(pointer)!) can be used to test whether the
+ /// pointer is still valid. If it is, deleting it will cancel the
+ /// callback.
+ template <typename CALLABLE>
+ static LLEventTimer* run_at(const LLDate& time, const CALLABLE& callable);
- /// Like run_at(), but after a time delta rather than at a timestamp.
- /// Same CAUTION.
- template <typename CALLABLE>
- static LLEventTimer* run_after(F32 interval, const CALLABLE& callable);
+ /// Like run_at(), but after a time delta rather than at a timestamp.
+ /// Same CAUTION.
+ template <typename CALLABLE>
+ static LLEventTimer* run_after(F32 interval, const CALLABLE& callable);
protected:
- LLTimer mEventTimer;
- F32 mPeriod;
+ LLTimer mEventTimer;
+ F32 mPeriod;
private:
- template <typename CALLABLE>
- class Generic;
+ template <typename CALLABLE>
+ class Generic;
};
template <typename CALLABLE>
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 0787bde57f..c0154a569f 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-08-12
* @brief Implementation for llexception.
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
@@ -99,8 +99,8 @@ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
const auto stack = to_string(boost::stacktrace::stacktrace());
- LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code
- << "\n Stack trace: \n"
+ LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code
+ << "\n Stack trace: \n"
<< stack << LL_ENDL;
if (code == STATUS_MSC_EXCEPTION)
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index 375bea4a57..68e609444e 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-06-29
* @brief Types needed for generic exception handling
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 2612d0f07c..722743f453 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfasttimer.cpp
* @brief Implementation of the fast timer.
*
* $LicenseInfo:firstyear=2004&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$
*/
@@ -49,8 +49,8 @@
#include "lltimer.h"
#elif LL_DARWIN
#include <sys/time.h>
-#include "lltimer.h" // get_clock_count()
-#else
+#include "lltimer.h" // get_clock_count()
+#else
#error "architecture not supported"
#endif
@@ -60,7 +60,7 @@ namespace LLTrace
//////////////////////////////////////////////////////////////////////////////
// statics
-bool BlockTimer::sLog = false;
+bool BlockTimer::sLog = false;
std::string BlockTimer::sLogName = "";
bool BlockTimer::sMetricLog = false;
@@ -70,83 +70,83 @@ U64 BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
U64 BlockTimer::sClockResolution = 1000000; // Microsecond resolution
#endif
-static LLMutex* sLogLock = NULL;
+static LLMutex* sLogLock = NULL;
static std::queue<LLSD> sLogQueue;
-block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& id)
-{
- return block_timer_tree_df_iterator_t(&id,
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& id)
+{
+ return block_timer_tree_df_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
}
-block_timer_tree_df_iterator_t end_block_timer_tree_df()
-{
- return block_timer_tree_df_iterator_t();
+block_timer_tree_df_iterator_t end_block_timer_tree_df()
+{
+ return block_timer_tree_df_iterator_t();
}
-block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& id)
-{
- return block_timer_tree_df_post_iterator_t(&id,
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& id)
+{
+ return block_timer_tree_df_post_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
}
-block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post()
-{
- return block_timer_tree_df_post_iterator_t();
+block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post()
+{
+ return block_timer_tree_df_post_iterator_t();
}
block_timer_tree_bf_iterator_t begin_block_timer_tree_bf(BlockTimerStatHandle& id)
-{
- return block_timer_tree_bf_iterator_t(&id,
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+{
+ return block_timer_tree_bf_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
}
block_timer_tree_bf_iterator_t end_block_timer_tree_bf()
- {
- return block_timer_tree_bf_iterator_t();
- }
-
-block_timer_tree_df_iterator_t begin_timer_tree(BlockTimerStatHandle& id)
- {
- return block_timer_tree_df_iterator_t(&id,
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
- boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
- }
-
-block_timer_tree_df_iterator_t end_timer_tree()
- {
- return block_timer_tree_df_iterator_t();
+ {
+ return block_timer_tree_bf_iterator_t();
+ }
+
+block_timer_tree_df_iterator_t begin_timer_tree(BlockTimerStatHandle& id)
+ {
+ return block_timer_tree_df_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+ }
+
+block_timer_tree_df_iterator_t end_timer_tree()
+ {
+ return block_timer_tree_df_iterator_t();
}
// sort child timers by name
struct SortTimerByName
- {
- bool operator()(const BlockTimerStatHandle* i1, const BlockTimerStatHandle* i2)
- {
- return i1->getName() < i2->getName();
- }
+ {
+ bool operator()(const BlockTimerStatHandle* i1, const BlockTimerStatHandle* i2)
+ {
+ return i1->getName() < i2->getName();
+ }
};
static BlockTimerStatHandle sRootTimer("root", NULL);
BlockTimerStatHandle& BlockTimer::getRootTimeBlock()
{
- return sRootTimer;
- }
+ return sRootTimer;
+ }
void BlockTimer::pushLog(LLSD log)
{
- LLMutexLock lock(sLogLock);
+ LLMutexLock lock(sLogLock);
- sLogQueue.push(log);
+ sLogQueue.push(log);
}
void BlockTimer::setLogLock(LLMutex* lock)
{
- sLogLock = lock;
+ sLogLock = lock;
}
@@ -154,40 +154,40 @@ void BlockTimer::setLogLock(LLMutex* lock)
#if (LL_DARWIN || LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
U64 BlockTimer::countsPerSecond()
{
- return sClockResolution;
+ return sClockResolution;
}
#else // windows or x86-mac or x86-linux
U64 BlockTimer::countsPerSecond()
{
#if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
- //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
- static LLUnit<U64, LLUnits::Hertz> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency();
- return sCPUClockFrequency.value();
+ //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
+ static LLUnit<U64, LLUnits::Hertz> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency();
+ return sCPUClockFrequency.value();
#else
- // If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
- // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
- // since that would change displayed MHz stats for CPUs
- static bool firstcall = true;
- static U64 sCPUClockFrequency;
- if (firstcall)
- {
- QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
- firstcall = false;
- }
- return sCPUClockFrequency.value();
+ // If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
+ // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
+ // since that would change displayed MHz stats for CPUs
+ static bool firstcall = true;
+ static U64 sCPUClockFrequency;
+ if (firstcall)
+ {
+ QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
+ firstcall = false;
+ }
+ return sCPUClockFrequency.value();
#endif
}
#endif
BlockTimerStatHandle::BlockTimerStatHandle(const char* name, const char* description)
-: StatType<TimeBlockAccumulator>(name, description)
+: StatType<TimeBlockAccumulator>(name, description)
{}
TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const
{
- TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex());
- llassert(nodep);
- return *nodep;
+ TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex());
+ llassert(nodep);
+ return *nodep;
}
@@ -223,71 +223,71 @@ void BlockTimer::bootstrapTimerTree()
void BlockTimer::incrementalUpdateTimerTree()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimer::getRootTimeBlock());
- it != end_block_timer_tree_df_post();
- ++it)
- {
- BlockTimerStatHandle* timerp = *it;
-
- // sort timers by time last called, so call graph makes sense
- TimeBlockTreeNode& tree_node = timerp->getTreeNode();
- if (tree_node.mNeedsSorting)
+ for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimer::getRootTimeBlock());
+ it != end_block_timer_tree_df_post();
+ ++it)
+ {
+ BlockTimerStatHandle* timerp = *it;
+
+ // sort timers by time last called, so call graph makes sense
+ TimeBlockTreeNode& tree_node = timerp->getTreeNode();
+ if (tree_node.mNeedsSorting)
{
- std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName());
+ std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName());
}
- // skip root timer
- if (timerp != &BlockTimer::getRootTimeBlock())
+ // skip root timer
+ if (timerp != &BlockTimer::getRootTimeBlock())
{
- TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator();
+ TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator();
- if (accumulator.mMoveUpTree)
+ if (accumulator.mMoveUpTree)
{
- // since ancestors have already been visited, re-parenting won't affect tree traversal
- //step up tree, bringing our descendants with us
- LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
- " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
- timerp->setParent(timerp->getParent()->getParent());
- accumulator.mParent = timerp->getParent();
- accumulator.mMoveUpTree = false;
-
- // don't bubble up any ancestors until descendants are done bubbling up
- // as ancestors may call this timer only on certain paths, so we want to resolve
- // child-most block locations before their parents
- it.skipAncestors();
- }
- }
- }
+ // since ancestors have already been visited, re-parenting won't affect tree traversal
+ //step up tree, bringing our descendants with us
+ LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
+ " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
+ timerp->setParent(timerp->getParent()->getParent());
+ accumulator.mParent = timerp->getParent();
+ accumulator.mMoveUpTree = false;
+
+ // don't bubble up any ancestors until descendants are done bubbling up
+ // as ancestors may call this timer only on certain paths, so we want to resolve
+ // child-most block locations before their parents
+ it.skipAncestors();
+ }
+ }
+ }
}
void BlockTimer::updateTimes()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- // walk up stack of active timers and accumulate current time while leaving timing structures active
- BlockTimerStackRecord* stack_record = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- if (!stack_record) return;
-
- U64 cur_time = getCPUClockCount64();
- BlockTimer* cur_timer = stack_record->mActiveTimer;
- TimeBlockAccumulator* accumulator = &stack_record->mTimeBlock->getCurrentAccumulator();
-
- while(cur_timer
- && cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
- {
- U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
- cur_timer->mStartTime = cur_time;
-
- accumulator->mTotalTimeCounter += cumulative_time_delta;
- accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
- stack_record->mChildTime = 0;
-
- stack_record = &cur_timer->mParentTimerData;
- accumulator = &stack_record->mTimeBlock->getCurrentAccumulator();
- cur_timer = stack_record->mActiveTimer;
-
- stack_record->mChildTime += cumulative_time_delta;
- }
+ // walk up stack of active timers and accumulate current time while leaving timing structures active
+ BlockTimerStackRecord* stack_record = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!stack_record) return;
+
+ U64 cur_time = getCPUClockCount64();
+ BlockTimer* cur_timer = stack_record->mActiveTimer;
+ TimeBlockAccumulator* accumulator = &stack_record->mTimeBlock->getCurrentAccumulator();
+
+ while(cur_timer
+ && cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
+ {
+ U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+ cur_timer->mStartTime = cur_time;
+
+ accumulator->mTotalTimeCounter += cumulative_time_delta;
+ accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
+ stack_record->mChildTime = 0;
+
+ stack_record = &cur_timer->mParentTimerData;
+ accumulator = &stack_record->mTimeBlock->getCurrentAccumulator();
+ cur_timer = stack_record->mActiveTimer;
+
+ stack_record->mChildTime += cumulative_time_delta;
+ }
}
static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times");
@@ -297,192 +297,192 @@ static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times"
void BlockTimer::processTimes()
{
#if LL_TRACE_ENABLED
- LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
- get_clock_count(); // good place to calculate clock frequency
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
+ get_clock_count(); // good place to calculate clock frequency
- // set up initial tree
- bootstrapTimerTree();
+ // set up initial tree
+ bootstrapTimerTree();
- incrementalUpdateTimerTree();
+ incrementalUpdateTimerTree();
- updateTimes();
+ updateTimes();
- // reset for next frame
- for (auto& base : BlockTimerStatHandle::instance_snapshot())
- {
- // because of indirect derivation from LLInstanceTracker, have to downcast
- BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(base);
- TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
+ // reset for next frame
+ for (auto& base : BlockTimerStatHandle::instance_snapshot())
+ {
+ // because of indirect derivation from LLInstanceTracker, have to downcast
+ BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(base);
+ TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
- accumulator.mLastCaller = NULL;
- accumulator.mMoveUpTree = false;
- }
+ accumulator.mLastCaller = NULL;
+ accumulator.mMoveUpTree = false;
+ }
#endif
}
std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::beginChildren()
- {
- return getTreeNode().mChildren.begin();
- }
+ {
+ return getTreeNode().mChildren.begin();
+ }
std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::endChildren()
- {
- return getTreeNode().mChildren.end();
+ {
+ return getTreeNode().mChildren.end();
}
std::vector<BlockTimerStatHandle*>& BlockTimerStatHandle::getChildren()
{
- return getTreeNode().mChildren;
- }
+ return getTreeNode().mChildren;
+ }
bool BlockTimerStatHandle::hasChildren()
{
- return ! getTreeNode().mChildren.empty();
+ return ! getTreeNode().mChildren.empty();
}
// static
void BlockTimer::logStats()
{
- // get ready for next frame
- if (sLog)
- { //output current frame counts to performance log
-
- static S32 call_count = 0;
- if (call_count % 100 == 0)
- {
- LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64() / (F64HertzImplicit)LLProcessorInfo().getCPUFrequency()) << LL_ENDL;
- }
- call_count++;
-
- F64Seconds total_time(0);
- LLSD sd;
-
- {
- for (auto& base : BlockTimerStatHandle::instance_snapshot())
- {
- // because of indirect derivation from LLInstanceTracker, have to downcast
- BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(base);
- LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
- sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecording().getSum(timer).value());
- sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecording().getSum(timer.callCount()));
-
- // computing total time here because getting the root timer's getCountHistory
- // doesn't work correctly on the first frame
- total_time += frame_recording.getLastRecording().getSum(timer);
- }
- }
-
- sd["Total"]["Time"] = (LLSD::Real) total_time.value();
- sd["Total"]["Calls"] = (LLSD::Integer) 1;
-
- {
- LLMutexLock lock(sLogLock);
- sLogQueue.push(sd);
- }
- }
+ // get ready for next frame
+ if (sLog)
+ { //output current frame counts to performance log
+
+ static S32 call_count = 0;
+ if (call_count % 100 == 0)
+ {
+ LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << LL_ENDL;
+ LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL;
+ LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL;
+ LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL;
+ LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64() / (F64HertzImplicit)LLProcessorInfo().getCPUFrequency()) << LL_ENDL;
+ }
+ call_count++;
+
+ F64Seconds total_time(0);
+ LLSD sd;
+
+ {
+ for (auto& base : BlockTimerStatHandle::instance_snapshot())
+ {
+ // because of indirect derivation from LLInstanceTracker, have to downcast
+ BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(base);
+ LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+ sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecording().getSum(timer).value());
+ sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecording().getSum(timer.callCount()));
+
+ // computing total time here because getting the root timer's getCountHistory
+ // doesn't work correctly on the first frame
+ total_time += frame_recording.getLastRecording().getSum(timer);
+ }
+ }
+
+ sd["Total"]["Time"] = (LLSD::Real) total_time.value();
+ sd["Total"]["Calls"] = (LLSD::Integer) 1;
+
+ {
+ LLMutexLock lock(sLogLock);
+ sLogQueue.push(sd);
+ }
+ }
}
//static
void BlockTimer::dumpCurTimes()
{
- LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
- LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
-
- // walk over timers in depth order and output timings
- for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimer::getRootTimeBlock());
- it != end_timer_tree();
- ++it)
- {
- BlockTimerStatHandle* timerp = (*it);
- F64Seconds total_time = last_frame_recording.getSum(*timerp);
- U32 num_calls = last_frame_recording.getSum(timerp->callCount());
-
- // Don't bother with really brief times, keep output concise
- if (total_time < F32Milliseconds(0.1f)) continue;
-
- std::ostringstream out_str;
- BlockTimerStatHandle* parent_timerp = timerp;
- while(parent_timerp && parent_timerp != parent_timerp->getParent())
- {
- out_str << "\t";
- parent_timerp = parent_timerp->getParent();
- }
-
- out_str << timerp->getName() << " "
- << std::setprecision(3) << total_time.valueInUnits<LLUnits::Milliseconds>() << " ms, "
- << num_calls << " calls";
-
- LL_INFOS() << out_str.str() << LL_ENDL;
+ LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+ LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
+
+ // walk over timers in depth order and output timings
+ for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimer::getRootTimeBlock());
+ it != end_timer_tree();
+ ++it)
+ {
+ BlockTimerStatHandle* timerp = (*it);
+ F64Seconds total_time = last_frame_recording.getSum(*timerp);
+ U32 num_calls = last_frame_recording.getSum(timerp->callCount());
+
+ // Don't bother with really brief times, keep output concise
+ if (total_time < F32Milliseconds(0.1f)) continue;
+
+ std::ostringstream out_str;
+ BlockTimerStatHandle* parent_timerp = timerp;
+ while(parent_timerp && parent_timerp != parent_timerp->getParent())
+ {
+ out_str << "\t";
+ parent_timerp = parent_timerp->getParent();
+ }
+
+ out_str << timerp->getName() << " "
+ << std::setprecision(3) << total_time.valueInUnits<LLUnits::Milliseconds>() << " ms, "
+ << num_calls << " calls";
+
+ LL_INFOS() << out_str.str() << LL_ENDL;
}
}
//static
void BlockTimer::writeLog(std::ostream& os)
{
- while (!sLogQueue.empty())
- {
- LLSD& sd = sLogQueue.front();
- LLSDSerialize::toXML(sd, os);
- LLMutexLock lock(sLogLock);
- sLogQueue.pop();
- }
+ while (!sLogQueue.empty())
+ {
+ LLSD& sd = sLogQueue.front();
+ LLSDSerialize::toXML(sd, os);
+ LLMutexLock lock(sLogLock);
+ sLogQueue.pop();
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TimeBlockAccumulator
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-TimeBlockAccumulator::TimeBlockAccumulator()
-: mTotalTimeCounter(0),
- mSelfTimeCounter(0),
- mCalls(0),
- mLastCaller(NULL),
- mActiveCount(0),
- mMoveUpTree(false),
- mParent(NULL)
+TimeBlockAccumulator::TimeBlockAccumulator()
+: mTotalTimeCounter(0),
+ mSelfTimeCounter(0),
+ mCalls(0),
+ mLastCaller(NULL),
+ mActiveCount(0),
+ mMoveUpTree(false),
+ mParent(NULL)
{}
void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBufferAppendType append_type )
{
#if LL_TRACE_ENABLED
- // we can't merge two unrelated time block samples, as that will screw with the nested timings
- // due to the call hierarchy of each thread
- llassert(append_type == SEQUENTIAL);
- mTotalTimeCounter += other.mTotalTimeCounter;
- mSelfTimeCounter += other.mSelfTimeCounter;
- mCalls += other.mCalls;
- mLastCaller = other.mLastCaller;
- mActiveCount = other.mActiveCount;
- mMoveUpTree = other.mMoveUpTree;
- mParent = other.mParent;
+ // we can't merge two unrelated time block samples, as that will screw with the nested timings
+ // due to the call hierarchy of each thread
+ llassert(append_type == SEQUENTIAL);
+ mTotalTimeCounter += other.mTotalTimeCounter;
+ mSelfTimeCounter += other.mSelfTimeCounter;
+ mCalls += other.mCalls;
+ mLastCaller = other.mLastCaller;
+ mActiveCount = other.mActiveCount;
+ mMoveUpTree = other.mMoveUpTree;
+ mParent = other.mParent;
#endif
}
void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
{
- mCalls = 0;
- mSelfTimeCounter = 0;
- mTotalTimeCounter = 0;
+ mCalls = 0;
+ mSelfTimeCounter = 0;
+ mTotalTimeCounter = 0;
- if (other)
+ if (other)
{
- mLastCaller = other->mLastCaller;
- mActiveCount = other->mActiveCount;
- mMoveUpTree = other->mMoveUpTree;
- mParent = other->mParent;
- }
+ mLastCaller = other->mLastCaller;
+ mActiveCount = other->mActiveCount;
+ mMoveUpTree = other->mMoveUpTree;
+ mParent = other->mParent;
+ }
}
F64Seconds BlockTimer::getElapsedTime()
{
- U64 total_time = getCPUClockCount64() - mStartTime;
+ U64 total_time = getCPUClockCount64() - mStartTime;
- return F64Seconds((F64)total_time / (F64)BlockTimer::countsPerSecond());
+ return F64Seconds((F64)total_time / (F64)BlockTimer::countsPerSecond());
}
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 9bd93d7240..17ad37b031 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2004&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$
*/
@@ -51,77 +51,77 @@ class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer);
class BlockTimer
{
public:
- typedef BlockTimer self_t;
- typedef class BlockTimerStatHandle DeclareTimer;
+ typedef BlockTimer self_t;
+ typedef class BlockTimerStatHandle DeclareTimer;
- ~BlockTimer();
+ ~BlockTimer();
- F64Seconds getElapsedTime();
+ F64Seconds getElapsedTime();
- //////////////////////////////////////////////////////////////////////////////
- //
- // Important note: These implementations must be FAST!
- //
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // Important note: These implementations must be FAST!
+ //
#if LL_WINDOWS
- //
- // Windows implementation of CPU clock
- //
-
- //
- // NOTE: put back in when we aren't using platform sdk anymore
- //
- // because MS has different signatures for these functions in winnt.h
- // need to rename them to avoid conflicts
- //#define _interlockedbittestandset _renamed_interlockedbittestandset
- //#define _interlockedbittestandreset _renamed_interlockedbittestandreset
- //#include <intrin.h>
- //#undef _interlockedbittestandset
- //#undef _interlockedbittestandreset
-
- //inline U32 getCPUClockCount32()
- //{
- // U64 time_stamp = __rdtsc();
- // return (U32)(time_stamp >> 8);
- //}
- //
- //// return full timer value, *not* shifted by 8 bits
- //inline U64 getCPUClockCount64()
- //{
- // return __rdtsc();
- //}
-
-
-
- // shift off lower 8 bits for lower resolution but longer term timing
- // on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
+ //
+ // Windows implementation of CPU clock
+ //
+
+ //
+ // NOTE: put back in when we aren't using platform sdk anymore
+ //
+ // because MS has different signatures for these functions in winnt.h
+ // need to rename them to avoid conflicts
+ //#define _interlockedbittestandset _renamed_interlockedbittestandset
+ //#define _interlockedbittestandreset _renamed_interlockedbittestandreset
+ //#include <intrin.h>
+ //#undef _interlockedbittestandset
+ //#undef _interlockedbittestandreset
+
+ //inline U32 getCPUClockCount32()
+ //{
+ // U64 time_stamp = __rdtsc();
+ // return (U32)(time_stamp >> 8);
+ //}
+ //
+ //// return full timer value, *not* shifted by 8 bits
+ //inline U64 getCPUClockCount64()
+ //{
+ // return __rdtsc();
+ //}
+
+
+
+ // shift off lower 8 bits for lower resolution but longer term timing
+ // on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
#if LL_FASTTIMER_USE_RDTSC
- static U32 getCPUClockCount32()
- {
- unsigned __int64 val = __rdtsc();
- val = val >> 8;
- return static_cast<U32>(val);
- }
-
- // return full timer value, *not* shifted by 8 bits
- static U64 getCPUClockCount64()
- {
- return static_cast<U64>( __rdtsc() );
- }
+ static U32 getCPUClockCount32()
+ {
+ unsigned __int64 val = __rdtsc();
+ val = val >> 8;
+ return static_cast<U32>(val);
+ }
+
+ // return full timer value, *not* shifted by 8 bits
+ static U64 getCPUClockCount64()
+ {
+ return static_cast<U64>( __rdtsc() );
+ }
#else
- //U64 get_clock_count(); // in lltimer.cpp
- // These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
- static U32 getCPUClockCount32()
- {
- return (U32)(get_clock_count()>>8);
- }
-
- static U64 getCPUClockCount64()
- {
- return get_clock_count();
- }
+ //U64 get_clock_count(); // in lltimer.cpp
+ // These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
+ static U32 getCPUClockCount32()
+ {
+ return (U32)(get_clock_count()>>8);
+ }
+
+ static U64 getCPUClockCount64()
+ {
+ return get_clock_count();
+ }
#endif
@@ -129,142 +129,142 @@ public:
#if (LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
- //
- // Linux implementation of CPU clock - non-x86.
- // This is accurate but SLOW! Only use out of desperation.
- //
- // Try to use the MONOTONIC clock if available, this is a constant time counter
- // with nanosecond resolution (but not necessarily accuracy) and attempts are
- // made to synchronize this value between cores at kernel start. It should not
- // be affected by CPU frequency. If not available use the REALTIME clock, but
- // this may be affected by NTP adjustments or other user activity affecting
- // the system time.
- static U64 getCPUClockCount64()
- {
- struct timespec tp;
+ //
+ // Linux implementation of CPU clock - non-x86.
+ // This is accurate but SLOW! Only use out of desperation.
+ //
+ // Try to use the MONOTONIC clock if available, this is a constant time counter
+ // with nanosecond resolution (but not necessarily accuracy) and attempts are
+ // made to synchronize this value between cores at kernel start. It should not
+ // be affected by CPU frequency. If not available use the REALTIME clock, but
+ // this may be affected by NTP adjustments or other user activity affecting
+ // the system time.
+ static U64 getCPUClockCount64()
+ {
+ struct timespec tp;
#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time?
- if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME
+ if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME
#endif
- clock_gettime(CLOCK_REALTIME,&tp);
+ clock_gettime(CLOCK_REALTIME,&tp);
- return (tp.tv_sec*sClockResolution)+tp.tv_nsec;
- }
+ return (tp.tv_sec*sClockResolution)+tp.tv_nsec;
+ }
- static U32 getCPUClockCount32()
- {
- return (U32)(getCPUClockCount64() >> 8);
- }
+ static U32 getCPUClockCount32()
+ {
+ return (U32)(getCPUClockCount64() >> 8);
+ }
#endif // (LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
#if (LL_LINUX || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
- //
- // Mac+Linux FAST x86 implementation of CPU clock
- static U32 getCPUClockCount32()
- {
- U32 low(0),high(0);
- __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
- return (low>>8) | (high<<24);
- }
-
- static U64 getCPUClockCount64()
- {
- U32 low(0),high(0);
- __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
- return (U64)low | ( ((U64)high) << 32);
- }
+ //
+ // Mac+Linux FAST x86 implementation of CPU clock
+ static U32 getCPUClockCount32()
+ {
+ U32 low(0),high(0);
+ __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
+ return (low>>8) | (high<<24);
+ }
+
+ static U64 getCPUClockCount64()
+ {
+ U32 low(0),high(0);
+ __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
+ return (U64)low | ( ((U64)high) << 32);
+ }
#endif
- static BlockTimerStatHandle& getRootTimeBlock();
- static void pushLog(LLSD sd);
- static void setLogLock(class LLMutex* mutex);
- static void writeLog(std::ostream& os);
- static void updateTimes();
-
- static U64 countsPerSecond();
+ static BlockTimerStatHandle& getRootTimeBlock();
+ static void pushLog(LLSD sd);
+ static void setLogLock(class LLMutex* mutex);
+ static void writeLog(std::ostream& os);
+ static void updateTimes();
+
+ static U64 countsPerSecond();
- // updates cumulative times and hierarchy,
- // can be called multiple times in a frame, at any point
- static void processTimes();
+ // updates cumulative times and hierarchy,
+ // can be called multiple times in a frame, at any point
+ static void processTimes();
- static void bootstrapTimerTree();
- static void incrementalUpdateTimerTree();
+ static void bootstrapTimerTree();
+ static void incrementalUpdateTimerTree();
- // call this once a frame to periodically log timers
- static void logStats();
+ // call this once a frame to periodically log timers
+ static void logStats();
- // dumps current cumulative frame stats to log
- // call nextFrame() to reset timers
- static void dumpCurTimes();
+ // dumps current cumulative frame stats to log
+ // call nextFrame() to reset timers
+ static void dumpCurTimes();
private:
- friend class BlockTimerStatHandle;
- // FIXME: this friendship exists so that each thread can instantiate a root timer,
- // which could be a derived class with a public constructor instead, possibly
- friend class ThreadRecorder;
- friend BlockTimer timeThisBlock(BlockTimerStatHandle&);
+ friend class BlockTimerStatHandle;
+ // FIXME: this friendship exists so that each thread can instantiate a root timer,
+ // which could be a derived class with a public constructor instead, possibly
+ friend class ThreadRecorder;
+ friend BlockTimer timeThisBlock(BlockTimerStatHandle&);
- BlockTimer(BlockTimerStatHandle& timer);
+ BlockTimer(BlockTimerStatHandle& timer);
- // no-copy
- BlockTimer(const BlockTimer& other);
- BlockTimer& operator=(const BlockTimer& other);
+ // no-copy
+ BlockTimer(const BlockTimer& other);
+ BlockTimer& operator=(const BlockTimer& other);
private:
- U64 mStartTime;
- BlockTimerStackRecord mParentTimerData;
+ U64 mStartTime;
+ BlockTimerStackRecord mParentTimerData;
public:
- // statics
- static std::string sLogName;
- static bool sMetricLog,
- sLog;
- static U64 sClockResolution;
+ // statics
+ static std::string sLogName;
+ static bool sMetricLog,
+ sLog;
+ static U64 sClockResolution;
};
// this dummy function assists in allocating a block timer with stack-based lifetime.
-// this is done by capturing the return value in a stack-allocated const reference variable.
+// this is done by capturing the return value in a stack-allocated const reference variable.
// (This is most easily done using the macro LL_RECORD_BLOCK_TIME)
-// Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes,
+// Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes,
// which would break the invariants of the timing hierarchy logic
LL_FORCE_INLINE class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer)
{
- return BlockTimer(timer);
+ return BlockTimer(timer);
}
// stores a "named" timer instance to be reused via multiple BlockTimer stack instances
-class BlockTimerStatHandle
-: public StatType<TimeBlockAccumulator>
+class BlockTimerStatHandle
+: public StatType<TimeBlockAccumulator>
{
public:
- BlockTimerStatHandle(const char* name, const char* description = "");
-
- TimeBlockTreeNode& getTreeNode() const;
- BlockTimerStatHandle* getParent() const { return getTreeNode().getParent(); }
- void setParent(BlockTimerStatHandle* parent) { getTreeNode().setParent(parent); }
-
- typedef std::vector<BlockTimerStatHandle*>::iterator child_iter;
- typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
- child_iter beginChildren();
- child_iter endChildren();
- bool hasChildren();
- std::vector<BlockTimerStatHandle*>& getChildren();
-
- StatType<TimeBlockAccumulator::CallCountFacet>& callCount()
- {
- return static_cast<StatType<TimeBlockAccumulator::CallCountFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
- }
-
- StatType<TimeBlockAccumulator::SelfTimeFacet>& selfTime()
- {
- return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
- }
-
- bool mCollapsed; // don't show children
+ BlockTimerStatHandle(const char* name, const char* description = "");
+
+ TimeBlockTreeNode& getTreeNode() const;
+ BlockTimerStatHandle* getParent() const { return getTreeNode().getParent(); }
+ void setParent(BlockTimerStatHandle* parent) { getTreeNode().setParent(parent); }
+
+ typedef std::vector<BlockTimerStatHandle*>::iterator child_iter;
+ typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
+ child_iter beginChildren();
+ child_iter endChildren();
+ bool hasChildren();
+ std::vector<BlockTimerStatHandle*>& getChildren();
+
+ StatType<TimeBlockAccumulator::CallCountFacet>& callCount()
+ {
+ return static_cast<StatType<TimeBlockAccumulator::CallCountFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
+ }
+
+ StatType<TimeBlockAccumulator::SelfTimeFacet>& selfTime()
+ {
+ return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
+ }
+
+ bool mCollapsed; // don't show children
};
// iterators and helper functions for walking the call hierarchy of block timers in different ways
@@ -282,61 +282,61 @@ block_timer_tree_bf_iterator_t end_block_timer_tree_bf();
LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
{
#if LL_FAST_TIMER_ON
- BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- if (!cur_timer_data)
- {
- // How likely is it that
- // LLThreadLocalSingletonPointer<T>::getInstance() will return NULL?
- // Even without researching, what we can say is that if we exit
- // without setting mStartTime at all, gcc 4.7 produces (fatal)
- // warnings about a possibly-uninitialized data member.
- mStartTime = 0;
- return;
- }
- TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
- accumulator.mActiveCount++;
- // keep current parent as long as it is active when we are
- accumulator.mMoveUpTree |= (accumulator.mParent->getCurrentAccumulator().mActiveCount == 0);
-
- // store top of stack
- mParentTimerData = *cur_timer_data;
- // push new information
- cur_timer_data->mActiveTimer = this;
- cur_timer_data->mTimeBlock = &timer;
- cur_timer_data->mChildTime = 0;
-
- mStartTime = getCPUClockCount64();
+ BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!cur_timer_data)
+ {
+ // How likely is it that
+ // LLThreadLocalSingletonPointer<T>::getInstance() will return NULL?
+ // Even without researching, what we can say is that if we exit
+ // without setting mStartTime at all, gcc 4.7 produces (fatal)
+ // warnings about a possibly-uninitialized data member.
+ mStartTime = 0;
+ return;
+ }
+ TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
+ accumulator.mActiveCount++;
+ // keep current parent as long as it is active when we are
+ accumulator.mMoveUpTree |= (accumulator.mParent->getCurrentAccumulator().mActiveCount == 0);
+
+ // store top of stack
+ mParentTimerData = *cur_timer_data;
+ // push new information
+ cur_timer_data->mActiveTimer = this;
+ cur_timer_data->mTimeBlock = &timer;
+ cur_timer_data->mChildTime = 0;
+
+ mStartTime = getCPUClockCount64();
#endif
}
LL_FORCE_INLINE BlockTimer::~BlockTimer()
{
#if LL_FAST_TIMER_ON
- U64 total_time = getCPUClockCount64() - mStartTime;
- BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- if (!cur_timer_data) return;
+ U64 total_time = getCPUClockCount64() - mStartTime;
+ BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!cur_timer_data) return;
- TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getCurrentAccumulator();
+ TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getCurrentAccumulator();
- accumulator.mCalls++;
- accumulator.mTotalTimeCounter += total_time;
- accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
- accumulator.mActiveCount--;
+ accumulator.mCalls++;
+ accumulator.mTotalTimeCounter += total_time;
+ accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
+ accumulator.mActiveCount--;
- // store last caller to bootstrap tree creation
- // do this in the destructor in case of recursion to get topmost caller
- accumulator.mLastCaller = mParentTimerData.mTimeBlock;
+ // store last caller to bootstrap tree creation
+ // do this in the destructor in case of recursion to get topmost caller
+ accumulator.mLastCaller = mParentTimerData.mTimeBlock;
- // we are only tracking self time, so subtract our total time delta from parents
- mParentTimerData.mChildTime += total_time;
+ // we are only tracking self time, so subtract our total time delta from parents
+ mParentTimerData.mChildTime += total_time;
- //pop stack
- *cur_timer_data = mParentTimerData;
+ //pop stack
+ *cur_timer_data = mParentTimerData;
#endif
}
}
-typedef LLTrace::BlockTimer LLFastTimer;
+typedef LLTrace::BlockTimer LLFastTimer;
#endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index 8355b1e797..1877dd54ed 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -52,9 +52,9 @@ static std::string empty;
// On Windows, use strerror_s().
std::string strerr(int errn)
{
- char buffer[256];
- strerror_s(buffer, errn); // infers sizeof(buffer) -- love it!
- return buffer;
+ char buffer[256];
+ strerror_s(buffer, errn); // infers sizeof(buffer) -- love it!
+ return buffer;
}
typedef std::basic_ios<char,std::char_traits < char > > _Myios;
@@ -69,295 +69,295 @@ typedef std::basic_ios<char,std::char_traits < char > > _Myios;
// strerror_r() returns char*
std::string message_from(int /*orig_errno*/, const char* /*buffer*/, size_t /*bufflen*/,
- const char* strerror_ret)
+ const char* strerror_ret)
{
- return strerror_ret;
+ return strerror_ret;
}
// strerror_r() returns int
std::string message_from(int orig_errno, const char* buffer, size_t bufflen,
- int strerror_ret)
+ int strerror_ret)
{
- if (strerror_ret == 0)
- {
- return buffer;
- }
- // Here strerror_r() has set errno. Since strerror_r() has already failed,
- // seems like a poor bet to call it again to diagnose its own error...
- int stre_errno = errno;
- if (stre_errno == ERANGE)
- {
- return STRINGIZE("strerror_r() can't explain errno " << orig_errno
- << " (" << bufflen << "-byte buffer too small)");
- }
- if (stre_errno == EINVAL)
- {
- return STRINGIZE("unknown errno " << orig_errno);
- }
- // Here we don't even understand the errno from strerror_r()!
- return STRINGIZE("strerror_r() can't explain errno " << orig_errno
- << " (error " << stre_errno << ')');
+ if (strerror_ret == 0)
+ {
+ return buffer;
+ }
+ // Here strerror_r() has set errno. Since strerror_r() has already failed,
+ // seems like a poor bet to call it again to diagnose its own error...
+ int stre_errno = errno;
+ if (stre_errno == ERANGE)
+ {
+ return STRINGIZE("strerror_r() can't explain errno " << orig_errno
+ << " (" << bufflen << "-byte buffer too small)");
+ }
+ if (stre_errno == EINVAL)
+ {
+ return STRINGIZE("unknown errno " << orig_errno);
+ }
+ // Here we don't even understand the errno from strerror_r()!
+ return STRINGIZE("strerror_r() can't explain errno " << orig_errno
+ << " (error " << stre_errno << ')');
}
std::string strerr(int errn)
{
- char buffer[256];
- // Select message_from() function matching the strerror_r() we have on hand.
- return message_from(errn, buffer, sizeof(buffer),
- strerror_r(errn, buffer, sizeof(buffer)));
+ char buffer[256];
+ // Select message_from() function matching the strerror_r() we have on hand.
+ return message_from(errn, buffer, sizeof(buffer),
+ strerror_r(errn, buffer, sizeof(buffer)));
}
-#endif // ! LL_WINDOWS
+#endif // ! LL_WINDOWS
// On either system, shorthand call just infers global 'errno'.
std::string strerr()
{
- return strerr(errno);
+ return strerr(errno);
}
int warnif(const std::string& desc, const std::string& filename, int rc, int accept=0)
{
- if (rc < 0)
- {
- // Capture errno before we start emitting output
- int errn = errno;
- // For certain operations, a particular errno value might be
- // acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit
- // EEXIST. Don't warn if caller explicitly says this errno is okay.
- if (errn != accept)
- {
- LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename
- << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL;
- }
+ if (rc < 0)
+ {
+ // Capture errno before we start emitting output
+ int errn = errno;
+ // For certain operations, a particular errno value might be
+ // acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit
+ // EEXIST. Don't warn if caller explicitly says this errno is okay.
+ if (errn != accept)
+ {
+ LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename
+ << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL;
+ }
#if 0 && LL_WINDOWS // turn on to debug file-locking problems
- // If the problem is "Permission denied," maybe it's because another
- // process has the file open. Try to find out.
- if (errn == EACCES) // *not* EPERM
- {
- // Only do any of this stuff (before LL_ENDL) if it will be logged.
- LL_DEBUGS("LLFile") << empty;
- // would be nice to use LLDir for this, but dependency goes the
- // wrong way
- const char* TEMP = LLFile::tmpdir();
- if (! (TEMP && *TEMP))
- {
- LL_CONT << "No $TEMP, not running 'handle'";
- }
- else
- {
- std::string tf(TEMP);
- tf += "\\handle.tmp";
- // http://technet.microsoft.com/en-us/sysinternals/bb896655
- std::string cmd(STRINGIZE("handle \"" << filename
- // "openfiles /query /v | fgrep -i \"" << filename
- << "\" > \"" << tf << '"'));
- LL_CONT << cmd;
- if (system(cmd.c_str()) != 0)
- {
- LL_CONT << "\nDownload 'handle.exe' from http://technet.microsoft.com/en-us/sysinternals/bb896655";
- }
- else
- {
- std::ifstream inf(tf);
- std::string line;
- while (std::getline(inf, line))
- {
- LL_CONT << '\n' << line;
- }
- }
- LLFile::remove(tf);
- }
- LL_CONT << LL_ENDL;
- }
+ // If the problem is "Permission denied," maybe it's because another
+ // process has the file open. Try to find out.
+ if (errn == EACCES) // *not* EPERM
+ {
+ // Only do any of this stuff (before LL_ENDL) if it will be logged.
+ LL_DEBUGS("LLFile") << empty;
+ // would be nice to use LLDir for this, but dependency goes the
+ // wrong way
+ const char* TEMP = LLFile::tmpdir();
+ if (! (TEMP && *TEMP))
+ {
+ LL_CONT << "No $TEMP, not running 'handle'";
+ }
+ else
+ {
+ std::string tf(TEMP);
+ tf += "\\handle.tmp";
+ // http://technet.microsoft.com/en-us/sysinternals/bb896655
+ std::string cmd(STRINGIZE("handle \"" << filename
+ // "openfiles /query /v | fgrep -i \"" << filename
+ << "\" > \"" << tf << '"'));
+ LL_CONT << cmd;
+ if (system(cmd.c_str()) != 0)
+ {
+ LL_CONT << "\nDownload 'handle.exe' from http://technet.microsoft.com/en-us/sysinternals/bb896655";
+ }
+ else
+ {
+ std::ifstream inf(tf);
+ std::string line;
+ while (std::getline(inf, line))
+ {
+ LL_CONT << '\n' << line;
+ }
+ }
+ LLFile::remove(tf);
+ }
+ LL_CONT << LL_ENDL;
+ }
#endif // LL_WINDOWS hack to identify processes holding file open
- }
- return rc;
+ }
+ return rc;
}
// static
-int LLFile::mkdir(const std::string& dirname, int perms)
+int LLFile::mkdir(const std::string& dirname, int perms)
{
#if LL_WINDOWS
- // permissions are ignored on Windows
- std::string utf8dirname = dirname;
- llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
- int rc = _wmkdir(utf16dirname.c_str());
+ // permissions are ignored on Windows
+ std::string utf8dirname = dirname;
+ llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
+ int rc = _wmkdir(utf16dirname.c_str());
#else
- int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
+ int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
#endif
- // We often use mkdir() to ensure the existence of a directory that might
- // already exist. There is no known case in which we want to call out as
- // an error the requested directory already existing.
- if (rc < 0 && errno == EEXIST)
- {
- // this is not the error you want, move along
- return 0;
- }
- // anything else might be a problem
- return warnif("mkdir", dirname, rc, EEXIST);
+ // We often use mkdir() to ensure the existence of a directory that might
+ // already exist. There is no known case in which we want to call out as
+ // an error the requested directory already existing.
+ if (rc < 0 && errno == EEXIST)
+ {
+ // this is not the error you want, move along
+ return 0;
+ }
+ // anything else might be a problem
+ return warnif("mkdir", dirname, rc, EEXIST);
}
// static
-int LLFile::rmdir(const std::string& dirname)
+int LLFile::rmdir(const std::string& dirname)
{
#if LL_WINDOWS
- // permissions are ignored on Windows
- std::string utf8dirname = dirname;
- llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
- int rc = _wrmdir(utf16dirname.c_str());
+ // permissions are ignored on Windows
+ std::string utf8dirname = dirname;
+ llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
+ int rc = _wrmdir(utf16dirname.c_str());
#else
- int rc = ::rmdir(dirname.c_str());
+ int rc = ::rmdir(dirname.c_str());
#endif
- return warnif("rmdir", dirname, rc);
+ return warnif("rmdir", dirname, rc);
}
// static
-LLFILE* LLFile::fopen(const std::string& filename, const char* mode) /* Flawfinder: ignore */
+LLFILE* LLFile::fopen(const std::string& filename, const char* mode) /* Flawfinder: ignore */
{
-#if LL_WINDOWS
- std::string utf8filename = filename;
- std::string utf8mode = std::string(mode);
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
- return _wfopen(utf16filename.c_str(),utf16mode.c_str());
+#if LL_WINDOWS
+ std::string utf8filename = filename;
+ std::string utf8mode = std::string(mode);
+ llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
+ llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
+ return _wfopen(utf16filename.c_str(),utf16mode.c_str());
#else
- return ::fopen(filename.c_str(),mode); /* Flawfinder: ignore */
+ return ::fopen(filename.c_str(),mode); /* Flawfinder: ignore */
#endif
}
-LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
+LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
{
-#if LL_WINDOWS
- std::string utf8filename = filename;
- std::string utf8mode = std::string(mode);
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
- return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
+#if LL_WINDOWS
+ std::string utf8filename = filename;
+ std::string utf8mode = std::string(mode);
+ llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
+ llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
+ return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
#else
- llassert(0);//No corresponding function on non-windows
- return NULL;
+ llassert(0);//No corresponding function on non-windows
+ return NULL;
#endif
}
-int LLFile::close(LLFILE * file)
+int LLFile::close(LLFILE * file)
{
- int ret_value = 0;
- if (file)
- {
- ret_value = fclose(file);
- }
- return ret_value;
+ int ret_value = 0;
+ if (file)
+ {
+ ret_value = fclose(file);
+ }
+ return ret_value;
}
-int LLFile::remove(const std::string& filename, int supress_error)
+int LLFile::remove(const std::string& filename, int supress_error)
{
-#if LL_WINDOWS
- std::string utf8filename = filename;
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- int rc = _wremove(utf16filename.c_str());
+#if LL_WINDOWS
+ std::string utf8filename = filename;
+ llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
+ int rc = _wremove(utf16filename.c_str());
#else
- int rc = ::remove(filename.c_str());
+ int rc = ::remove(filename.c_str());
#endif
- return warnif("remove", filename, rc, supress_error);
+ return warnif("remove", filename, rc, supress_error);
}
-int LLFile::rename(const std::string& filename, const std::string& newname, int supress_error)
+int LLFile::rename(const std::string& filename, const std::string& newname, int supress_error)
{
-#if LL_WINDOWS
- std::string utf8filename = filename;
- std::string utf8newname = newname;
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
- int rc = _wrename(utf16filename.c_str(),utf16newname.c_str());
+#if LL_WINDOWS
+ std::string utf8filename = filename;
+ std::string utf8newname = newname;
+ llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
+ llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
+ int rc = _wrename(utf16filename.c_str(),utf16newname.c_str());
#else
- int rc = ::rename(filename.c_str(),newname.c_str());
+ int rc = ::rename(filename.c_str(),newname.c_str());
#endif
- return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error);
+ return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error);
}
bool LLFile::copy(const std::string from, const std::string to)
{
- bool copied = false;
- LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */
- if (in)
- {
- LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */
- if (out)
- {
- char buf[16384]; /* Flawfinder: ignore */
- size_t readbytes;
- bool write_ok = true;
- while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
- {
- if (fwrite(buf, 1, readbytes, out) != readbytes)
- {
- LL_WARNS("LLFile") << "Short write" << LL_ENDL;
- write_ok = false;
- }
- }
- if ( write_ok )
- {
- copied = true;
- }
- fclose(out);
- }
- fclose(in);
- }
- return copied;
+ bool copied = false;
+ LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */
+ if (in)
+ {
+ LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */
+ if (out)
+ {
+ char buf[16384]; /* Flawfinder: ignore */
+ size_t readbytes;
+ bool write_ok = true;
+ while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
+ {
+ if (fwrite(buf, 1, readbytes, out) != readbytes)
+ {
+ LL_WARNS("LLFile") << "Short write" << LL_ENDL;
+ write_ok = false;
+ }
+ }
+ if ( write_ok )
+ {
+ copied = true;
+ }
+ fclose(out);
+ }
+ fclose(in);
+ }
+ return copied;
}
-int LLFile::stat(const std::string& filename, llstat* filestatus)
+int LLFile::stat(const std::string& filename, llstat* filestatus)
{
#if LL_WINDOWS
- std::string utf8filename = filename;
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- int rc = _wstat(utf16filename.c_str(),filestatus);
+ std::string utf8filename = filename;
+ llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
+ int rc = _wstat(utf16filename.c_str(),filestatus);
#else
- int rc = ::stat(filename.c_str(),filestatus);
+ int rc = ::stat(filename.c_str(),filestatus);
#endif
- // We use stat() to determine existence (see isfile(), isdir()).
- // Don't spam the log if the subject pathname doesn't exist.
- return warnif("stat", filename, rc, ENOENT);
+ // We use stat() to determine existence (see isfile(), isdir()).
+ // Don't spam the log if the subject pathname doesn't exist.
+ return warnif("stat", filename, rc, ENOENT);
}
bool LLFile::isdir(const std::string& filename)
{
- llstat st;
+ llstat st;
- return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
+ return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
}
bool LLFile::isfile(const std::string& filename)
{
- llstat st;
+ llstat st;
- return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
+ return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
}
const char *LLFile::tmpdir()
{
- static std::string utf8path;
+ static std::string utf8path;
- if (utf8path.empty())
- {
- char sep;
+ if (utf8path.empty())
+ {
+ char sep;
#if LL_WINDOWS
- sep = '\\';
+ sep = '\\';
- std::vector<wchar_t> utf16path(MAX_PATH + 1);
- GetTempPathW(utf16path.size(), &utf16path[0]);
- utf8path = ll_convert_wide_to_string(&utf16path[0]);
+ std::vector<wchar_t> utf16path(MAX_PATH + 1);
+ GetTempPathW(utf16path.size(), &utf16path[0]);
+ utf8path = ll_convert_wide_to_string(&utf16path[0]);
#else
- sep = '/';
+ sep = '/';
- utf8path = LLStringUtil::getenv("TMPDIR", "/tmp/");
+ utf8path = LLStringUtil::getenv("TMPDIR", "/tmp/");
#endif
- if (utf8path[utf8path.size() - 1] != sep)
- {
- utf8path += sep;
- }
- }
- return utf8path.c_str();
+ if (utf8path[utf8path.size() - 1] != sep)
+ {
+ utf8path += sep;
+ }
+ }
+ return utf8path.c_str();
}
@@ -365,64 +365,64 @@ const char *LLFile::tmpdir()
#if LL_WINDOWS
-LLFILE * LLFile::_Fiopen(const std::string& filename,
- std::ios::openmode mode)
-{ // open a file
- static const char *mods[] =
- { // fopen mode strings corresponding to valid[i]
- "r", "w", "w", "a", "rb", "wb", "wb", "ab",
- "r+", "w+", "a+", "r+b", "w+b", "a+b",
- 0};
- static const int valid[] =
- { // valid combinations of open flags
- ios_base::in,
- ios_base::out,
- ios_base::out | ios_base::trunc,
- ios_base::out | ios_base::app,
- ios_base::in | ios_base::binary,
- ios_base::out | ios_base::binary,
- ios_base::out | ios_base::trunc | ios_base::binary,
- ios_base::out | ios_base::app | ios_base::binary,
- ios_base::in | ios_base::out,
- ios_base::in | ios_base::out | ios_base::trunc,
- ios_base::in | ios_base::out | ios_base::app,
- ios_base::in | ios_base::out | ios_base::binary,
- ios_base::in | ios_base::out | ios_base::trunc
- | ios_base::binary,
- ios_base::in | ios_base::out | ios_base::app
- | ios_base::binary,
- 0};
-
- LLFILE *fp = 0;
- int n;
- ios_base::openmode atendflag = mode & ios_base::ate;
- ios_base::openmode norepflag = mode & ios_base::_Noreplace;
-
- if (mode & ios_base::_Nocreate)
- mode |= ios_base::in; // file must exist
- mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
- for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
- ; // look for a valid mode
-
- if (valid[n] == 0)
- return (0); // no valid mode
- else if (norepflag && mode & (ios_base::out || ios_base::app)
- && (fp = LLFile::fopen(filename, "r")) != 0) /* Flawfinder: ignore */
- { // file must not exist, close and fail
- fclose(fp);
- return (0);
- }
- else if (fp != 0 && fclose(fp) != 0)
- return (0); // can't close after test open
+LLFILE * LLFile::_Fiopen(const std::string& filename,
+ std::ios::openmode mode)
+{ // open a file
+ static const char *mods[] =
+ { // fopen mode strings corresponding to valid[i]
+ "r", "w", "w", "a", "rb", "wb", "wb", "ab",
+ "r+", "w+", "a+", "r+b", "w+b", "a+b",
+ 0};
+ static const int valid[] =
+ { // valid combinations of open flags
+ ios_base::in,
+ ios_base::out,
+ ios_base::out | ios_base::trunc,
+ ios_base::out | ios_base::app,
+ ios_base::in | ios_base::binary,
+ ios_base::out | ios_base::binary,
+ ios_base::out | ios_base::trunc | ios_base::binary,
+ ios_base::out | ios_base::app | ios_base::binary,
+ ios_base::in | ios_base::out,
+ ios_base::in | ios_base::out | ios_base::trunc,
+ ios_base::in | ios_base::out | ios_base::app,
+ ios_base::in | ios_base::out | ios_base::binary,
+ ios_base::in | ios_base::out | ios_base::trunc
+ | ios_base::binary,
+ ios_base::in | ios_base::out | ios_base::app
+ | ios_base::binary,
+ 0};
+
+ LLFILE *fp = 0;
+ int n;
+ ios_base::openmode atendflag = mode & ios_base::ate;
+ ios_base::openmode norepflag = mode & ios_base::_Noreplace;
+
+ if (mode & ios_base::_Nocreate)
+ mode |= ios_base::in; // file must exist
+ mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
+ for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
+ ; // look for a valid mode
+
+ if (valid[n] == 0)
+ return (0); // no valid mode
+ else if (norepflag && mode & (ios_base::out || ios_base::app)
+ && (fp = LLFile::fopen(filename, "r")) != 0) /* Flawfinder: ignore */
+ { // file must not exist, close and fail
+ fclose(fp);
+ return (0);
+ }
+ else if (fp != 0 && fclose(fp) != 0)
+ return (0); // can't close after test open
// should open with protection here, if other than default
- else if ((fp = LLFile::fopen(filename, mods[n])) == 0) /* Flawfinder: ignore */
- return (0); // open failed
+ else if ((fp = LLFile::fopen(filename, mods[n])) == 0) /* Flawfinder: ignore */
+ return (0); // open failed
- if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
- return (fp); // no need to seek to end, or seek succeeded
+ if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
+ return (fp); // no need to seek to end, or seek succeeded
- fclose(fp); // can't position at end
- return (0);
+ fclose(fp); // can't position at end
+ return (0);
}
#endif /* LL_WINDOWS */
@@ -469,26 +469,26 @@ void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode)
std::streamsize llifstream_size(llifstream& ifstr)
{
- if(!ifstr.is_open()) return 0;
- std::streampos pos_old = ifstr.tellg();
- ifstr.seekg(0, ios_base::beg);
- std::streampos pos_beg = ifstr.tellg();
- ifstr.seekg(0, ios_base::end);
- std::streampos pos_end = ifstr.tellg();
- ifstr.seekg(pos_old, ios_base::beg);
- return pos_end - pos_beg;
+ if(!ifstr.is_open()) return 0;
+ std::streampos pos_old = ifstr.tellg();
+ ifstr.seekg(0, ios_base::beg);
+ std::streampos pos_beg = ifstr.tellg();
+ ifstr.seekg(0, ios_base::end);
+ std::streampos pos_end = ifstr.tellg();
+ ifstr.seekg(pos_old, ios_base::beg);
+ return pos_end - pos_beg;
}
std::streamsize llofstream_size(llofstream& ofstr)
{
- if(!ofstr.is_open()) return 0;
- std::streampos pos_old = ofstr.tellp();
- ofstr.seekp(0, ios_base::beg);
- std::streampos pos_beg = ofstr.tellp();
- ofstr.seekp(0, ios_base::end);
- std::streampos pos_end = ofstr.tellp();
- ofstr.seekp(pos_old, ios_base::beg);
- return pos_end - pos_beg;
+ if(!ofstr.is_open()) return 0;
+ std::streampos pos_old = ofstr.tellp();
+ ofstr.seekp(0, ios_base::beg);
+ std::streampos pos_beg = ofstr.tellp();
+ ofstr.seekp(0, ios_base::end);
+ std::streampos pos_end = ofstr.tellp();
+ ofstr.seekp(pos_old, ios_base::beg);
+ return pos_end - pos_beg;
}
#endif // LL_WINDOWS
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 9de095b45d..08a008c19a 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfile.h
* @author Michael Schlachter
* @date 2006-03-23
@@ -8,21 +8,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,16 +35,16 @@
* Attempts to mostly mirror the POSIX style IO functions.
*/
-typedef FILE LLFILE;
+typedef FILE LLFILE;
#include <fstream>
#include <sys/stat.h>
#if LL_WINDOWS
// windows version of stat function and stat data structure are called _stat
-typedef struct _stat llstat;
+typedef struct _stat llstat;
#else
-typedef struct stat llstat;
+typedef struct stat llstat;
#include <sys/types.h>
#endif
@@ -61,29 +61,29 @@ typedef struct stat llstat;
class LL_COMMON_API LLFile
{
public:
- // All these functions take UTF8 path/filenames.
- static LLFILE* fopen(const std::string& filename,const char* accessmode); /* Flawfinder: ignore */
- static LLFILE* _fsopen(const std::string& filename,const char* accessmode,int sharingFlag);
+ // All these functions take UTF8 path/filenames.
+ static LLFILE* fopen(const std::string& filename,const char* accessmode); /* Flawfinder: ignore */
+ static LLFILE* _fsopen(const std::string& filename,const char* accessmode,int sharingFlag);
- static int close(LLFILE * file);
+ static int close(LLFILE * file);
- // perms is a permissions mask like 0777 or 0700. In most cases it will
- // be overridden by the user's umask. It is ignored on Windows.
- // mkdir() considers "directory already exists" to be SUCCESS.
- static int mkdir(const std::string& filename, int perms = 0700);
+ // perms is a permissions mask like 0777 or 0700. In most cases it will
+ // be overridden by the user's umask. It is ignored on Windows.
+ // mkdir() considers "directory already exists" to be SUCCESS.
+ static int mkdir(const std::string& filename, int perms = 0700);
- static int rmdir(const std::string& filename);
- static int remove(const std::string& filename, int supress_error = 0);
- static int rename(const std::string& filename,const std::string& newname, int supress_error = 0);
- static bool copy(const std::string from, const std::string to);
+ static int rmdir(const std::string& filename);
+ static int remove(const std::string& filename, int supress_error = 0);
+ static int rename(const std::string& filename,const std::string& newname, int supress_error = 0);
+ static bool copy(const std::string from, const std::string to);
- static int stat(const std::string& filename,llstat* file_status);
- static bool isdir(const std::string& filename);
- static bool isfile(const std::string& filename);
- static LLFILE * _Fiopen(const std::string& filename,
- std::ios::openmode mode);
+ static int stat(const std::string& filename,llstat* file_status);
+ static bool isdir(const std::string& filename);
+ static bool isfile(const std::string& filename);
+ static LLFILE * _Fiopen(const std::string& filename,
+ std::ios::openmode mode);
- static const char * tmpdir();
+ static const char * tmpdir();
};
/// RAII class
@@ -158,39 +158,39 @@ private:
* Does The Right Thing when passed a non-ASCII pathname. Sadly, that isn't
* true of Microsoft's std::ifstream.
*/
-class LL_COMMON_API llifstream : public std::ifstream
+class LL_COMMON_API llifstream : public std::ifstream
{
- // input stream associated with a C stream
+ // input stream associated with a C stream
public:
- // Constructors:
- /**
- * @brief Default constructor.
- *
- * Initializes @c sb using its default constructor, and passes
- * @c &sb to the base class initializer. Does not open any files
- * (you haven't given it a filename to open).
+ // Constructors:
+ /**
+ * @brief Default constructor.
+ *
+ * Initializes @c sb using its default constructor, and passes
+ * @c &sb to the base class initializer. Does not open any files
+ * (you haven't given it a filename to open).
*/
- llifstream();
+ llifstream();
- /**
- * @brief Create an input file stream.
- * @param Filename String specifying the filename.
- * @param Mode Open file in specified mode (see std::ios_base).
- *
+ /**
+ * @brief Create an input file stream.
+ * @param Filename String specifying the filename.
+ * @param Mode Open file in specified mode (see std::ios_base).
+ *
* @c ios_base::in is automatically included in @a mode.
*/
- explicit llifstream(const std::string& _Filename,
+ explicit llifstream(const std::string& _Filename,
ios_base::openmode _Mode = ios_base::in);
- /**
- * @brief Opens an external file.
- * @param Filename The name of the file.
- * @param Node The open mode flags.
- *
- * Calls @c llstdio_filebuf::open(s,mode|in). If that function
- * fails, @c failbit is set in the stream's error state.
+ /**
+ * @brief Opens an external file.
+ * @param Filename The name of the file.
+ * @param Node The open mode flags.
+ *
+ * Calls @c llstdio_filebuf::open(s,mode|in). If that function
+ * fails, @c failbit is set in the stream's error state.
*/
- void open(const std::string& _Filename,
+ void open(const std::string& _Filename,
ios_base::openmode _Mode = ios_base::in);
};
@@ -203,37 +203,37 @@ class LL_COMMON_API llifstream : public std::ifstream
* Right Thing when passed a non-ASCII pathname. Sadly, that isn't true of
* Microsoft's std::ofstream.
*/
-class LL_COMMON_API llofstream : public std::ofstream
+class LL_COMMON_API llofstream : public std::ofstream
{
public:
- // Constructors:
- /**
- * @brief Default constructor.
- *
- * Initializes @c sb using its default constructor, and passes
- * @c &sb to the base class initializer. Does not open any files
- * (you haven't given it a filename to open).
+ // Constructors:
+ /**
+ * @brief Default constructor.
+ *
+ * Initializes @c sb using its default constructor, and passes
+ * @c &sb to the base class initializer. Does not open any files
+ * (you haven't given it a filename to open).
*/
- llofstream();
-
- /**
- * @brief Create an output file stream.
- * @param Filename String specifying the filename.
- * @param Mode Open file in specified mode (see std::ios_base).
- *
- * @c ios_base::out is automatically included in @a mode.
+ llofstream();
+
+ /**
+ * @brief Create an output file stream.
+ * @param Filename String specifying the filename.
+ * @param Mode Open file in specified mode (see std::ios_base).
+ *
+ * @c ios_base::out is automatically included in @a mode.
*/
- explicit llofstream(const std::string& _Filename,
+ explicit llofstream(const std::string& _Filename,
ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
- /**
- * @brief Opens an external file.
- * @param Filename The name of the file.
- * @param Node The open mode flags.
- *
- * @c ios_base::out is automatically included in @a mode.
+ /**
+ * @brief Opens an external file.
+ * @param Filename The name of the file.
+ * @param Node The open mode flags.
+ *
+ * @c ios_base::out is automatically included in @a mode.
*/
- void open(const std::string& _Filename,
+ void open(const std::string& _Filename,
ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
};
diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp
index f019bd0c64..e39812bfc4 100644
--- a/indra/llcommon/llfindlocale.cpp
+++ b/indra/llcommon/llfindlocale.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfindlocale.cpp
* @brief Detect system language setting
*
* $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$
*/
diff --git a/indra/llcommon/llfindlocale.h b/indra/llcommon/llfindlocale.h
index 6770db5774..07b59853c3 100644
--- a/indra/llcommon/llfindlocale.h
+++ b/indra/llcommon/llfindlocale.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfindlocale.h
* @brief Detect system language setting
*
* $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$
*/
diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp
index bd4db8be84..4f28d2240e 100644
--- a/indra/llcommon/llfixedbuffer.cpp
+++ b/indra/llcommon/llfixedbuffer.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llfixedbuffer.cpp
*
* $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$
*/
@@ -29,69 +29,69 @@
////////////////////////////////////////////////////////////////////////////
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
- : LLLineBuffer(),
- mMaxLines(max_lines),
- mMutex()
+ : LLLineBuffer(),
+ mMaxLines(max_lines),
+ mMutex()
{
- mTimer.reset();
+ mTimer.reset();
}
LLFixedBuffer::~LLFixedBuffer()
{
- clear();
+ clear();
}
void LLFixedBuffer::clear()
{
- mMutex.lock() ;
- mLines.clear();
- mAddTimes.clear();
- mLineLengths.clear();
- mMutex.unlock() ;
+ mMutex.lock() ;
+ mLines.clear();
+ mAddTimes.clear();
+ mLineLengths.clear();
+ mMutex.unlock() ;
- mTimer.reset();
+ mTimer.reset();
}
void LLFixedBuffer::addLine(const std::string& utf8line)
{
- LLWString wstring = utf8str_to_wstring(utf8line);
- addWLine(wstring);
+ LLWString wstring = utf8str_to_wstring(utf8line);
+ addWLine(wstring);
}
void LLFixedBuffer::addWLine(const LLWString& line)
{
- if (line.empty())
- {
- return;
- }
-
- removeExtraLines();
-
- mMutex.lock() ;
- mLines.push_back(line);
- mLineLengths.push_back((S32)line.length());
- mAddTimes.push_back(mTimer.getElapsedTimeF32());
- mMutex.unlock() ;
+ if (line.empty())
+ {
+ return;
+ }
+
+ removeExtraLines();
+
+ mMutex.lock() ;
+ mLines.push_back(line);
+ mLineLengths.push_back((S32)line.length());
+ mAddTimes.push_back(mTimer.getElapsedTimeF32());
+ mMutex.unlock() ;
}
void LLFixedBuffer::setMaxLines(S32 max_lines)
{
- mMaxLines = max_lines;
+ mMaxLines = max_lines;
- removeExtraLines();
+ removeExtraLines();
}
void LLFixedBuffer::removeExtraLines()
{
- mMutex.lock() ;
- while ((S32)mLines.size() > llmax((S32)0, (S32)(mMaxLines - 1)))
- {
- mLines.pop_front();
- mAddTimes.pop_front();
- mLineLengths.pop_front();
- }
- mMutex.unlock() ;
+ mMutex.lock() ;
+ while ((S32)mLines.size() > llmax((S32)0, (S32)(mMaxLines - 1)))
+ {
+ mLines.pop_front();
+ mAddTimes.pop_front();
+ mLineLengths.pop_front();
+ }
+ mMutex.unlock() ;
}
diff --git a/indra/llcommon/llfixedbuffer.h b/indra/llcommon/llfixedbuffer.h
index 554cf48a4c..eca0792d35 100644
--- a/indra/llcommon/llfixedbuffer.h
+++ b/indra/llcommon/llfixedbuffer.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfixedbuffer.h
* @brief A fixed size buffer of lines.
*
* $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$
*/
@@ -38,27 +38,27 @@
class LL_COMMON_API LLFixedBuffer : public LLLineBuffer
{
public:
- LLFixedBuffer(const U32 max_lines = 20);
- ~LLFixedBuffer();
+ LLFixedBuffer(const U32 max_lines = 20);
+ ~LLFixedBuffer();
+
+ LLTimer mTimer;
+ U32 mMaxLines;
+ std::deque<LLWString> mLines;
+ std::deque<F32> mAddTimes;
+ std::deque<S32> mLineLengths;
- LLTimer mTimer;
- U32 mMaxLines;
- std::deque<LLWString> mLines;
- std::deque<F32> mAddTimes;
- std::deque<S32> mLineLengths;
+ /*virtual*/ void clear(); // Clear the buffer, and reset it.
- /*virtual*/ void clear(); // Clear the buffer, and reset it.
+ /*virtual*/ void addLine(const std::string& utf8line);
- /*virtual*/ void addLine(const std::string& utf8line);
+ void setMaxLines(S32 max_lines);
- void setMaxLines(S32 max_lines);
-
protected:
- void removeExtraLines();
- void addWLine(const LLWString& line);
+ void removeExtraLines();
+ void addWLine(const LLWString& line);
protected:
- LLMutex mMutex ;
+ LLMutex mMutex ;
};
#endif //LL_FIXED_BUFFER_H
diff --git a/indra/llcommon/llformat.cpp b/indra/llcommon/llformat.cpp
index 3b2b3038ea..dc5726e29f 100644
--- a/indra/llcommon/llformat.cpp
+++ b/indra/llcommon/llformat.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llformat.cpp
* @date January 2007
* @brief string formatting utility
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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,36 +35,36 @@
// wrapper for vsnprintf to be called from llformatXXX functions.
static void va_format(std::string& out, const char *fmt, va_list va)
{
- char tstr[1024]; /* Flawfinder: ignore */
+ char tstr[1024]; /* Flawfinder: ignore */
#if LL_WINDOWS
- _vsnprintf(tstr, 1024, fmt, va);
+ _vsnprintf(tstr, 1024, fmt, va);
#else
- vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
+ vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
#endif
- out.assign(tstr);
+ out.assign(tstr);
}
std::string llformat(const char *fmt, ...)
{
- std::string res;
- va_list va;
- va_start(va, fmt);
- va_format(res, fmt, va);
- va_end(va);
- return res;
+ std::string res;
+ va_list va;
+ va_start(va, fmt);
+ va_format(res, fmt, va);
+ va_end(va);
+ return res;
}
std::string llformat_to_utf8(const char *fmt, ...)
{
- std::string res;
- va_list va;
- va_start(va, fmt);
- va_format(res, fmt, va);
- va_end(va);
+ std::string res;
+ va_list va;
+ va_start(va, fmt);
+ va_format(res, fmt, va);
+ va_end(va);
#if LL_WINDOWS
- // made converting to utf8. See EXT-8318.
- res = ll_convert_string_to_utf8_string(res);
+ // made converting to utf8. See EXT-8318.
+ res = ll_convert_string_to_utf8_string(res);
#endif
- return res;
+ return res;
}
diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h
index fb8e7cd045..4456a72696 100644
--- a/indra/llcommon/llformat.h
+++ b/indra/llcommon/llformat.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llformat.h
* @date January 2007
* @brief string formatting utility
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index 1e9920746b..2805662d6f 100644
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llframetimer.cpp
*
* $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$
*/
@@ -30,7 +30,7 @@
#include "llframetimer.h"
// Static members
-//LLTimer LLFrameTimer::sInternalTimer;
+//LLTimer LLFrameTimer::sInternalTimer;
U64 LLFrameTimer::sStartTotalTime = totalTime();
F64 LLFrameTimer::sFrameTime = 0.0;
U64 LLFrameTimer::sTotalTime = 0;
@@ -42,34 +42,34 @@ const F64 USEC_TO_SEC_F64 = 0.000001;
// static
void LLFrameTimer::updateFrameTime()
{
- U64 total_time = totalTime();
- sFrameDeltaTime = total_time - sTotalTime;
- sTotalTime = total_time;
- sTotalSeconds = U64_to_F64(sTotalTime) * USEC_TO_SEC_F64;
- sFrameTime = U64_to_F64(sTotalTime - sStartTotalTime) * USEC_TO_SEC_F64;
-}
+ U64 total_time = totalTime();
+ sFrameDeltaTime = total_time - sTotalTime;
+ sTotalTime = total_time;
+ sTotalSeconds = U64_to_F64(sTotalTime) * USEC_TO_SEC_F64;
+ sFrameTime = U64_to_F64(sTotalTime - sStartTotalTime) * USEC_TO_SEC_F64;
+}
void LLFrameTimer::start()
{
- reset();
- mStarted = TRUE;
+ reset();
+ mStarted = TRUE;
}
void LLFrameTimer::stop()
{
- mStarted = FALSE;
+ mStarted = FALSE;
}
void LLFrameTimer::reset()
{
- mStartTime = sFrameTime;
- mExpiry = sFrameTime;
+ mStartTime = sFrameTime;
+ mExpiry = sFrameTime;
}
void LLFrameTimer::resetWithExpiry(F32 expiration)
{
- reset();
- setTimerExpirySec(expiration);
+ reset();
+ setTimerExpirySec(expiration);
}
// Don't combine pause/unpause with start/stop
@@ -82,69 +82,69 @@ void LLFrameTimer::resetWithExpiry(F32 expiration)
// Note: elapsed would also be valid with no unpause() call (= time run until pause() called)
void LLFrameTimer::pause()
{
- if (mStarted)
- mStartTime = sFrameTime - mStartTime; // save dtime
- mStarted = FALSE;
+ if (mStarted)
+ mStartTime = sFrameTime - mStartTime; // save dtime
+ mStarted = FALSE;
}
void LLFrameTimer::unpause()
{
- if (!mStarted)
- mStartTime = sFrameTime - mStartTime; // restore dtime
- mStarted = TRUE;
+ if (!mStarted)
+ mStartTime = sFrameTime - mStartTime; // restore dtime
+ mStarted = TRUE;
}
void LLFrameTimer::setTimerExpirySec(F32 expiration)
{
- mExpiry = expiration + mStartTime;
+ mExpiry = expiration + mStartTime;
}
void LLFrameTimer::setExpiryAt(F64 seconds_since_epoch)
{
- mStartTime = sFrameTime;
- mExpiry = seconds_since_epoch - (USEC_TO_SEC_F64 * sStartTotalTime);
+ mStartTime = sFrameTime;
+ mExpiry = seconds_since_epoch - (USEC_TO_SEC_F64 * sStartTotalTime);
}
F64 LLFrameTimer::expiresAt() const
{
- F64 expires_at = U64_to_F64(sStartTotalTime) * USEC_TO_SEC_F64;
- expires_at += mExpiry;
- return expires_at;
+ F64 expires_at = U64_to_F64(sStartTotalTime) * USEC_TO_SEC_F64;
+ expires_at += mExpiry;
+ return expires_at;
}
BOOL LLFrameTimer::checkExpirationAndReset(F32 expiration)
{
- //LL_INFOS() << "LLFrameTimer::checkExpirationAndReset()" << LL_ENDL;
- //LL_INFOS() << " mStartTime:" << mStartTime << LL_ENDL;
- //LL_INFOS() << " sFrameTime:" << sFrameTime << LL_ENDL;
- //LL_INFOS() << " mExpiry: " << mExpiry << LL_ENDL;
-
- if(hasExpired())
- {
- reset();
- setTimerExpirySec(expiration);
- return TRUE;
- }
- return FALSE;
+ //LL_INFOS() << "LLFrameTimer::checkExpirationAndReset()" << LL_ENDL;
+ //LL_INFOS() << " mStartTime:" << mStartTime << LL_ENDL;
+ //LL_INFOS() << " sFrameTime:" << sFrameTime << LL_ENDL;
+ //LL_INFOS() << " mExpiry: " << mExpiry << LL_ENDL;
+
+ if(hasExpired())
+ {
+ reset();
+ setTimerExpirySec(expiration);
+ return TRUE;
+ }
+ return FALSE;
}
// static
F32 LLFrameTimer::getFrameDeltaTimeF32()
{
- return (F32)(U64_to_F64(sFrameDeltaTime) * USEC_TO_SEC_F64);
+ return (F32)(U64_to_F64(sFrameDeltaTime) * USEC_TO_SEC_F64);
}
-// static
+// static
// Return seconds since the current frame started
F32 LLFrameTimer::getCurrentFrameTime()
{
- U64 frame_time = totalTime() - sTotalTime;
- return (F32)(U64_to_F64(frame_time) * USEC_TO_SEC_F64);
+ U64 frame_time = totalTime() - sTotalTime;
+ return (F32)(U64_to_F64(frame_time) * USEC_TO_SEC_F64);
}
// Glue code to avoid full class .h file #includes
F32 getCurrentFrameTime()
{
- return (F32)(LLFrameTimer::getCurrentFrameTime());
+ return (F32)(LLFrameTimer::getCurrentFrameTime());
}
diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index 81bd5da8a3..876d933fd1 100644
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llframetimer.h
* @brief A lightweight timer that measures seconds and is only
* updated once per frame.
@@ -6,21 +6,21 @@
* $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$
*/
@@ -36,113 +36,113 @@
#include "lltimer.h"
-class LL_COMMON_API LLFrameTimer
+class LL_COMMON_API LLFrameTimer
{
public:
- LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {}
+ LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {}
- // Return the number of seconds since the start of this
- // application instance.
- static F64SecondsImplicit getElapsedSeconds()
- {
- // Loses msec precision after ~4.5 hours...
- return sFrameTime;
- }
-
- // Return a low precision usec since epoch
- static U64 getTotalTime()
- {
- return sTotalTime ? U64MicrosecondsImplicit(sTotalTime) : totalTime();
- }
-
- // Return a low precision seconds since epoch
- static F64 getTotalSeconds()
- {
- return sTotalSeconds;
- }
-
- // Call this method once per frame to update the current frame time. This is actually called
- // at some other times as well
- static void updateFrameTime();
-
- // Call this method once, and only once, per frame to update the current frame count.
- static void updateFrameCount() { sFrameCount++; }
-
- static U32 getFrameCount() { return sFrameCount; }
-
- static F32 getFrameDeltaTimeF32();
-
- // Return seconds since the current frame started
- static F32 getCurrentFrameTime();
-
- // MANIPULATORS
- void start();
- void stop();
- void reset();
- void resetWithExpiry(F32 expiration);
- void pause();
- void unpause();
- void setTimerExpirySec(F32 expiration);
- void setExpiryAt(F64 seconds_since_epoch);
- BOOL checkExpirationAndReset(F32 expiration);
- F32 getElapsedTimeAndResetF32() { F32 t = F32(sFrameTime - mStartTime); reset(); return t; }
-
- void setAge(const F64 age) { mStartTime = sFrameTime - age; }
-
- // ACCESSORS
- BOOL hasExpired() const { return (sFrameTime >= mExpiry); }
- F32 getTimeToExpireF32() const { return (F32)(mExpiry - sFrameTime); }
- F32 getElapsedTimeF32() const { return mStarted ? (F32)(sFrameTime - mStartTime) : (F32)mStartTime; }
- BOOL getStarted() const { return mStarted; }
-
- // return the seconds since epoch when this timer will expire.
- F64 expiresAt() const;
-
-protected:
- // A single, high resolution timer that drives all LLFrameTimers
- // *NOTE: no longer used.
- //static LLTimer sInternalTimer;
-
- //
- // Aplication constants
- //
-
- // Start time of opp in usec since epoch
- static U64 sStartTotalTime;
-
- //
- // Data updated per frame
- //
-
- // Seconds since application start
- static F64 sFrameTime;
-
- // Time that has elapsed since last call to updateFrameTime()
- static U64 sFrameDeltaTime;
-
- // Total microseconds since epoch.
- static U64 sTotalTime;
-
- // Seconds since epoch.
- static F64 sTotalSeconds;
-
- // Total number of frames elapsed in application
- static S32 sFrameCount;
-
- //
- // Member data
- //
-
- // Number of seconds after application start when this timer was
- // started. Set equal to sFrameTime when reset.
- F64 mStartTime;
-
- // Timer expires this many seconds after application start time.
- F64 mExpiry;
-
- // Useful bit of state usually associated with timers, but does
- // not affect actual functionality
- BOOL mStarted;
+ // Return the number of seconds since the start of this
+ // application instance.
+ static F64SecondsImplicit getElapsedSeconds()
+ {
+ // Loses msec precision after ~4.5 hours...
+ return sFrameTime;
+ }
+
+ // Return a low precision usec since epoch
+ static U64 getTotalTime()
+ {
+ return sTotalTime ? U64MicrosecondsImplicit(sTotalTime) : totalTime();
+ }
+
+ // Return a low precision seconds since epoch
+ static F64 getTotalSeconds()
+ {
+ return sTotalSeconds;
+ }
+
+ // Call this method once per frame to update the current frame time. This is actually called
+ // at some other times as well
+ static void updateFrameTime();
+
+ // Call this method once, and only once, per frame to update the current frame count.
+ static void updateFrameCount() { sFrameCount++; }
+
+ static U32 getFrameCount() { return sFrameCount; }
+
+ static F32 getFrameDeltaTimeF32();
+
+ // Return seconds since the current frame started
+ static F32 getCurrentFrameTime();
+
+ // MANIPULATORS
+ void start();
+ void stop();
+ void reset();
+ void resetWithExpiry(F32 expiration);
+ void pause();
+ void unpause();
+ void setTimerExpirySec(F32 expiration);
+ void setExpiryAt(F64 seconds_since_epoch);
+ BOOL checkExpirationAndReset(F32 expiration);
+ F32 getElapsedTimeAndResetF32() { F32 t = F32(sFrameTime - mStartTime); reset(); return t; }
+
+ void setAge(const F64 age) { mStartTime = sFrameTime - age; }
+
+ // ACCESSORS
+ BOOL hasExpired() const { return (sFrameTime >= mExpiry); }
+ F32 getTimeToExpireF32() const { return (F32)(mExpiry - sFrameTime); }
+ F32 getElapsedTimeF32() const { return mStarted ? (F32)(sFrameTime - mStartTime) : (F32)mStartTime; }
+ BOOL getStarted() const { return mStarted; }
+
+ // return the seconds since epoch when this timer will expire.
+ F64 expiresAt() const;
+
+protected:
+ // A single, high resolution timer that drives all LLFrameTimers
+ // *NOTE: no longer used.
+ //static LLTimer sInternalTimer;
+
+ //
+ // Aplication constants
+ //
+
+ // Start time of opp in usec since epoch
+ static U64 sStartTotalTime;
+
+ //
+ // Data updated per frame
+ //
+
+ // Seconds since application start
+ static F64 sFrameTime;
+
+ // Time that has elapsed since last call to updateFrameTime()
+ static U64 sFrameDeltaTime;
+
+ // Total microseconds since epoch.
+ static U64 sTotalTime;
+
+ // Seconds since epoch.
+ static F64 sTotalSeconds;
+
+ // Total number of frames elapsed in application
+ static S32 sFrameCount;
+
+ //
+ // Member data
+ //
+
+ // Number of seconds after application start when this timer was
+ // started. Set equal to sFrameTime when reset.
+ F64 mStartTime;
+
+ // Timer expires this many seconds after application start time.
+ F64 mExpiry;
+
+ // Useful bit of state usually associated with timers, but does
+ // not affect actual functionality
+ BOOL mStarted;
};
// Glue code for Havok (or anything else that doesn't want the full .h files)
diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h
index 570cd330b8..ceea1d9c48 100644
--- a/indra/llcommon/llhandle.h
+++ b/indra/llcommon/llhandle.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llhandle.h
* @brief "Handle" to an object (usually a floater) whose lifetime you don't
* control.
@@ -6,21 +6,21 @@
* $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$
*/
@@ -42,22 +42,22 @@
class LLTombStone : public LLRefCount
{
public:
- LLTombStone(void* target = NULL) : mTarget(target) {}
+ LLTombStone(void* target = NULL) : mTarget(target) {}
- void setTarget(void* target) { mTarget = target; }
- void* getTarget() const { return mTarget; }
+ void setTarget(void* target) { mTarget = target; }
+ void* getTarget() const { return mTarget; }
private:
- mutable void* mTarget;
+ mutable void* mTarget;
};
/**
- * LLHandles are used to refer to objects whose lifetime you do not control or influence.
- * Calling get() on a handle will return a pointer to the referenced object or NULL,
- * if the object no longer exists. Note that during the lifetime of the returned pointer,
- * you are assuming that the object will not be deleted by any action you perform,
- * or any other thread, as normal when using pointers, so avoid using that pointer outside of
- * the local code block.
- *
+ * LLHandles are used to refer to objects whose lifetime you do not control or influence.
+ * Calling get() on a handle will return a pointer to the referenced object or NULL,
+ * if the object no longer exists. Note that during the lifetime of the returned pointer,
+ * you are assuming that the object will not be deleted by any action you perform,
+ * or any other thread, as normal when using pointers, so avoid using that pointer outside of
+ * the local code block.
+ *
* https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
*
* The implementation is like some "weak pointer" implementations. When we
@@ -84,58 +84,58 @@ private:
template <typename T>
class LLHandle
{
- template <typename U> friend class LLHandle;
- template <typename U> friend class LLHandleProvider;
+ template <typename U> friend class LLHandle;
+ template <typename U> friend class LLHandleProvider;
public:
- LLHandle() : mTombStone(getDefaultTombStone()) {}
-
- template<typename U>
- LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
- : mTombStone(other.mTombStone)
- {}
-
- bool isDead() const
- {
- return mTombStone->getTarget() == NULL;
- }
-
- void markDead()
- {
- mTombStone = getDefaultTombStone();
- }
-
- T* get() const
- {
- return reinterpret_cast<T*>(mTombStone->getTarget());
- }
-
- friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return lhs.mTombStone == rhs.mTombStone;
- }
- friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return !(lhs == rhs);
- }
- friend bool operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return lhs.mTombStone < rhs.mTombStone;
- }
- friend bool operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return lhs.mTombStone > rhs.mTombStone;
- }
+ LLHandle() : mTombStone(getDefaultTombStone()) {}
+
+ template<typename U>
+ LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
+ : mTombStone(other.mTombStone)
+ {}
+
+ bool isDead() const
+ {
+ return mTombStone->getTarget() == NULL;
+ }
+
+ void markDead()
+ {
+ mTombStone = getDefaultTombStone();
+ }
+
+ T* get() const
+ {
+ return reinterpret_cast<T*>(mTombStone->getTarget());
+ }
+
+ friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone == rhs.mTombStone;
+ }
+ friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return !(lhs == rhs);
+ }
+ friend bool operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone < rhs.mTombStone;
+ }
+ friend bool operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone > rhs.mTombStone;
+ }
protected:
- LLPointer<LLTombStone> mTombStone;
+ LLPointer<LLTombStone> mTombStone;
private:
- typedef T* pointer_t;
- static LLPointer<LLTombStone>& getDefaultTombStone()
- {
- static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
- return sDefaultTombStone;
- }
+ typedef T* pointer_t;
+ static LLPointer<LLTombStone>& getDefaultTombStone()
+ {
+ static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
+ return sDefaultTombStone;
+ }
};
/**
@@ -150,36 +150,36 @@ template <typename T>
class LLRootHandle : public LLHandle<T>
{
public:
- typedef LLRootHandle<T> self_t;
- typedef LLHandle<T> base_t;
-
- LLRootHandle(T* object) { bind(object); }
- LLRootHandle() {};
- ~LLRootHandle() { unbind(); }
-
- // this is redundant, since an LLRootHandle *is* an LLHandle
- //LLHandle<T> getHandle() { return LLHandle<T>(*this); }
-
- void bind(T* object)
- {
- // unbind existing tombstone
- if (LLHandle<T>::mTombStone.notNull())
- {
- if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
- LLHandle<T>::mTombStone->setTarget(NULL);
- }
- // tombstone reference counted, so no paired delete
- LLHandle<T>::mTombStone = new LLTombStone((void*)object);
- }
-
- void unbind()
- {
- LLHandle<T>::mTombStone->setTarget(NULL);
- }
-
- //don't allow copying of root handles, since there should only be one
+ typedef LLRootHandle<T> self_t;
+ typedef LLHandle<T> base_t;
+
+ LLRootHandle(T* object) { bind(object); }
+ LLRootHandle() {};
+ ~LLRootHandle() { unbind(); }
+
+ // this is redundant, since an LLRootHandle *is* an LLHandle
+ //LLHandle<T> getHandle() { return LLHandle<T>(*this); }
+
+ void bind(T* object)
+ {
+ // unbind existing tombstone
+ if (LLHandle<T>::mTombStone.notNull())
+ {
+ if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
+ LLHandle<T>::mTombStone->setTarget(NULL);
+ }
+ // tombstone reference counted, so no paired delete
+ LLHandle<T>::mTombStone = new LLTombStone((void*)object);
+ }
+
+ void unbind()
+ {
+ LLHandle<T>::mTombStone->setTarget(NULL);
+ }
+
+ //don't allow copying of root handles, since there should only be one
private:
- LLRootHandle(const LLRootHandle& other) {};
+ LLRootHandle(const LLRootHandle& other) {};
};
/**
@@ -190,31 +190,31 @@ template <typename T>
class LLHandleProvider
{
public:
- LLHandle<T> getHandle() const
- {
- // perform lazy binding to avoid small tombstone allocations for handle
- // providers whose handles are never referenced
- mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this)));
- return mHandle;
- }
-
- template <typename U>
- LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
- {
- LLHandle<U> downcast_handle;
- downcast_handle.mTombStone = getHandle().mTombStone;
- return downcast_handle;
- }
+ LLHandle<T> getHandle() const
+ {
+ // perform lazy binding to avoid small tombstone allocations for handle
+ // providers whose handles are never referenced
+ mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this)));
+ return mHandle;
+ }
+
+ template <typename U>
+ LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
+ {
+ LLHandle<U> downcast_handle;
+ downcast_handle.mTombStone = getHandle().mTombStone;
+ return downcast_handle;
+ }
protected:
- typedef LLHandle<T> handle_type_t;
- LLHandleProvider()
- {
- // provided here to enforce T deriving from LLHandleProvider<T>
- }
+ typedef LLHandle<T> handle_type_t;
+ LLHandleProvider()
+ {
+ // provided here to enforce T deriving from LLHandleProvider<T>
+ }
private:
- mutable LLRootHandle<T> mHandle;
+ mutable LLRootHandle<T> mHandle;
};
@@ -236,12 +236,12 @@ protected:
};
/**
- * This is a simple wrapper for Handles, allowing direct calls to the underlying
- * pointer. The checked handle will throw a Stale if an attempt
- * is made to access the object referenced by the handle and that object has
+ * This is a simple wrapper for Handles, allowing direct calls to the underlying
+ * pointer. The checked handle will throw a Stale if an attempt
+ * is made to access the object referenced by the handle and that object has
* been destroyed.
**/
-template <typename T>
+template <typename T>
class LLCheckedHandle: public LLCheckedHandleBase
{
public:
@@ -269,7 +269,7 @@ public:
}
/**
- * Converts the LLCheckedHandle to a bool. Allows for if (chkdHandle) {}
+ * Converts the LLCheckedHandle to a bool. Allows for if (chkdHandle) {}
* Does not throw.
*/
/*explicit*/ operator bool() const // explicit conversion operator not available with Linux compiler
@@ -278,8 +278,8 @@ public:
}
/**
- * Attempt to call a method or access a member in the structure referenced
- * by the handle. If the handle no longer points to a valid structure
+ * Attempt to call a method or access a member in the structure referenced
+ * by the handle. If the handle no longer points to a valid structure
* throw a Stale.
*/
T* operator ->() const
diff --git a/indra/llcommon/llhash.h b/indra/llcommon/llhash.h
index 4b58e81565..aa1fa2d336 100644
--- a/indra/llcommon/llhash.h
+++ b/indra/llcommon/llhash.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llhash.h
* @brief Wrapper for a hash function.
*
* $LicenseInfo:firstyear=2004&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,17 +36,17 @@
inline size_t llhash( const char * value )
{
- // boost::hash is defined for std::string and for char, but there's no
- // special overload for const char*. The lazy approach would be to
- // instantiate a std::string and take its hash, but that might be more
- // overhead than our callers want. Or we could use boost::hash_range() --
- // but that would require a preliminary pass over the value to determine
- // the end iterator. Instead, use boost::hash_combine() to hash individual
- // characters.
- std::size_t seed = 0;
- for ( ; *value; ++value)
- boost::hash_combine(seed, *value);
- return seed;
+ // boost::hash is defined for std::string and for char, but there's no
+ // special overload for const char*. The lazy approach would be to
+ // instantiate a std::string and take its hash, but that might be more
+ // overhead than our callers want. Or we could use boost::hash_range() --
+ // but that would require a preliminary pass over the value to determine
+ // the end iterator. Instead, use boost::hash_combine() to hash individual
+ // characters.
+ std::size_t seed = 0;
+ for ( ; *value; ++value)
+ boost::hash_combine(seed, *value);
+ return seed;
}
#endif
diff --git a/indra/llcommon/llheartbeat.cpp b/indra/llcommon/llheartbeat.cpp
index 19b7452748..96480050a5 100644
--- a/indra/llcommon/llheartbeat.cpp
+++ b/indra/llcommon/llheartbeat.cpp
@@ -5,21 +5,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$
*/
@@ -33,28 +33,28 @@
#include "llheartbeat.h"
LLHeartbeat::LLHeartbeat(F32 secs_between_heartbeat,
- F32 aggressive_heartbeat_panic_secs,
- F32 aggressive_heartbeat_max_blocking_secs)
- : mSecsBetweenHeartbeat(secs_between_heartbeat),
- mAggressiveHeartbeatPanicSecs(aggressive_heartbeat_panic_secs),
- mAggressiveHeartbeatMaxBlockingSecs(aggressive_heartbeat_max_blocking_secs),
- mSuppressed(false)
+ F32 aggressive_heartbeat_panic_secs,
+ F32 aggressive_heartbeat_max_blocking_secs)
+ : mSecsBetweenHeartbeat(secs_between_heartbeat),
+ mAggressiveHeartbeatPanicSecs(aggressive_heartbeat_panic_secs),
+ mAggressiveHeartbeatMaxBlockingSecs(aggressive_heartbeat_max_blocking_secs),
+ mSuppressed(false)
{
- mBeatTimer.reset();
- mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
- mPanicTimer.reset();
- mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
+ mBeatTimer.reset();
+ mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
+ mPanicTimer.reset();
+ mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
}
LLHeartbeat::~LLHeartbeat()
{
- // do nothing.
+ // do nothing.
}
void
LLHeartbeat::setSuppressed(bool is_suppressed)
{
- mSuppressed = is_suppressed;
+ mSuppressed = is_suppressed;
}
// returns 0 on success, -1 on permanent failure, 1 on temporary failure
@@ -62,104 +62,104 @@ int
LLHeartbeat::rawSend()
{
#if LL_WINDOWS
- return 0; // Pretend we succeeded.
+ return 0; // Pretend we succeeded.
#else
- if (mSuppressed)
- return 0; // Pretend we succeeded.
+ if (mSuppressed)
+ return 0; // Pretend we succeeded.
- int result;
+ int result;
#ifndef LL_DARWIN
- union sigval dummy;
- result = sigqueue(getppid(), LL_HEARTBEAT_SIGNAL, dummy);
+ union sigval dummy;
+ result = sigqueue(getppid(), LL_HEARTBEAT_SIGNAL, dummy);
#else
- result = kill(getppid(), LL_HEARTBEAT_SIGNAL);
+ result = kill(getppid(), LL_HEARTBEAT_SIGNAL);
#endif
- if (result == 0)
- return 0; // success
+ if (result == 0)
+ return 0; // success
- int err = errno;
- if (err == EAGAIN)
- return 1; // failed to queue, try again
+ int err = errno;
+ if (err == EAGAIN)
+ return 1; // failed to queue, try again
- return -1; // other failure.
+ return -1; // other failure.
#endif
}
int
LLHeartbeat::rawSendWithTimeout(F32 timeout_sec)
{
- int result = 0;
-
- // Spin tightly until our heartbeat is digested by the watchdog
- // or we time-out. We don't really want to sleep because our
- // wake-up time might be undesirably synchronised to a hidden
- // clock by the system's scheduler.
- mTimeoutTimer.reset();
- mTimeoutTimer.setTimerExpirySec(timeout_sec);
- do {
- result = rawSend();
- //LL_INFOS() << " HEARTSENDc=" << result << LL_ENDL;
- } while (result==1 && !mTimeoutTimer.hasExpired());
-
- return result;
+ int result = 0;
+
+ // Spin tightly until our heartbeat is digested by the watchdog
+ // or we time-out. We don't really want to sleep because our
+ // wake-up time might be undesirably synchronised to a hidden
+ // clock by the system's scheduler.
+ mTimeoutTimer.reset();
+ mTimeoutTimer.setTimerExpirySec(timeout_sec);
+ do {
+ result = rawSend();
+ //LL_INFOS() << " HEARTSENDc=" << result << LL_ENDL;
+ } while (result==1 && !mTimeoutTimer.hasExpired());
+
+ return result;
}
bool
LLHeartbeat::send(F32 timeout_sec)
{
- bool total_success = false;
- int result = 1;
-
- if (timeout_sec > 0.f) {
- // force a spin until success or timeout
- result = rawSendWithTimeout(timeout_sec);
- } else {
- if (mBeatTimer.hasExpired()) {
- // zero-timeout; we don't care too much whether our
- // heartbeat was digested.
- result = rawSend();
- //LL_INFOS() << " HEARTSENDb=" << result << LL_ENDL;
- }
- }
-
- if (result == -1) {
- // big failure.
- } else if (result == 0) {
- total_success = true;
- } else {
- // need to retry at some point
- }
-
- if (total_success) {
- mBeatTimer.reset();
- mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
- // reset the time until we start panicking about lost
- // heartbeats again.
- mPanicTimer.reset();
- mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
- } else {
- // leave mBeatTimer as expired so we'll lazily poke the
- // watchdog again next time through.
- }
-
- if (mPanicTimer.hasExpired()) {
- // It's been ages since we successfully had a heartbeat
- // digested by the watchdog. Sit here and spin a while
- // in the hope that we can force it through.
- LL_WARNS() << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
- result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs);
- if (result == 0) {
- total_success = true;
- } else {
- // we couldn't even force it through. That's bad,
- // but we'll try again in a while.
- LL_WARNS() << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
- }
-
- // in any case, reset the panic timer.
- mPanicTimer.reset();
- mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
- }
-
- return total_success;
+ bool total_success = false;
+ int result = 1;
+
+ if (timeout_sec > 0.f) {
+ // force a spin until success or timeout
+ result = rawSendWithTimeout(timeout_sec);
+ } else {
+ if (mBeatTimer.hasExpired()) {
+ // zero-timeout; we don't care too much whether our
+ // heartbeat was digested.
+ result = rawSend();
+ //LL_INFOS() << " HEARTSENDb=" << result << LL_ENDL;
+ }
+ }
+
+ if (result == -1) {
+ // big failure.
+ } else if (result == 0) {
+ total_success = true;
+ } else {
+ // need to retry at some point
+ }
+
+ if (total_success) {
+ mBeatTimer.reset();
+ mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
+ // reset the time until we start panicking about lost
+ // heartbeats again.
+ mPanicTimer.reset();
+ mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
+ } else {
+ // leave mBeatTimer as expired so we'll lazily poke the
+ // watchdog again next time through.
+ }
+
+ if (mPanicTimer.hasExpired()) {
+ // It's been ages since we successfully had a heartbeat
+ // digested by the watchdog. Sit here and spin a while
+ // in the hope that we can force it through.
+ LL_WARNS() << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
+ result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs);
+ if (result == 0) {
+ total_success = true;
+ } else {
+ // we couldn't even force it through. That's bad,
+ // but we'll try again in a while.
+ LL_WARNS() << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
+ }
+
+ // in any case, reset the panic timer.
+ mPanicTimer.reset();
+ mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
+ }
+
+ return total_success;
}
diff --git a/indra/llcommon/llheartbeat.h b/indra/llcommon/llheartbeat.h
index 4a75fcc103..54feeb4c92 100644
--- a/indra/llcommon/llheartbeat.h
+++ b/indra/llcommon/llheartbeat.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llheartbeat.h
* @brief Class encapsulating logic for telling a watchdog that we live.
*
* $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$
*/
@@ -37,32 +37,32 @@
class LL_COMMON_API LLHeartbeat
{
public:
- // secs_between_heartbeat: after a heartbeat is successfully delivered,
- // we suppress sending more for this length of time.
- // aggressive_heartbeat_panic_secs: if we've been failing to
- // successfully deliver heartbeats for this length of time then
- // we block for a while until we're really sure we got one delivered.
- // aggressive_heartbeat_max_blocking_secs: this is the length of
- // time we block for when we're aggressively ensuring that a 'panic'
- // heartbeat was delivered.
- LLHeartbeat(F32 secs_between_heartbeat = 5.0f,
- F32 aggressive_heartbeat_panic_secs = 10.0f,
- F32 aggressive_heartbeat_max_blocking_secs = 4.0f);
- ~LLHeartbeat();
+ // secs_between_heartbeat: after a heartbeat is successfully delivered,
+ // we suppress sending more for this length of time.
+ // aggressive_heartbeat_panic_secs: if we've been failing to
+ // successfully deliver heartbeats for this length of time then
+ // we block for a while until we're really sure we got one delivered.
+ // aggressive_heartbeat_max_blocking_secs: this is the length of
+ // time we block for when we're aggressively ensuring that a 'panic'
+ // heartbeat was delivered.
+ LLHeartbeat(F32 secs_between_heartbeat = 5.0f,
+ F32 aggressive_heartbeat_panic_secs = 10.0f,
+ F32 aggressive_heartbeat_max_blocking_secs = 4.0f);
+ ~LLHeartbeat();
- bool send(F32 timeout_sec = 0.0f);
- void setSuppressed(bool is_suppressed);
+ bool send(F32 timeout_sec = 0.0f);
+ void setSuppressed(bool is_suppressed);
private:
- int rawSend();
- int rawSendWithTimeout(F32 timeout_sec);
- F32 mSecsBetweenHeartbeat;
- F32 mAggressiveHeartbeatPanicSecs;
- F32 mAggressiveHeartbeatMaxBlockingSecs;
- bool mSuppressed;
- LLTimer mBeatTimer;
- LLTimer mPanicTimer;
- LLTimer mTimeoutTimer;
+ int rawSend();
+ int rawSendWithTimeout(F32 timeout_sec);
+ F32 mSecsBetweenHeartbeat;
+ F32 mAggressiveHeartbeatPanicSecs;
+ F32 mAggressiveHeartbeatMaxBlockingSecs;
+ bool mSuppressed;
+ LLTimer mBeatTimer;
+ LLTimer mPanicTimer;
+ LLTimer mTimeoutTimer;
};
#endif // LL_HEARTBEAT_H
diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp
index c84e49d085..823bea7a3c 100644
--- a/indra/llcommon/llheteromap.cpp
+++ b/indra/llcommon/llheteromap.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-10-12
* @brief Implementation for llheteromap.
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
@@ -22,7 +22,7 @@ LLHeteroMap::~LLHeteroMap()
{
// For each entry in our map, we must call its deleter, which is the only
// record we have of its original type.
- for (TypeMap::value_type& pair : mMap)
+ for (TypeMap::value_type& pair : mMap)
{
// pair.second is the std::pair; pair.second.first is the void*;
// pair.second.second points to the deleter function
diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h
index 7e96172333..d8e6fefb17 100644
--- a/indra/llcommon/llheteromap.h
+++ b/indra/llcommon/llheteromap.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-10-12
* @brief Map capable of storing objects of diverse types, looked up by type.
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llindexedvector.h b/indra/llcommon/llindexedvector.h
index 68c3821802..de3ae0dcc4 100644
--- a/indra/llcommon/llindexedvector.h
+++ b/indra/llcommon/llindexedvector.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldarray.h
* @brief Wrapped std::vector for backward compatibility.
*
* $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$
*/
@@ -36,65 +36,65 @@
// LLIndexedVector
//--------------------------------------------------------
-template <typename Type, typename Key, int BlockSize = 32>
+template <typename Type, typename Key, int BlockSize = 32>
class LLIndexedVector
{
public:
- typedef typename std::vector<Type>::iterator iterator;
- typedef typename std::vector<Type>::const_iterator const_iterator;
- typedef typename std::vector<Type>::reverse_iterator reverse_iterator;
- typedef typename std::vector<Type>::const_reverse_iterator const_reverse_iterator;
- typedef typename std::vector<Type>::size_type size_type;
+ typedef typename std::vector<Type>::iterator iterator;
+ typedef typename std::vector<Type>::const_iterator const_iterator;
+ typedef typename std::vector<Type>::reverse_iterator reverse_iterator;
+ typedef typename std::vector<Type>::const_reverse_iterator const_reverse_iterator;
+ typedef typename std::vector<Type>::size_type size_type;
protected:
- std::vector<Type> mVector;
- std::map<Key, U32> mIndexMap;
-
+ std::vector<Type> mVector;
+ std::map<Key, U32> mIndexMap;
+
public:
- LLIndexedVector() { mVector.reserve(BlockSize); }
-
- iterator begin() { return mVector.begin(); }
- const_iterator begin() const { return mVector.begin(); }
- iterator end() { return mVector.end(); }
- const_iterator end() const { return mVector.end(); }
+ LLIndexedVector() { mVector.reserve(BlockSize); }
+
+ iterator begin() { return mVector.begin(); }
+ const_iterator begin() const { return mVector.begin(); }
+ iterator end() { return mVector.end(); }
+ const_iterator end() const { return mVector.end(); }
+
+ reverse_iterator rbegin() { return mVector.rbegin(); }
+ const_reverse_iterator rbegin() const { return mVector.rbegin(); }
+ reverse_iterator rend() { return mVector.rend(); }
+ const_reverse_iterator rend() const { return mVector.rend(); }
- reverse_iterator rbegin() { return mVector.rbegin(); }
- const_reverse_iterator rbegin() const { return mVector.rbegin(); }
- reverse_iterator rend() { return mVector.rend(); }
- const_reverse_iterator rend() const { return mVector.rend(); }
+ void reset() { mVector.resize(0); mIndexMap.resize(0); }
+ bool empty() const { return mVector.empty(); }
+ size_type size() const { return mVector.size(); }
- void reset() { mVector.resize(0); mIndexMap.resize(0); }
- bool empty() const { return mVector.empty(); }
- size_type size() const { return mVector.size(); }
-
- Type& operator[](const Key& k)
- {
- typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
- if (iter == mIndexMap.end())
- {
- U32 n = mVector.size();
- mIndexMap[k] = n;
- mVector.push_back(Type());
- llassert(mVector.size() == mIndexMap.size());
- return mVector[n];
- }
- else
- {
- return mVector[iter->second];
- }
- }
+ Type& operator[](const Key& k)
+ {
+ typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
+ if (iter == mIndexMap.end())
+ {
+ U32 n = mVector.size();
+ mIndexMap[k] = n;
+ mVector.push_back(Type());
+ llassert(mVector.size() == mIndexMap.size());
+ return mVector[n];
+ }
+ else
+ {
+ return mVector[iter->second];
+ }
+ }
- const_iterator find(const Key& k) const
- {
- typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
- if(iter == mIndexMap.end())
- {
- return mVector.end();
- }
- else
- {
- return mVector.begin() + iter->second;
- }
- }
+ const_iterator find(const Key& k) const
+ {
+ typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
+ if(iter == mIndexMap.end())
+ {
+ return mVector.end();
+ }
+ else
+ {
+ return mVector.begin() + iter->second;
+ }
+ }
};
#endif
diff --git a/indra/llcommon/llinitdestroyclass.cpp b/indra/llcommon/llinitdestroyclass.cpp
index e3b9e6d099..50e6e24b8d 100644
--- a/indra/llcommon/llinitdestroyclass.cpp
+++ b/indra/llcommon/llinitdestroyclass.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-08-30
* @brief Implementation for llinitdestroyclass.
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
@@ -21,9 +21,9 @@
void LLCallbackRegistry::fireCallbacks() const
{
- for (FuncList::value_type pair : mCallbacks)
- {
- LL_INFOS("LLInitDestroyClass") << "calling " << pair.first << "()" << LL_ENDL;
- pair.second();
- }
+ for (FuncList::value_type pair : mCallbacks)
+ {
+ LL_INFOS("LLInitDestroyClass") << "calling " << pair.first << "()" << LL_ENDL;
+ pair.second();
+ }
}
diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h
index 5f979614fe..2354c9f2ed 100644
--- a/indra/llcommon/llinitdestroyclass.h
+++ b/indra/llcommon/llinitdestroyclass.h
@@ -50,21 +50,21 @@
class LLCallbackRegistry
{
public:
- typedef boost::function<void()> func_t;
+ typedef boost::function<void()> func_t;
- void registerCallback(const std::string& name, const func_t& func)
- {
- mCallbacks.push_back(FuncList::value_type(name, func));
- }
+ void registerCallback(const std::string& name, const func_t& func)
+ {
+ mCallbacks.push_back(FuncList::value_type(name, func));
+ }
- void fireCallbacks() const;
+ void fireCallbacks() const;
private:
- // Arguably this should be a boost::signals2::signal, which is, after all,
- // a sequence of callables. We manage it by hand so we can log a name for
- // each registered function we call.
- typedef std::vector< std::pair<std::string, func_t> > FuncList;
- FuncList mCallbacks;
+ // Arguably this should be a boost::signals2::signal, which is, after all,
+ // a sequence of callables. We manage it by hand so we can log a name for
+ // each registered function we call.
+ typedef std::vector< std::pair<std::string, func_t> > FuncList;
+ FuncList mCallbacks;
};
/**
@@ -74,11 +74,11 @@ private:
* (before main()), requiring LLInitClassList to be fully constructed on
* demand regardless of module initialization order.
*/
-class LLInitClassList :
- public LLCallbackRegistry,
- public LLSingleton<LLInitClassList>
+class LLInitClassList :
+ public LLCallbackRegistry,
+ public LLSingleton<LLInitClassList>
{
- LLSINGLETON_EMPTY_CTOR(LLInitClassList);
+ LLSINGLETON_EMPTY_CTOR(LLInitClassList);
};
/**
@@ -88,11 +88,11 @@ class LLInitClassList :
* time (before main()), requiring LLDestroyClassList to be fully constructed
* on demand regardless of module initialization order.
*/
-class LLDestroyClassList :
- public LLCallbackRegistry,
- public LLSingleton<LLDestroyClassList>
+class LLDestroyClassList :
+ public LLCallbackRegistry,
+ public LLSingleton<LLDestroyClassList>
{
- LLSINGLETON_EMPTY_CTOR(LLDestroyClassList);
+ LLSINGLETON_EMPTY_CTOR(LLDestroyClassList);
};
/**
@@ -105,19 +105,19 @@ template<typename T>
class LLRegisterWith
{
public:
- LLRegisterWith(const std::string& name, const LLCallbackRegistry::func_t& func)
- {
- T::instance().registerCallback(name, func);
- }
-
- // this avoids a MSVC bug where non-referenced static members are "optimized" away
- // even if their constructors have side effects
- S32 reference()
- {
- S32 dummy;
- dummy = 0;
- return dummy;
- }
+ LLRegisterWith(const std::string& name, const LLCallbackRegistry::func_t& func)
+ {
+ T::instance().registerCallback(name, func);
+ }
+
+ // this avoids a MSVC bug where non-referenced static members are "optimized" away
+ // even if their constructors have side effects
+ S32 reference()
+ {
+ S32 dummy;
+ dummy = 0;
+ return dummy;
+ }
};
/**
@@ -133,11 +133,11 @@ template<typename T>
class LLInitClass
{
public:
- LLInitClass() { sRegister.reference(); }
+ LLInitClass() { sRegister.reference(); }
- // When this static member is initialized, the subclass initClass() method
- // is registered on LLInitClassList. See sRegister definition below.
- static LLRegisterWith<LLInitClassList> sRegister;
+ // When this static member is initialized, the subclass initClass() method
+ // is registered on LLInitClassList. See sRegister definition below.
+ static LLRegisterWith<LLInitClassList> sRegister;
};
/**
@@ -153,23 +153,23 @@ template<typename T>
class LLDestroyClass
{
public:
- LLDestroyClass() { sRegister.reference(); }
+ LLDestroyClass() { sRegister.reference(); }
- // When this static member is initialized, the subclass destroyClass()
- // method is registered on LLInitClassList. See sRegister definition
- // below.
- static LLRegisterWith<LLDestroyClassList> sRegister;
+ // When this static member is initialized, the subclass destroyClass()
+ // method is registered on LLInitClassList. See sRegister definition
+ // below.
+ static LLRegisterWith<LLDestroyClassList> sRegister;
};
// Here's where LLInitClass<T> specifies the subclass initClass() method.
template <typename T>
LLRegisterWith<LLInitClassList>
LLInitClass<T>::sRegister(std::string(typeid(T).name()) + "::initClass",
- &T::initClass);
+ &T::initClass);
// Here's where LLDestroyClass<T> specifies the subclass destroyClass() method.
template <typename T>
LLRegisterWith<LLDestroyClassList>
LLDestroyClass<T>::sRegister(std::string(typeid(T).name()) + "::destroyClass",
- &T::destroyClass);
+ &T::destroyClass);
#endif /* ! defined(LL_LLINITDESTROYCLASS_H) */
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index d15bd2f619..7bba1a540d 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -1,26 +1,26 @@
-/**
+/**
* @file llinitparam.cpp
- * @brief parameter block abstraction for creating complex objects and
+ * @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $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$
*/
@@ -34,434 +34,434 @@
namespace LLInitParam
{
- predicate_rule_t default_parse_rules()
- {
- return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY);
- }
-
- //
- // Param
- //
- Param::Param(BaseBlock* enclosing_block)
- : mIsProvided(false)
- {
- const U8* my_addr = reinterpret_cast<const U8*>(this);
- const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
- U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr);
- mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff;
- mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;
- }
-
- //
- // ParamDescriptor
- //
- ParamDescriptor::ParamDescriptor(param_handle_t p,
- merge_func_t merge_func,
- deserialize_func_t deserialize_func,
- serialize_func_t serialize_func,
- validation_func_t validation_func,
- inspect_func_t inspect_func,
- S32 min_count,
- S32 max_count)
- : mParamHandle(p),
- mMergeFunc(merge_func),
- mDeserializeFunc(deserialize_func),
- mSerializeFunc(serialize_func),
- mValidationFunc(validation_func),
- mInspectFunc(inspect_func),
- mMinCount(min_count),
- mMaxCount(max_count),
- mUserData(NULL)
- {}
-
- ParamDescriptor::ParamDescriptor()
- : mParamHandle(0),
- mMergeFunc(NULL),
- mDeserializeFunc(NULL),
- mSerializeFunc(NULL),
- mValidationFunc(NULL),
- mInspectFunc(NULL),
- mMinCount(0),
- mMaxCount(0),
- mUserData(NULL)
- {}
-
- ParamDescriptor::~ParamDescriptor()
- {
- delete mUserData;
- }
-
- //
- // Parser
- //
- Parser::~Parser()
- {}
-
- void Parser::parserWarning(const std::string& message)
- {
- if (mParseSilently) return;
- LL_WARNS() << message << LL_ENDL;
- }
-
- void Parser::parserError(const std::string& message)
- {
- if (mParseSilently) return;
- LL_ERRS() << message << LL_ENDL;
- }
-
-
- //
- // BlockDescriptor
- //
- void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data)
- {
- mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
- std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
- std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
- std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
- }
-
- void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name)
- {
- // create a copy of the param descriptor in mAllParams
- // so other data structures can store a pointer to it
- mAllParams.push_back(in_param);
- ParamDescriptorPtr param(mAllParams.back());
-
- std::string name(char_name);
- if ((size_t)param->mParamHandle > mMaxParamOffset)
- {
- LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
- }
-
- if (name.empty())
- {
- mUnnamedParams.push_back(param);
- }
- else
- {
- // don't use insert, since we want to overwrite existing entries
- mNamedParams[name] = param;
- }
-
- if (param->mValidationFunc)
- {
- mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
- }
- }
-
- BlockDescriptor::BlockDescriptor()
- : mMaxParamOffset(0),
- mInitializationState(UNINITIALIZED),
- mCurrentBlockPtr(NULL)
- {}
-
- // called by each derived class in least to most derived order
- void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
- {
- descriptor.mCurrentBlockPtr = this;
- descriptor.mMaxParamOffset = block_size;
-
- switch(descriptor.mInitializationState)
- {
- case BlockDescriptor::UNINITIALIZED:
- // copy params from base class here
- descriptor.aggregateBlockData(base_descriptor);
-
- descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
- break;
- case BlockDescriptor::INITIALIZING:
- descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
- break;
- case BlockDescriptor::INITIALIZED:
- // nothing to do
- break;
- }
- }
-
- param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
- {
- const U8* param_address = reinterpret_cast<const U8*>(param);
- const U8* baseblock_address = reinterpret_cast<const U8*>(this);
- return (param_address - baseblock_address);
- }
-
- bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
- {
- Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end());
- if (!deserializeBlock(p, range, true))
- {
- if (!silent)
- {
- p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
- }
- return false;
- }
- return true;
- }
-
-
- bool BaseBlock::validateBlock(bool emit_errors) const
- {
- // only validate block when it hasn't already passed validation with current data
- if (!mValidated)
- {
- const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
- for (const BlockDescriptor::param_validation_list_t::value_type& pair : block_data.mValidationList)
- {
- const Param* param = getParamFromHandle(pair.first);
- if (!pair.second(param))
- {
- if (emit_errors)
- {
- LL_WARNS() << "Invalid param \"" << getParamName(block_data, param) << "\"" << LL_ENDL;
- }
- return false;
- }
- }
- mValidated = true;
- }
- return mValidated;
- }
-
- bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const
- {
- bool serialized = false;
- if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided())))
- {
- return false;
- }
- // named param is one like LLView::Params::follows
- // unnamed param is like LLView::Params::rect - implicit
- const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-
- for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
- {
- param_handle_t param_handle = ptr->mParamHandle;
- const Param* param = getParamFromHandle(param_handle);
- ParamDescriptor::serialize_func_t serialize_func = ptr->mSerializeFunc;
- if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
- {
- const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
- serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
- }
- }
-
- for (const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams)
- {
- param_handle_t param_handle = pair.second->mParamHandle;
- const Param* param = getParamFromHandle(param_handle);
- ParamDescriptor::serialize_func_t serialize_func = pair.second->mSerializeFunc;
- if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
- {
- // Ensure this param has not already been serialized
- // Prevents <rect> from being serialized as its own tag.
- bool duplicate = false;
- for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
- {
- if (param_handle == ptr->mParamHandle)
- {
- duplicate = true;
- break;
- }
- }
-
- //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
- // don't know how to detect them
- if (duplicate)
- {
- continue;
- }
-
- name_stack.push_back(std::make_pair(pair.first, !duplicate));
- const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
- serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
- name_stack.pop_back();
- }
- }
-
- if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
- {
- serialized |= parser.writeValue(Flag(), name_stack);
- }
- // was anything serialized in this block?
- return serialized;
- }
-
- bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
- {
- // named param is one like LLView::Params::follows
- // unnamed param is like LLView::Params::rect - implicit
- const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-
- for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
- {
- param_handle_t param_handle = ptr->mParamHandle;
- const Param* param = getParamFromHandle(param_handle);
- ParamDescriptor::inspect_func_t inspect_func = ptr->mInspectFunc;
- if (inspect_func)
- {
- name_stack.push_back(std::make_pair("", true));
- inspect_func(*param, parser, name_stack, ptr->mMinCount, ptr->mMaxCount);
- name_stack.pop_back();
- }
- }
-
- for(const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams)
- {
- param_handle_t param_handle = pair.second->mParamHandle;
- const Param* param = getParamFromHandle(param_handle);
- ParamDescriptor::inspect_func_t inspect_func = pair.second->mInspectFunc;
- if (inspect_func)
- {
- // Ensure this param has not already been inspected
- bool duplicate = false;
+ predicate_rule_t default_parse_rules()
+ {
+ return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY);
+ }
+
+ //
+ // Param
+ //
+ Param::Param(BaseBlock* enclosing_block)
+ : mIsProvided(false)
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+ U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr);
+ mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff;
+ mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;
+ }
+
+ //
+ // ParamDescriptor
+ //
+ ParamDescriptor::ParamDescriptor(param_handle_t p,
+ merge_func_t merge_func,
+ deserialize_func_t deserialize_func,
+ serialize_func_t serialize_func,
+ validation_func_t validation_func,
+ inspect_func_t inspect_func,
+ S32 min_count,
+ S32 max_count)
+ : mParamHandle(p),
+ mMergeFunc(merge_func),
+ mDeserializeFunc(deserialize_func),
+ mSerializeFunc(serialize_func),
+ mValidationFunc(validation_func),
+ mInspectFunc(inspect_func),
+ mMinCount(min_count),
+ mMaxCount(max_count),
+ mUserData(NULL)
+ {}
+
+ ParamDescriptor::ParamDescriptor()
+ : mParamHandle(0),
+ mMergeFunc(NULL),
+ mDeserializeFunc(NULL),
+ mSerializeFunc(NULL),
+ mValidationFunc(NULL),
+ mInspectFunc(NULL),
+ mMinCount(0),
+ mMaxCount(0),
+ mUserData(NULL)
+ {}
+
+ ParamDescriptor::~ParamDescriptor()
+ {
+ delete mUserData;
+ }
+
+ //
+ // Parser
+ //
+ Parser::~Parser()
+ {}
+
+ void Parser::parserWarning(const std::string& message)
+ {
+ if (mParseSilently) return;
+ LL_WARNS() << message << LL_ENDL;
+ }
+
+ void Parser::parserError(const std::string& message)
+ {
+ if (mParseSilently) return;
+ LL_ERRS() << message << LL_ENDL;
+ }
+
+
+ //
+ // BlockDescriptor
+ //
+ void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data)
+ {
+ mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
+ std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
+ std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
+ std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
+ }
+
+ void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name)
+ {
+ // create a copy of the param descriptor in mAllParams
+ // so other data structures can store a pointer to it
+ mAllParams.push_back(in_param);
+ ParamDescriptorPtr param(mAllParams.back());
+
+ std::string name(char_name);
+ if ((size_t)param->mParamHandle > mMaxParamOffset)
+ {
+ LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
+ }
+
+ if (name.empty())
+ {
+ mUnnamedParams.push_back(param);
+ }
+ else
+ {
+ // don't use insert, since we want to overwrite existing entries
+ mNamedParams[name] = param;
+ }
+
+ if (param->mValidationFunc)
+ {
+ mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
+ }
+ }
+
+ BlockDescriptor::BlockDescriptor()
+ : mMaxParamOffset(0),
+ mInitializationState(UNINITIALIZED),
+ mCurrentBlockPtr(NULL)
+ {}
+
+ // called by each derived class in least to most derived order
+ void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+ {
+ descriptor.mCurrentBlockPtr = this;
+ descriptor.mMaxParamOffset = block_size;
+
+ switch(descriptor.mInitializationState)
+ {
+ case BlockDescriptor::UNINITIALIZED:
+ // copy params from base class here
+ descriptor.aggregateBlockData(base_descriptor);
+
+ descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
+ break;
+ case BlockDescriptor::INITIALIZING:
+ descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
+ break;
+ case BlockDescriptor::INITIALIZED:
+ // nothing to do
+ break;
+ }
+ }
+
+ param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
+ {
+ const U8* param_address = reinterpret_cast<const U8*>(param);
+ const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+ return (param_address - baseblock_address);
+ }
+
+ bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
+ {
+ Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end());
+ if (!deserializeBlock(p, range, true))
+ {
+ if (!silent)
+ {
+ p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
+ }
+ return false;
+ }
+ return true;
+ }
+
+
+ bool BaseBlock::validateBlock(bool emit_errors) const
+ {
+ // only validate block when it hasn't already passed validation with current data
+ if (!mValidated)
+ {
+ const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+ for (const BlockDescriptor::param_validation_list_t::value_type& pair : block_data.mValidationList)
+ {
+ const Param* param = getParamFromHandle(pair.first);
+ if (!pair.second(param))
+ {
+ if (emit_errors)
+ {
+ LL_WARNS() << "Invalid param \"" << getParamName(block_data, param) << "\"" << LL_ENDL;
+ }
+ return false;
+ }
+ }
+ mValidated = true;
+ }
+ return mValidated;
+ }
+
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const
+ {
+ bool serialized = false;
+ if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided())))
+ {
+ return false;
+ }
+ // named param is one like LLView::Params::follows
+ // unnamed param is like LLView::Params::rect - implicit
+ const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+
+ for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
+ {
+ param_handle_t param_handle = ptr->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::serialize_func_t serialize_func = ptr->mSerializeFunc;
+ if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
+ {
+ const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+ serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
+ }
+ }
+
+ for (const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams)
+ {
+ param_handle_t param_handle = pair.second->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::serialize_func_t serialize_func = pair.second->mSerializeFunc;
+ if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
+ {
+ // Ensure this param has not already been serialized
+ // Prevents <rect> from being serialized as its own tag.
+ bool duplicate = false;
+ for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
+ {
+ if (param_handle == ptr->mParamHandle)
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
+ // don't know how to detect them
+ if (duplicate)
+ {
+ continue;
+ }
+
+ name_stack.push_back(std::make_pair(pair.first, !duplicate));
+ const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+ serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
+ name_stack.pop_back();
+ }
+ }
+
+ if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+ {
+ serialized |= parser.writeValue(Flag(), name_stack);
+ }
+ // was anything serialized in this block?
+ return serialized;
+ }
+
+ bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
+ {
+ // named param is one like LLView::Params::follows
+ // unnamed param is like LLView::Params::rect - implicit
+ const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+
+ for (const ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
+ {
+ param_handle_t param_handle = ptr->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::inspect_func_t inspect_func = ptr->mInspectFunc;
+ if (inspect_func)
+ {
+ name_stack.push_back(std::make_pair("", true));
+ inspect_func(*param, parser, name_stack, ptr->mMinCount, ptr->mMaxCount);
+ name_stack.pop_back();
+ }
+ }
+
+ for(const BlockDescriptor::param_map_t::value_type& pair : block_data.mNamedParams)
+ {
+ param_handle_t param_handle = pair.second->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::inspect_func_t inspect_func = pair.second->mInspectFunc;
+ if (inspect_func)
+ {
+ // Ensure this param has not already been inspected
+ bool duplicate = false;
for (const ParamDescriptorPtr &ptr : block_data.mUnnamedParams)
- {
- if (param_handle == ptr->mParamHandle)
- {
- duplicate = true;
- break;
- }
- }
-
- name_stack.push_back(std::make_pair(pair.first, !duplicate));
- inspect_func(*param, parser, name_stack, pair.second->mMinCount, pair.second->mMaxCount);
- name_stack.pop_back();
- }
- }
-
- return true;
- }
-
- bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored)
- {
- BlockDescriptor& block_data = mostDerivedBlockDescriptor();
- bool names_left = name_stack_range.first != name_stack_range.second;
-
- bool new_name = names_left
- ? name_stack_range.first->second
- : true;
-
- if (names_left)
- {
- const std::string& top_name = name_stack_range.first->first;
-
- BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
- if (found_it != block_data.mNamedParams.end())
- {
- // find pointer to member parameter from offset table
- Param* paramp = getParamFromHandle(found_it->second->mParamHandle);
- ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc;
-
- Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
- ++new_name_stack.first;
- if (deserialize_func(*paramp, p, new_name_stack, new_name))
- {
- // value is no longer new, we know about it now
- name_stack_range.first->second = false;
- return true;
- }
- else
- {
- return false;
- }
- }
- }
-
- // try to parse unnamed parameters, in declaration order
- for (ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
- {
- Param* paramp = getParamFromHandle(ptr->mParamHandle);
- ParamDescriptor::deserialize_func_t deserialize_func = ptr->mDeserializeFunc;
-
- if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name))
- {
- return true;
- }
- }
-
- // if no match, and no names left on stack, this is just an existence assertion of this block
- // verify by calling readValue with NoParamValue type, an inherently unparseable type
- if (!names_left)
- {
- Flag no_value;
- return p.readValue(no_value);
- }
-
- return false;
- }
-
- void BaseBlock::addSynonym(Param& param, const std::string& synonym)
- {
- BlockDescriptor& block_data = mostDerivedBlockDescriptor();
- if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
- {
- param_handle_t handle = getHandleFromParam(&param);
-
- // check for invalid derivation from a paramblock (i.e. without using
- // Block<T, Base_Class>
- if ((size_t)handle > block_data.mMaxParamOffset)
- {
- LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
- }
-
- ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
- if (param_descriptor)
- {
- if (synonym.empty())
- {
- block_data.mUnnamedParams.push_back(param_descriptor);
- }
- else
- {
- block_data.mNamedParams[synonym] = param_descriptor;
- }
- }
- }
- }
-
- const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
- {
- param_handle_t handle = getHandleFromParam(paramp);
- for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
- {
- if (it->second->mParamHandle == handle)
- {
- return it->first;
- }
- }
-
- return LLStringUtil::null;
- }
-
- ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param)
- {
- param_handle_t handle = getHandleFromParam(&param);
- BlockDescriptor& descriptor = mostDerivedBlockDescriptor();
- for (ParamDescriptorPtr& ptr : descriptor.mAllParams)
- {
- if (ptr->mParamHandle == handle) return ptr;
- }
- return ParamDescriptorPtr();
- }
-
- // take all provided params from other and apply to self
- // NOTE: this requires that "other" is of the same derived type as this
- bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
- {
- bool some_param_changed = false;
- for (const ParamDescriptorPtr& ptr : block_data.mAllParams)
- {
- const Param* other_paramp = other.getParamFromHandle(ptr->mParamHandle);
- ParamDescriptor::merge_func_t merge_func = ptr->mMergeFunc;
- if (merge_func)
- {
- Param* paramp = getParamFromHandle(ptr->mParamHandle);
- llassert(paramp->getEnclosingBlockOffset() == ptr->mParamHandle);
- some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);
- }
- }
- return some_param_changed;
- }
+ {
+ if (param_handle == ptr->mParamHandle)
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ name_stack.push_back(std::make_pair(pair.first, !duplicate));
+ inspect_func(*param, parser, name_stack, pair.second->mMinCount, pair.second->mMaxCount);
+ name_stack.pop_back();
+ }
+ }
+
+ return true;
+ }
+
+ bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored)
+ {
+ BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+ bool names_left = name_stack_range.first != name_stack_range.second;
+
+ bool new_name = names_left
+ ? name_stack_range.first->second
+ : true;
+
+ if (names_left)
+ {
+ const std::string& top_name = name_stack_range.first->first;
+
+ BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
+ if (found_it != block_data.mNamedParams.end())
+ {
+ // find pointer to member parameter from offset table
+ Param* paramp = getParamFromHandle(found_it->second->mParamHandle);
+ ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc;
+
+ Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
+ ++new_name_stack.first;
+ if (deserialize_func(*paramp, p, new_name_stack, new_name))
+ {
+ // value is no longer new, we know about it now
+ name_stack_range.first->second = false;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ // try to parse unnamed parameters, in declaration order
+ for (ParamDescriptorPtr& ptr : block_data.mUnnamedParams)
+ {
+ Param* paramp = getParamFromHandle(ptr->mParamHandle);
+ ParamDescriptor::deserialize_func_t deserialize_func = ptr->mDeserializeFunc;
+
+ if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name))
+ {
+ return true;
+ }
+ }
+
+ // if no match, and no names left on stack, this is just an existence assertion of this block
+ // verify by calling readValue with NoParamValue type, an inherently unparseable type
+ if (!names_left)
+ {
+ Flag no_value;
+ return p.readValue(no_value);
+ }
+
+ return false;
+ }
+
+ void BaseBlock::addSynonym(Param& param, const std::string& synonym)
+ {
+ BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+ if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ param_handle_t handle = getHandleFromParam(&param);
+
+ // check for invalid derivation from a paramblock (i.e. without using
+ // Block<T, Base_Class>
+ if ((size_t)handle > block_data.mMaxParamOffset)
+ {
+ LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
+ }
+
+ ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
+ if (param_descriptor)
+ {
+ if (synonym.empty())
+ {
+ block_data.mUnnamedParams.push_back(param_descriptor);
+ }
+ else
+ {
+ block_data.mNamedParams[synonym] = param_descriptor;
+ }
+ }
+ }
+ }
+
+ const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
+ {
+ param_handle_t handle = getHandleFromParam(paramp);
+ for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
+ {
+ if (it->second->mParamHandle == handle)
+ {
+ return it->first;
+ }
+ }
+
+ return LLStringUtil::null;
+ }
+
+ ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param)
+ {
+ param_handle_t handle = getHandleFromParam(&param);
+ BlockDescriptor& descriptor = mostDerivedBlockDescriptor();
+ for (ParamDescriptorPtr& ptr : descriptor.mAllParams)
+ {
+ if (ptr->mParamHandle == handle) return ptr;
+ }
+ return ParamDescriptorPtr();
+ }
+
+ // take all provided params from other and apply to self
+ // NOTE: this requires that "other" is of the same derived type as this
+ bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
+ {
+ bool some_param_changed = false;
+ for (const ParamDescriptorPtr& ptr : block_data.mAllParams)
+ {
+ const Param* other_paramp = other.getParamFromHandle(ptr->mParamHandle);
+ ParamDescriptor::merge_func_t merge_func = ptr->mMergeFunc;
+ if (merge_func)
+ {
+ Param* paramp = getParamFromHandle(ptr->mParamHandle);
+ llassert(paramp->getEnclosingBlockOffset() == ptr->mParamHandle);
+ some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);
+ }
+ }
+ return some_param_changed;
+ }
}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index e0d0ab9ac7..206aa51ba3 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -1,26 +1,26 @@
-/**
+/**
* @file llinitparam.h
- * @brief parameter block abstraction for creating complex objects and
+ * @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $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$
*/
@@ -43,2796 +43,2796 @@
namespace LLTypeTags
{
- template <typename INNER_TYPE, int _SORT_ORDER>
- struct TypeTagBase
- {
- typedef void is_tag_t;
- typedef INNER_TYPE inner_t;
- static const int SORT_ORDER=_SORT_ORDER;
- };
-
- template <int VAL1, int VAL2>
- struct GreaterThan
- {
- static const bool value = VAL1 > VAL2;
- };
-
- template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value >
- struct Swap
- {
- typedef typename ITEM::template Cons<REST>::value_t value_t;
- };
-
- template<typename ITEM, typename REST>
- struct Swap<ITEM, REST, true>
- {
- typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t;
- };
-
- template<typename T, typename SORTABLE = void>
- struct IsSortable
- {
- static const bool value = false;
- };
-
- template<typename T>
- struct IsSortable<T, typename T::is_tag_t>
- {
- static const bool value = true;
- };
-
- template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value>
- struct InsertInto
- {
- typedef typename ITEM::template Cons<REST>::value_t value_t;
- };
-
- template<typename ITEM, typename REST>
- struct InsertInto <ITEM, REST, true>
- {
- typedef typename Swap<ITEM, REST>::value_t value_t;
- };
-
- template<typename T, bool SORTABLE = IsSortable<T>::value>
- struct Sorted
- {
- typedef T value_t;
- };
-
- template<typename T>
- struct Sorted <T, true>
- {
- typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t;
- };
+ template <typename INNER_TYPE, int _SORT_ORDER>
+ struct TypeTagBase
+ {
+ typedef void is_tag_t;
+ typedef INNER_TYPE inner_t;
+ static const int SORT_ORDER=_SORT_ORDER;
+ };
+
+ template <int VAL1, int VAL2>
+ struct GreaterThan
+ {
+ static const bool value = VAL1 > VAL2;
+ };
+
+ template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value >
+ struct Swap
+ {
+ typedef typename ITEM::template Cons<REST>::value_t value_t;
+ };
+
+ template<typename ITEM, typename REST>
+ struct Swap<ITEM, REST, true>
+ {
+ typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t;
+ };
+
+ template<typename T, typename SORTABLE = void>
+ struct IsSortable
+ {
+ static const bool value = false;
+ };
+
+ template<typename T>
+ struct IsSortable<T, typename T::is_tag_t>
+ {
+ static const bool value = true;
+ };
+
+ template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value>
+ struct InsertInto
+ {
+ typedef typename ITEM::template Cons<REST>::value_t value_t;
+ };
+
+ template<typename ITEM, typename REST>
+ struct InsertInto <ITEM, REST, true>
+ {
+ typedef typename Swap<ITEM, REST>::value_t value_t;
+ };
+
+ template<typename T, bool SORTABLE = IsSortable<T>::value>
+ struct Sorted
+ {
+ typedef T value_t;
+ };
+
+ template<typename T>
+ struct Sorted <T, true>
+ {
+ typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t;
+ };
}
namespace LLInitParam
{
- // used to indicate no matching value to a given name when parsing
- struct Flag{};
-
- template<typename T> const T& defaultValue() { static T value; return value; }
-
- // wraps comparison operator between any 2 values of the same type
- // specialize to handle cases where equality isn't defined well, or at all
- template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
- struct ParamCompare
- {
- static bool equals(const T &a, const T &b)
- {
- return a == b;
- }
+ // used to indicate no matching value to a given name when parsing
+ struct Flag{};
+
+ template<typename T> const T& defaultValue() { static T value; return value; }
+
+ // wraps comparison operator between any 2 values of the same type
+ // specialize to handle cases where equality isn't defined well, or at all
+ template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
+ struct ParamCompare
+ {
+ static bool equals(const T &a, const T &b)
+ {
+ return a == b;
+ }
+ };
+
+ // boost function types are not comparable
+ template<typename T>
+ struct ParamCompare<T, true>
+ {
+ static bool equals(const T&a, const T &b)
+ {
+ return false;
+ }
+ };
+
+ template<>
+ struct ParamCompare<LLSD, false>
+ {
+ static bool equals(const LLSD &a, const LLSD &b) { return false; }
+ };
+
+ template<>
+ struct ParamCompare<Flag, false>
+ {
+ static bool equals(const Flag& a, const Flag& b) { return false; }
+ };
+
+
+ // helper functions and classes
+ typedef ptrdiff_t param_handle_t;
+ struct IS_A_BLOCK {};
+ struct NOT_BLOCK {};
+
+ // these templates allow us to distinguish between template parameters
+ // that derive from BaseBlock and those that don't
+ template<typename T, typename BLOCK_IDENTIFIER = void>
+ struct IsBlock
+ {
+ typedef NOT_BLOCK value_t;
+ };
+
+ template<typename T>
+ struct IsBlock<T, typename T::baseblock_base_class_t>
+ {
+ typedef IS_A_BLOCK value_t;
+ };
+
+ // ParamValue class directly manages the wrapped value
+ // by holding on to a copy (scalar params)
+ // or deriving from it (blocks)
+ // has specializations for custom value behavior
+ // and "tag" values like Lazy and Atomic
+ template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t>
+ class ParamValue
+ {
+ typedef ParamValue<T, VALUE_IS_BLOCK> self_t;
+
+ public:
+ typedef T default_value_t;
+ typedef T value_t;
+
+ ParamValue(): mValue() {}
+ ParamValue(const default_value_t& other) : mValue(other) {}
+
+ void setValue(const value_t& val)
+ {
+ mValue = val;
+ }
+
+ const value_t& getValue() const
+ {
+ return mValue;
+ }
+
+ T& getValue()
+ {
+ return mValue;
+ }
+
+ bool isValid() const { return true; }
+
+ protected:
+ T mValue;
+ };
+
+ template<typename T>
+ class ParamValue<T, IS_A_BLOCK>
+ : public T
+ {
+ typedef ParamValue<T, IS_A_BLOCK> self_t;
+ public:
+ typedef T default_value_t;
+ typedef T value_t;
+
+ ParamValue()
+ : T()
+ {}
+
+ ParamValue(const default_value_t& other)
+ : T(other)
+ {}
+
+ void setValue(const value_t& val)
+ {
+ *this = val;
+ }
+
+ const value_t& getValue() const
+ {
+ return *this;
+ }
+
+ T& getValue()
+ {
+ return *this;
+ }
};
- // boost function types are not comparable
- template<typename T>
- struct ParamCompare<T, true>
- {
- static bool equals(const T&a, const T &b)
- {
- return false;
- }
- };
-
- template<>
- struct ParamCompare<LLSD, false>
- {
- static bool equals(const LLSD &a, const LLSD &b) { return false; }
- };
-
- template<>
- struct ParamCompare<Flag, false>
- {
- static bool equals(const Flag& a, const Flag& b) { return false; }
- };
-
-
- // helper functions and classes
- typedef ptrdiff_t param_handle_t;
- struct IS_A_BLOCK {};
- struct NOT_BLOCK {};
-
- // these templates allow us to distinguish between template parameters
- // that derive from BaseBlock and those that don't
- template<typename T, typename BLOCK_IDENTIFIER = void>
- struct IsBlock
- {
- typedef NOT_BLOCK value_t;
- };
-
- template<typename T>
- struct IsBlock<T, typename T::baseblock_base_class_t>
- {
- typedef IS_A_BLOCK value_t;
- };
-
- // ParamValue class directly manages the wrapped value
- // by holding on to a copy (scalar params)
- // or deriving from it (blocks)
- // has specializations for custom value behavior
- // and "tag" values like Lazy and Atomic
- template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t>
- class ParamValue
- {
- typedef ParamValue<T, VALUE_IS_BLOCK> self_t;
-
- public:
- typedef T default_value_t;
- typedef T value_t;
-
- ParamValue(): mValue() {}
- ParamValue(const default_value_t& other) : mValue(other) {}
-
- void setValue(const value_t& val)
- {
- mValue = val;
- }
-
- const value_t& getValue() const
- {
- return mValue;
- }
-
- T& getValue()
- {
- return mValue;
- }
-
- bool isValid() const { return true; }
-
- protected:
- T mValue;
- };
-
- template<typename T>
- class ParamValue<T, IS_A_BLOCK>
- : public T
- {
- typedef ParamValue<T, IS_A_BLOCK> self_t;
- public:
- typedef T default_value_t;
- typedef T value_t;
-
- ParamValue()
- : T()
- {}
-
- ParamValue(const default_value_t& other)
- : T(other)
- {}
-
- void setValue(const value_t& val)
- {
- *this = val;
- }
-
- const value_t& getValue() const
- {
- return *this;
- }
-
- T& getValue()
- {
- return *this;
- }
- };
-
-
- // empty default implementation of key cache
- // leverages empty base class optimization
- template <typename T>
- class TypeValues
- : public ParamValue<typename LLTypeTags::Sorted<T>::value_t>
- {
- private:
- struct Inaccessable{};
- public:
- typedef std::map<std::string, T> value_name_map_t;
- typedef Inaccessable name_t;
- typedef TypeValues<T> type_value_t;
- typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
- typedef typename param_value_t::value_t value_t;
-
- TypeValues(const typename param_value_t::value_t& val)
- : param_value_t(val)
- {}
-
- void setValueName(const std::string& key) {}
- std::string getValueName() const { return ""; }
- std::string calcValueName(const value_t& value) const { return ""; }
- void clearValueName() const {}
-
- static bool getValueFromName(const std::string& name, value_t& value)
- {
- return false;
- }
-
- static bool valueNamesExist()
- {
- return false;
- }
-
- static std::vector<std::string>* getPossibleValues()
- {
- return NULL;
- }
-
- void assignNamedValue(const Inaccessable& name)
- {}
-
- operator const value_t&() const
- {
- return param_value_t::getValue();
- }
-
- const value_t& operator()() const
- {
- return param_value_t::getValue();
- }
-
- static value_name_map_t* getValueNames() {return NULL;}
- };
-
- // helper class to implement name value lookups
- // and caching of last used name
- template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true >
- class TypeValuesHelper
- : public ParamValue<typename LLTypeTags::Sorted<T>::value_t>
- {
- typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t;
- public:
- typedef typename std::map<std::string, T> value_name_map_t;
- typedef std::string name_t;
- typedef self_t type_value_t;
- typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
- typedef typename param_value_t::value_t value_t;
-
- TypeValuesHelper(const typename param_value_t::value_t& val)
- : param_value_t(val)
- {}
-
- //TODO: cache key by index to save on param block size
- void setValueName(const std::string& value_name)
- {
- mValueName = value_name;
- }
-
- std::string getValueName() const
- {
- return mValueName;
- }
-
- std::string calcValueName(const value_t& value) const
- {
- value_name_map_t* map = getValueNames();
- for (typename value_name_map_t::value_type& map_pair : *map)
- {
- if (ParamCompare<T>::equals(map_pair.second, value))
- {
- return map_pair.first;
- }
- }
-
- return "";
- }
-
- void clearValueName() const
- {
- mValueName.clear();
- }
-
- static bool getValueFromName(const std::string& name, value_t& value)
- {
- value_name_map_t* map = getValueNames();
- typename value_name_map_t::iterator found_it = map->find(name);
- if (found_it == map->end()) return false;
-
- value = found_it->second;
- return true;
- }
-
- static bool valueNamesExist()
- {
- return !getValueNames()->empty();
- }
-
- static value_name_map_t* getValueNames()
- {
- static value_name_map_t sMap;
- static bool sInitialized = false;
-
- if (!sInitialized)
- {
- sInitialized = true;
- DERIVED_TYPE::declareValues();
- }
- return &sMap;
- }
-
- static std::vector<std::string>* getPossibleValues()
- {
- static std::vector<std::string> sValues;
-
- value_name_map_t* map = getValueNames();
- for (typename value_name_map_t::value_type& map_pair : *map)
- {
- sValues.push_back(map_pair.first);
- }
- return &sValues;
- }
-
- static void declare(const std::string& name, const value_t& value)
- {
- (*getValueNames())[name] = value;
- }
-
- void operator ()(const std::string& name)
- {
- *this = name;
- }
-
- void assignNamedValue(const std::string& name)
- {
- if (getValueFromName(name, param_value_t::getValue()))
- {
- setValueName(name);
- }
- }
-
- operator const value_t&() const
- {
- return param_value_t::getValue();
- }
-
- const value_t& operator()() const
- {
- return param_value_t::getValue();
- }
-
- protected:
- static void getName(const std::string& name, const value_t& value)
- {}
-
- mutable std::string mValueName;
- };
-
- // string types can support custom named values, but need
- // to disambiguate in code between a string that is a named value
- // and a string that is a name
- template <typename DERIVED_TYPE>
- class TypeValuesHelper<std::string, DERIVED_TYPE, true>
- : public TypeValuesHelper<std::string, DERIVED_TYPE, false>
- {
- public:
- typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t;
- typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t;
- typedef std::string value_t;
- typedef std::string name_t;
- typedef self_t type_value_t;
-
- TypeValuesHelper(const std::string& val)
- : base_t(val)
- {}
-
- void operator ()(const std::string& name)
- {
- *this = name;
- }
-
- self_t& operator =(const std::string& name)
- {
- if (base_t::getValueFromName(name, ParamValue<std::string>::getValue()))
- {
- base_t::setValueName(name);
- }
- else
- {
- ParamValue<std::string>::setValue(name);
- }
- return *this;
- }
-
- operator const value_t&() const
- {
- return ParamValue<std::string>::getValue();
- }
-
- const value_t& operator()() const
- {
- return ParamValue<std::string>::getValue();
- }
-
- };
-
- // parser base class with mechanisms for registering readers/writers/inspectors of different types
- class LL_COMMON_API Parser
- {
- LOG_CLASS(Parser);
- public:
- typedef std::vector<std::pair<std::string, bool> > name_stack_t;
- typedef std::pair<name_stack_t::iterator, name_stack_t::iterator> name_stack_range_t;
- typedef std::vector<std::string> possible_values_t;
-
- typedef bool (*parser_read_func_t)(Parser& parser, void* output);
- typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
- typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t;
-
- typedef std::map<const std::type_info*, parser_read_func_t> parser_read_func_map_t;
- typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t;
- typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t;
-
- public:
-
- Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
- : mParseSilently(false),
- mParserReadFuncs(&read_map),
- mParserWriteFuncs(&write_map),
- mParserInspectFuncs(&inspect_map)
- {}
-
- virtual ~Parser();
-
- template <typename T> bool readValue(T& param, typename boost::disable_if<boost::is_enum<T> >::type* dummy = 0)
- {
- parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
- if (found_it != mParserReadFuncs->end())
- {
- return found_it->second(*this, (void*)&param);
- }
-
- return false;
- }
-
- template <typename T> bool readValue(T& param, typename boost::enable_if<boost::is_enum<T> >::type* dummy = 0)
- {
- parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
- if (found_it != mParserReadFuncs->end())
- {
- return found_it->second(*this, (void*)&param);
- }
- else
- {
- found_it = mParserReadFuncs->find(&typeid(S32));
- if (found_it != mParserReadFuncs->end())
- {
- S32 int_value;
- bool parsed = found_it->second(*this, (void*)&int_value);
- param = (T)int_value;
- return parsed;
- }
- }
- return false;
- }
-
- template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
- {
- parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
- if (found_it != mParserWriteFuncs->end())
- {
- return found_it->second(*this, (const void*)&param, name_stack);
- }
- return false;
- }
-
- // dispatch inspection to registered inspection functions, for each parameter in a param block
- template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
- {
- parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
- if (found_it != mParserInspectFuncs->end())
- {
- found_it->second(name_stack, min_count, max_count, possible_values);
- return true;
- }
- return false;
- }
-
- virtual std::string getCurrentElementName() = 0;
- virtual std::string getCurrentFileName() = 0;
- virtual void parserWarning(const std::string& message);
- virtual void parserError(const std::string& message);
- void setParseSilently(bool silent) { mParseSilently = silent; }
-
- protected:
- template <typename T>
- void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
- {
- mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
- mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
- }
-
- template <typename T>
- void registerInspectFunc(parser_inspect_func_t inspect_func)
- {
- mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
- }
-
- bool mParseSilently;
-
- private:
- parser_read_func_map_t* mParserReadFuncs;
- parser_write_func_map_t* mParserWriteFuncs;
- parser_inspect_func_map_t* mParserInspectFuncs;
- };
-
- class Param;
-
- enum ESerializePredicates
- {
- PROVIDED,
- REQUIRED,
- VALID,
- HAS_DEFAULT_VALUE,
- EMPTY
- };
-
- typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t;
-
- predicate_rule_t default_parse_rules();
-
- // various callbacks and constraints associated with an individual param
- struct LL_COMMON_API ParamDescriptor
- {
- struct UserData
- {
- virtual ~UserData() {}
- };
-
- typedef bool(*merge_func_t)(Param&, const Param&, bool);
- typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool);
- typedef bool(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const predicate_rule_t rules, const Param* diff_param);
- typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
- typedef bool(*validation_func_t)(const Param*);
-
- ParamDescriptor(param_handle_t p,
- merge_func_t merge_func,
- deserialize_func_t deserialize_func,
- serialize_func_t serialize_func,
- validation_func_t validation_func,
- inspect_func_t inspect_func,
- S32 min_count,
- S32 max_count);
-
- ParamDescriptor();
- ~ParamDescriptor();
-
- param_handle_t mParamHandle;
- merge_func_t mMergeFunc;
- deserialize_func_t mDeserializeFunc;
- serialize_func_t mSerializeFunc;
- inspect_func_t mInspectFunc;
- validation_func_t mValidationFunc;
- S32 mMinCount;
- S32 mMaxCount;
- S32 mNumRefs;
- UserData* mUserData;
- };
-
- typedef std::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
-
- // each derived Block class keeps a static data structure maintaining offsets to various params
- class LL_COMMON_API BlockDescriptor
- {
- public:
- BlockDescriptor();
-
- typedef enum e_initialization_state
- {
- UNINITIALIZED,
- INITIALIZING,
- INITIALIZED
- } EInitializationState;
-
- void aggregateBlockData(BlockDescriptor& src_block_data);
- void addParam(ParamDescriptorPtr param, const char* name);
-
- typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t;
- typedef std::vector<ParamDescriptorPtr> param_list_t;
- typedef std::list<ParamDescriptorPtr> all_params_list_t;
- typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t;
-
- param_map_t mNamedParams; // parameters with associated names
- param_list_t mUnnamedParams; // parameters with_out_ associated names
- param_validation_list_t mValidationList; // parameters that must be validated
- all_params_list_t mAllParams; // all parameters, owns descriptors
- size_t mMaxParamOffset;
- EInitializationState mInitializationState; // whether or not static block data has been initialized
- class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
- };
-
- //TODO: implement in terms of owned_ptr
- template<typename T>
- class LazyValue
- {
- public:
- LazyValue()
- : mPtr(NULL)
- {}
-
- ~LazyValue()
- {
- delete mPtr;
- }
-
- LazyValue(const T& value)
- {
- mPtr = new T(value);
- }
-
- LazyValue(const LazyValue& other)
- : mPtr(NULL)
- {
- *this = other;
- }
-
- LazyValue& operator = (const LazyValue& other)
- {
- if (!other.mPtr)
- {
- delete mPtr;
- mPtr = NULL;
- }
- else
- {
- if (!mPtr)
- {
- mPtr = new T(*other.mPtr);
- }
- else
- {
- *mPtr = *(other.mPtr);
- }
- }
- return *this;
- }
-
- bool operator==(const LazyValue& other) const
- {
- if (empty() || other.empty()) return false;
- return *mPtr == *other.mPtr;
- }
-
- bool empty() const
- {
- return mPtr == NULL;
- }
-
- void set(const T& other)
- {
- if (!mPtr)
- {
- mPtr = new T(other);
- }
- else
- {
- *mPtr = other;
- }
- }
-
- const T& get() const
- {
- return *ensureInstance();
- }
-
- T& get()
- {
- return *ensureInstance();
- }
-
- operator const T&() const
- {
- return get();
- }
-
- private:
- // lazily allocate an instance of T
- T* ensureInstance() const
- {
- if (mPtr == NULL)
- {
- mPtr = new T();
- }
- return mPtr;
- }
-
- private:
-
- mutable T* mPtr;
- };
-
- // root class of all parameter blocks
-
- class LL_COMMON_API BaseBlock
- {
- public:
- // lift block tags into baseblock namespace so derived classes do not need to qualify them
- typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK;
- typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK;
-
- template<typename T>
- struct Sequential : public LLTypeTags::TypeTagBase<T, 2>
- {
- template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; };
- template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; };
- };
-
- template<typename T>
- struct Atomic : public LLTypeTags::TypeTagBase<T, 1>
- {
- template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; };
- template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; };
- };
-
- template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t >
- struct Lazy : public LLTypeTags::TypeTagBase<T, 0>
- {
- template <typename S> struct Cons
- {
- typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t;
- };
- template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> >
- {
- typedef Lazy<S, IS_A_BLOCK> value_t;
- };
- template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> >
- {
- typedef Lazy<S, BLOCK_T> value_t;
- };
- };
-
- // "Multiple" constraint types, put here in root class to avoid ambiguity during use
- struct AnyAmount
- {
- enum { minCount = 0 };
- enum { maxCount = U32_MAX };
- };
-
- template<U32 MIN_AMOUNT>
- struct AtLeast
- {
- enum { minCount = MIN_AMOUNT };
- enum { maxCount = U32_MAX };
- };
-
- template<U32 MAX_AMOUNT>
- struct AtMost
- {
- enum { minCount = 0 };
- enum { maxCount = MAX_AMOUNT };
- };
-
- template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
- struct Between
- {
- enum { minCount = MIN_AMOUNT };
- enum { maxCount = MAX_AMOUNT };
- };
-
- template<U32 EXACT_COUNT>
- struct Exactly
- {
- enum { minCount = EXACT_COUNT };
- enum { maxCount = EXACT_COUNT };
- };
-
- // this typedef identifies derived classes as being blocks
- typedef void baseblock_base_class_t;
- LOG_CLASS(BaseBlock);
- friend class Param;
-
- BaseBlock()
- : mValidated(false),
- mParamProvided(false)
- {}
-
- virtual ~BaseBlock() {}
- bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
-
- param_handle_t getHandleFromParam(const Param* param) const;
- bool validateBlock(bool emit_errors = true) const;
-
- bool isProvided() const
- {
- return mParamProvided;
- }
-
- bool isValid() const
- {
- return validateBlock(false);
- }
-
-
- Param* getParamFromHandle(const param_handle_t param_handle)
- {
- if (param_handle == 0) return NULL;
-
- U8* baseblock_address = reinterpret_cast<U8*>(this);
- return reinterpret_cast<Param*>(baseblock_address + param_handle);
- }
-
- const Param* getParamFromHandle(const param_handle_t param_handle) const
- {
- const U8* baseblock_address = reinterpret_cast<const U8*>(this);
- return reinterpret_cast<const Param*>(baseblock_address + param_handle);
- }
-
- void addSynonym(Param& param, const std::string& synonym);
-
- // Blocks can override this to do custom tracking of changes
- virtual void paramChanged(const Param& changed_param, bool user_provided)
- {
- if (user_provided)
- {
- // a child param has been explicitly changed
- // so *some* aspect of this block is now provided
- mValidated = false;
- mParamProvided = true;
- }
- }
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);
- bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule, const BaseBlock* diff_block = NULL) const;
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
-
- virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
- virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }
-
- // take all provided params from other and apply to self
- bool overwriteFrom(const BaseBlock& other)
- {
- return false;
- }
-
- // take all provided params that are not already provided, and apply to self
- bool fillFrom(const BaseBlock& other)
- {
- return false;
- }
-
- ParamDescriptorPtr findParamDescriptor(const Param& param);
-
- // take all provided params from other and apply to self
- bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
-
- static BlockDescriptor& getBlockDescriptor()
- {
- static BlockDescriptor sBlockDescriptor;
- return sBlockDescriptor;
- }
-
- protected:
- void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
-
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
- {
- return mergeBlock(block_data, source, overwrite);
- }
-
- mutable bool mValidated; // lazy validation flag
- bool mParamProvided;
-
- private:
- const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
- };
-
- class LL_COMMON_API Param
- {
- public:
- void setProvided(bool is_provided = true)
- {
- mIsProvided = is_provided;
- enclosingBlock().paramChanged(*this, is_provided);
- }
-
- Param& operator =(const Param& other)
- {
- mIsProvided = other.mIsProvided;
- // don't change mEnclosingblockoffset
- return *this;
- }
- protected:
-
- bool anyProvided() const { return mIsProvided; }
-
- Param(BaseBlock* enclosing_block);
-
- // store pointer to enclosing block as offset to reduce space and allow for quick copying
- BaseBlock& enclosingBlock() const
- {
- const U8* my_addr = reinterpret_cast<const U8*>(this);
- // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
- return *const_cast<BaseBlock*>
- (reinterpret_cast<const BaseBlock*>
- (my_addr - (ptrdiff_t)getEnclosingBlockOffset()));
- }
-
- U32 getEnclosingBlockOffset() const
- {
- return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow;
- }
-
- private:
- friend class BaseBlock;
-
- //24 bits for member offset field and 1 bit for provided flag
- U16 mEnclosingBlockOffsetLow;
- U8 mEnclosingBlockOffsetHigh:7;
- U8 mIsProvided:1;
-
- };
-
- template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
- struct ParamIterator
- {
- typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator const_iterator;
- typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator iterator;
- };
-
- // wrapper for parameter with a known type
- // specialized to handle 4 cases:
- // simple "scalar" value
- // parameter that is itself a block
- // multiple scalar values, stored in a vector
- // multiple blocks, stored in a vector
- template<typename T,
- typename NAME_VALUE_LOOKUP = TypeValues<T>,
- bool HAS_MULTIPLE_VALUES = false,
- typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t>
- class TypedParam
- : public Param,
- public NAME_VALUE_LOOKUP::type_value_t
- {
- protected:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t;
- typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
- typedef typename param_value_t::default_value_t default_value_t;
- typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
- public:
- typedef typename param_value_t::value_t value_t;
-
- using named_value_t::operator();
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr),
- named_value_t(value)
- {
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- init(block_descriptor, validate_func, min_count, max_count, name);
- }
- }
-
- bool isProvided() const { return Param::anyProvided(); }
-
- bool isValid() const { return true; }
-
- static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- self_t& typed_param = static_cast<self_t&>(param);
- // no further names in stack, attempt to parse value now
- if (name_stack_range.first == name_stack_range.second)
- {
- std::string name;
-
- // try to parse a known named value
- if(named_value_t::valueNamesExist()
- && parser.readValue(name)
- && named_value_t::getValueFromName(name, typed_param.getValue()))
- {
- typed_param.setValueName(name);
- typed_param.setProvided();
- return true;
- }
- // try to read value directly
- else if (parser.readValue(typed_param.getValue()))
- {
- typed_param.clearValueName();
- typed_param.setProvided();
- return true;
- }
- }
- return false;
- }
-
- static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
- {
- bool serialized = false;
- const self_t& typed_param = static_cast<const self_t&>(param);
- const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
-
- LLPredicate::Value<ESerializePredicates> predicate;
- if (diff_typed_param && ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
- {
- predicate.set(HAS_DEFAULT_VALUE);
- }
-
- predicate.set(VALID, typed_param.isValid());
- predicate.set(PROVIDED, typed_param.anyProvided());
- predicate.set(EMPTY, false);
-
- if (!predicate_rule.check(predicate)) return false;
-
- if (!name_stack.empty())
- {
- name_stack.back().second = true;
- }
-
- std::string key = typed_param.getValueName();
-
- // first try to write out name of name/value pair
-
- if (!key.empty())
- {
- if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), key))
- {
- serialized = parser.writeValue(key, name_stack);
- }
- }
- // then try to serialize value directly
- else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
- {
- serialized = parser.writeValue(typed_param.getValue(), name_stack);
- if (!serialized)
- {
- std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
- if (calculated_key.size()
- && (!diff_typed_param
- || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)))
- {
- serialized = parser.writeValue(calculated_key, name_stack);
- }
- }
- }
- return serialized;
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- // tell parser about our actual type
- parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
- // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
- if (named_value_t::getPossibleValues())
- {
- parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
- }
- }
-
- void set(const value_t& val, bool flag_as_provided = true)
- {
- named_value_t::clearValueName();
- named_value_t::setValue(val);
- setProvided(flag_as_provided);
- }
-
- self_t& operator =(const typename named_value_t::name_t& name)
- {
- named_value_t::assignNamedValue(name);
- return *this;
- }
-
- protected:
-
- self_t& operator =(const self_t& other)
- {
- param_value_t::operator =(other);
- Param::operator =(other);
- return *this;
- }
-
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (src_typed_param.isProvided()
- && (overwrite || !dst_typed_param.isProvided()))
- {
- dst_typed_param.set(src_typed_param.getValue());
- return true;
- }
- return false;
- }
- private:
- void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- block_descriptor.addParam(param_descriptor, name);
- }
- };
-
- // parameter that is a block
- template <typename BLOCK_T, typename NAME_VALUE_LOOKUP>
- class TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>
- : public Param,
- public NAME_VALUE_LOOKUP::type_value_t
- {
- protected:
- typedef ParamValue<typename LLTypeTags::Sorted<BLOCK_T>::value_t> param_value_t;
- typedef typename param_value_t::default_value_t default_value_t;
- typedef TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t;
- typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
- public:
- using named_value_t::operator();
- typedef typename param_value_t::value_t value_t;
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr),
- named_value_t(value)
- {
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- init(block_descriptor, validate_func, min_count, max_count, name);
- }
- }
-
- static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- self_t& typed_param = static_cast<self_t&>(param);
-
- if (name_stack_range.first == name_stack_range.second)
- { // try to parse a known named value
- std::string name;
-
- if(named_value_t::valueNamesExist()
- && parser.readValue(name)
- && named_value_t::getValueFromName(name, typed_param.getValue()))
- {
- typed_param.setValueName(name);
- typed_param.setProvided();
- return true;
- }
- }
-
- if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
- { // attempt to parse block...
- typed_param.clearValueName();
- typed_param.setProvided();
- return true;
- }
-
-
- return false;
- }
-
- static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
- {
- const self_t& typed_param = static_cast<const self_t&>(param);
-
- LLPredicate::Value<ESerializePredicates> predicate;
-
- predicate.set(VALID, typed_param.isValid());
- predicate.set(PROVIDED, typed_param.anyProvided());
-
- if (!predicate_rule.check(predicate)) return false;
-
- if (!name_stack.empty())
- {
- name_stack.back().second = true;
- }
-
- std::string key = typed_param.getValueName();
- if (!key.empty())
- {
- if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
- {
- parser.writeValue(key, name_stack);
- return true;
- }
- }
- else
- {
- return typed_param.serializeBlock(parser, name_stack, predicate_rule, static_cast<const self_t*>(diff_param));
- }
-
- return false;
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- const self_t& typed_param = static_cast<const self_t&>(param);
-
- // tell parser about our actual type
- parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL);
- // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
- if (named_value_t::getPossibleValues())
- {
- parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
- }
-
- typed_param.inspectBlock(parser, name_stack, min_count, max_count);
- }
-
- // a param-that-is-a-block is provided when the user has set one of its child params
- // *and* the block as a whole validates
- bool isProvided() const
- {
- return Param::anyProvided() && isValid();
- }
-
- bool isValid() const
- {
- return param_value_t::isValid();
- }
-
- // assign block contents to this param-that-is-a-block
- void set(const value_t& val, bool flag_as_provided = true)
- {
- named_value_t::setValue(val);
- named_value_t::clearValueName();
- setProvided(flag_as_provided);
- }
-
- self_t& operator =(const typename named_value_t::name_t& name)
- {
- named_value_t::assignNamedValue(name);
- return *this;
- }
-
- // propagate changed status up to enclosing block
- /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
- {
- param_value_t::paramChanged(changed_param, user_provided);
-
- if (user_provided)
- {
- setProvided();
- named_value_t::clearValueName();
- }
- else
- {
- Param::enclosingBlock().paramChanged(*this, user_provided);
- }
- }
-
- protected:
-
- self_t& operator =(const self_t& other)
- {
- param_value_t::operator =(other);
- Param::operator =(other);
- return *this;
- }
-
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (src_typed_param.anyProvided())
- {
- if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite))
- {
- dst_typed_param.clearValueName();
- dst_typed_param.setProvided(true);
- return true;
- }
- }
- return false;
- }
-
- private:
- void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- block_descriptor.addParam(param_descriptor, name);
- }
- };
-
- // list of non-block parameters
- template <typename MULTI_VALUE_T, typename NAME_VALUE_LOOKUP>
- class TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK>
- : public Param
- {
- protected:
- typedef TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t;
- typedef ParamValue<typename LLTypeTags::Sorted<MULTI_VALUE_T>::value_t> param_value_t;
- typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t;
- typedef container_t default_value_t;
- typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
-
- public:
- typedef typename param_value_t::value_t value_t;
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr),
- mMinCount(min_count),
- mMaxCount(max_count)
- {
- std::copy(value.begin(), value.end(), std::back_inserter(mValues));
-
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- init(block_descriptor, validate_func, min_count, max_count, name);
-
- }
- }
-
- bool isProvided() const { return Param::anyProvided() && isValid(); }
-
- bool isValid() const
- {
- size_t num_elements = numValidElements();
- return mMinCount < num_elements && num_elements < mMaxCount;
- }
-
- static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- Parser::name_stack_range_t new_name_stack_range(name_stack_range);
- self_t& typed_param = static_cast<self_t&>(param);
- value_t value;
-
- // pop first element if empty string
- if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty())
- {
- ++new_name_stack_range.first;
- }
-
- // no further names in stack, attempt to parse value now
- if (new_name_stack_range.first == new_name_stack_range.second)
- {
- std::string name;
-
- // try to parse a known named value
- if(named_value_t::valueNamesExist()
- && parser.readValue(name)
- && named_value_t::getValueFromName(name, value))
- {
- typed_param.add(value);
- typed_param.mValues.back().setValueName(name);
- return true;
- }
- else if (parser.readValue(value)) // attempt to read value directly
- {
- typed_param.add(value);
- return true;
- }
- }
- return false;
- }
-
- static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
- {
- bool serialized = false;
- const self_t& typed_param = static_cast<const self_t&>(param);
-
- LLPredicate::Value<ESerializePredicates> predicate;
-
- predicate.set(REQUIRED, typed_param.mMinCount > 0);
- predicate.set(VALID, typed_param.isValid());
- predicate.set(PROVIDED, typed_param.anyProvided());
- predicate.set(EMPTY, typed_param.mValues.empty());
-
- if (!predicate_rule.check(predicate)) return false;
-
- for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
- it != end_it;
- ++it)
- {
- std::string key = it->getValueName();
- name_stack.push_back(std::make_pair(std::string(), true));
-
- if(key.empty())
- // not parsed via name values, write out value directly
- {
- bool value_written = parser.writeValue(*it, name_stack);
- if (!value_written)
- {
- std::string calculated_key = it->calcValueName(it->getValue());
- if (parser.writeValue(calculated_key, name_stack))
- {
- serialized = true;
- }
- else
- {
- break;
- }
- }
- }
- else
- {
- if(parser.writeValue(key, name_stack))
- {
- serialized = true;
- }
- else
- {
- break;
- }
- }
- }
-
- return serialized;
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- parser.inspectValue<MULTI_VALUE_T>(name_stack, min_count, max_count, NULL);
- if (named_value_t::getPossibleValues())
- {
- parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
- }
- }
-
- void set(const container_t& val, bool flag_as_provided = true)
- {
- mValues = val;
- setProvided(flag_as_provided);
- }
-
- param_value_t& add()
- {
- mValues.push_back(value_t());
- Param::setProvided();
- return mValues.back();
- }
-
- self_t& add(const value_t& item)
- {
- mValues.push_back(item);
- setProvided();
- return *this;
- }
-
- self_t& add(const typename named_value_t::name_t& name)
- {
- value_t value;
-
- // try to parse a per type named value
- if (named_value_t::getValueFromName(name, value))
- {
- add(value);
- mValues.back().setValueName(name);
- }
-
- return *this;
- }
-
- // implicit conversion
- operator const container_t&() const { return mValues; }
- // explicit conversion
- const container_t& operator()() const { return mValues; }
-
- typedef typename container_t::iterator iterator;
- typedef typename container_t::const_iterator const_iterator;
- iterator begin() { return mValues.begin(); }
- iterator end() { return mValues.end(); }
- const_iterator begin() const { return mValues.begin(); }
- const_iterator end() const { return mValues.end(); }
- bool empty() const { return mValues.empty(); }
- size_t size() const { return mValues.size(); }
-
- size_t numValidElements() const
- {
- return mValues.size();
- }
-
- protected:
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (overwrite)
- {
- std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
- }
- else
- {
- container_t new_values(src_typed_param.mValues);
- std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
- std::swap(dst_typed_param.mValues, new_values);
- }
-
- if (src_typed_param.begin() != src_typed_param.end())
- {
- dst_typed_param.setProvided();
- }
- return true;
- }
-
- container_t mValues;
- size_t mMinCount,
- mMaxCount;
-
- private:
- void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- block_descriptor.addParam(param_descriptor, name);
- }
- };
-
- // list of block parameters
- template <typename MULTI_BLOCK_T, typename NAME_VALUE_LOOKUP>
- class TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>
- : public Param
- {
- protected:
- typedef TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t;
- typedef ParamValue<typename LLTypeTags::Sorted<MULTI_BLOCK_T>::value_t> param_value_t;
- typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t;
- typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
- typedef container_t default_value_t;
- typedef typename container_t::iterator iterator;
- typedef typename container_t::const_iterator const_iterator;
- public:
- typedef typename param_value_t::value_t value_t;
-
- TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr),
- mMinCount(min_count),
- mMaxCount(max_count)
- {
- std::copy(value.begin(), value.end(), back_inserter(mValues));
-
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- init(block_descriptor, validate_func, min_count, max_count, name);
- }
- }
-
- bool isProvided() const { return Param::anyProvided() && isValid(); }
-
- bool isValid() const
- {
- size_t num_elements = numValidElements();
- return mMinCount < num_elements && num_elements < mMaxCount;
- }
-
-
- static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- Parser::name_stack_range_t new_name_stack_range(name_stack_range);
- self_t& typed_param = static_cast<self_t&>(param);
- bool new_value = false;
- bool new_array_value = false;
-
- // pop first element if empty string
- if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty())
- {
- new_array_value = new_name_stack_range.first->second;
- ++new_name_stack_range.first;
- }
-
- if (new_name || new_array_value || typed_param.mValues.empty())
- {
- new_value = true;
- typed_param.mValues.push_back(value_t());
- }
- param_value_t& value = typed_param.mValues.back();
-
- if (new_name_stack_range.first == new_name_stack_range.second)
- { // try to parse a known named value
- std::string name;
-
- if(named_value_t::valueNamesExist()
- && parser.readValue(name)
- && named_value_t::getValueFromName(name, value.getValue()))
- {
- typed_param.mValues.back().setValueName(name);
- typed_param.setProvided();
- if (new_array_value)
- {
- name_stack_range.first->second = false;
- }
- return true;
- }
- }
-
- // attempt to parse block...
- if(value.deserializeBlock(parser, new_name_stack_range, new_name))
- {
- typed_param.setProvided();
- if (new_array_value)
- {
- name_stack_range.first->second = false;
- }
- return true;
- }
-
-
- if (new_value)
- { // failed to parse new value, pop it off
- typed_param.mValues.pop_back();
- }
-
- return false;
- }
-
- static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
- {
- bool serialized = false;
- const self_t& typed_param = static_cast<const self_t&>(param);
- LLPredicate::Value<ESerializePredicates> predicate;
-
- predicate.set(REQUIRED, typed_param.mMinCount > 0);
- predicate.set(VALID, typed_param.isValid());
- predicate.set(PROVIDED, typed_param.anyProvided());
- predicate.set(EMPTY, typed_param.mValues.empty());
-
- if (!predicate_rule.check(predicate)) return false;
-
- for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
- it != end_it;
- ++it)
- {
- name_stack.push_back(std::make_pair(std::string(), true));
-
- std::string key = it->getValueName();
- if (!key.empty())
- {
- serialized |= parser.writeValue(key, name_stack);
- }
- // Not parsed via named values, write out value directly
- // NOTE: currently we don't do diffing of Multiples
- else
- {
- serialized = it->serializeBlock(parser, name_stack, predicate_rule, NULL);
- }
-
- name_stack.pop_back();
- }
-
- if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
- {
- serialized |= parser.writeValue(Flag(), name_stack);
- }
-
- return serialized;
- }
-
- static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
- {
- const param_value_t& value_param = param_value_t(value_t());
-
- // tell parser about our actual type
- parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL);
- // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
- if (named_value_t::getPossibleValues())
- {
- parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
- }
-
- value_param.inspectBlock(parser, name_stack, min_count, max_count);
- }
-
- void set(const container_t& val, bool flag_as_provided = true)
- {
- mValues = val;
- setProvided(flag_as_provided);
- }
-
- param_value_t& add()
- {
- mValues.push_back(value_t());
- setProvided();
- return mValues.back();
- }
-
- self_t& add(const value_t& item)
- {
- mValues.push_back(item);
- setProvided();
- return *this;
- }
-
- self_t& add(const typename named_value_t::name_t& name)
- {
- value_t value;
-
- // try to parse a per type named value
- if (named_value_t::getValueFromName(name, value))
- {
- add(value);
- mValues.back().setValueName(name);
- }
- return *this;
- }
-
- // implicit conversion
- operator const container_t&() const { return mValues; }
- // explicit conversion
- const container_t& operator()() const { return mValues; }
-
- iterator begin() { return mValues.begin(); }
- iterator end() { return mValues.end(); }
- const_iterator begin() const { return mValues.begin(); }
- const_iterator end() const { return mValues.end(); }
- bool empty() const { return mValues.empty(); }
- size_t size() const { return mValues.size(); }
-
- size_t numValidElements() const
- {
- size_t count = 0;
- for (const_iterator it = mValues.begin(), end_it = mValues.end();
- it != end_it;
- ++it)
- {
- if(it->isValid()) count++;
- }
- return count;
- }
-
- protected:
-
- static bool mergeWith(Param& dst, const Param& src, bool overwrite)
- {
- const self_t& src_typed_param = static_cast<const self_t&>(src);
- self_t& dst_typed_param = static_cast<self_t&>(dst);
-
- if (overwrite)
- {
- std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
- }
- else
- {
- container_t new_values(src_typed_param.mValues);
- std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
- std::swap(dst_typed_param.mValues, new_values);
- }
-
- if (src_typed_param.begin() != src_typed_param.end())
- {
- dst_typed_param.setProvided();
- }
-
- return true;
- }
-
- container_t mValues;
- size_t mMinCount,
- mMaxCount;
-
- private:
- void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- &mergeWith,
- &deserializeParam,
- &serializeParam,
- validate_func,
- &inspectParam,
- min_count, max_count));
- block_descriptor.addParam(param_descriptor, name);
- }
- };
-
- template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
- class ChoiceBlock : public BASE_BLOCK
- {
- typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
- typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK> enclosing_block_t;
- typedef BASE_BLOCK base_block_t;
-
- LOG_CLASS(self_t);
- public:
- // take all provided params from other and apply to self
- bool overwriteFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);
- }
-
- // take all provided params that are not already provided, and apply to self
- bool fillFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);
- }
-
- bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
- {
- bool source_override = source_provided && (overwrite || !dest_provided);
-
- if (source_override || source.mCurChoice == mCurChoice)
- {
- return mergeBlock(block_data, source, overwrite);
- }
- return false;
- }
-
- // merge with other block
- bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)
- {
- mCurChoice = other.mCurChoice;
- return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite);
- }
-
- // clear out old choice when param has changed
- /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
- {
- param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param);
- // if we have a new choice...
- if (changed_param_handle != mCurChoice)
- {
- // clear provided flag on previous choice
- Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice);
- if (previous_choice)
- {
- previous_choice->setProvided(false);
- }
- mCurChoice = changed_param_handle;
- }
- base_block_t::paramChanged(changed_param, user_provided);
- }
-
- virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
- virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }
-
- protected:
- ChoiceBlock()
- : mCurChoice(0)
- {
- BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK));
- }
-
- // Alternatives are mutually exclusive wrt other Alternatives in the same block.
- // One alternative in a block will always have isChosen() == true.
- // At most one alternative in a block will have isProvided() == true.
- template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
- class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
- {
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
- typedef typename super_t::value_t value_t;
- typedef typename super_t::default_value_t default_value_t;
-
- public:
- friend class ChoiceBlock<DERIVED_BLOCK>;
-
- using super_t::operator =;
-
- explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>())
- : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1),
- mOriginalValue(val)
- {
- // assign initial choice to first declared option
- DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr);
- if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
- {
- if(blockp->mCurChoice == 0)
- {
- blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
- }
- }
- }
-
- void choose()
- {
- static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);
- }
-
- void chooseAs(const value_t& val)
- {
- super_t::set(val);
- }
-
- void operator =(const value_t& val)
- {
- super_t::set(val);
- }
-
- void operator()(const value_t& val)
- {
- super_t::set(val);
- }
-
- operator const value_t&() const
- {
- return (*this)();
- }
-
- const value_t& operator()() const
- {
- if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
- {
- return super_t::getValue();
- }
- return mOriginalValue;
- }
-
- bool isChosen() const
- {
- return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
- }
-
- private:
- default_value_t mOriginalValue;
- };
-
- public:
- static BlockDescriptor& getBlockDescriptor()
- {
- static BlockDescriptor sBlockDescriptor;
- return sBlockDescriptor;
- }
-
- private:
- param_handle_t mCurChoice;
-
- const Param* getCurrentChoice() const
- {
- return base_block_t::getParamFromHandle(mCurChoice);
- }
- };
-
- template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
- class Block
- : public BASE_BLOCK
- {
- typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t;
-
- protected:
- typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t;
-
- public:
- typedef BASE_BLOCK base_block_t;
-
- // take all provided params from other and apply to self
- bool overwriteFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);
- }
-
- // take all provided params that are not already provided, and apply to self
- bool fillFrom(const self_t& other)
- {
- return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);
- }
-
- virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
- virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }
-
- protected:
- Block()
- {
- //#pragma message("Parsing LLInitParam::Block")
- BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK));
- }
-
- //
- // Nested classes for declaring parameters
- //
- template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
- class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
- {
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
- typedef typename super_t::value_t value_t;
- typedef typename super_t::default_value_t default_value_t;
-
- public:
- using super_t::operator();
- using super_t::operator =;
-
- explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>())
- : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1)
- {
- //#pragma message("Parsing LLInitParam::Block::Optional")
- }
-
- Optional& operator =(const value_t& val)
- {
- super_t::set(val);
- return *this;
- }
-
- DERIVED_BLOCK& operator()(const value_t& val)
- {
- super_t::set(val);
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
- };
-
- template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
- class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
- {
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
- typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
- typedef typename super_t::value_t value_t;
- typedef typename super_t::default_value_t default_value_t;
-
- public:
- using super_t::operator();
- using super_t::operator =;
-
- // mandatory parameters require a name to be parseable
- explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>())
- : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1)
- {}
-
- Mandatory& operator =(const value_t& val)
- {
- super_t::set(val);
- return *this;
- }
-
- DERIVED_BLOCK& operator()(const value_t& val)
- {
- super_t::set(val);
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
-
- static bool validate(const Param* p)
- {
- // valid only if provided
- return static_cast<const self_t*>(p)->isProvided();
- }
-
- };
-
- template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
- class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
- {
- typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t;
- typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t;
- typedef typename super_t::container_t container_t;
- typedef typename super_t::value_t value_t;
-
- public:
- typedef typename super_t::iterator iterator;
- typedef typename super_t::const_iterator const_iterator;
-
- using super_t::operator();
- using super_t::operator const container_t&;
-
- explicit Multiple(const char* name = "")
- : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
- {}
-
- Multiple& operator =(const container_t& val)
- {
- super_t::set(val);
- return *this;
- }
-
- DERIVED_BLOCK& operator()(const container_t& val)
- {
- super_t::set(val);
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
-
- static bool validate(const Param* paramp)
- {
- size_t num_valid = ((super_t*)paramp)->numValidElements();
- return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
- }
- };
-
- // can appear in data files, but will ignored during parsing
- // cannot read or write in code
- class Ignored : public Param
- {
- public:
- explicit Ignored(const char* name)
- : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr)
- {
- BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor();
- if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
- {
- ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
- block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
- NULL,
- &deserializeParam,
- NULL,
- NULL,
- NULL,
- 0, S32_MAX));
- block_descriptor.addParam(param_descriptor, name);
- }
- }
-
- static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- if (name_stack_range.first == name_stack_range.second)
- {
- //std::string message = llformat("Deprecated value %s ignored", getName().c_str());
- //parser.parserWarning(message);
- return true;
- }
-
- return false;
- }
- };
-
- // can appear in data files, or be written to in code, but data will be ignored
- // cannot be read in code
- class Deprecated : public Ignored
- {
- public:
- explicit Deprecated(const char* name) : Ignored(name) {}
-
- // dummy writer interfaces
- template<typename T>
- Deprecated& operator =(const T& val)
- {
- // do nothing
- return *this;
- }
-
- template<typename T>
- DERIVED_BLOCK& operator()(const T& val)
- {
- // do nothing
- return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
- }
-
- template<typename T>
- void set(const T& val, bool flag_as_provided = true)
- {
- // do nothing
- }
- };
-
- public:
- static BlockDescriptor& getBlockDescriptor()
- {
- static BlockDescriptor sBlockDescriptor;
- return sBlockDescriptor;
- }
-
- protected:
- template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block>
- void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param,
- const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value)
- {
- if (!param.isProvided())
- {
- param.set(value, false);
- }
- }
-
- };
-
- template<typename T, typename BLOCK_T>
- struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void>
- {
- typedef IS_A_BLOCK value_t;
- };
-
- template<typename T, typename BLOCK_T>
- struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void>
- {
- typedef NOT_BLOCK value_t;
- };
-
- template<typename T, typename BLOCK_IDENTIFIER>
- struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER>
- {
- typedef typename IsBlock<T>::value_t value_t;
- };
-
- template<typename T, typename BLOCK_IDENTIFIER>
- struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER>
- {
- typedef typename IsBlock<T>::value_t value_t;
- };
-
-
- template<typename T>
- struct InnerMostType
- {
- typedef T value_t;
- };
-
- template<typename T>
- struct InnerMostType<ParamValue<T, NOT_BLOCK> >
- {
- typedef typename InnerMostType<T>::value_t value_t;
- };
-
- template<typename T>
- struct InnerMostType<ParamValue<T, IS_A_BLOCK> >
- {
- typedef typename InnerMostType<T>::value_t value_t;
- };
-
- template<typename T, typename BLOCK_T>
- class ParamValue <BaseBlock::Atomic<T>, BLOCK_T>
- {
- typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t;
-
- public:
- typedef typename InnerMostType<T>::value_t value_t;
- typedef T default_value_t;
-
- ParamValue()
- : mValue()
- {}
-
- ParamValue(const default_value_t& value)
- : mValue(value)
- {}
-
- void setValue(const value_t& val)
- {
- mValue.setValue(val);
- }
-
- const value_t& getValue() const
- {
- return mValue.getValue();
- }
-
- value_t& getValue()
- {
- return mValue.getValue();
- }
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- if (new_name)
- {
- resetToDefault();
- }
- return mValue.deserializeBlock(p, name_stack_range, new_name);
- }
-
- bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
- {
- const BaseBlock* base_block = diff_block
- ? &(diff_block->mValue)
- : NULL;
- return mValue.serializeBlock(p, name_stack, predicate_rule, base_block);
- }
-
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- return mValue.inspectBlock(p, name_stack, min_count, max_count);
- }
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
- {
- if ((overwrite && source_provided) // new values coming in on top or...
- || (!overwrite && !dst_provided)) // values being pushed under with nothing already there
- {
- // clear away what is there and take the new stuff as a whole
- resetToDefault();
- return mValue.mergeBlock(block_data, source.getValue(), overwrite);
- }
- return mValue.mergeBlock(block_data, source.getValue(), overwrite);
- }
-
- bool validateBlock(bool emit_errors = true) const
- {
- return mValue.validateBlock(emit_errors);
- }
-
- bool isValid() const
- {
- return validateBlock(false);
- }
-
- static BlockDescriptor& getBlockDescriptor()
- {
- return value_t::getBlockDescriptor();
- }
-
-
- private:
- void resetToDefault()
- {
- static T default_value;
- mValue = default_value;
- }
-
- T mValue;
- };
-
- template<typename T>
- class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK>
- {
- typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t;
-
- public:
- typedef typename InnerMostType<T>::value_t value_t;
- typedef T default_value_t;
-
- ParamValue()
- : mValue()
- {
- mCurParam = getBlockDescriptor().mAllParams.begin();
- }
-
- ParamValue(const default_value_t& value)
- : mValue(value)
- {
- mCurParam = getBlockDescriptor().mAllParams.begin();
- }
-
- void setValue(const value_t& val)
- {
- mValue.setValue(val);
- }
-
- const value_t& getValue() const
- {
- return mValue.getValue();
- }
-
- value_t& getValue()
- {
- return mValue.getValue();
- }
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- if (new_name)
- {
- mCurParam = getBlockDescriptor().mAllParams.begin();
- }
- if (name_stack_range.first == name_stack_range.second
- && mCurParam != getBlockDescriptor().mAllParams.end())
- {
- // deserialize to mCurParam
- ParamDescriptor& pd = *(*mCurParam);
- ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc;
- Param* paramp = mValue.getParamFromHandle(pd.mParamHandle);
-
- if (deserialize_func
- && paramp
- && deserialize_func(*paramp, p, name_stack_range, new_name))
- {
- ++mCurParam;
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- return mValue.deserializeBlock(p, name_stack_range, new_name);
- }
- }
-
- bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
- {
- const BaseBlock* base_block = diff_block
- ? &(diff_block->mValue)
- : NULL;
- return mValue.serializeBlock(p, name_stack, predicate_rule, base_block);
- }
-
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- return mValue.inspectBlock(p, name_stack, min_count, max_count);
- }
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
- {
- return mValue.mergeBlock(block_data, source.getValue(), overwrite);
- }
-
- bool validateBlock(bool emit_errors = true) const
- {
- return mValue.validateBlock(emit_errors);
- }
-
- bool isValid() const
- {
- return validateBlock(false);
- }
-
- static BlockDescriptor& getBlockDescriptor()
- {
- return value_t::getBlockDescriptor();
- }
-
- private:
-
- BlockDescriptor::all_params_list_t::iterator mCurParam;
- T mValue;
- };
-
- template<typename T>
- class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK>
- : public T
- {
- typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t;
-
- public:
- typedef typename InnerMostType<T>::value_t value_t;
- typedef T default_value_t;
-
- ParamValue()
- : T()
- {}
-
- ParamValue(const default_value_t& value)
- : T(value.getValue())
- {}
-
- bool isValid() const { return true; }
- };
-
- template<typename T, typename BLOCK_T>
- class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T>
- {
- typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t;
-
- public:
- typedef typename InnerMostType<T>::value_t value_t;
- typedef LazyValue<T> default_value_t;
-
- ParamValue()
- : mValue()
- {}
-
- ParamValue(const default_value_t& other)
- : mValue(other)
- {}
-
- ParamValue(const T& value)
- : mValue(value)
- {}
-
- void setValue(const value_t& val)
- {
- mValue.set(val);
- }
-
- const value_t& getValue() const
- {
- return mValue.get().getValue();
- }
-
- value_t& getValue()
- {
- return mValue.get().getValue();
- }
-
- bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- return mValue.get().deserializeBlock(p, name_stack_range, new_name);
- }
-
- bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
- {
- if (mValue.empty()) return false;
-
- const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty())
- ? &(diff_block->mValue.get().getValue())
- : NULL;
- return mValue.get().serializeBlock(p, name_stack, predicate_rule, base_block);
- }
-
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
- }
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
- {
- return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);
- }
-
- bool validateBlock(bool emit_errors = true) const
- {
- return mValue.empty() || mValue.get().validateBlock(emit_errors);
- }
-
- bool isValid() const
- {
- return validateBlock(false);
- }
-
- static BlockDescriptor& getBlockDescriptor()
- {
- return value_t::getBlockDescriptor();
- }
-
- private:
- LazyValue<T> mValue;
- };
-
- template<typename T, typename BLOCK_T>
- class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T>
- {
- typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t;
-
- public:
- typedef typename InnerMostType<T>::value_t value_t;
- typedef LazyValue<T> default_value_t;
-
- ParamValue()
- : mValue()
- {}
-
- ParamValue(const default_value_t& other)
- : mValue(other)
- {}
-
- ParamValue(const T& value)
- : mValue(value)
- {}
-
- void setValue(const value_t& val)
- {
- mValue.set(val);
- }
-
- const value_t& getValue() const
- {
- return mValue.get().getValue();
- }
-
- value_t& getValue()
- {
- return mValue.get().getValue();
- }
-
- bool isValid() const
- {
- return true;
- }
-
- private:
- LazyValue<T> mValue;
- };
-
- template <>
- class ParamValue <LLSD, NOT_BLOCK>
- : public BaseBlock
- {
- public:
- typedef LLSD value_t;
- typedef LLSD default_value_t;
-
- ParamValue()
- {}
-
- ParamValue(const default_value_t& other)
- : mValue(other)
- {}
-
- void setValue(const value_t& val) { mValue = val; }
-
- const value_t& getValue() const { return mValue; }
- LLSD& getValue() { return mValue; }
-
- // block param interface
- LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);
- LL_COMMON_API bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const;
- bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
- //TODO: implement LLSD params as schema type Any
- return true;
- }
-
- private:
- static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
-
- LLSD mValue;
- };
-
- template<typename T>
- class CustomParamValue
- : public Block<ParamValue<T> >
- {
- public:
- typedef enum e_value_age
- {
- VALUE_NEEDS_UPDATE, // mValue needs to be refreshed from the block parameters
- VALUE_AUTHORITATIVE, // mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue)
- BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative
- } EValueAge;
-
- typedef TypeValues<T> derived_t;
- typedef CustomParamValue<T> self_t;
- typedef Block<ParamValue<T> > block_t;
- typedef T default_value_t;
- typedef T value_t;
- typedef void baseblock_base_class_t;
-
-
- CustomParamValue(const default_value_t& value = T())
- : mValue(value),
- mValueAge(VALUE_AUTHORITATIVE)
- {}
-
- bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
- {
- derived_t& typed_param = static_cast<derived_t&>(*this);
- // try to parse direct value T
- if (name_stack_range.first == name_stack_range.second)
- {
- if(parser.readValue(typed_param.mValue))
- {
- typed_param.mValueAge = VALUE_AUTHORITATIVE;
- typed_param.updateBlockFromValue(false);
-
- return true;
- }
- }
-
- // fall back on parsing block components for T
- return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
- }
-
- bool serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const
- {
- const derived_t& typed_param = static_cast<const derived_t&>(*this);
- const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
-
- //std::string key = typed_param.getValueName();
-
- //// first try to write out name of name/value pair
- //if (!key.empty())
- //{
- // if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
- // {
- // return parser.writeValue(key, name_stack);
- // }
- //}
- // then try to serialize value directly
- if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
- {
-
- if (parser.writeValue(typed_param.getValue(), name_stack))
- {
- return true;
- }
- else
- {
- //RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
- // since these tend to be viewed as the constructor arguments for the value T. It seems
- // cleaner to treat the uniqueness of a BlockValue according to the generated value, and
- // not the individual components. This way <color red="0" green="1" blue="0"/> will not
- // be exported as <color green="1"/>, since it was probably the intent of the user to
- // be specific about the RGB color values. This also fixes an issue where we distinguish
- // between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
-
- if (typed_param.mValueAge == VALUE_AUTHORITATIVE)
- {
- // if the value is authoritative but the parser doesn't accept the value type
- // go ahead and make a copy, and splat the value out to its component params
- // and serialize those params
- derived_t copy(typed_param);
- copy.updateBlockFromValue(true);
- return copy.block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
- }
- else
- {
- return block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
- }
- }
- }
- return false;
- }
-
- bool validateBlock(bool emit_errors = true) const
- {
- if (mValueAge == VALUE_NEEDS_UPDATE)
- {
- if (block_t::validateBlock(emit_errors))
- {
- // clear stale keyword associated with old value
- mValueAge = BLOCK_AUTHORITATIVE;
- static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();
- return true;
- }
- else
- {
- //block value incomplete, so not considered provided
- // will attempt to revalidate on next call to isProvided()
- return false;
- }
- }
- else
- {
- // we have a valid value in hand
- return true;
- }
- }
-
- // propagate change status up to enclosing block
- /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
- {
- BaseBlock::paramChanged(changed_param, user_provided);
- if (user_provided)
- {
- // a parameter changed, so our value is out of date
- mValueAge = VALUE_NEEDS_UPDATE;
- }
- }
-
- void setValue(const value_t& val)
- {
- // set param version number to be up to date, so we ignore block contents
- mValueAge = VALUE_AUTHORITATIVE;
- mValue = val;
- static_cast<derived_t*>(this)->updateBlockFromValue(false);
- }
-
- const value_t& getValue() const
- {
- validateBlock(true);
- return mValue;
- }
-
- T& getValue()
- {
- validateBlock(true);
- return mValue;
- }
-
- protected:
-
- // use this from within updateValueFromBlock() to set the value without making it authoritative
- void updateValue(const value_t& value)
- {
- mValue = value;
- }
-
- bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
- {
- bool source_override = source_provided && (overwrite || !dst_provided);
-
- const derived_t& src_typed_param = static_cast<const derived_t&>(source);
-
- if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE)
- {
- // copy value over
- setValue(src_typed_param.getValue());
- return true;
- }
- // merge individual parameters into destination
- if (mValueAge == VALUE_AUTHORITATIVE)
- {
- static_cast<derived_t*>(this)->updateBlockFromValue(dst_provided);
- }
- return mergeBlock(block_data, source, overwrite);
- }
-
- bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
- {
- return block_t::mergeBlock(block_data, source, overwrite);
- }
-
- private:
- mutable T mValue;
- mutable EValueAge mValueAge;
- };
+
+ // empty default implementation of key cache
+ // leverages empty base class optimization
+ template <typename T>
+ class TypeValues
+ : public ParamValue<typename LLTypeTags::Sorted<T>::value_t>
+ {
+ private:
+ struct Inaccessable{};
+ public:
+ typedef std::map<std::string, T> value_name_map_t;
+ typedef Inaccessable name_t;
+ typedef TypeValues<T> type_value_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
+ typedef typename param_value_t::value_t value_t;
+
+ TypeValues(const typename param_value_t::value_t& val)
+ : param_value_t(val)
+ {}
+
+ void setValueName(const std::string& key) {}
+ std::string getValueName() const { return ""; }
+ std::string calcValueName(const value_t& value) const { return ""; }
+ void clearValueName() const {}
+
+ static bool getValueFromName(const std::string& name, value_t& value)
+ {
+ return false;
+ }
+
+ static bool valueNamesExist()
+ {
+ return false;
+ }
+
+ static std::vector<std::string>* getPossibleValues()
+ {
+ return NULL;
+ }
+
+ void assignNamedValue(const Inaccessable& name)
+ {}
+
+ operator const value_t&() const
+ {
+ return param_value_t::getValue();
+ }
+
+ const value_t& operator()() const
+ {
+ return param_value_t::getValue();
+ }
+
+ static value_name_map_t* getValueNames() {return NULL;}
+ };
+
+ // helper class to implement name value lookups
+ // and caching of last used name
+ template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true >
+ class TypeValuesHelper
+ : public ParamValue<typename LLTypeTags::Sorted<T>::value_t>
+ {
+ typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t;
+ public:
+ typedef typename std::map<std::string, T> value_name_map_t;
+ typedef std::string name_t;
+ typedef self_t type_value_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
+ typedef typename param_value_t::value_t value_t;
+
+ TypeValuesHelper(const typename param_value_t::value_t& val)
+ : param_value_t(val)
+ {}
+
+ //TODO: cache key by index to save on param block size
+ void setValueName(const std::string& value_name)
+ {
+ mValueName = value_name;
+ }
+
+ std::string getValueName() const
+ {
+ return mValueName;
+ }
+
+ std::string calcValueName(const value_t& value) const
+ {
+ value_name_map_t* map = getValueNames();
+ for (typename value_name_map_t::value_type& map_pair : *map)
+ {
+ if (ParamCompare<T>::equals(map_pair.second, value))
+ {
+ return map_pair.first;
+ }
+ }
+
+ return "";
+ }
+
+ void clearValueName() const
+ {
+ mValueName.clear();
+ }
+
+ static bool getValueFromName(const std::string& name, value_t& value)
+ {
+ value_name_map_t* map = getValueNames();
+ typename value_name_map_t::iterator found_it = map->find(name);
+ if (found_it == map->end()) return false;
+
+ value = found_it->second;
+ return true;
+ }
+
+ static bool valueNamesExist()
+ {
+ return !getValueNames()->empty();
+ }
+
+ static value_name_map_t* getValueNames()
+ {
+ static value_name_map_t sMap;
+ static bool sInitialized = false;
+
+ if (!sInitialized)
+ {
+ sInitialized = true;
+ DERIVED_TYPE::declareValues();
+ }
+ return &sMap;
+ }
+
+ static std::vector<std::string>* getPossibleValues()
+ {
+ static std::vector<std::string> sValues;
+
+ value_name_map_t* map = getValueNames();
+ for (typename value_name_map_t::value_type& map_pair : *map)
+ {
+ sValues.push_back(map_pair.first);
+ }
+ return &sValues;
+ }
+
+ static void declare(const std::string& name, const value_t& value)
+ {
+ (*getValueNames())[name] = value;
+ }
+
+ void operator ()(const std::string& name)
+ {
+ *this = name;
+ }
+
+ void assignNamedValue(const std::string& name)
+ {
+ if (getValueFromName(name, param_value_t::getValue()))
+ {
+ setValueName(name);
+ }
+ }
+
+ operator const value_t&() const
+ {
+ return param_value_t::getValue();
+ }
+
+ const value_t& operator()() const
+ {
+ return param_value_t::getValue();
+ }
+
+ protected:
+ static void getName(const std::string& name, const value_t& value)
+ {}
+
+ mutable std::string mValueName;
+ };
+
+ // string types can support custom named values, but need
+ // to disambiguate in code between a string that is a named value
+ // and a string that is a name
+ template <typename DERIVED_TYPE>
+ class TypeValuesHelper<std::string, DERIVED_TYPE, true>
+ : public TypeValuesHelper<std::string, DERIVED_TYPE, false>
+ {
+ public:
+ typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t;
+ typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t;
+ typedef std::string value_t;
+ typedef std::string name_t;
+ typedef self_t type_value_t;
+
+ TypeValuesHelper(const std::string& val)
+ : base_t(val)
+ {}
+
+ void operator ()(const std::string& name)
+ {
+ *this = name;
+ }
+
+ self_t& operator =(const std::string& name)
+ {
+ if (base_t::getValueFromName(name, ParamValue<std::string>::getValue()))
+ {
+ base_t::setValueName(name);
+ }
+ else
+ {
+ ParamValue<std::string>::setValue(name);
+ }
+ return *this;
+ }
+
+ operator const value_t&() const
+ {
+ return ParamValue<std::string>::getValue();
+ }
+
+ const value_t& operator()() const
+ {
+ return ParamValue<std::string>::getValue();
+ }
+
+ };
+
+ // parser base class with mechanisms for registering readers/writers/inspectors of different types
+ class LL_COMMON_API Parser
+ {
+ LOG_CLASS(Parser);
+ public:
+ typedef std::vector<std::pair<std::string, bool> > name_stack_t;
+ typedef std::pair<name_stack_t::iterator, name_stack_t::iterator> name_stack_range_t;
+ typedef std::vector<std::string> possible_values_t;
+
+ typedef bool (*parser_read_func_t)(Parser& parser, void* output);
+ typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
+ typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t;
+
+ typedef std::map<const std::type_info*, parser_read_func_t> parser_read_func_map_t;
+ typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t;
+ typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t;
+
+ public:
+
+ Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
+ : mParseSilently(false),
+ mParserReadFuncs(&read_map),
+ mParserWriteFuncs(&write_map),
+ mParserInspectFuncs(&inspect_map)
+ {}
+
+ virtual ~Parser();
+
+ template <typename T> bool readValue(T& param, typename boost::disable_if<boost::is_enum<T> >::type* dummy = 0)
+ {
+ parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+ if (found_it != mParserReadFuncs->end())
+ {
+ return found_it->second(*this, (void*)&param);
+ }
+
+ return false;
+ }
+
+ template <typename T> bool readValue(T& param, typename boost::enable_if<boost::is_enum<T> >::type* dummy = 0)
+ {
+ parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+ if (found_it != mParserReadFuncs->end())
+ {
+ return found_it->second(*this, (void*)&param);
+ }
+ else
+ {
+ found_it = mParserReadFuncs->find(&typeid(S32));
+ if (found_it != mParserReadFuncs->end())
+ {
+ S32 int_value;
+ bool parsed = found_it->second(*this, (void*)&int_value);
+ param = (T)int_value;
+ return parsed;
+ }
+ }
+ return false;
+ }
+
+ template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
+ {
+ parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+ if (found_it != mParserWriteFuncs->end())
+ {
+ return found_it->second(*this, (const void*)&param, name_stack);
+ }
+ return false;
+ }
+
+ // dispatch inspection to registered inspection functions, for each parameter in a param block
+ template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
+ {
+ parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+ if (found_it != mParserInspectFuncs->end())
+ {
+ found_it->second(name_stack, min_count, max_count, possible_values);
+ return true;
+ }
+ return false;
+ }
+
+ virtual std::string getCurrentElementName() = 0;
+ virtual std::string getCurrentFileName() = 0;
+ virtual void parserWarning(const std::string& message);
+ virtual void parserError(const std::string& message);
+ void setParseSilently(bool silent) { mParseSilently = silent; }
+
+ protected:
+ template <typename T>
+ void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
+ {
+ mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+ mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
+ }
+
+ template <typename T>
+ void registerInspectFunc(parser_inspect_func_t inspect_func)
+ {
+ mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
+ }
+
+ bool mParseSilently;
+
+ private:
+ parser_read_func_map_t* mParserReadFuncs;
+ parser_write_func_map_t* mParserWriteFuncs;
+ parser_inspect_func_map_t* mParserInspectFuncs;
+ };
+
+ class Param;
+
+ enum ESerializePredicates
+ {
+ PROVIDED,
+ REQUIRED,
+ VALID,
+ HAS_DEFAULT_VALUE,
+ EMPTY
+ };
+
+ typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t;
+
+ predicate_rule_t default_parse_rules();
+
+ // various callbacks and constraints associated with an individual param
+ struct LL_COMMON_API ParamDescriptor
+ {
+ struct UserData
+ {
+ virtual ~UserData() {}
+ };
+
+ typedef bool(*merge_func_t)(Param&, const Param&, bool);
+ typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool);
+ typedef bool(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const predicate_rule_t rules, const Param* diff_param);
+ typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
+ typedef bool(*validation_func_t)(const Param*);
+
+ ParamDescriptor(param_handle_t p,
+ merge_func_t merge_func,
+ deserialize_func_t deserialize_func,
+ serialize_func_t serialize_func,
+ validation_func_t validation_func,
+ inspect_func_t inspect_func,
+ S32 min_count,
+ S32 max_count);
+
+ ParamDescriptor();
+ ~ParamDescriptor();
+
+ param_handle_t mParamHandle;
+ merge_func_t mMergeFunc;
+ deserialize_func_t mDeserializeFunc;
+ serialize_func_t mSerializeFunc;
+ inspect_func_t mInspectFunc;
+ validation_func_t mValidationFunc;
+ S32 mMinCount;
+ S32 mMaxCount;
+ S32 mNumRefs;
+ UserData* mUserData;
+ };
+
+ typedef std::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
+
+ // each derived Block class keeps a static data structure maintaining offsets to various params
+ class LL_COMMON_API BlockDescriptor
+ {
+ public:
+ BlockDescriptor();
+
+ typedef enum e_initialization_state
+ {
+ UNINITIALIZED,
+ INITIALIZING,
+ INITIALIZED
+ } EInitializationState;
+
+ void aggregateBlockData(BlockDescriptor& src_block_data);
+ void addParam(ParamDescriptorPtr param, const char* name);
+
+ typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t;
+ typedef std::vector<ParamDescriptorPtr> param_list_t;
+ typedef std::list<ParamDescriptorPtr> all_params_list_t;
+ typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t;
+
+ param_map_t mNamedParams; // parameters with associated names
+ param_list_t mUnnamedParams; // parameters with_out_ associated names
+ param_validation_list_t mValidationList; // parameters that must be validated
+ all_params_list_t mAllParams; // all parameters, owns descriptors
+ size_t mMaxParamOffset;
+ EInitializationState mInitializationState; // whether or not static block data has been initialized
+ class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
+ };
+
+ //TODO: implement in terms of owned_ptr
+ template<typename T>
+ class LazyValue
+ {
+ public:
+ LazyValue()
+ : mPtr(NULL)
+ {}
+
+ ~LazyValue()
+ {
+ delete mPtr;
+ }
+
+ LazyValue(const T& value)
+ {
+ mPtr = new T(value);
+ }
+
+ LazyValue(const LazyValue& other)
+ : mPtr(NULL)
+ {
+ *this = other;
+ }
+
+ LazyValue& operator = (const LazyValue& other)
+ {
+ if (!other.mPtr)
+ {
+ delete mPtr;
+ mPtr = NULL;
+ }
+ else
+ {
+ if (!mPtr)
+ {
+ mPtr = new T(*other.mPtr);
+ }
+ else
+ {
+ *mPtr = *(other.mPtr);
+ }
+ }
+ return *this;
+ }
+
+ bool operator==(const LazyValue& other) const
+ {
+ if (empty() || other.empty()) return false;
+ return *mPtr == *other.mPtr;
+ }
+
+ bool empty() const
+ {
+ return mPtr == NULL;
+ }
+
+ void set(const T& other)
+ {
+ if (!mPtr)
+ {
+ mPtr = new T(other);
+ }
+ else
+ {
+ *mPtr = other;
+ }
+ }
+
+ const T& get() const
+ {
+ return *ensureInstance();
+ }
+
+ T& get()
+ {
+ return *ensureInstance();
+ }
+
+ operator const T&() const
+ {
+ return get();
+ }
+
+ private:
+ // lazily allocate an instance of T
+ T* ensureInstance() const
+ {
+ if (mPtr == NULL)
+ {
+ mPtr = new T();
+ }
+ return mPtr;
+ }
+
+ private:
+
+ mutable T* mPtr;
+ };
+
+ // root class of all parameter blocks
+
+ class LL_COMMON_API BaseBlock
+ {
+ public:
+ // lift block tags into baseblock namespace so derived classes do not need to qualify them
+ typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK;
+ typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK;
+
+ template<typename T>
+ struct Sequential : public LLTypeTags::TypeTagBase<T, 2>
+ {
+ template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; };
+ template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; };
+ };
+
+ template<typename T>
+ struct Atomic : public LLTypeTags::TypeTagBase<T, 1>
+ {
+ template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; };
+ template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; };
+ };
+
+ template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t >
+ struct Lazy : public LLTypeTags::TypeTagBase<T, 0>
+ {
+ template <typename S> struct Cons
+ {
+ typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t;
+ };
+ template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> >
+ {
+ typedef Lazy<S, IS_A_BLOCK> value_t;
+ };
+ template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> >
+ {
+ typedef Lazy<S, BLOCK_T> value_t;
+ };
+ };
+
+ // "Multiple" constraint types, put here in root class to avoid ambiguity during use
+ struct AnyAmount
+ {
+ enum { minCount = 0 };
+ enum { maxCount = U32_MAX };
+ };
+
+ template<U32 MIN_AMOUNT>
+ struct AtLeast
+ {
+ enum { minCount = MIN_AMOUNT };
+ enum { maxCount = U32_MAX };
+ };
+
+ template<U32 MAX_AMOUNT>
+ struct AtMost
+ {
+ enum { minCount = 0 };
+ enum { maxCount = MAX_AMOUNT };
+ };
+
+ template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
+ struct Between
+ {
+ enum { minCount = MIN_AMOUNT };
+ enum { maxCount = MAX_AMOUNT };
+ };
+
+ template<U32 EXACT_COUNT>
+ struct Exactly
+ {
+ enum { minCount = EXACT_COUNT };
+ enum { maxCount = EXACT_COUNT };
+ };
+
+ // this typedef identifies derived classes as being blocks
+ typedef void baseblock_base_class_t;
+ LOG_CLASS(BaseBlock);
+ friend class Param;
+
+ BaseBlock()
+ : mValidated(false),
+ mParamProvided(false)
+ {}
+
+ virtual ~BaseBlock() {}
+ bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
+
+ param_handle_t getHandleFromParam(const Param* param) const;
+ bool validateBlock(bool emit_errors = true) const;
+
+ bool isProvided() const
+ {
+ return mParamProvided;
+ }
+
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
+
+ Param* getParamFromHandle(const param_handle_t param_handle)
+ {
+ if (param_handle == 0) return NULL;
+
+ U8* baseblock_address = reinterpret_cast<U8*>(this);
+ return reinterpret_cast<Param*>(baseblock_address + param_handle);
+ }
+
+ const Param* getParamFromHandle(const param_handle_t param_handle) const
+ {
+ const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+ return reinterpret_cast<const Param*>(baseblock_address + param_handle);
+ }
+
+ void addSynonym(Param& param, const std::string& synonym);
+
+ // Blocks can override this to do custom tracking of changes
+ virtual void paramChanged(const Param& changed_param, bool user_provided)
+ {
+ if (user_provided)
+ {
+ // a child param has been explicitly changed
+ // so *some* aspect of this block is now provided
+ mValidated = false;
+ mParamProvided = true;
+ }
+ }
+
+ bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule, const BaseBlock* diff_block = NULL) const;
+ bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
+
+ virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
+ virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }
+
+ // take all provided params from other and apply to self
+ bool overwriteFrom(const BaseBlock& other)
+ {
+ return false;
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFrom(const BaseBlock& other)
+ {
+ return false;
+ }
+
+ ParamDescriptorPtr findParamDescriptor(const Param& param);
+
+ // take all provided params from other and apply to self
+ bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
+
+ static BlockDescriptor& getBlockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
+
+ protected:
+ void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
+
+
+ bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
+ {
+ return mergeBlock(block_data, source, overwrite);
+ }
+
+ mutable bool mValidated; // lazy validation flag
+ bool mParamProvided;
+
+ private:
+ const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
+ };
+
+ class LL_COMMON_API Param
+ {
+ public:
+ void setProvided(bool is_provided = true)
+ {
+ mIsProvided = is_provided;
+ enclosingBlock().paramChanged(*this, is_provided);
+ }
+
+ Param& operator =(const Param& other)
+ {
+ mIsProvided = other.mIsProvided;
+ // don't change mEnclosingblockoffset
+ return *this;
+ }
+ protected:
+
+ bool anyProvided() const { return mIsProvided; }
+
+ Param(BaseBlock* enclosing_block);
+
+ // store pointer to enclosing block as offset to reduce space and allow for quick copying
+ BaseBlock& enclosingBlock() const
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
+ return *const_cast<BaseBlock*>
+ (reinterpret_cast<const BaseBlock*>
+ (my_addr - (ptrdiff_t)getEnclosingBlockOffset()));
+ }
+
+ U32 getEnclosingBlockOffset() const
+ {
+ return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow;
+ }
+
+ private:
+ friend class BaseBlock;
+
+ //24 bits for member offset field and 1 bit for provided flag
+ U16 mEnclosingBlockOffsetLow;
+ U8 mEnclosingBlockOffsetHigh:7;
+ U8 mIsProvided:1;
+
+ };
+
+ template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+ struct ParamIterator
+ {
+ typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator const_iterator;
+ typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator iterator;
+ };
+
+ // wrapper for parameter with a known type
+ // specialized to handle 4 cases:
+ // simple "scalar" value
+ // parameter that is itself a block
+ // multiple scalar values, stored in a vector
+ // multiple blocks, stored in a vector
+ template<typename T,
+ typename NAME_VALUE_LOOKUP = TypeValues<T>,
+ bool HAS_MULTIPLE_VALUES = false,
+ typename VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t>
+ class TypedParam
+ : public Param,
+ public NAME_VALUE_LOOKUP::type_value_t
+ {
+ protected:
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
+ typedef typename param_value_t::default_value_t default_value_t;
+ typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
+ public:
+ typedef typename param_value_t::value_t value_t;
+
+ using named_value_t::operator();
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ named_value_t(value)
+ {
+ if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ init(block_descriptor, validate_func, min_count, max_count, name);
+ }
+ }
+
+ bool isProvided() const { return Param::anyProvided(); }
+
+ bool isValid() const { return true; }
+
+ static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+ // no further names in stack, attempt to parse value now
+ if (name_stack_range.first == name_stack_range.second)
+ {
+ std::string name;
+
+ // try to parse a known named value
+ if(named_value_t::valueNamesExist()
+ && parser.readValue(name)
+ && named_value_t::getValueFromName(name, typed_param.getValue()))
+ {
+ typed_param.setValueName(name);
+ typed_param.setProvided();
+ return true;
+ }
+ // try to read value directly
+ else if (parser.readValue(typed_param.getValue()))
+ {
+ typed_param.clearValueName();
+ typed_param.setProvided();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
+ {
+ bool serialized = false;
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
+
+ LLPredicate::Value<ESerializePredicates> predicate;
+ if (diff_typed_param && ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+ {
+ predicate.set(HAS_DEFAULT_VALUE);
+ }
+
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+ predicate.set(EMPTY, false);
+
+ if (!predicate_rule.check(predicate)) return false;
+
+ if (!name_stack.empty())
+ {
+ name_stack.back().second = true;
+ }
+
+ std::string key = typed_param.getValueName();
+
+ // first try to write out name of name/value pair
+
+ if (!key.empty())
+ {
+ if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), key))
+ {
+ serialized = parser.writeValue(key, name_stack);
+ }
+ }
+ // then try to serialize value directly
+ else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+ {
+ serialized = parser.writeValue(typed_param.getValue(), name_stack);
+ if (!serialized)
+ {
+ std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
+ if (calculated_key.size()
+ && (!diff_typed_param
+ || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)))
+ {
+ serialized = parser.writeValue(calculated_key, name_stack);
+ }
+ }
+ }
+ return serialized;
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ // tell parser about our actual type
+ parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
+ // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
+ if (named_value_t::getPossibleValues())
+ {
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
+ }
+ }
+
+ void set(const value_t& val, bool flag_as_provided = true)
+ {
+ named_value_t::clearValueName();
+ named_value_t::setValue(val);
+ setProvided(flag_as_provided);
+ }
+
+ self_t& operator =(const typename named_value_t::name_t& name)
+ {
+ named_value_t::assignNamedValue(name);
+ return *this;
+ }
+
+ protected:
+
+ self_t& operator =(const self_t& other)
+ {
+ param_value_t::operator =(other);
+ Param::operator =(other);
+ return *this;
+ }
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (src_typed_param.isProvided()
+ && (overwrite || !dst_typed_param.isProvided()))
+ {
+ dst_typed_param.set(src_typed_param.getValue());
+ return true;
+ }
+ return false;
+ }
+ private:
+ void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
+ {
+ ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+ block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count));
+ block_descriptor.addParam(param_descriptor, name);
+ }
+ };
+
+ // parameter that is a block
+ template <typename BLOCK_T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>
+ : public Param,
+ public NAME_VALUE_LOOKUP::type_value_t
+ {
+ protected:
+ typedef ParamValue<typename LLTypeTags::Sorted<BLOCK_T>::value_t> param_value_t;
+ typedef typename param_value_t::default_value_t default_value_t;
+ typedef TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t;
+ typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
+ public:
+ using named_value_t::operator();
+ typedef typename param_value_t::value_t value_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ named_value_t(value)
+ {
+ if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ init(block_descriptor, validate_func, min_count, max_count, name);
+ }
+ }
+
+ static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+
+ if (name_stack_range.first == name_stack_range.second)
+ { // try to parse a known named value
+ std::string name;
+
+ if(named_value_t::valueNamesExist()
+ && parser.readValue(name)
+ && named_value_t::getValueFromName(name, typed_param.getValue()))
+ {
+ typed_param.setValueName(name);
+ typed_param.setProvided();
+ return true;
+ }
+ }
+
+ if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
+ { // attempt to parse block...
+ typed_param.clearValueName();
+ typed_param.setProvided();
+ return true;
+ }
+
+
+ return false;
+ }
+
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+
+ LLPredicate::Value<ESerializePredicates> predicate;
+
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+
+ if (!predicate_rule.check(predicate)) return false;
+
+ if (!name_stack.empty())
+ {
+ name_stack.back().second = true;
+ }
+
+ std::string key = typed_param.getValueName();
+ if (!key.empty())
+ {
+ if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
+ {
+ parser.writeValue(key, name_stack);
+ return true;
+ }
+ }
+ else
+ {
+ return typed_param.serializeBlock(parser, name_stack, predicate_rule, static_cast<const self_t*>(diff_param));
+ }
+
+ return false;
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+
+ // tell parser about our actual type
+ parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL);
+ // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
+ if (named_value_t::getPossibleValues())
+ {
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
+ }
+
+ typed_param.inspectBlock(parser, name_stack, min_count, max_count);
+ }
+
+ // a param-that-is-a-block is provided when the user has set one of its child params
+ // *and* the block as a whole validates
+ bool isProvided() const
+ {
+ return Param::anyProvided() && isValid();
+ }
+
+ bool isValid() const
+ {
+ return param_value_t::isValid();
+ }
+
+ // assign block contents to this param-that-is-a-block
+ void set(const value_t& val, bool flag_as_provided = true)
+ {
+ named_value_t::setValue(val);
+ named_value_t::clearValueName();
+ setProvided(flag_as_provided);
+ }
+
+ self_t& operator =(const typename named_value_t::name_t& name)
+ {
+ named_value_t::assignNamedValue(name);
+ return *this;
+ }
+
+ // propagate changed status up to enclosing block
+ /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
+ {
+ param_value_t::paramChanged(changed_param, user_provided);
+
+ if (user_provided)
+ {
+ setProvided();
+ named_value_t::clearValueName();
+ }
+ else
+ {
+ Param::enclosingBlock().paramChanged(*this, user_provided);
+ }
+ }
+
+ protected:
+
+ self_t& operator =(const self_t& other)
+ {
+ param_value_t::operator =(other);
+ Param::operator =(other);
+ return *this;
+ }
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (src_typed_param.anyProvided())
+ {
+ if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite))
+ {
+ dst_typed_param.clearValueName();
+ dst_typed_param.setProvided(true);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private:
+ void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
+ {
+ ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+ block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count));
+ block_descriptor.addParam(param_descriptor, name);
+ }
+ };
+
+ // list of non-block parameters
+ template <typename MULTI_VALUE_T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK>
+ : public Param
+ {
+ protected:
+ typedef TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<MULTI_VALUE_T>::value_t> param_value_t;
+ typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t;
+ typedef container_t default_value_t;
+ typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
+
+ public:
+ typedef typename param_value_t::value_t value_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mMinCount(min_count),
+ mMaxCount(max_count)
+ {
+ std::copy(value.begin(), value.end(), std::back_inserter(mValues));
+
+ if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ init(block_descriptor, validate_func, min_count, max_count, name);
+
+ }
+ }
+
+ bool isProvided() const { return Param::anyProvided() && isValid(); }
+
+ bool isValid() const
+ {
+ size_t num_elements = numValidElements();
+ return mMinCount < num_elements && num_elements < mMaxCount;
+ }
+
+ static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ Parser::name_stack_range_t new_name_stack_range(name_stack_range);
+ self_t& typed_param = static_cast<self_t&>(param);
+ value_t value;
+
+ // pop first element if empty string
+ if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty())
+ {
+ ++new_name_stack_range.first;
+ }
+
+ // no further names in stack, attempt to parse value now
+ if (new_name_stack_range.first == new_name_stack_range.second)
+ {
+ std::string name;
+
+ // try to parse a known named value
+ if(named_value_t::valueNamesExist()
+ && parser.readValue(name)
+ && named_value_t::getValueFromName(name, value))
+ {
+ typed_param.add(value);
+ typed_param.mValues.back().setValueName(name);
+ return true;
+ }
+ else if (parser.readValue(value)) // attempt to read value directly
+ {
+ typed_param.add(value);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
+ {
+ bool serialized = false;
+ const self_t& typed_param = static_cast<const self_t&>(param);
+
+ LLPredicate::Value<ESerializePredicates> predicate;
+
+ predicate.set(REQUIRED, typed_param.mMinCount > 0);
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+ predicate.set(EMPTY, typed_param.mValues.empty());
+
+ if (!predicate_rule.check(predicate)) return false;
+
+ for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
+ it != end_it;
+ ++it)
+ {
+ std::string key = it->getValueName();
+ name_stack.push_back(std::make_pair(std::string(), true));
+
+ if(key.empty())
+ // not parsed via name values, write out value directly
+ {
+ bool value_written = parser.writeValue(*it, name_stack);
+ if (!value_written)
+ {
+ std::string calculated_key = it->calcValueName(it->getValue());
+ if (parser.writeValue(calculated_key, name_stack))
+ {
+ serialized = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ if(parser.writeValue(key, name_stack))
+ {
+ serialized = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return serialized;
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ parser.inspectValue<MULTI_VALUE_T>(name_stack, min_count, max_count, NULL);
+ if (named_value_t::getPossibleValues())
+ {
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
+ }
+ }
+
+ void set(const container_t& val, bool flag_as_provided = true)
+ {
+ mValues = val;
+ setProvided(flag_as_provided);
+ }
+
+ param_value_t& add()
+ {
+ mValues.push_back(value_t());
+ Param::setProvided();
+ return mValues.back();
+ }
+
+ self_t& add(const value_t& item)
+ {
+ mValues.push_back(item);
+ setProvided();
+ return *this;
+ }
+
+ self_t& add(const typename named_value_t::name_t& name)
+ {
+ value_t value;
+
+ // try to parse a per type named value
+ if (named_value_t::getValueFromName(name, value))
+ {
+ add(value);
+ mValues.back().setValueName(name);
+ }
+
+ return *this;
+ }
+
+ // implicit conversion
+ operator const container_t&() const { return mValues; }
+ // explicit conversion
+ const container_t& operator()() const { return mValues; }
+
+ typedef typename container_t::iterator iterator;
+ typedef typename container_t::const_iterator const_iterator;
+ iterator begin() { return mValues.begin(); }
+ iterator end() { return mValues.end(); }
+ const_iterator begin() const { return mValues.begin(); }
+ const_iterator end() const { return mValues.end(); }
+ bool empty() const { return mValues.empty(); }
+ size_t size() const { return mValues.size(); }
+
+ size_t numValidElements() const
+ {
+ return mValues.size();
+ }
+
+ protected:
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (overwrite)
+ {
+ std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
+ }
+ else
+ {
+ container_t new_values(src_typed_param.mValues);
+ std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
+ std::swap(dst_typed_param.mValues, new_values);
+ }
+
+ if (src_typed_param.begin() != src_typed_param.end())
+ {
+ dst_typed_param.setProvided();
+ }
+ return true;
+ }
+
+ container_t mValues;
+ size_t mMinCount,
+ mMaxCount;
+
+ private:
+ void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
+ {
+ ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+ block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count));
+ block_descriptor.addParam(param_descriptor, name);
+ }
+ };
+
+ // list of block parameters
+ template <typename MULTI_BLOCK_T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>
+ : public Param
+ {
+ protected:
+ typedef TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<MULTI_BLOCK_T>::value_t> param_value_t;
+ typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t;
+ typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
+ typedef container_t default_value_t;
+ typedef typename container_t::iterator iterator;
+ typedef typename container_t::const_iterator const_iterator;
+ public:
+ typedef typename param_value_t::value_t value_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mMinCount(min_count),
+ mMaxCount(max_count)
+ {
+ std::copy(value.begin(), value.end(), back_inserter(mValues));
+
+ if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ init(block_descriptor, validate_func, min_count, max_count, name);
+ }
+ }
+
+ bool isProvided() const { return Param::anyProvided() && isValid(); }
+
+ bool isValid() const
+ {
+ size_t num_elements = numValidElements();
+ return mMinCount < num_elements && num_elements < mMaxCount;
+ }
+
+
+ static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ Parser::name_stack_range_t new_name_stack_range(name_stack_range);
+ self_t& typed_param = static_cast<self_t&>(param);
+ bool new_value = false;
+ bool new_array_value = false;
+
+ // pop first element if empty string
+ if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty())
+ {
+ new_array_value = new_name_stack_range.first->second;
+ ++new_name_stack_range.first;
+ }
+
+ if (new_name || new_array_value || typed_param.mValues.empty())
+ {
+ new_value = true;
+ typed_param.mValues.push_back(value_t());
+ }
+ param_value_t& value = typed_param.mValues.back();
+
+ if (new_name_stack_range.first == new_name_stack_range.second)
+ { // try to parse a known named value
+ std::string name;
+
+ if(named_value_t::valueNamesExist()
+ && parser.readValue(name)
+ && named_value_t::getValueFromName(name, value.getValue()))
+ {
+ typed_param.mValues.back().setValueName(name);
+ typed_param.setProvided();
+ if (new_array_value)
+ {
+ name_stack_range.first->second = false;
+ }
+ return true;
+ }
+ }
+
+ // attempt to parse block...
+ if(value.deserializeBlock(parser, new_name_stack_range, new_name))
+ {
+ typed_param.setProvided();
+ if (new_array_value)
+ {
+ name_stack_range.first->second = false;
+ }
+ return true;
+ }
+
+
+ if (new_value)
+ { // failed to parse new value, pop it off
+ typed_param.mValues.pop_back();
+ }
+
+ return false;
+ }
+
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
+ {
+ bool serialized = false;
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ LLPredicate::Value<ESerializePredicates> predicate;
+
+ predicate.set(REQUIRED, typed_param.mMinCount > 0);
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+ predicate.set(EMPTY, typed_param.mValues.empty());
+
+ if (!predicate_rule.check(predicate)) return false;
+
+ for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
+ it != end_it;
+ ++it)
+ {
+ name_stack.push_back(std::make_pair(std::string(), true));
+
+ std::string key = it->getValueName();
+ if (!key.empty())
+ {
+ serialized |= parser.writeValue(key, name_stack);
+ }
+ // Not parsed via named values, write out value directly
+ // NOTE: currently we don't do diffing of Multiples
+ else
+ {
+ serialized = it->serializeBlock(parser, name_stack, predicate_rule, NULL);
+ }
+
+ name_stack.pop_back();
+ }
+
+ if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+ {
+ serialized |= parser.writeValue(Flag(), name_stack);
+ }
+
+ return serialized;
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ const param_value_t& value_param = param_value_t(value_t());
+
+ // tell parser about our actual type
+ parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL);
+ // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
+ if (named_value_t::getPossibleValues())
+ {
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
+ }
+
+ value_param.inspectBlock(parser, name_stack, min_count, max_count);
+ }
+
+ void set(const container_t& val, bool flag_as_provided = true)
+ {
+ mValues = val;
+ setProvided(flag_as_provided);
+ }
+
+ param_value_t& add()
+ {
+ mValues.push_back(value_t());
+ setProvided();
+ return mValues.back();
+ }
+
+ self_t& add(const value_t& item)
+ {
+ mValues.push_back(item);
+ setProvided();
+ return *this;
+ }
+
+ self_t& add(const typename named_value_t::name_t& name)
+ {
+ value_t value;
+
+ // try to parse a per type named value
+ if (named_value_t::getValueFromName(name, value))
+ {
+ add(value);
+ mValues.back().setValueName(name);
+ }
+ return *this;
+ }
+
+ // implicit conversion
+ operator const container_t&() const { return mValues; }
+ // explicit conversion
+ const container_t& operator()() const { return mValues; }
+
+ iterator begin() { return mValues.begin(); }
+ iterator end() { return mValues.end(); }
+ const_iterator begin() const { return mValues.begin(); }
+ const_iterator end() const { return mValues.end(); }
+ bool empty() const { return mValues.empty(); }
+ size_t size() const { return mValues.size(); }
+
+ size_t numValidElements() const
+ {
+ size_t count = 0;
+ for (const_iterator it = mValues.begin(), end_it = mValues.end();
+ it != end_it;
+ ++it)
+ {
+ if(it->isValid()) count++;
+ }
+ return count;
+ }
+
+ protected:
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (overwrite)
+ {
+ std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));
+ }
+ else
+ {
+ container_t new_values(src_typed_param.mValues);
+ std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values));
+ std::swap(dst_typed_param.mValues, new_values);
+ }
+
+ if (src_typed_param.begin() != src_typed_param.end())
+ {
+ dst_typed_param.setProvided();
+ }
+
+ return true;
+ }
+
+ container_t mValues;
+ size_t mMinCount,
+ mMaxCount;
+
+ private:
+ void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
+ {
+ ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+ block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count));
+ block_descriptor.addParam(param_descriptor, name);
+ }
+ };
+
+ template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
+ class ChoiceBlock : public BASE_BLOCK
+ {
+ typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK> self_t;
+ typedef ChoiceBlock<DERIVED_BLOCK, BASE_BLOCK> enclosing_block_t;
+ typedef BASE_BLOCK base_block_t;
+
+ LOG_CLASS(self_t);
+ public:
+ // take all provided params from other and apply to self
+ bool overwriteFrom(const self_t& other)
+ {
+ return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFrom(const self_t& other)
+ {
+ return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);
+ }
+
+ bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
+ {
+ bool source_override = source_provided && (overwrite || !dest_provided);
+
+ if (source_override || source.mCurChoice == mCurChoice)
+ {
+ return mergeBlock(block_data, source, overwrite);
+ }
+ return false;
+ }
+
+ // merge with other block
+ bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)
+ {
+ mCurChoice = other.mCurChoice;
+ return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite);
+ }
+
+ // clear out old choice when param has changed
+ /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
+ {
+ param_handle_t changed_param_handle = base_block_t::getHandleFromParam(&changed_param);
+ // if we have a new choice...
+ if (changed_param_handle != mCurChoice)
+ {
+ // clear provided flag on previous choice
+ Param* previous_choice = base_block_t::getParamFromHandle(mCurChoice);
+ if (previous_choice)
+ {
+ previous_choice->setProvided(false);
+ }
+ mCurChoice = changed_param_handle;
+ }
+ base_block_t::paramChanged(changed_param, user_provided);
+ }
+
+ virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
+ virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }
+
+ protected:
+ ChoiceBlock()
+ : mCurChoice(0)
+ {
+ BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK));
+ }
+
+ // Alternatives are mutually exclusive wrt other Alternatives in the same block.
+ // One alternative in a block will always have isChosen() == true.
+ // At most one alternative in a block will have isProvided() == true.
+ template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
+ class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+ {
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
+ typedef typename super_t::value_t value_t;
+ typedef typename super_t::default_value_t default_value_t;
+
+ public:
+ friend class ChoiceBlock<DERIVED_BLOCK>;
+
+ using super_t::operator =;
+
+ explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>())
+ : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1),
+ mOriginalValue(val)
+ {
+ // assign initial choice to first declared option
+ DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr);
+ if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ if(blockp->mCurChoice == 0)
+ {
+ blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
+ }
+ }
+ }
+
+ void choose()
+ {
+ static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);
+ }
+
+ void chooseAs(const value_t& val)
+ {
+ super_t::set(val);
+ }
+
+ void operator =(const value_t& val)
+ {
+ super_t::set(val);
+ }
+
+ void operator()(const value_t& val)
+ {
+ super_t::set(val);
+ }
+
+ operator const value_t&() const
+ {
+ return (*this)();
+ }
+
+ const value_t& operator()() const
+ {
+ if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
+ {
+ return super_t::getValue();
+ }
+ return mOriginalValue;
+ }
+
+ bool isChosen() const
+ {
+ return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
+ }
+
+ private:
+ default_value_t mOriginalValue;
+ };
+
+ public:
+ static BlockDescriptor& getBlockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
+
+ private:
+ param_handle_t mCurChoice;
+
+ const Param* getCurrentChoice() const
+ {
+ return base_block_t::getParamFromHandle(mCurChoice);
+ }
+ };
+
+ template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
+ class Block
+ : public BASE_BLOCK
+ {
+ typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t;
+
+ protected:
+ typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t;
+
+ public:
+ typedef BASE_BLOCK base_block_t;
+
+ // take all provided params from other and apply to self
+ bool overwriteFrom(const self_t& other)
+ {
+ return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFrom(const self_t& other)
+ {
+ return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);
+ }
+
+ virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
+ virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }
+
+ protected:
+ Block()
+ {
+ //#pragma message("Parsing LLInitParam::Block")
+ BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK));
+ }
+
+ //
+ // Nested classes for declaring parameters
+ //
+ template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
+ class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+ {
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
+ typedef typename super_t::value_t value_t;
+ typedef typename super_t::default_value_t default_value_t;
+
+ public:
+ using super_t::operator();
+ using super_t::operator =;
+
+ explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>())
+ : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1)
+ {
+ //#pragma message("Parsing LLInitParam::Block::Optional")
+ }
+
+ Optional& operator =(const value_t& val)
+ {
+ super_t::set(val);
+ return *this;
+ }
+
+ DERIVED_BLOCK& operator()(const value_t& val)
+ {
+ super_t::set(val);
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+ };
+
+ template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
+ class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+ {
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
+ typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
+ typedef typename super_t::value_t value_t;
+ typedef typename super_t::default_value_t default_value_t;
+
+ public:
+ using super_t::operator();
+ using super_t::operator =;
+
+ // mandatory parameters require a name to be parseable
+ explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>())
+ : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1)
+ {}
+
+ Mandatory& operator =(const value_t& val)
+ {
+ super_t::set(val);
+ return *this;
+ }
+
+ DERIVED_BLOCK& operator()(const value_t& val)
+ {
+ super_t::set(val);
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+
+ static bool validate(const Param* p)
+ {
+ // valid only if provided
+ return static_cast<const self_t*>(p)->isProvided();
+ }
+
+ };
+
+ template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >
+ class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
+ {
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t;
+ typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t;
+ typedef typename super_t::container_t container_t;
+ typedef typename super_t::value_t value_t;
+
+ public:
+ typedef typename super_t::iterator iterator;
+ typedef typename super_t::const_iterator const_iterator;
+
+ using super_t::operator();
+ using super_t::operator const container_t&;
+
+ explicit Multiple(const char* name = "")
+ : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)
+ {}
+
+ Multiple& operator =(const container_t& val)
+ {
+ super_t::set(val);
+ return *this;
+ }
+
+ DERIVED_BLOCK& operator()(const container_t& val)
+ {
+ super_t::set(val);
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+
+ static bool validate(const Param* paramp)
+ {
+ size_t num_valid = ((super_t*)paramp)->numValidElements();
+ return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
+ }
+ };
+
+ // can appear in data files, but will ignored during parsing
+ // cannot read or write in code
+ class Ignored : public Param
+ {
+ public:
+ explicit Ignored(const char* name)
+ : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr)
+ {
+ BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor();
+ if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+ block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ NULL,
+ &deserializeParam,
+ NULL,
+ NULL,
+ NULL,
+ 0, S32_MAX));
+ block_descriptor.addParam(param_descriptor, name);
+ }
+ }
+
+ static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ if (name_stack_range.first == name_stack_range.second)
+ {
+ //std::string message = llformat("Deprecated value %s ignored", getName().c_str());
+ //parser.parserWarning(message);
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ // can appear in data files, or be written to in code, but data will be ignored
+ // cannot be read in code
+ class Deprecated : public Ignored
+ {
+ public:
+ explicit Deprecated(const char* name) : Ignored(name) {}
+
+ // dummy writer interfaces
+ template<typename T>
+ Deprecated& operator =(const T& val)
+ {
+ // do nothing
+ return *this;
+ }
+
+ template<typename T>
+ DERIVED_BLOCK& operator()(const T& val)
+ {
+ // do nothing
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+
+ template<typename T>
+ void set(const T& val, bool flag_as_provided = true)
+ {
+ // do nothing
+ }
+ };
+
+ public:
+ static BlockDescriptor& getBlockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
+
+ protected:
+ template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block>
+ void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param,
+ const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value)
+ {
+ if (!param.isProvided())
+ {
+ param.set(value, false);
+ }
+ }
+
+ };
+
+ template<typename T, typename BLOCK_T>
+ struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void>
+ {
+ typedef IS_A_BLOCK value_t;
+ };
+
+ template<typename T, typename BLOCK_T>
+ struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void>
+ {
+ typedef NOT_BLOCK value_t;
+ };
+
+ template<typename T, typename BLOCK_IDENTIFIER>
+ struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER>
+ {
+ typedef typename IsBlock<T>::value_t value_t;
+ };
+
+ template<typename T, typename BLOCK_IDENTIFIER>
+ struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER>
+ {
+ typedef typename IsBlock<T>::value_t value_t;
+ };
+
+
+ template<typename T>
+ struct InnerMostType
+ {
+ typedef T value_t;
+ };
+
+ template<typename T>
+ struct InnerMostType<ParamValue<T, NOT_BLOCK> >
+ {
+ typedef typename InnerMostType<T>::value_t value_t;
+ };
+
+ template<typename T>
+ struct InnerMostType<ParamValue<T, IS_A_BLOCK> >
+ {
+ typedef typename InnerMostType<T>::value_t value_t;
+ };
+
+ template<typename T, typename BLOCK_T>
+ class ParamValue <BaseBlock::Atomic<T>, BLOCK_T>
+ {
+ typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t;
+
+ public:
+ typedef typename InnerMostType<T>::value_t value_t;
+ typedef T default_value_t;
+
+ ParamValue()
+ : mValue()
+ {}
+
+ ParamValue(const default_value_t& value)
+ : mValue(value)
+ {}
+
+ void setValue(const value_t& val)
+ {
+ mValue.setValue(val);
+ }
+
+ const value_t& getValue() const
+ {
+ return mValue.getValue();
+ }
+
+ value_t& getValue()
+ {
+ return mValue.getValue();
+ }
+
+ bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ if (new_name)
+ {
+ resetToDefault();
+ }
+ return mValue.deserializeBlock(p, name_stack_range, new_name);
+ }
+
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
+ {
+ const BaseBlock* base_block = diff_block
+ ? &(diff_block->mValue)
+ : NULL;
+ return mValue.serializeBlock(p, name_stack, predicate_rule, base_block);
+ }
+
+ bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+ {
+ return mValue.inspectBlock(p, name_stack, min_count, max_count);
+ }
+
+ bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
+ {
+ if ((overwrite && source_provided) // new values coming in on top or...
+ || (!overwrite && !dst_provided)) // values being pushed under with nothing already there
+ {
+ // clear away what is there and take the new stuff as a whole
+ resetToDefault();
+ return mValue.mergeBlock(block_data, source.getValue(), overwrite);
+ }
+ return mValue.mergeBlock(block_data, source.getValue(), overwrite);
+ }
+
+ bool validateBlock(bool emit_errors = true) const
+ {
+ return mValue.validateBlock(emit_errors);
+ }
+
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
+ static BlockDescriptor& getBlockDescriptor()
+ {
+ return value_t::getBlockDescriptor();
+ }
+
+
+ private:
+ void resetToDefault()
+ {
+ static T default_value;
+ mValue = default_value;
+ }
+
+ T mValue;
+ };
+
+ template<typename T>
+ class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK>
+ {
+ typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t;
+
+ public:
+ typedef typename InnerMostType<T>::value_t value_t;
+ typedef T default_value_t;
+
+ ParamValue()
+ : mValue()
+ {
+ mCurParam = getBlockDescriptor().mAllParams.begin();
+ }
+
+ ParamValue(const default_value_t& value)
+ : mValue(value)
+ {
+ mCurParam = getBlockDescriptor().mAllParams.begin();
+ }
+
+ void setValue(const value_t& val)
+ {
+ mValue.setValue(val);
+ }
+
+ const value_t& getValue() const
+ {
+ return mValue.getValue();
+ }
+
+ value_t& getValue()
+ {
+ return mValue.getValue();
+ }
+
+ bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ if (new_name)
+ {
+ mCurParam = getBlockDescriptor().mAllParams.begin();
+ }
+ if (name_stack_range.first == name_stack_range.second
+ && mCurParam != getBlockDescriptor().mAllParams.end())
+ {
+ // deserialize to mCurParam
+ ParamDescriptor& pd = *(*mCurParam);
+ ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc;
+ Param* paramp = mValue.getParamFromHandle(pd.mParamHandle);
+
+ if (deserialize_func
+ && paramp
+ && deserialize_func(*paramp, p, name_stack_range, new_name))
+ {
+ ++mCurParam;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return mValue.deserializeBlock(p, name_stack_range, new_name);
+ }
+ }
+
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
+ {
+ const BaseBlock* base_block = diff_block
+ ? &(diff_block->mValue)
+ : NULL;
+ return mValue.serializeBlock(p, name_stack, predicate_rule, base_block);
+ }
+
+ bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+ {
+ return mValue.inspectBlock(p, name_stack, min_count, max_count);
+ }
+
+ bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
+ {
+ return mValue.mergeBlock(block_data, source.getValue(), overwrite);
+ }
+
+ bool validateBlock(bool emit_errors = true) const
+ {
+ return mValue.validateBlock(emit_errors);
+ }
+
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
+ static BlockDescriptor& getBlockDescriptor()
+ {
+ return value_t::getBlockDescriptor();
+ }
+
+ private:
+
+ BlockDescriptor::all_params_list_t::iterator mCurParam;
+ T mValue;
+ };
+
+ template<typename T>
+ class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK>
+ : public T
+ {
+ typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t;
+
+ public:
+ typedef typename InnerMostType<T>::value_t value_t;
+ typedef T default_value_t;
+
+ ParamValue()
+ : T()
+ {}
+
+ ParamValue(const default_value_t& value)
+ : T(value.getValue())
+ {}
+
+ bool isValid() const { return true; }
+ };
+
+ template<typename T, typename BLOCK_T>
+ class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T>
+ {
+ typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t;
+
+ public:
+ typedef typename InnerMostType<T>::value_t value_t;
+ typedef LazyValue<T> default_value_t;
+
+ ParamValue()
+ : mValue()
+ {}
+
+ ParamValue(const default_value_t& other)
+ : mValue(other)
+ {}
+
+ ParamValue(const T& value)
+ : mValue(value)
+ {}
+
+ void setValue(const value_t& val)
+ {
+ mValue.set(val);
+ }
+
+ const value_t& getValue() const
+ {
+ return mValue.get().getValue();
+ }
+
+ value_t& getValue()
+ {
+ return mValue.get().getValue();
+ }
+
+ bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ return mValue.get().deserializeBlock(p, name_stack_range, new_name);
+ }
+
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
+ {
+ if (mValue.empty()) return false;
+
+ const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty())
+ ? &(diff_block->mValue.get().getValue())
+ : NULL;
+ return mValue.get().serializeBlock(p, name_stack, predicate_rule, base_block);
+ }
+
+ bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+ {
+ return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
+ }
+
+ bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
+ {
+ return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);
+ }
+
+ bool validateBlock(bool emit_errors = true) const
+ {
+ return mValue.empty() || mValue.get().validateBlock(emit_errors);
+ }
+
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
+ static BlockDescriptor& getBlockDescriptor()
+ {
+ return value_t::getBlockDescriptor();
+ }
+
+ private:
+ LazyValue<T> mValue;
+ };
+
+ template<typename T, typename BLOCK_T>
+ class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T>
+ {
+ typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t;
+
+ public:
+ typedef typename InnerMostType<T>::value_t value_t;
+ typedef LazyValue<T> default_value_t;
+
+ ParamValue()
+ : mValue()
+ {}
+
+ ParamValue(const default_value_t& other)
+ : mValue(other)
+ {}
+
+ ParamValue(const T& value)
+ : mValue(value)
+ {}
+
+ void setValue(const value_t& val)
+ {
+ mValue.set(val);
+ }
+
+ const value_t& getValue() const
+ {
+ return mValue.get().getValue();
+ }
+
+ value_t& getValue()
+ {
+ return mValue.get().getValue();
+ }
+
+ bool isValid() const
+ {
+ return true;
+ }
+
+ private:
+ LazyValue<T> mValue;
+ };
+
+ template <>
+ class ParamValue <LLSD, NOT_BLOCK>
+ : public BaseBlock
+ {
+ public:
+ typedef LLSD value_t;
+ typedef LLSD default_value_t;
+
+ ParamValue()
+ {}
+
+ ParamValue(const default_value_t& other)
+ : mValue(other)
+ {}
+
+ void setValue(const value_t& val) { mValue = val; }
+
+ const value_t& getValue() const { return mValue; }
+ LLSD& getValue() { return mValue; }
+
+ // block param interface
+ LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);
+ LL_COMMON_API bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const;
+ bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
+ {
+ //TODO: implement LLSD params as schema type Any
+ return true;
+ }
+
+ private:
+ static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
+
+ LLSD mValue;
+ };
+
+ template<typename T>
+ class CustomParamValue
+ : public Block<ParamValue<T> >
+ {
+ public:
+ typedef enum e_value_age
+ {
+ VALUE_NEEDS_UPDATE, // mValue needs to be refreshed from the block parameters
+ VALUE_AUTHORITATIVE, // mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue)
+ BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative
+ } EValueAge;
+
+ typedef TypeValues<T> derived_t;
+ typedef CustomParamValue<T> self_t;
+ typedef Block<ParamValue<T> > block_t;
+ typedef T default_value_t;
+ typedef T value_t;
+ typedef void baseblock_base_class_t;
+
+
+ CustomParamValue(const default_value_t& value = T())
+ : mValue(value),
+ mValueAge(VALUE_AUTHORITATIVE)
+ {}
+
+ bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
+ {
+ derived_t& typed_param = static_cast<derived_t&>(*this);
+ // try to parse direct value T
+ if (name_stack_range.first == name_stack_range.second)
+ {
+ if(parser.readValue(typed_param.mValue))
+ {
+ typed_param.mValueAge = VALUE_AUTHORITATIVE;
+ typed_param.updateBlockFromValue(false);
+
+ return true;
+ }
+ }
+
+ // fall back on parsing block components for T
+ return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
+ }
+
+ bool serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const
+ {
+ const derived_t& typed_param = static_cast<const derived_t&>(*this);
+ const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
+
+ //std::string key = typed_param.getValueName();
+
+ //// first try to write out name of name/value pair
+ //if (!key.empty())
+ //{
+ // if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
+ // {
+ // return parser.writeValue(key, name_stack);
+ // }
+ //}
+ // then try to serialize value directly
+ if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
+ {
+
+ if (parser.writeValue(typed_param.getValue(), name_stack))
+ {
+ return true;
+ }
+ else
+ {
+ //RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
+ // since these tend to be viewed as the constructor arguments for the value T. It seems
+ // cleaner to treat the uniqueness of a BlockValue according to the generated value, and
+ // not the individual components. This way <color red="0" green="1" blue="0"/> will not
+ // be exported as <color green="1"/>, since it was probably the intent of the user to
+ // be specific about the RGB color values. This also fixes an issue where we distinguish
+ // between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
+
+ if (typed_param.mValueAge == VALUE_AUTHORITATIVE)
+ {
+ // if the value is authoritative but the parser doesn't accept the value type
+ // go ahead and make a copy, and splat the value out to its component params
+ // and serialize those params
+ derived_t copy(typed_param);
+ copy.updateBlockFromValue(true);
+ return copy.block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
+ }
+ else
+ {
+ return block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
+ }
+ }
+ }
+ return false;
+ }
+
+ bool validateBlock(bool emit_errors = true) const
+ {
+ if (mValueAge == VALUE_NEEDS_UPDATE)
+ {
+ if (block_t::validateBlock(emit_errors))
+ {
+ // clear stale keyword associated with old value
+ mValueAge = BLOCK_AUTHORITATIVE;
+ static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();
+ return true;
+ }
+ else
+ {
+ //block value incomplete, so not considered provided
+ // will attempt to revalidate on next call to isProvided()
+ return false;
+ }
+ }
+ else
+ {
+ // we have a valid value in hand
+ return true;
+ }
+ }
+
+ // propagate change status up to enclosing block
+ /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)
+ {
+ BaseBlock::paramChanged(changed_param, user_provided);
+ if (user_provided)
+ {
+ // a parameter changed, so our value is out of date
+ mValueAge = VALUE_NEEDS_UPDATE;
+ }
+ }
+
+ void setValue(const value_t& val)
+ {
+ // set param version number to be up to date, so we ignore block contents
+ mValueAge = VALUE_AUTHORITATIVE;
+ mValue = val;
+ static_cast<derived_t*>(this)->updateBlockFromValue(false);
+ }
+
+ const value_t& getValue() const
+ {
+ validateBlock(true);
+ return mValue;
+ }
+
+ T& getValue()
+ {
+ validateBlock(true);
+ return mValue;
+ }
+
+ protected:
+
+ // use this from within updateValueFromBlock() to set the value without making it authoritative
+ void updateValue(const value_t& value)
+ {
+ mValue = value;
+ }
+
+ bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
+ {
+ bool source_override = source_provided && (overwrite || !dst_provided);
+
+ const derived_t& src_typed_param = static_cast<const derived_t&>(source);
+
+ if (source_override && src_typed_param.mValueAge == VALUE_AUTHORITATIVE)
+ {
+ // copy value over
+ setValue(src_typed_param.getValue());
+ return true;
+ }
+ // merge individual parameters into destination
+ if (mValueAge == VALUE_AUTHORITATIVE)
+ {
+ static_cast<derived_t*>(this)->updateBlockFromValue(dst_provided);
+ }
+ return mergeBlock(block_data, source, overwrite);
+ }
+
+ bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& source, bool overwrite)
+ {
+ return block_t::mergeBlock(block_data, source, overwrite);
+ }
+
+ private:
+ mutable T mValue;
+ mutable EValueAge mValueAge;
+ };
}
diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp
index e7193b70b5..d1b02066bd 100644
--- a/indra/llcommon/llinstancetracker.cpp
+++ b/indra/llcommon/llinstancetracker.cpp
@@ -1,24 +1,24 @@
/**
* @file lllinstancetracker.cpp
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 27422e1266..3232a0e219 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llinstancetracker.h
* @brief LLInstanceTracker is a mixin class that automatically tracks object
* instances with or without an associated key
@@ -6,21 +6,21 @@
* $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$
*/
@@ -99,11 +99,11 @@ public:
return mSelf;
}
- static size_t instanceCount()
- {
- return LockStatic()->mMap.size();
+ static size_t instanceCount()
+ {
+ return LockStatic()->mMap.size();
}
-
+
// snapshot of std::pair<const KEY, std::shared_ptr<SUBCLASS>> pairs, for
// some SUBCLASS derived from T
template <typename SUBCLASS>
@@ -243,7 +243,7 @@ public:
}
protected:
- LLInstanceTracker(const KEY& key)
+ LLInstanceTracker(const KEY& key)
{
// We do not intend to manage the lifespan of this object with
// shared_ptr, so give it a no-op deleter. We store shared_ptrs in our
@@ -286,9 +286,9 @@ private:
static std::string report(const char* key) { return report(std::string(key)); }
// caller must instantiate LockStatic
- void add_(LockStatic& lock, const KEY& key, const ptr_t& ptr)
- {
- mInstanceKey = key;
+ void add_(LockStatic& lock, const KEY& key, const ptr_t& ptr)
+ {
+ mInstanceKey = key;
InstanceMap& map = lock->mMap;
switch(KEY_COLLISION_BEHAVIOR)
{
@@ -373,7 +373,7 @@ public:
{
return mSelf;
}
-
+
static size_t instanceCount()
{
return LockStatic()->mSet.size();
diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp
index b89160cc55..e36c1d0a4c 100644
--- a/indra/llcommon/llkeybind.cpp
+++ b/indra/llcommon/llkeybind.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llkeybind.cpp
* @brief Information about key combinations.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, 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$
*/
@@ -207,7 +207,7 @@ bool LLKeyBind::operator!=(const LLKeyBind& rhs)
bool LLKeyBind::isEmpty() const
{
- for (const LLKeyData& key_data : mData)
+ for (const LLKeyData& key_data : mData)
{
if (!key_data.isEmpty()) return false;
}
@@ -225,7 +225,7 @@ LLKeyBind::data_vector_t::const_iterator LLKeyBind::endNonEmpty() const
LLSD LLKeyBind::asLLSD() const
{
LLSD data;
- for (const LLKeyData& key_data : mData)
+ for (const LLKeyData& key_data : mData)
{
// append intermediate entries even if empty to not affect visual
// representation
@@ -242,7 +242,7 @@ bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
return false;
}
- for (const LLKeyData& key_data : mData)
+ for (const LLKeyData& key_data : mData)
{
if (key_data.canHandle(mouse, key, mask))
{
@@ -266,7 +266,7 @@ bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignor
{
if (mouse != CLICK_NONE || key != KEY_NONE)
{
- for (const LLKeyData& key_data : mData)
+ for (const LLKeyData& key_data : mData)
{
if (key_data.mKey == key
&& key_data.mMask == mask
@@ -353,7 +353,7 @@ void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
{
// if both click and key are none (isEmpty()), we are inserting a placeholder, we don't want to reset anything
// otherwise reset identical key
- for (LLKeyData& key_data : mData)
+ for (LLKeyData& key_data : mData)
{
if (key_data.mKey == data.mKey
&& key_data.mMouse == data.mMouse
diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h
index 488f509411..1bbb2fadb5 100644
--- a/indra/llcommon/llkeybind.h
+++ b/indra/llcommon/llkeybind.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llkeybind.h
* @brief Information about key combinations.
*
* $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$
*/
@@ -54,7 +54,7 @@ public:
KEY mKey;
MASK mMask;
// Either to expect exact match or ignore not expected masks as long as expected mask-bit is present
- bool mIgnoreMasks;
+ bool mIgnoreMasks;
};
// One function can bind to multiple Key options
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 1f576cc19e..a5b5eaa946 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llkeythrottle.h
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -46,44 +46,44 @@ template <class T> class LLKeyThrottle;
template <class T>
class LLKeyThrottleImpl
{
- friend class LLKeyThrottle<T>;
+ friend class LLKeyThrottle<T>;
protected:
- struct Entry {
- U32 count;
- bool blocked;
-
- Entry() : count(0), blocked(false) { }
- };
-
- typedef std::map<T, Entry> EntryMap;
-
- EntryMap* prevMap;
- EntryMap* currMap;
-
- U32 countLimit;
- // maximum number of keys allowed per interval
-
- U64 intervalLength; // each map covers this time period (usec or frame number)
- U64 startTime; // start of the time period (usec or frame number)
- // currMap started counting at this time
- // prevMap covers the previous interval
-
- LLKeyThrottleImpl() :
- prevMap(NULL),
- currMap(NULL),
- countLimit(0),
- intervalLength(1),
- startTime(0)
- {}
-
- static U64 getTime()
- {
- return LLFrameTimer::getTotalTime();
- }
- static U64 getFrame() // Return the current frame number
- {
- return (U64) LLFrameTimer::getFrameCount();
- }
+ struct Entry {
+ U32 count;
+ bool blocked;
+
+ Entry() : count(0), blocked(false) { }
+ };
+
+ typedef std::map<T, Entry> EntryMap;
+
+ EntryMap* prevMap;
+ EntryMap* currMap;
+
+ U32 countLimit;
+ // maximum number of keys allowed per interval
+
+ U64 intervalLength; // each map covers this time period (usec or frame number)
+ U64 startTime; // start of the time period (usec or frame number)
+ // currMap started counting at this time
+ // prevMap covers the previous interval
+
+ LLKeyThrottleImpl() :
+ prevMap(NULL),
+ currMap(NULL),
+ countLimit(0),
+ intervalLength(1),
+ startTime(0)
+ {}
+
+ static U64 getTime()
+ {
+ return LLFrameTimer::getTotalTime();
+ }
+ static U64 getFrame() // Return the current frame number
+ {
+ return (U64) LLFrameTimer::getFrameCount();
+ }
};
@@ -91,241 +91,241 @@ template< class T >
class LLKeyThrottle
{
public:
- // @param realtime = FALSE for frame-based throttle, TRUE for usec
- // real-time throttle
- LLKeyThrottle(U32 limit, F32 interval, BOOL realtime = TRUE)
- : m(* new LLKeyThrottleImpl<T>)
- {
- setParameters( limit, interval, realtime );
- }
-
- ~LLKeyThrottle()
- {
- delete m.prevMap;
- delete m.currMap;
- delete &m;
- }
-
- enum State {
- THROTTLE_OK, // rate not exceeded, let pass
- THROTTLE_NEWLY_BLOCKED, // rate exceed for the first time
- THROTTLE_BLOCKED, // rate exceed, block key
- };
-
- F64 getActionCount(const T& id)
- {
- U64 now = 0;
- if ( mIsRealtime )
- {
- now = LLKeyThrottleImpl<T>::getTime();
- }
- else
- {
- now = LLKeyThrottleImpl<T>::getFrame();
- }
-
- if (now >= (m.startTime + m.intervalLength))
- {
- if (now < (m.startTime + 2 * m.intervalLength))
- {
- // prune old data
- delete m.prevMap;
- m.prevMap = m.currMap;
- m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
-
- m.startTime += m.intervalLength;
- }
- else
- {
- // lots of time has passed, all data is stale
- delete m.prevMap;
- delete m.currMap;
- m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
- m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
-
- m.startTime = now;
- }
- }
-
- U32 prevCount = 0;
-
- typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
- if (prev != m.prevMap->end())
- {
- prevCount = prev->second.count;
- }
-
- typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
-
- // curr.count is the number of keys in
- // this current 'time slice' from the beginning of it until now
- // prevCount is the number of keys in the previous
- // time slice scaled to be one full time slice back from the current
- // (now) time.
-
- // compute current, windowed rate
- F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
- F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
- return averageCount;
- }
-
- // call each time the key wants use
- State noteAction(const T& id, S32 weight = 1)
- {
- U64 now = 0;
- if ( mIsRealtime )
- {
- now = LLKeyThrottleImpl<T>::getTime();
- }
- else
- {
- now = LLKeyThrottleImpl<T>::getFrame();
- }
-
- if (now >= (m.startTime + m.intervalLength))
- {
- if (now < (m.startTime + 2 * m.intervalLength))
- {
- // prune old data
- delete m.prevMap;
- m.prevMap = m.currMap;
- m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
-
- m.startTime += m.intervalLength;
- }
- else
- {
- // lots of time has passed, all data is stale
- delete m.prevMap;
- delete m.currMap;
- m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
- m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
-
- m.startTime = now;
- }
- }
-
- U32 prevCount = 0;
- bool prevBlocked = false;
-
- typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
- if (prev != m.prevMap->end())
- {
- prevCount = prev->second.count;
- prevBlocked = prev->second.blocked;
- }
-
- typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
-
- bool wereBlocked = curr.blocked || prevBlocked;
-
- curr.count += weight;
-
- // curr.count is the number of keys in
- // this current 'time slice' from the beginning of it until now
- // prevCount is the number of keys in the previous
- // time slice scaled to be one full time slice back from the current
- // (now) time.
-
- // compute current, windowed rate
- F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
- F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
-
- curr.blocked |= averageCount > m.countLimit;
-
- bool nowBlocked = curr.blocked || prevBlocked;
-
- if (!nowBlocked)
- {
- return THROTTLE_OK;
- }
- else if (!wereBlocked)
- {
- return THROTTLE_NEWLY_BLOCKED;
- }
- else
- {
- return THROTTLE_BLOCKED;
- }
- }
-
- // call to force throttle conditions for id
- void throttleAction(const T& id)
- {
- noteAction(id);
- typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
- curr.count = llmax(m.countLimit, curr.count);
- curr.blocked = true;
- }
-
- // returns true if key is blocked
- bool isThrottled(const T& id) const
- {
- if (m.currMap->empty()
- && m.prevMap->empty())
- {
- // most of the time we'll fall in here
- return false;
- }
-
- // NOTE, we ignore the case where id is in the map but the map is stale.
- // You might think that we'd stop throttling things in such a case,
- // however it may be that a god has disabled scripts in the region or
- // estate --> we probably want to report the state of the id when the
- // scripting engine was paused.
- typename LLKeyThrottleImpl<T>::EntryMap::const_iterator entry = m.currMap->find(id);
- if (entry != m.currMap->end())
- {
- return entry->second.blocked;
- }
- entry = m.prevMap->find(id);
- if (entry != m.prevMap->end())
- {
- return entry->second.blocked;
- }
- return false;
- }
-
- // Get the throttling parameters
- void getParameters( U32 & out_limit, F32 & out_interval, BOOL & out_realtime )
- {
- out_limit = m.countLimit;
- out_interval = m.intervalLength;
- out_realtime = mIsRealtime;
- }
-
- // Set the throttling behavior
- void setParameters( U32 limit, F32 interval, BOOL realtime = TRUE )
- {
- // limit is the maximum number of keys
- // allowed per interval (in seconds or frames)
- mIsRealtime = realtime;
- m.countLimit = limit;
- if ( mIsRealtime )
- {
- m.intervalLength = (U64)(interval * USEC_PER_SEC);
- m.startTime = LLKeyThrottleImpl<T>::getTime();
- }
- else
- {
- m.intervalLength = (U64)interval;
- m.startTime = LLKeyThrottleImpl<T>::getFrame();
- }
-
- if ( m.intervalLength == 0 )
- { // Don't allow zero intervals
- m.intervalLength = 1;
- }
-
- delete m.prevMap;
- m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
- delete m.currMap;
- m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
- }
+ // @param realtime = FALSE for frame-based throttle, TRUE for usec
+ // real-time throttle
+ LLKeyThrottle(U32 limit, F32 interval, BOOL realtime = TRUE)
+ : m(* new LLKeyThrottleImpl<T>)
+ {
+ setParameters( limit, interval, realtime );
+ }
+
+ ~LLKeyThrottle()
+ {
+ delete m.prevMap;
+ delete m.currMap;
+ delete &m;
+ }
+
+ enum State {
+ THROTTLE_OK, // rate not exceeded, let pass
+ THROTTLE_NEWLY_BLOCKED, // rate exceed for the first time
+ THROTTLE_BLOCKED, // rate exceed, block key
+ };
+
+ F64 getActionCount(const T& id)
+ {
+ U64 now = 0;
+ if ( mIsRealtime )
+ {
+ now = LLKeyThrottleImpl<T>::getTime();
+ }
+ else
+ {
+ now = LLKeyThrottleImpl<T>::getFrame();
+ }
+
+ if (now >= (m.startTime + m.intervalLength))
+ {
+ if (now < (m.startTime + 2 * m.intervalLength))
+ {
+ // prune old data
+ delete m.prevMap;
+ m.prevMap = m.currMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime += m.intervalLength;
+ }
+ else
+ {
+ // lots of time has passed, all data is stale
+ delete m.prevMap;
+ delete m.currMap;
+ m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime = now;
+ }
+ }
+
+ U32 prevCount = 0;
+
+ typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+ if (prev != m.prevMap->end())
+ {
+ prevCount = prev->second.count;
+ }
+
+ typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+ // curr.count is the number of keys in
+ // this current 'time slice' from the beginning of it until now
+ // prevCount is the number of keys in the previous
+ // time slice scaled to be one full time slice back from the current
+ // (now) time.
+
+ // compute current, windowed rate
+ F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+ F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+ return averageCount;
+ }
+
+ // call each time the key wants use
+ State noteAction(const T& id, S32 weight = 1)
+ {
+ U64 now = 0;
+ if ( mIsRealtime )
+ {
+ now = LLKeyThrottleImpl<T>::getTime();
+ }
+ else
+ {
+ now = LLKeyThrottleImpl<T>::getFrame();
+ }
+
+ if (now >= (m.startTime + m.intervalLength))
+ {
+ if (now < (m.startTime + 2 * m.intervalLength))
+ {
+ // prune old data
+ delete m.prevMap;
+ m.prevMap = m.currMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime += m.intervalLength;
+ }
+ else
+ {
+ // lots of time has passed, all data is stale
+ delete m.prevMap;
+ delete m.currMap;
+ m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime = now;
+ }
+ }
+
+ U32 prevCount = 0;
+ bool prevBlocked = false;
+
+ typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+ if (prev != m.prevMap->end())
+ {
+ prevCount = prev->second.count;
+ prevBlocked = prev->second.blocked;
+ }
+
+ typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+ bool wereBlocked = curr.blocked || prevBlocked;
+
+ curr.count += weight;
+
+ // curr.count is the number of keys in
+ // this current 'time slice' from the beginning of it until now
+ // prevCount is the number of keys in the previous
+ // time slice scaled to be one full time slice back from the current
+ // (now) time.
+
+ // compute current, windowed rate
+ F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+ F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+
+ curr.blocked |= averageCount > m.countLimit;
+
+ bool nowBlocked = curr.blocked || prevBlocked;
+
+ if (!nowBlocked)
+ {
+ return THROTTLE_OK;
+ }
+ else if (!wereBlocked)
+ {
+ return THROTTLE_NEWLY_BLOCKED;
+ }
+ else
+ {
+ return THROTTLE_BLOCKED;
+ }
+ }
+
+ // call to force throttle conditions for id
+ void throttleAction(const T& id)
+ {
+ noteAction(id);
+ typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+ curr.count = llmax(m.countLimit, curr.count);
+ curr.blocked = true;
+ }
+
+ // returns true if key is blocked
+ bool isThrottled(const T& id) const
+ {
+ if (m.currMap->empty()
+ && m.prevMap->empty())
+ {
+ // most of the time we'll fall in here
+ return false;
+ }
+
+ // NOTE, we ignore the case where id is in the map but the map is stale.
+ // You might think that we'd stop throttling things in such a case,
+ // however it may be that a god has disabled scripts in the region or
+ // estate --> we probably want to report the state of the id when the
+ // scripting engine was paused.
+ typename LLKeyThrottleImpl<T>::EntryMap::const_iterator entry = m.currMap->find(id);
+ if (entry != m.currMap->end())
+ {
+ return entry->second.blocked;
+ }
+ entry = m.prevMap->find(id);
+ if (entry != m.prevMap->end())
+ {
+ return entry->second.blocked;
+ }
+ return false;
+ }
+
+ // Get the throttling parameters
+ void getParameters( U32 & out_limit, F32 & out_interval, BOOL & out_realtime )
+ {
+ out_limit = m.countLimit;
+ out_interval = m.intervalLength;
+ out_realtime = mIsRealtime;
+ }
+
+ // Set the throttling behavior
+ void setParameters( U32 limit, F32 interval, BOOL realtime = TRUE )
+ {
+ // limit is the maximum number of keys
+ // allowed per interval (in seconds or frames)
+ mIsRealtime = realtime;
+ m.countLimit = limit;
+ if ( mIsRealtime )
+ {
+ m.intervalLength = (U64)(interval * USEC_PER_SEC);
+ m.startTime = LLKeyThrottleImpl<T>::getTime();
+ }
+ else
+ {
+ m.intervalLength = (U64)interval;
+ m.startTime = LLKeyThrottleImpl<T>::getFrame();
+ }
+
+ if ( m.intervalLength == 0 )
+ { // Don't allow zero intervals
+ m.intervalLength = 1;
+ }
+
+ delete m.prevMap;
+ m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ delete m.currMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ }
protected:
- LLKeyThrottleImpl<T>& m;
- BOOL mIsRealtime; // TRUE to be time based (default), FALSE for frame based
+ LLKeyThrottleImpl<T>& m;
+ BOOL mIsRealtime; // TRUE to be time based (default), FALSE for frame based
};
#endif
diff --git a/indra/llcommon/llkeyusetracker.h b/indra/llcommon/llkeyusetracker.h
index 1fb222dd40..790c7b713b 100644
--- a/indra/llcommon/llkeyusetracker.h
+++ b/indra/llcommon/llkeyusetracker.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llkeyusetracker.h
* @brief Declaration of the LLKeyUseTracker 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$
*/
@@ -40,176 +40,176 @@ template <class TKey, class TData>
class KeyUseTrackerNodeImpl
{
public:
- U64 mLastUse;
- U32 mUseCount;
- TKey mKey;
- TData mData;
-
- KeyUseTrackerNodeImpl( TKey k, TData d ) :
- mLastUse(0),
- mUseCount(0),
- mKey( k ),
- mData( d )
- {
- }
+ U64 mLastUse;
+ U32 mUseCount;
+ TKey mKey;
+ TData mData;
+
+ KeyUseTrackerNodeImpl( TKey k, TData d ) :
+ mLastUse(0),
+ mUseCount(0),
+ mKey( k ),
+ mData( d )
+ {
+ }
};
template <class TKey, class TData>
class LLKeyUseTracker
{
- typedef KeyUseTrackerNodeImpl<TKey,TData> TKeyUseTrackerNode;
- typedef std::list<TKeyUseTrackerNode *> TKeyList;
- TKeyList mKeyList;
- U64 mMemUsecs;
- U64 mLastExpire;
- U32 mMaxCount;
- U32 mCount;
-
- static U64 getTime()
- {
- // This function operates on a frame basis, not instantaneous.
- // We can rely on its output for determining first use in a
- // frame.
- return LLFrameTimer::getTotalTime();
- }
-
- void ageKeys()
- {
- U64 now = getTime();
- if( now == mLastExpire )
- {
- return;
- }
- mLastExpire = now;
-
- while( !mKeyList.empty() && (now - mKeyList.front()->mLastUse > mMemUsecs ) )
- {
- delete mKeyList.front();
- mKeyList.pop_front();
- mCount--;
- }
- }
-
- TKeyUseTrackerNode *findNode( TKey key )
- {
- ageKeys();
-
- typename TKeyList::iterator i;
- for( i = mKeyList.begin(); i != mKeyList.end(); i++ )
- {
- if( (*i)->mKey == key )
- return *i;
- }
-
- return NULL;
- }
-
- TKeyUseTrackerNode *removeNode( TKey key )
- {
- TKeyUseTrackerNode *i;
- i = findNode( key );
- if( i )
- {
- mKeyList.remove( i );
- mCount--;
- return i;
- }
-
- return NULL;
- }
+ typedef KeyUseTrackerNodeImpl<TKey,TData> TKeyUseTrackerNode;
+ typedef std::list<TKeyUseTrackerNode *> TKeyList;
+ TKeyList mKeyList;
+ U64 mMemUsecs;
+ U64 mLastExpire;
+ U32 mMaxCount;
+ U32 mCount;
+
+ static U64 getTime()
+ {
+ // This function operates on a frame basis, not instantaneous.
+ // We can rely on its output for determining first use in a
+ // frame.
+ return LLFrameTimer::getTotalTime();
+ }
+
+ void ageKeys()
+ {
+ U64 now = getTime();
+ if( now == mLastExpire )
+ {
+ return;
+ }
+ mLastExpire = now;
+
+ while( !mKeyList.empty() && (now - mKeyList.front()->mLastUse > mMemUsecs ) )
+ {
+ delete mKeyList.front();
+ mKeyList.pop_front();
+ mCount--;
+ }
+ }
+
+ TKeyUseTrackerNode *findNode( TKey key )
+ {
+ ageKeys();
+
+ typename TKeyList::iterator i;
+ for( i = mKeyList.begin(); i != mKeyList.end(); i++ )
+ {
+ if( (*i)->mKey == key )
+ return *i;
+ }
+
+ return NULL;
+ }
+
+ TKeyUseTrackerNode *removeNode( TKey key )
+ {
+ TKeyUseTrackerNode *i;
+ i = findNode( key );
+ if( i )
+ {
+ mKeyList.remove( i );
+ mCount--;
+ return i;
+ }
+
+ return NULL;
+ }
public:
- LLKeyUseTracker( U32 memory_seconds, U32 max_count ) :
- mLastExpire(0),
- mMaxCount( max_count ),
- mCount(0)
- {
- mMemUsecs = ((U64)memory_seconds) * 1000000;
- }
-
- ~LLKeyUseTracker()
- {
- // Flush list
- while( !mKeyList.empty() )
- {
- delete mKeyList.front();
- mKeyList.pop_front();
- mCount--;
- }
- }
-
- void markUse( TKey key, TData data )
- {
- TKeyUseTrackerNode *node = removeNode( key );
- if( !node )
- {
- node = new TKeyUseTrackerNode(key, data);
- }
- else
- {
- // Update data
- node->mData = data;
- }
- node->mLastUse = getTime();
- node->mUseCount++;
- mKeyList.push_back( node );
- mCount++;
-
- // Too many items? Drop head
- if( mCount > mMaxCount )
- {
- delete mKeyList.front();
- mKeyList.pop_front();
- mCount--;
- }
- }
-
- void forgetKey( TKey key )
- {
- TKeyUseTrackerNode *node = removeNode( key );
- if( node )
- {
- delete node;
- }
- }
-
- U32 getUseCount( TKey key )
- {
- TKeyUseTrackerNode *node = findNode( key );
- if( node )
- {
- return node->mUseCount;
- }
- return 0;
- }
-
- U64 getTimeSinceUse( TKey key )
- {
- TKeyUseTrackerNode *node = findNode( key );
- if( node )
- {
- U64 now = getTime();
- U64 delta = now - node->mLastUse;
- return (U32)( delta / 1000000 );
- }
- return 0;
- }
-
- TData *getLastUseData( TKey key )
- {
- TKeyUseTrackerNode *node = findNode( key );
- if( node )
- {
- return &node->mData;
- }
- return NULL;
- }
-
- U32 getKeyCount()
- {
- return mCount;
- }
+ LLKeyUseTracker( U32 memory_seconds, U32 max_count ) :
+ mLastExpire(0),
+ mMaxCount( max_count ),
+ mCount(0)
+ {
+ mMemUsecs = ((U64)memory_seconds) * 1000000;
+ }
+
+ ~LLKeyUseTracker()
+ {
+ // Flush list
+ while( !mKeyList.empty() )
+ {
+ delete mKeyList.front();
+ mKeyList.pop_front();
+ mCount--;
+ }
+ }
+
+ void markUse( TKey key, TData data )
+ {
+ TKeyUseTrackerNode *node = removeNode( key );
+ if( !node )
+ {
+ node = new TKeyUseTrackerNode(key, data);
+ }
+ else
+ {
+ // Update data
+ node->mData = data;
+ }
+ node->mLastUse = getTime();
+ node->mUseCount++;
+ mKeyList.push_back( node );
+ mCount++;
+
+ // Too many items? Drop head
+ if( mCount > mMaxCount )
+ {
+ delete mKeyList.front();
+ mKeyList.pop_front();
+ mCount--;
+ }
+ }
+
+ void forgetKey( TKey key )
+ {
+ TKeyUseTrackerNode *node = removeNode( key );
+ if( node )
+ {
+ delete node;
+ }
+ }
+
+ U32 getUseCount( TKey key )
+ {
+ TKeyUseTrackerNode *node = findNode( key );
+ if( node )
+ {
+ return node->mUseCount;
+ }
+ return 0;
+ }
+
+ U64 getTimeSinceUse( TKey key )
+ {
+ TKeyUseTrackerNode *node = findNode( key );
+ if( node )
+ {
+ U64 now = getTime();
+ U64 delta = now - node->mLastUse;
+ return (U32)( delta / 1000000 );
+ }
+ return 0;
+ }
+
+ TData *getLastUseData( TKey key )
+ {
+ TKeyUseTrackerNode *node = findNode( key );
+ if( node )
+ {
+ return &node->mData;
+ }
+ return NULL;
+ }
+
+ U32 getKeyCount()
+ {
+ return mCount;
+ }
};
#endif
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index b2b1162f63..d0fb586459 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-20
* @brief Implementation for llleap.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h
index 7cecdf2f8f..acf9edf418 100644
--- a/indra/llcommon/llleap.h
+++ b/indra/llcommon/llleap.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-20
* @brief Class that implements "LLSD Event API Plugin"
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp
index 471f52e91c..050d71c327 100644
--- a/indra/llcommon/llleaplistener.cpp
+++ b/indra/llcommon/llleaplistener.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-03-16
* @brief Implementation for llleaplistener.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llleaplistener.h b/indra/llcommon/llleaplistener.h
index 0ca5893657..cad4543d02 100644
--- a/indra/llcommon/llleaplistener.h
+++ b/indra/llcommon/llleaplistener.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-03-16
* @brief LLEventAPI supporting LEAP plugins
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp
index a9b1cdf4f6..559bfc443c 100644
--- a/indra/llcommon/llliveappconfig.cpp
+++ b/indra/llcommon/llliveappconfig.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llliveappconfig.cpp
* @brief Configuration information for an LLApp that overrides indra.xml
*
* $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$
*/
@@ -33,48 +33,48 @@
#include "llsdserialize.h"
LLLiveAppConfig::LLLiveAppConfig(
- const std::string& filename,
- F32 refresh_period,
- LLApp::OptionPriority priority) :
- LLLiveFile(filename, refresh_period),
- mPriority(priority)
+ const std::string& filename,
+ F32 refresh_period,
+ LLApp::OptionPriority priority) :
+ LLLiveFile(filename, refresh_period),
+ mPriority(priority)
{ }
LLLiveAppConfig::~LLLiveAppConfig()
{ }
-// virtual
+// virtual
bool LLLiveAppConfig::loadFile()
{
- LL_INFOS() << "LLLiveAppConfig::loadFile(): reading from "
- << filename() << LL_ENDL;
+ LL_INFOS() << "LLLiveAppConfig::loadFile(): reading from "
+ << filename() << LL_ENDL;
llifstream file(filename().c_str());
- LLSD config;
+ LLSD config;
if (file.is_open())
{
LLSDSerialize::fromXML(config, file);
- if(!config.isMap())
- {
- LL_WARNS() << "Live app config not an map in " << filename()
- << " Ignoring the data." << LL_ENDL;
- return false;
- }
- file.close();
+ if(!config.isMap())
+ {
+ LL_WARNS() << "Live app config not an map in " << filename()
+ << " Ignoring the data." << LL_ENDL;
+ return false;
+ }
+ file.close();
+ }
+ else
+ {
+ LL_INFOS() << "Live file " << filename() << " does not exit." << LL_ENDL;
}
- else
- {
- LL_INFOS() << "Live file " << filename() << " does not exit." << LL_ENDL;
- }
- // *NOTE: we do not handle the else case here because we would not
- // have attempted to load the file unless LLLiveFile had
- // determined there was a reason to load it. This only happens
- // when either the file has been updated or it is either suddenly
- // in existence or has passed out of existence. Therefore, we want
- // to set the config to an empty config, and return that it
- // changed.
+ // *NOTE: we do not handle the else case here because we would not
+ // have attempted to load the file unless LLLiveFile had
+ // determined there was a reason to load it. This only happens
+ // when either the file has been updated or it is either suddenly
+ // in existence or has passed out of existence. Therefore, we want
+ // to set the config to an empty config, and return that it
+ // changed.
- LLApp* app = LLApp::instance();
- if(app) app->setOptionData(mPriority, config);
- return true;
+ LLApp* app = LLApp::instance();
+ if(app) app->setOptionData(mPriority, config);
+ return true;
}
diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h
index 4fd7c26a07..0dea643d87 100644
--- a/indra/llcommon/llliveappconfig.h
+++ b/indra/llcommon/llliveappconfig.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llliveappconfig.h
* @brief Configuration information for an LLApp that overrides indra.xml
*
* $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$
*/
@@ -43,27 +43,27 @@ class LL_COMMON_API LLLiveAppConfig : public LLLiveFile
{
public:
- /**
- * @brief Constructor
- *
- * @param filename. The name of the file for periodically checking
- * configuration.
- * @param refresh_period How often the internal timer should
- * bother checking the filesystem.
- * @param The application priority level of that configuration file.
- */
- LLLiveAppConfig(
- const std::string& filename,
- F32 refresh_period,
- LLApp::OptionPriority priority);
+ /**
+ * @brief Constructor
+ *
+ * @param filename. The name of the file for periodically checking
+ * configuration.
+ * @param refresh_period How often the internal timer should
+ * bother checking the filesystem.
+ * @param The application priority level of that configuration file.
+ */
+ LLLiveAppConfig(
+ const std::string& filename,
+ F32 refresh_period,
+ LLApp::OptionPriority priority);
- ~LLLiveAppConfig(); ///< Destructor
+ ~LLLiveAppConfig(); ///< Destructor
protected:
- /*virtual*/ bool loadFile();
+ /*virtual*/ bool loadFile();
private:
- LLApp::OptionPriority mPriority;
+ LLApp::OptionPriority mPriority;
};
#endif
diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp
index ea485c2d86..15651a6813 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()
- {
- mLiveFile.checkAndReload();
- return FALSE;
- }
-
- private:
- LLLiveFile& mLiveFile;
- };
-
+ class LiveFileEventTimer : public LLEventTimer
+ {
+ public:
+ LiveFileEventTimer(LLLiveFile& f, F32 refresh)
+ : LLEventTimer(refresh), mLiveFile(f)
+ { }
+
+ BOOL tick()
+ {
+ 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/lllivefile.h b/indra/llcommon/lllivefile.h
index 320aa4bc3e..305b205a68 100644
--- a/indra/llcommon/lllivefile.h
+++ b/indra/llcommon/lllivefile.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lllivefile.h
* @brief Automatically reloads a file whenever it changes or is removed.
*
* $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$
*/
@@ -33,63 +33,63 @@ extern const F32 DEFAULT_CONFIG_FILE_REFRESH;
class LL_COMMON_API LLLiveFile
{
public:
- LLLiveFile(const std::string& filename, const F32 refresh_period = 5.f);
- virtual ~LLLiveFile();
+ LLLiveFile(const std::string& filename, const F32 refresh_period = 5.f);
+ virtual ~LLLiveFile();
+
+ /**
+ * @brief Check to see if this live file should reload.
+ *
+ * Call this before using anything that was read & cached
+ * from the file.
+ *
+ * This method calls the <code>loadFile()</code> method if
+ * any of:
+ * file has a new modify time since the last check
+ * file used to exist and now does not
+ * file used to not exist but now does
+ * @return Returns true if the file was reloaded.
+ */
+ bool checkAndReload();
- /**
- * @brief Check to see if this live file should reload.
- *
- * Call this before using anything that was read & cached
- * from the file.
- *
- * This method calls the <code>loadFile()</code> method if
- * any of:
- * file has a new modify time since the last check
- * file used to exist and now does not
- * file used to not exist but now does
- * @return Returns true if the file was reloaded.
- */
- bool checkAndReload();
-
- std::string filename() const;
+ std::string filename() const;
- /**
- * @brief Add this live file to an automated recheck.
- *
- * Normally, just calling checkAndReload() is enough. In some
- * cases though, you may need to let the live file periodically
- * check itself.
- */
- void addToEventTimer();
+ /**
+ * @brief Add this live file to an automated recheck.
+ *
+ * Normally, just calling checkAndReload() is enough. In some
+ * cases though, you may need to let the live file periodically
+ * check itself.
+ */
+ void addToEventTimer();
- void setRefreshPeriod(F32 seconds);
+ void setRefreshPeriod(F32 seconds);
protected:
- /**
- * @breif Implement this to load your file if it changed.
- *
- * This method is called automatically by <code>checkAndReload()</code>,
- * so though you must implement this in derived classes, you do
- * not need to call it manually.
- * @return Returns true if the file was successfully loaded.
- */
- virtual bool loadFile() = 0;
+ /**
+ * @breif Implement this to load your file if it changed.
+ *
+ * This method is called automatically by <code>checkAndReload()</code>,
+ * so though you must implement this in derived classes, you do
+ * not need to call it manually.
+ * @return Returns true if the file was successfully loaded.
+ */
+ virtual bool loadFile() = 0;
- /**
- * @brief Implement this method if you want to get a change callback.
- *
- * This virtual function will be called automatically at the end
- * of <code>checkAndReload()</code> if a new configuration was
- * loaded. This does not track differences between the current and
- * newly loaded file, so any successful load event will trigger a
- * <code>changed()</code> callback. Default is to do nothing.
- */
- virtual void changed() {}
+ /**
+ * @brief Implement this method if you want to get a change callback.
+ *
+ * This virtual function will be called automatically at the end
+ * of <code>checkAndReload()</code> if a new configuration was
+ * loaded. This does not track differences between the current and
+ * newly loaded file, so any successful load event will trigger a
+ * <code>changed()</code> callback. Default is to do nothing.
+ */
+ virtual void changed() {}
private:
- class Impl;
- Impl& impl;
+ class Impl;
+ Impl& impl;
};
#endif //LL_LLLIVEFILE_H
diff --git a/indra/llcommon/llmainthreadtask.cpp b/indra/llcommon/llmainthreadtask.cpp
index e0d70cacd8..eb26ded63f 100644
--- a/indra/llcommon/llmainthreadtask.cpp
+++ b/indra/llcommon/llmainthreadtask.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2019-12-05
* @brief Implementation for llmainthreadtask.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llmainthreadtask.h b/indra/llcommon/llmainthreadtask.h
index d509b687c0..28ad62830b 100644
--- a/indra/llcommon/llmainthreadtask.h
+++ b/indra/llcommon/llmainthreadtask.h
@@ -4,7 +4,7 @@
* @date 2019-12-04
* @brief LLMainThreadTask dispatches work to the main thread. When invoked on
* the main thread, it performs the work inline.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llmake.h b/indra/llcommon/llmake.h
index 02463d97ea..e575128be7 100644
--- a/indra/llcommon/llmake.h
+++ b/indra/llcommon/llmake.h
@@ -9,7 +9,7 @@
* make an instance with arguments of arbitrary type. llmake()
* eliminates the need to declare a new helper function for every such
* class template.
- *
+ *
* also relevant:
*
* Template argument deduction for class templates (C++17)
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index 0abe817f1d..f64f54c262 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -1,42 +1,42 @@
-/**
+/**
* @file llmd5.cpp
*
* $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$
*/
-// llMD5.CC - source code for the C++/object oriented translation and
+// llMD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
//
// Adapted to Linden Lab by Frank Filipanits, 6/25/2002
// Fixed potential memory leak, James Cook, 6/27/2002
-// Translation and modification (c) 1995 by Mordechai T. Abzug
+// Translation and modification (c) 1995 by Mordechai T. Abzug
-// This translation/ modification is provided "as is," without express or
+// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
-// The translator/ modifier does not claim (1) that MD5 will do what you think
-// it does; (2) that this translation/ modification is accurate; or (3) that
-// this software is "merchantible." (Language for this disclaimer partially
+// The translator/ modifier does not claim (1) that MD5 will do what you think
+// it does; (2) that this translation/ modification is accurate; or (3) that
+// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
@@ -76,7 +76,7 @@ documentation and/or software.
#include "llmd5.h"
-#include <iostream> // cerr
+#include <iostream> // cerr
// how many bytes to grab at a time when checking files
const int LLMD5::BLOCK_LEN = 4096;
@@ -102,7 +102,7 @@ void LLMD5::update (const uint8_t *input, const size_t input_length) {
size_t buffer_space; // how much space is left in buffer
if (finalized){ // so we can't update!
- std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl;
+ std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl;
return;
}
@@ -116,21 +116,21 @@ void LLMD5::update (const uint8_t *input, const size_t input_length) {
// now, transform each 64-byte piece of the input, bypassing the buffer
if (input == NULL || input_length == 0){
- std::cerr << "LLMD5::update: Invalid input!" << std::endl;
- return;
+ std::cerr << "LLMD5::update: Invalid input!" << std::endl;
+ return;
}
// Transform as many times as possible.
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
// fill the rest of the buffer and transform
- memcpy( /* Flawfinder: ignore */
- buffer + buffer_index,
- input,
- buffer_space);
+ memcpy( /* Flawfinder: ignore */
+ buffer + buffer_index,
+ input,
+ buffer_space);
transform (buffer);
- for (input_index = buffer_space; input_index + 63 < input_length;
- input_index += 64)
+ for (input_index = buffer_space; input_index + 63 < input_length;
+ input_index += 64)
transform (input+input_index);
buffer_index = 0; // so we can buffer remaining
@@ -140,7 +140,7 @@ void LLMD5::update (const uint8_t *input, const size_t input_length) {
// and here we do the buffering:
- memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */
+ memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */
}
@@ -150,7 +150,7 @@ void LLMD5::update (const uint8_t *input, const size_t input_length) {
void LLMD5::update(FILE* file){
- unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
+ unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
int len;
while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) )
@@ -165,11 +165,11 @@ void LLMD5::update(FILE* file){
void LLMD5::update(std::istream& stream){
- unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
+ unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
int len;
while (stream.good()){
- stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
+ stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
len=(int)stream.gcount();
update(buffer, len);
}
@@ -178,7 +178,7 @@ void LLMD5::update(std::istream& stream){
void LLMD5::update(const std::string& s)
{
- update((unsigned char *)s.c_str(),s.length());
+ update((unsigned char *)s.c_str(),s.length());
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
@@ -187,7 +187,7 @@ void LLMD5::update(const std::string& s)
void LLMD5::finalize (){
- unsigned char bits[8]; /* Flawfinder: ignore */
+ unsigned char bits[8]; /* Flawfinder: ignore */
size_t index, padLen;
static uint8_t PADDING[64]={
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -245,60 +245,60 @@ LLMD5::LLMD5(std::istream& stream){
// Digest a string of the format ("%s:%i" % (s, number))
LLMD5::LLMD5(const unsigned char *string, const unsigned int number)
{
- const char *colon = ":";
- char tbuf[16]; /* Flawfinder: ignore */
- init();
- update(string, (U32)strlen((const char *) string)); /* Flawfinder: ignore */
- update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
- snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */
- update((const unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
- finalize();
+ const char *colon = ":";
+ char tbuf[16]; /* Flawfinder: ignore */
+ init();
+ update(string, (U32)strlen((const char *) string)); /* Flawfinder: ignore */
+ update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+ snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */
+ update((const unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
+ finalize();
}
// Digest a string
LLMD5::LLMD5(const unsigned char *s)
{
- init();
- update(s, (U32)strlen((const char *) s)); /* Flawfinder: ignore */
- finalize();
+ init();
+ update(s, (U32)strlen((const char *) s)); /* Flawfinder: ignore */
+ finalize();
}
void LLMD5::raw_digest(unsigned char *s) const
{
- if (!finalized)
- {
- std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<<
- "finalized the digest!" << std::endl;
- s[0] = '\0';
- return;
- }
-
- memcpy(s, digest, 16); /* Flawfinder: ignore */
- return;
+ if (!finalized)
+ {
+ std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<<
+ "finalized the digest!" << std::endl;
+ s[0] = '\0';
+ return;
+ }
+
+ memcpy(s, digest, 16); /* Flawfinder: ignore */
+ return;
}
void LLMD5::hex_digest(char *s) const
{
- int i;
+ int i;
- if (!finalized)
- {
- std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<<
- "finalized the digest!" <<std::endl;
- s[0] = '\0';
- return;
- }
+ if (!finalized)
+ {
+ std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<<
+ "finalized the digest!" <<std::endl;
+ s[0] = '\0';
+ return;
+ }
- for (i=0; i<16; i++)
- {
- sprintf(s+i*2, "%02x", digest[i]); /* Flawfinder: ignore */
- }
+ for (i=0; i<16; i++)
+ {
+ sprintf(s+i*2, "%02x", digest[i]); /* Flawfinder: ignore */
+ }
- s[32]='\0';
+ s[32]='\0';
- return;
+ return;
}
@@ -308,27 +308,27 @@ void LLMD5::hex_digest(char *s) const
std::ostream& operator<<(std::ostream &stream, LLMD5 context)
{
- char s[33]; /* Flawfinder: ignore */
- context.hex_digest(s);
- stream << s;
- return stream;
+ char s[33]; /* Flawfinder: ignore */
+ context.hex_digest(s);
+ stream << s;
+ return stream;
}
bool operator==(const LLMD5& a, const LLMD5& b)
{
- unsigned char a_guts[16];
- unsigned char b_guts[16];
- a.raw_digest(a_guts);
- b.raw_digest(b_guts);
- if (memcmp(a_guts,b_guts,16)==0)
- return true;
- else
- return false;
+ unsigned char a_guts[16];
+ unsigned char b_guts[16];
+ a.raw_digest(a_guts);
+ b.raw_digest(b_guts);
+ if (memcmp(a_guts,b_guts,16)==0)
+ return true;
+ else
+ return false;
}
bool operator!=(const LLMD5& a, const LLMD5& b)
{
- return !(a==b);
+ return !(a==b);
}
// PRIVATE METHODS:
diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h
index 7d6373c20c..46c79cf5a2 100644
--- a/indra/llcommon/llmd5.h
+++ b/indra/llcommon/llmd5.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llmd5.h
*
* $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$
*/
@@ -26,17 +26,17 @@
#ifndef LL_LLMD5_H
#define LL_LLMD5_H
-// LLMD5.CC - source code for the C++/object oriented translation and
+// LLMD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
-// Translation and modification (c) 1995 by Mordechai T. Abzug
+// Translation and modification (c) 1995 by Mordechai T. Abzug
-// This translation/ modification is provided "as is," without express or
+// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
-// The translator/ modifier does not claim (1) that MD5 will do what you think
-// it does; (2) that this translation/ modification is accurate; or (3) that
-// this software is "merchantible." (Language for this disclaimer partially
+// The translator/ modifier does not claim (1) that MD5 will do what you think
+// it does; (2) that this translation/ modification is accurate; or (3) that
+// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
@@ -95,10 +95,10 @@ public:
LLMD5 (std::istream& stream); // digest stream, finalize
LLMD5 (FILE *file); // digest file, close, finalize
LLMD5 (const unsigned char *string, const unsigned int number);
-
+
// methods to acquire finalized result
- void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data
- void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string
+ void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data
+ void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string
friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context);
@@ -114,7 +114,7 @@ private:
// last, the private methods, mostly static:
void init (); // called by all constructors
- void transform (const uint8_t *buffer); // does the real update work. Note
+ void transform (const uint8_t *buffer); // does the real update work. Note
// that length is implied to be 64.
static void encode (uint8_t *dest, const uint32_t *src, const size_t length);
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 574b9b8b3b..cf5ead718d 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmemory.cpp
* @brief Very special memory allocation/deallocation stuff here
*
* $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$
*/
@@ -61,56 +61,56 @@ U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
{
#if defined(LL_WINDOWS) && defined(LL_DEBUG_BUFFER_OVERRUN)
- //do not check
- return;
+ //do not check
+ return;
#else
- #ifdef SHOW_ASSERT
- // Redundant, place to set breakpoints.
- if (ptr%alignment!=0)
- {
- LL_WARNS() << "alignment check failed" << LL_ENDL;
- }
- llassert(ptr%alignment==0);
- #endif
+ #ifdef SHOW_ASSERT
+ // Redundant, place to set breakpoints.
+ if (ptr%alignment!=0)
+ {
+ LL_WARNS() << "alignment check failed" << LL_ENDL;
+ }
+ llassert(ptr%alignment==0);
+ #endif
#endif
}
-//static
+//static
void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size)
{
- sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
+ sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
}
-//static
-void LLMemory::updateMemoryInfo()
+//static
+void LLMemory::updateMemoryInfo()
{
- LL_PROFILE_ZONE_SCOPED
+ LL_PROFILE_ZONE_SCOPED
#if LL_WINDOWS
- PROCESS_MEMORY_COUNTERS counters;
-
- if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
- {
- LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
- return ;
- }
-
- sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
- sample(sAllocatedMem, sAllocatedMemInKB);
- sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
- sample(sVirtualMem, sAllocatedPageSizeInKB);
-
- U32Kilobytes avail_phys, avail_virtual;
- LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
- sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
-
- if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
- {
- sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
- }
- else
- {
- sAvailPhysicalMemInKB = U32Kilobytes(0);
- }
+ PROCESS_MEMORY_COUNTERS counters;
+
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+ {
+ LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
+ return ;
+ }
+
+ sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
+ sample(sAllocatedMem, sAllocatedMemInKB);
+ sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
+ sample(sVirtualMem, sAllocatedPageSizeInKB);
+
+ U32Kilobytes avail_phys, avail_virtual;
+ LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
+ sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
+
+ if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
+ {
+ sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
+ }
+ else
+ {
+ sAvailPhysicalMemInKB = U32Kilobytes(0);
+ }
#elif defined(LL_DARWIN)
task_vm_info info;
@@ -156,13 +156,13 @@ void LLMemory::updateMemoryInfo()
}
#else
- //not valid for other systems for now.
- sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
- sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
- sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
+ //not valid for other systems for now.
+ sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
+ sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
+ sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
#endif
- return ;
+ return ;
}
//
@@ -171,126 +171,126 @@ void LLMemory::updateMemoryInfo()
//if success, it returns the address where the memory chunk can fit in;
//otherwise it returns NULL.
//
-//static
+//static
void* LLMemory::tryToAlloc(void* address, U32 size)
{
#if LL_WINDOWS
- address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ;
- if(address)
- {
- if(!VirtualFree(address, 0, MEM_RELEASE))
- {
- LL_ERRS() << "error happens when free some memory reservation." << LL_ENDL ;
- }
- }
- return address ;
+ address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ;
+ if(address)
+ {
+ if(!VirtualFree(address, 0, MEM_RELEASE))
+ {
+ LL_ERRS() << "error happens when free some memory reservation." << LL_ENDL ;
+ }
+ }
+ return address ;
#else
- return (void*)0x01 ; //skip checking
+ return (void*)0x01 ; //skip checking
#endif
}
-//static
+//static
void LLMemory::logMemoryInfo(BOOL update)
{
- LL_PROFILE_ZONE_SCOPED
- if(update)
- {
- updateMemoryInfo() ;
- }
-
- LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
- LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
- LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
- LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
+ LL_PROFILE_ZONE_SCOPED
+ if(update)
+ {
+ updateMemoryInfo() ;
+ }
+
+ LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
+ LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
+ LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
+ LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
}
-//static
-U32Kilobytes LLMemory::getAvailableMemKB()
+//static
+U32Kilobytes LLMemory::getAvailableMemKB()
{
- return sAvailPhysicalMemInKB ;
+ return sAvailPhysicalMemInKB ;
}
-//static
-U32Kilobytes LLMemory::getMaxMemKB()
+//static
+U32Kilobytes LLMemory::getMaxMemKB()
{
- return sMaxPhysicalMemInKB ;
+ return sMaxPhysicalMemInKB ;
}
-//static
-U32Kilobytes LLMemory::getAllocatedMemKB()
+//static
+U32Kilobytes LLMemory::getAllocatedMemKB()
{
- return sAllocatedMemInKB ;
+ return sAllocatedMemInKB ;
}
//----------------------------------------------------------------------------
#if defined(LL_WINDOWS)
-//static
+//static
U64 LLMemory::getCurrentRSS()
{
- PROCESS_MEMORY_COUNTERS counters;
+ PROCESS_MEMORY_COUNTERS counters;
- if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
- {
- LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
- return 0;
- }
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+ {
+ LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
+ return 0;
+ }
- return counters.WorkingSetSize;
+ return counters.WorkingSetSize;
}
#elif defined(LL_DARWIN)
-// if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
-// {
-// LL_WARNS() << "Couldn't get page size" << LL_ENDL;
-// return 0;
-// } else {
-// return page_size;
-// }
+// if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
+// {
+// LL_WARNS() << "Couldn't get page size" << LL_ENDL;
+// return 0;
+// } else {
+// return page_size;
+// }
// }
U64 LLMemory::getCurrentRSS()
{
- U64 residentSize = 0;
- mach_task_basic_info_data_t basicInfo;
- mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
- if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
- {
+ U64 residentSize = 0;
+ mach_task_basic_info_data_t basicInfo;
+ mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
+ if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
+ {
residentSize = basicInfo.resident_size;
// 64-bit macos apps allocate 32 GB or more at startup, and this is reflected in virtual_size.
// basicInfo.virtual_size is not what we want.
- }
- else
- {
- LL_WARNS() << "task_info failed" << LL_ENDL;
- }
+ }
+ else
+ {
+ LL_WARNS() << "task_info failed" << LL_ENDL;
+ }
- return residentSize;
+ return residentSize;
}
#elif defined(LL_LINUX)
U64 LLMemory::getCurrentRSS()
{
- struct rusage usage;
+ struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage) != 0) {
- // Error handling code could be here
- return 0;
- }
+ if (getrusage(RUSAGE_SELF, &usage) != 0) {
+ // Error handling code could be here
+ return 0;
+ }
- // ru_maxrss (since Linux 2.6.32)
- // This is the maximum resident set size used (in kilobytes).
- return usage.ru_maxrss * 1024;
+ // ru_maxrss (since Linux 2.6.32)
+ // This is the maximum resident set size used (in kilobytes).
+ return usage.ru_maxrss * 1024;
}
#else
U64 LLMemory::getCurrentRSS()
{
- return 0;
+ return 0;
}
#endif
@@ -302,53 +302,53 @@ U64 LLMemory::getCurrentRSS()
#include <map>
struct mem_info {
- std::map<void*, void*> memory_info;
- LLMutex mutex;
+ std::map<void*, void*> memory_info;
+ LLMutex mutex;
- static mem_info& get() {
- static mem_info instance;
- return instance;
- }
+ static mem_info& get() {
+ static mem_info instance;
+ return instance;
+ }
private:
- mem_info(){}
+ mem_info(){}
};
void* ll_aligned_malloc_fallback( size_t size, int align )
{
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
-
- unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize;
-
- void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
- if(NULL == p) {
- // call debugger
- __asm int 3;
- }
- DWORD old;
- BOOL Res = VirtualProtect((void*)((char*)p + for_alloc), sysinfo.dwPageSize, PAGE_NOACCESS, &old);
- if(FALSE == Res) {
- // call debugger
- __asm int 3;
- }
-
- void* ret = (void*)((char*)p + for_alloc-size);
-
- {
- LLMutexLock lock(&mem_info::get().mutex);
- mem_info::get().memory_info.insert(std::pair<void*, void*>(ret, p));
- }
-
-
- return ret;
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+
+ unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize;
+
+ void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
+ if(NULL == p) {
+ // call debugger
+ __asm int 3;
+ }
+ DWORD old;
+ BOOL Res = VirtualProtect((void*)((char*)p + for_alloc), sysinfo.dwPageSize, PAGE_NOACCESS, &old);
+ if(FALSE == Res) {
+ // call debugger
+ __asm int 3;
+ }
+
+ void* ret = (void*)((char*)p + for_alloc-size);
+
+ {
+ LLMutexLock lock(&mem_info::get().mutex);
+ mem_info::get().memory_info.insert(std::pair<void*, void*>(ret, p));
+ }
+
+
+ return ret;
}
void ll_aligned_free_fallback( void* ptr )
{
- LLMutexLock lock(&mem_info::get().mutex);
- VirtualFree(mem_info::get().memory_info.find(ptr)->second, 0, MEM_RELEASE);
- mem_info::get().memory_info.erase(ptr);
+ LLMutexLock lock(&mem_info::get().mutex);
+ VirtualFree(mem_info::get().memory_info.find(ptr)->second, 0, MEM_RELEASE);
+ mem_info::get().memory_info.erase(ptr);
}
#endif
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index ac6c969d70..313c380587 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -38,7 +38,7 @@ class LLMutex ;
#if LL_WINDOWS && LL_DEBUG
#define LL_CHECK_MEMORY llassert(_CrtCheckMemory());
#else
-#define LL_CHECK_MEMORY
+#define LL_CHECK_MEMORY
#endif
@@ -73,27 +73,27 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#include <xmmintrin.h>
-template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)
-{
- return reinterpret_cast<T*>(
- (uintptr_t(address) + 0xF) & ~0xF);
+template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)
+{
+ return reinterpret_cast<T*>(
+ (uintptr_t(address) + 0xF) & ~0xF);
}
-template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
-{
- return reinterpret_cast<T*>(
- (uintptr_t(address) + 0x3F) & ~0x3F);
+template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
+{
+ return reinterpret_cast<T*>(
+ (uintptr_t(address) + 0x3F) & ~0x3F);
}
#if LL_LINUX || LL_DARWIN
-#define LL_ALIGN_PREFIX(x)
-#define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x)))
+#define LL_ALIGN_PREFIX(x)
+#define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x)))
#elif LL_WINDOWS
-#define LL_ALIGN_PREFIX(x) __declspec(align(x))
-#define LL_ALIGN_POSTFIX(x)
+#define LL_ALIGN_PREFIX(x) __declspec(align(x))
+#define LL_ALIGN_POSTFIX(x)
#else
#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined"
@@ -126,22 +126,22 @@ public: \
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
- // for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
- // change preprocessor code to: #if 1 && defined(LL_WINDOWS)
+ // for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
+ // change preprocessor code to: #if 1 && defined(LL_WINDOWS)
#if 0 && defined(LL_WINDOWS)
- void* ll_aligned_malloc_fallback( size_t size, int align );
- void ll_aligned_free_fallback( void* ptr );
+ void* ll_aligned_malloc_fallback( size_t size, int align );
+ void ll_aligned_free_fallback( void* ptr );
//------------------------------------------------------------------------------------------------
#else
- inline void* ll_aligned_malloc_fallback( size_t size, int align )
- {
+ inline void* ll_aligned_malloc_fallback( size_t size, int align )
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
- #if defined(LL_WINDOWS)
+ #if defined(LL_WINDOWS)
void* ret = _aligned_malloc(size, align);
- #else
+ #else
char* aligned = NULL;
- void* mem = malloc( size + (align - 1) + sizeof(void*) );
+ void* mem = malloc( size + (align - 1) + sizeof(void*) );
if (mem)
{
aligned = ((char*)mem) + sizeof(void*);
@@ -149,25 +149,25 @@ public: \
((void**)aligned)[-1] = mem;
}
- void* ret = aligned;
- #endif
+ void* ret = aligned;
+ #endif
LL_PROFILE_ALLOC(ret, size);
return ret;
- }
+ }
- inline void ll_aligned_free_fallback( void* ptr )
- {
+ inline void ll_aligned_free_fallback( void* ptr )
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
LL_PROFILE_FREE(ptr);
- #if defined(LL_WINDOWS)
- _aligned_free(ptr);
- #else
- if (ptr)
- {
- free( ((void**)ptr)[-1] );
- }
- #endif
- }
+ #if defined(LL_WINDOWS)
+ _aligned_free(ptr);
+ #else
+ if (ptr)
+ {
+ free( ((void**)ptr)[-1] );
+ }
+ #endif
+ }
#endif
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
@@ -176,11 +176,11 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
#if defined(LL_WINDOWS)
- void* ret = _aligned_malloc(size, 16);
+ void* ret = _aligned_malloc(size, 16);
#elif defined(LL_DARWIN)
- void* ret = malloc(size); // default osx malloc is 16 byte aligned.
+ void* ret = malloc(size); // default osx malloc is 16 byte aligned.
#else
- void *ret;
+ void *ret;
if (0 != posix_memalign(&ret, 16, size))
return nullptr;
#endif
@@ -193,11 +193,11 @@ inline void ll_aligned_free_16(void *p)
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
LL_PROFILE_FREE(p);
#if defined(LL_WINDOWS)
- _aligned_free(p);
+ _aligned_free(p);
#elif defined(LL_DARWIN)
- return free(p);
+ return free(p);
#else
- free(p); // posix_memalign() is compatible with heap deallocator
+ free(p); // posix_memalign() is compatible with heap deallocator
#endif
}
@@ -206,21 +206,21 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
LL_PROFILE_FREE(ptr);
#if defined(LL_WINDOWS)
- void* ret = _aligned_realloc(ptr, size, 16);
+ void* ret = _aligned_realloc(ptr, size, 16);
#elif defined(LL_DARWIN)
- void* ret = realloc(ptr,size); // default osx malloc is 16 byte aligned.
+ void* ret = realloc(ptr,size); // default osx malloc is 16 byte aligned.
#else
- //FIXME: memcpy is SLOW
- void* ret = ll_aligned_malloc_16(size);
- if (ptr)
- {
- if (ret)
- {
- // Only copy the size of the smallest memory block to avoid memory corruption.
- memcpy(ret, ptr, llmin(old_size, size));
- }
- ll_aligned_free_16(ptr);
- }
+ //FIXME: memcpy is SLOW
+ void* ret = ll_aligned_malloc_16(size);
+ if (ptr)
+ {
+ if (ret)
+ {
+ // Only copy the size of the smallest memory block to avoid memory corruption.
+ memcpy(ret, ptr, llmin(old_size, size));
+ }
+ ll_aligned_free_16(ptr);
+ }
#endif
LL_PROFILE_ALLOC(ptr, size);
return ret;
@@ -230,11 +230,11 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
#if defined(LL_WINDOWS)
- void* ret = _aligned_malloc(size, 32);
+ void* ret = _aligned_malloc(size, 32);
#elif defined(LL_DARWIN)
- void* ret = ll_aligned_malloc_fallback( size, 32 );
+ void* ret = ll_aligned_malloc_fallback( size, 32 );
#else
- void *ret;
+ void *ret;
if (0 != posix_memalign(&ret, 32, size))
return nullptr;
#endif
@@ -247,11 +247,11 @@ inline void ll_aligned_free_32(void *p)
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
LL_PROFILE_FREE(p);
#if defined(LL_WINDOWS)
- _aligned_free(p);
+ _aligned_free(p);
#elif defined(LL_DARWIN)
- ll_aligned_free_fallback( p );
+ ll_aligned_free_fallback( p );
#else
- free(p); // posix_memalign() is compatible with heap deallocator
+ free(p); // posix_memalign() is compatible with heap deallocator
#endif
}
@@ -261,23 +261,23 @@ LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
void* ret;
- if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
- {
- ret = malloc(size);
+ if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
+ {
+ ret = malloc(size);
LL_PROFILE_ALLOC(ret, size);
- }
- else if (ALIGNMENT == 16)
- {
- ret = ll_aligned_malloc_16(size);
- }
- else if (ALIGNMENT == 32)
- {
- ret = ll_aligned_malloc_32(size);
- }
- else
- {
- ret = ll_aligned_malloc_fallback(size, ALIGNMENT);
- }
+ }
+ else if (ALIGNMENT == 16)
+ {
+ ret = ll_aligned_malloc_16(size);
+ }
+ else if (ALIGNMENT == 32)
+ {
+ ret = ll_aligned_malloc_32(size);
+ }
+ else
+ {
+ ret = ll_aligned_malloc_fallback(size, ALIGNMENT);
+ }
return ret;
}
@@ -285,96 +285,96 @@ template<size_t ALIGNMENT>
LL_FORCE_INLINE void ll_aligned_free(void* ptr)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
- if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
- {
+ if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
+ {
LL_PROFILE_FREE(ptr);
- free(ptr);
- }
- else if (ALIGNMENT == 16)
- {
- ll_aligned_free_16(ptr);
- }
- else if (ALIGNMENT == 32)
- {
- return ll_aligned_free_32(ptr);
- }
- else
- {
- return ll_aligned_free_fallback(ptr);
- }
+ free(ptr);
+ }
+ else if (ALIGNMENT == 16)
+ {
+ ll_aligned_free_16(ptr);
+ }
+ else if (ALIGNMENT == 32)
+ {
+ return ll_aligned_free_32(ptr);
+ }
+ else
+ {
+ return ll_aligned_free_fallback(ptr);
+ }
}
-// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
+// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
// Source and dest must be 16-byte aligned and size must be multiple of 16.
//
inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
- assert(src != NULL);
- assert(dst != NULL);
- assert(bytes > 0);
- assert((bytes % sizeof(F32))== 0);
- ll_assert_aligned(src,16);
- ll_assert_aligned(dst,16);
-
- assert((src < dst) ? ((src + bytes) <= dst) : ((dst + bytes) <= src));
- assert(bytes%16==0);
-
- char* end = dst + bytes;
-
- if (bytes > 64)
- {
-
- // Find start of 64b aligned area within block
- //
- void* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst);
-
- //at least 64 bytes before the end of the destination, switch to 16 byte copies
- void* end_64 = end-64;
-
- // Prefetch the head of the 64b area now
- //
- _mm_prefetch((char*)begin_64, _MM_HINT_NTA);
- _mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA);
- _mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA);
- _mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA);
-
- // Copy 16b chunks until we're 64b aligned
- //
- while (dst < begin_64)
- {
-
- _mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
- dst += 16;
- src += 16;
- }
-
- // Copy 64b chunks up to your tail
- //
- // might be good to shmoo the 512b prefetch offset
- // (characterize performance for various values)
- //
- while (dst < end_64)
- {
- _mm_prefetch((char*)src + 512, _MM_HINT_NTA);
- _mm_prefetch((char*)dst + 512, _MM_HINT_NTA);
- _mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
- _mm_store_ps((F32*)(dst + 16), _mm_load_ps((F32*)(src + 16)));
- _mm_store_ps((F32*)(dst + 32), _mm_load_ps((F32*)(src + 32)));
- _mm_store_ps((F32*)(dst + 48), _mm_load_ps((F32*)(src + 48)));
- dst += 64;
- src += 64;
- }
- }
-
- // Copy remainder 16b tail chunks (or ALL 16b chunks for sub-64b copies)
- //
- while (dst < end)
- {
- _mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
- dst += 16;
- src += 16;
- }
+ assert(src != NULL);
+ assert(dst != NULL);
+ assert(bytes > 0);
+ assert((bytes % sizeof(F32))== 0);
+ ll_assert_aligned(src,16);
+ ll_assert_aligned(dst,16);
+
+ assert((src < dst) ? ((src + bytes) <= dst) : ((dst + bytes) <= src));
+ assert(bytes%16==0);
+
+ char* end = dst + bytes;
+
+ if (bytes > 64)
+ {
+
+ // Find start of 64b aligned area within block
+ //
+ void* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst);
+
+ //at least 64 bytes before the end of the destination, switch to 16 byte copies
+ void* end_64 = end-64;
+
+ // Prefetch the head of the 64b area now
+ //
+ _mm_prefetch((char*)begin_64, _MM_HINT_NTA);
+ _mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA);
+ _mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA);
+ _mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA);
+
+ // Copy 16b chunks until we're 64b aligned
+ //
+ while (dst < begin_64)
+ {
+
+ _mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
+ dst += 16;
+ src += 16;
+ }
+
+ // Copy 64b chunks up to your tail
+ //
+ // might be good to shmoo the 512b prefetch offset
+ // (characterize performance for various values)
+ //
+ while (dst < end_64)
+ {
+ _mm_prefetch((char*)src + 512, _MM_HINT_NTA);
+ _mm_prefetch((char*)dst + 512, _MM_HINT_NTA);
+ _mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
+ _mm_store_ps((F32*)(dst + 16), _mm_load_ps((F32*)(src + 16)));
+ _mm_store_ps((F32*)(dst + 32), _mm_load_ps((F32*)(src + 32)));
+ _mm_store_ps((F32*)(dst + 48), _mm_load_ps((F32*)(src + 48)));
+ dst += 64;
+ src += 64;
+ }
+ }
+
+ // Copy remainder 16b tail chunks (or ALL 16b chunks for sub-64b copies)
+ //
+ while (dst < end)
+ {
+ _mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
+ dst += 16;
+ src += 16;
+ }
}
#ifndef __DEBUG_PRIVATE_MEM__
@@ -384,24 +384,24 @@ inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __
class LL_COMMON_API LLMemory
{
public:
- // Return the resident set size of the current process, in bytes.
- // Return value is zero if not known.
- static U64 getCurrentRSS();
- static void* tryToAlloc(void* address, U32 size);
- static void initMaxHeapSizeGB(F32Gigabytes max_heap_size);
- static void updateMemoryInfo() ;
- static void logMemoryInfo(BOOL update = FALSE);
-
- static U32Kilobytes getAvailableMemKB() ;
- static U32Kilobytes getMaxMemKB() ;
- static U32Kilobytes getAllocatedMemKB() ;
+ // Return the resident set size of the current process, in bytes.
+ // Return value is zero if not known.
+ static U64 getCurrentRSS();
+ static void* tryToAlloc(void* address, U32 size);
+ static void initMaxHeapSizeGB(F32Gigabytes max_heap_size);
+ static void updateMemoryInfo() ;
+ static void logMemoryInfo(BOOL update = FALSE);
+
+ static U32Kilobytes getAvailableMemKB() ;
+ static U32Kilobytes getMaxMemKB() ;
+ static U32Kilobytes getAllocatedMemKB() ;
private:
- static U32Kilobytes sAvailPhysicalMemInKB ;
- static U32Kilobytes sMaxPhysicalMemInKB ;
- static U32Kilobytes sAllocatedMemInKB;
- static U32Kilobytes sAllocatedPageSizeInKB ;
+ static U32Kilobytes sAvailPhysicalMemInKB ;
+ static U32Kilobytes sMaxPhysicalMemInKB ;
+ static U32Kilobytes sAllocatedMemInKB;
+ static U32Kilobytes sAllocatedPageSizeInKB ;
- static U32Kilobytes sMaxHeapSizeInKB;
+ static U32Kilobytes sMaxHeapSizeInKB;
};
// LLRefCount moved to llrefcount.h
diff --git a/indra/llcommon/llmemorystream.cpp b/indra/llcommon/llmemorystream.cpp
index 707ac8fd0f..b3acc8c7d3 100644
--- a/indra/llcommon/llmemorystream.cpp
+++ b/indra/llcommon/llmemorystream.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmemorystream.cpp
* @author Phoenix
* @date 2005-06-03
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&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$
*/
@@ -31,7 +31,7 @@
LLMemoryStreamBuf::LLMemoryStreamBuf(const U8* start, S32 length)
{
- reset(start, length);
+ reset(start, length);
}
LLMemoryStreamBuf::~LLMemoryStreamBuf()
@@ -40,26 +40,26 @@ LLMemoryStreamBuf::~LLMemoryStreamBuf()
void LLMemoryStreamBuf::reset(const U8* start, S32 length)
{
- setg((char*)start, (char*)start, (char*)start + length);
+ setg((char*)start, (char*)start, (char*)start + length);
}
int LLMemoryStreamBuf::underflow()
{
- //LL_DEBUGS() << "LLMemoryStreamBuf::underflow()" << LL_ENDL;
- if(gptr() < egptr())
- {
- return *gptr();
- }
- return EOF;
+ //LL_DEBUGS() << "LLMemoryStreamBuf::underflow()" << LL_ENDL;
+ if(gptr() < egptr())
+ {
+ return *gptr();
+ }
+ return EOF;
}
-/**
+/**
* @class LLMemoryStreamBuf
*/
LLMemoryStream::LLMemoryStream(const U8* start, S32 length) :
- std::istream(&mStreamBuf),
- mStreamBuf(start, length)
+ std::istream(&mStreamBuf),
+ mStreamBuf(start, length)
{
}
diff --git a/indra/llcommon/llmemorystream.h b/indra/llcommon/llmemorystream.h
index e28f012192..6024bc5d37 100644
--- a/indra/llcommon/llmemorystream.h
+++ b/indra/llcommon/llmemorystream.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmemorystream.h
* @author Phoenix
* @date 2005-06-03
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&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 @@
#ifndef LL_LLMEMORYSTREAM_H
#define LL_LLMEMORYSTREAM_H
-/**
+/**
* This is a simple but effective optimization when you want to treat
* a chunk of memory as an istream. I wrote this to avoid turing a
* buffer into a string, and then throwing the string into an
@@ -38,7 +38,7 @@
#include <iostream>
-/**
+/**
* @class LLMemoryStreamBuf
* @brief This implements a wrapper around a piece of memory for istreams
*
@@ -49,18 +49,18 @@
class LL_COMMON_API LLMemoryStreamBuf : public std::streambuf
{
public:
- LLMemoryStreamBuf(const U8* start, S32 length);
- ~LLMemoryStreamBuf();
+ LLMemoryStreamBuf(const U8* start, S32 length);
+ ~LLMemoryStreamBuf();
- void reset(const U8* start, S32 length);
+ void reset(const U8* start, S32 length);
protected:
- int underflow();
- //std::streamsize xsgetn(char* dest, std::streamsize n);
+ int underflow();
+ //std::streamsize xsgetn(char* dest, std::streamsize n);
};
-/**
+/**
* @class LLMemoryStream
* @brief This implements a wrapper around a piece of memory for istreams
*
@@ -71,11 +71,11 @@ protected:
class LL_COMMON_API LLMemoryStream : public std::istream
{
public:
- LLMemoryStream(const U8* start, S32 length);
- ~LLMemoryStream();
+ LLMemoryStream(const U8* start, S32 length);
+ ~LLMemoryStream();
protected:
- LLMemoryStreamBuf mStreamBuf;
+ LLMemoryStreamBuf mStreamBuf;
};
#endif // LL_LLMEMORYSTREAM_H
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index ab509b46eb..e05c2558f6 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmetricperformancetester.cpp
* @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes implementation
*
* $LicenseInfo:firstyear=2004&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,129 +39,129 @@
LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;
-/*static*/
-void LLMetricPerformanceTesterBasic::cleanupClass()
+/*static*/
+void LLMetricPerformanceTesterBasic::cleanupClass()
{
- for (name_tester_map_t::value_type& pair : sTesterMap)
- {
- delete pair.second;
- }
- sTesterMap.clear() ;
+ for (name_tester_map_t::value_type& pair : sTesterMap)
+ {
+ delete pair.second;
+ }
+ sTesterMap.clear() ;
}
-/*static*/
-BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester)
+/*static*/
+BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester)
{
- llassert_always(tester != NULL);
- std::string name = tester->getTesterName() ;
- if (getTester(name))
- {
- LL_ERRS() << "Tester name is already used by some other tester : " << name << LL_ENDL ;
- return FALSE;
- }
-
- sTesterMap.insert(std::make_pair(name, tester));
- return TRUE;
+ llassert_always(tester != NULL);
+ std::string name = tester->getTesterName() ;
+ if (getTester(name))
+ {
+ LL_ERRS() << "Tester name is already used by some other tester : " << name << LL_ENDL ;
+ return FALSE;
+ }
+
+ sTesterMap.insert(std::make_pair(name, tester));
+ return TRUE;
}
-/*static*/
+/*static*/
void LLMetricPerformanceTesterBasic::deleteTester(std::string name)
{
- name_tester_map_t::iterator tester = sTesterMap.find(name);
- if (tester != sTesterMap.end())
- {
- delete tester->second;
- sTesterMap.erase(tester);
- }
+ name_tester_map_t::iterator tester = sTesterMap.find(name);
+ if (tester != sTesterMap.end())
+ {
+ delete tester->second;
+ sTesterMap.erase(tester);
+ }
}
-/*static*/
-LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name)
+/*static*/
+LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name)
{
- // Check for the requested metric name
- name_tester_map_t::iterator found_it = sTesterMap.find(name) ;
- if (found_it != sTesterMap.end())
- {
- return found_it->second ;
- }
- return NULL ;
+ // Check for the requested metric name
+ name_tester_map_t::iterator found_it = sTesterMap.find(name) ;
+ if (found_it != sTesterMap.end())
+ {
+ return found_it->second ;
+ }
+ return NULL ;
}
-/*static*/
+/*static*/
// Return TRUE if this metric is requested or if the general default "catch all" metric is requested
BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
{
- return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME)));
+ return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME)));
}
-/*static*/
+/*static*/
LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& is)
{
- LLSD ret;
- LLSD cur;
-
- while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is))
- {
- for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
- {
- std::string label = iter->first;
-
- LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
- if(tester)
- {
- ret[label]["Name"] = iter->second["Name"] ;
-
- auto num_of_metrics = tester->getNumberOfMetrics() ;
- for(size_t index = 0 ; index < num_of_metrics ; index++)
- {
- ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
- }
- }
- }
- }
-
- return ret;
+ LLSD ret;
+ LLSD cur;
+
+ while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is))
+ {
+ for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
+ {
+ std::string label = iter->first;
+
+ LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
+ if(tester)
+ {
+ ret[label]["Name"] = iter->second["Name"] ;
+
+ auto num_of_metrics = tester->getNumberOfMetrics() ;
+ for(size_t index = 0 ; index < num_of_metrics ; index++)
+ {
+ ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
+ }
+ }
+ }
+ }
+
+ return ret;
}
-/*static*/
+/*static*/
void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
{
- if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
- {
- return ;
- }
-
- // Open baseline and current target, exit if one is inexistent
- llifstream base_is(baseline.c_str());
- llifstream target_is(target.c_str());
- if (!base_is.is_open() || !target_is.is_open())
- {
- LL_WARNS() << "'-analyzeperformance' error : baseline or current target file inexistent" << LL_ENDL;
- base_is.close();
- target_is.close();
- return;
- }
-
- //analyze baseline
- LLSD base = analyzeMetricPerformanceLog(base_is);
- base_is.close();
-
- //analyze current
- LLSD current = analyzeMetricPerformanceLog(target_is);
- target_is.close();
-
- //output comparision
- llofstream os(output.c_str());
-
- os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
- for (LLMetricPerformanceTesterBasic::name_tester_map_t::value_type& pair : LLMetricPerformanceTesterBasic::sTesterMap)
- {
- LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)pair.second);
- tester->analyzePerformance(&os, &base, &current) ;
- }
-
- os.flush();
- os.close();
+ if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
+ {
+ return ;
+ }
+
+ // Open baseline and current target, exit if one is inexistent
+ llifstream base_is(baseline.c_str());
+ llifstream target_is(target.c_str());
+ if (!base_is.is_open() || !target_is.is_open())
+ {
+ LL_WARNS() << "'-analyzeperformance' error : baseline or current target file inexistent" << LL_ENDL;
+ base_is.close();
+ target_is.close();
+ return;
+ }
+
+ //analyze baseline
+ LLSD base = analyzeMetricPerformanceLog(base_is);
+ base_is.close();
+
+ //analyze current
+ LLSD current = analyzeMetricPerformanceLog(target_is);
+ target_is.close();
+
+ //output comparision
+ llofstream os(output.c_str());
+
+ os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
+ for (LLMetricPerformanceTesterBasic::name_tester_map_t::value_type& pair : LLMetricPerformanceTesterBasic::sTesterMap)
+ {
+ LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)pair.second);
+ tester->analyzePerformance(&os, &base, &current) ;
+ }
+
+ os.flush();
+ os.close();
}
@@ -169,157 +169,157 @@ void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std
// LLMetricPerformanceTesterBasic : Tester instance methods
//----------------------------------------------------------------------------------------------
-LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name) :
- mName(name),
- mCount(0)
+LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name) :
+ mName(name),
+ mCount(0)
{
- if (mName == std::string())
- {
- LL_ERRS() << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << LL_ENDL ;
- }
+ if (mName == std::string())
+ {
+ LL_ERRS() << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << LL_ENDL ;
+ }
- mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
+ mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
}
-LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
+LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
{
}
-void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
+void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
{
- incrementCurrentCount() ;
+ incrementCurrentCount() ;
}
void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
{
- LLTrace::BlockTimer::pushLog(*sd);
+ LLTrace::BlockTimer::pushLog(*sd);
}
-void LLMetricPerformanceTesterBasic::outputTestResults()
+void LLMetricPerformanceTesterBasic::outputTestResults()
{
- LLSD sd;
+ LLSD sd;
- preOutputTestResults(&sd) ;
- outputTestRecord(&sd) ;
- postOutputTestResults(&sd) ;
+ preOutputTestResults(&sd) ;
+ outputTestRecord(&sd) ;
+ postOutputTestResults(&sd) ;
}
void LLMetricPerformanceTesterBasic::addMetric(std::string str)
{
- mMetricStrings.push_back(str) ;
+ mMetricStrings.push_back(str) ;
}
-/*virtual*/
-void LLMetricPerformanceTesterBasic::analyzePerformance(llofstream* os, LLSD* base, LLSD* current)
+/*virtual*/
+void LLMetricPerformanceTesterBasic::analyzePerformance(llofstream* os, LLSD* base, LLSD* current)
{
- resetCurrentCount() ;
-
- std::string current_label = getCurrentLabelName();
- BOOL in_base = (*base).has(current_label) ;
- BOOL in_current = (*current).has(current_label) ;
-
- while(in_base || in_current)
- {
- LLSD::String label = current_label ;
-
- if(in_base && in_current)
- {
- *os << llformat("%s\n", label.c_str()) ;
-
- for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
- {
- switch((*current)[label][ mMetricStrings[index] ].type())
- {
- case LLSD::TypeInteger:
- compareTestResults(os, mMetricStrings[index],
- (S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
- break ;
- case LLSD::TypeReal:
- compareTestResults(os, mMetricStrings[index],
- (F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
- break;
- default:
- LL_ERRS() << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << LL_ENDL ;
- }
- }
- }
-
- incrementCurrentCount();
- current_label = getCurrentLabelName();
- in_base = (*base).has(current_label) ;
- in_current = (*current).has(current_label) ;
- }
+ resetCurrentCount() ;
+
+ std::string current_label = getCurrentLabelName();
+ BOOL in_base = (*base).has(current_label) ;
+ BOOL in_current = (*current).has(current_label) ;
+
+ while(in_base || in_current)
+ {
+ LLSD::String label = current_label ;
+
+ if(in_base && in_current)
+ {
+ *os << llformat("%s\n", label.c_str()) ;
+
+ for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
+ {
+ switch((*current)[label][ mMetricStrings[index] ].type())
+ {
+ case LLSD::TypeInteger:
+ compareTestResults(os, mMetricStrings[index],
+ (S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
+ break ;
+ case LLSD::TypeReal:
+ compareTestResults(os, mMetricStrings[index],
+ (F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
+ break;
+ default:
+ LL_ERRS() << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << LL_ENDL ;
+ }
+ }
+ }
+
+ incrementCurrentCount();
+ current_label = getCurrentLabelName();
+ in_base = (*base).has(current_label) ;
+ in_current = (*current).has(current_label) ;
+ }
}
-/*virtual*/
-void LLMetricPerformanceTesterBasic::compareTestResults(llofstream* os, std::string metric_string, S32 v_base, S32 v_current)
+/*virtual*/
+void LLMetricPerformanceTesterBasic::compareTestResults(llofstream* os, std::string metric_string, S32 v_base, S32 v_current)
{
- *os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
- v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
+ *os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
+ v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
}
-/*virtual*/
-void LLMetricPerformanceTesterBasic::compareTestResults(llofstream* os, std::string metric_string, F32 v_base, F32 v_current)
+/*virtual*/
+void LLMetricPerformanceTesterBasic::compareTestResults(llofstream* os, std::string metric_string, F32 v_base, F32 v_current)
{
- *os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
- v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
+ *os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
+ v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
}
//----------------------------------------------------------------------------------------------
// LLMetricPerformanceTesterWithSession
//----------------------------------------------------------------------------------------------
-LLMetricPerformanceTesterWithSession::LLMetricPerformanceTesterWithSession(std::string name) :
- LLMetricPerformanceTesterBasic(name),
- mBaseSessionp(NULL),
- mCurrentSessionp(NULL)
+LLMetricPerformanceTesterWithSession::LLMetricPerformanceTesterWithSession(std::string name) :
+ LLMetricPerformanceTesterBasic(name),
+ mBaseSessionp(NULL),
+ mCurrentSessionp(NULL)
{
}
LLMetricPerformanceTesterWithSession::~LLMetricPerformanceTesterWithSession()
{
- if (mBaseSessionp)
- {
- delete mBaseSessionp ;
- mBaseSessionp = NULL ;
- }
- if (mCurrentSessionp)
- {
- delete mCurrentSessionp ;
- mCurrentSessionp = NULL ;
- }
+ if (mBaseSessionp)
+ {
+ delete mBaseSessionp ;
+ mBaseSessionp = NULL ;
+ }
+ if (mCurrentSessionp)
+ {
+ delete mCurrentSessionp ;
+ mCurrentSessionp = NULL ;
+ }
}
-/*virtual*/
-void LLMetricPerformanceTesterWithSession::analyzePerformance(llofstream* os, LLSD* base, LLSD* current)
+/*virtual*/
+void LLMetricPerformanceTesterWithSession::analyzePerformance(llofstream* os, LLSD* base, LLSD* current)
{
- // Load the base session
- resetCurrentCount() ;
- mBaseSessionp = loadTestSession(base) ;
-
- // Load the current session
- resetCurrentCount() ;
- mCurrentSessionp = loadTestSession(current) ;
-
- if (!mBaseSessionp || !mCurrentSessionp)
- {
- LL_ERRS() << "Error loading test sessions." << LL_ENDL ;
- }
-
- // Compare
- compareTestSessions(os) ;
-
- // Release memory
- if (mBaseSessionp)
- {
- delete mBaseSessionp ;
- mBaseSessionp = NULL ;
- }
- if (mCurrentSessionp)
- {
- delete mCurrentSessionp ;
- mCurrentSessionp = NULL ;
- }
+ // Load the base session
+ resetCurrentCount() ;
+ mBaseSessionp = loadTestSession(base) ;
+
+ // Load the current session
+ resetCurrentCount() ;
+ mCurrentSessionp = loadTestSession(current) ;
+
+ if (!mBaseSessionp || !mCurrentSessionp)
+ {
+ LL_ERRS() << "Error loading test sessions." << LL_ENDL ;
+ }
+
+ // Compare
+ compareTestSessions(os) ;
+
+ // Release memory
+ if (mBaseSessionp)
+ {
+ delete mBaseSessionp ;
+ mBaseSessionp = NULL ;
+ }
+ if (mCurrentSessionp)
+ {
+ delete mCurrentSessionp ;
+ mCurrentSessionp = NULL ;
+ }
}
@@ -327,7 +327,7 @@ void LLMetricPerformanceTesterWithSession::analyzePerformance(llofstream* os, LL
// LLTestSession
//----------------------------------------------------------------------------------------------
-LLMetricPerformanceTesterWithSession::LLTestSession::~LLTestSession()
+LLMetricPerformanceTesterWithSession::LLTestSession::~LLTestSession()
{
}
diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h
index 6561a78f03..15c564f2ca 100644
--- a/indra/llcommon/llmetricperformancetester.h
+++ b/indra/llcommon/llmetricperformancetester.h
@@ -1,31 +1,31 @@
-/**
- * @file llmetricperformancetester.h
+/**
+ * @file llmetricperformancetester.h
* @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes definition
*
* $LicenseInfo:firstyear=2004&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$
*/
-#ifndef LL_METRICPERFORMANCETESTER_H
-#define LL_METRICPERFORMANCETESTER_H
+#ifndef LL_METRICPERFORMANCETESTER_H
+#define LL_METRICPERFORMANCETESTER_H
char const* const DEFAULT_METRIC_NAME = "metric";
@@ -36,179 +36,179 @@ char const* const DEFAULT_METRIC_NAME = "metric";
class LL_COMMON_API LLMetricPerformanceTesterBasic
{
public:
- /**
- * @brief Creates a basic tester instance.
- * @param[in] name - Unique string identifying this tester instance.
- */
- LLMetricPerformanceTesterBasic(std::string name);
- virtual ~LLMetricPerformanceTesterBasic();
-
- /**
- * @return Returns true if the instance has been added to the tester map.
- * Need to be tested after creation of a tester instance so to know if the tester is correctly handled.
- * A tester might not be added to the map if another tester with the same name already exists.
- */
- BOOL isValid() const { return mValidInstance; }
-
- /**
- * @brief Write a set of test results to the log LLSD.
- */
- void outputTestResults() ;
-
- /**
- * @brief Compare the test results.
- * By default, compares the test results against the baseline one by one, item by item,
- * in the increasing order of the LLSD record counter, starting from the first one.
- */
- virtual void analyzePerformance(llofstream* os, LLSD* base, LLSD* current) ;
-
- static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
-
- /**
- * @return Returns the number of the test metrics in this tester instance.
- */
- auto getNumberOfMetrics() const { return mMetricStrings.size() ;}
- /**
- * @return Returns the metric name at index
- * @param[in] index - Index on the list of metrics managed by this tester instance.
- */
- std::string getMetricName(size_t index) const { return mMetricStrings[index] ;}
+ /**
+ * @brief Creates a basic tester instance.
+ * @param[in] name - Unique string identifying this tester instance.
+ */
+ LLMetricPerformanceTesterBasic(std::string name);
+ virtual ~LLMetricPerformanceTesterBasic();
+
+ /**
+ * @return Returns true if the instance has been added to the tester map.
+ * Need to be tested after creation of a tester instance so to know if the tester is correctly handled.
+ * A tester might not be added to the map if another tester with the same name already exists.
+ */
+ BOOL isValid() const { return mValidInstance; }
+
+ /**
+ * @brief Write a set of test results to the log LLSD.
+ */
+ void outputTestResults() ;
+
+ /**
+ * @brief Compare the test results.
+ * By default, compares the test results against the baseline one by one, item by item,
+ * in the increasing order of the LLSD record counter, starting from the first one.
+ */
+ virtual void analyzePerformance(llofstream* os, LLSD* base, LLSD* current) ;
+
+ static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
+
+ /**
+ * @return Returns the number of the test metrics in this tester instance.
+ */
+ auto getNumberOfMetrics() const { return mMetricStrings.size() ;}
+ /**
+ * @return Returns the metric name at index
+ * @param[in] index - Index on the list of metrics managed by this tester instance.
+ */
+ std::string getMetricName(size_t index) const { return mMetricStrings[index] ;}
protected:
- /**
- * @return Returns the name of this tester instance.
- */
- std::string getTesterName() const { return mName ;}
-
- /**
- * @brief Insert a new metric to be managed by this tester instance.
- * @param[in] str - Unique string identifying the new metric.
- */
- void addMetric(std::string str) ;
-
- /**
- * @brief Compare test results, provided in 2 flavors: compare integers and compare floats.
- * @param[out] os - Formatted output string holding the compared values.
- * @param[in] metric_string - Name of the metric.
- * @param[in] v_base - Base value of the metric.
- * @param[in] v_current - Current value of the metric.
- */
- virtual void compareTestResults(llofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
- virtual void compareTestResults(llofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
-
- /**
- * @brief Reset internal record count. Count starts with 1.
- */
- void resetCurrentCount() { mCount = 1; }
- /**
- * @brief Increment internal record count.
- */
- void incrementCurrentCount() { mCount++; }
- /**
- * @return Returns the label to be used for the current count. It's "TesterName"-"Count".
- */
- std::string getCurrentLabelName() const { return llformat("%s-%d", mName.c_str(), mCount) ;}
-
- /**
- * @brief Write a test record to the LLSD. Implementers need to overload this method.
- * @param[out] sd - The LLSD record to store metric data into.
- */
- virtual void outputTestRecord(LLSD* sd) = 0 ;
+ /**
+ * @return Returns the name of this tester instance.
+ */
+ std::string getTesterName() const { return mName ;}
+
+ /**
+ * @brief Insert a new metric to be managed by this tester instance.
+ * @param[in] str - Unique string identifying the new metric.
+ */
+ void addMetric(std::string str) ;
+
+ /**
+ * @brief Compare test results, provided in 2 flavors: compare integers and compare floats.
+ * @param[out] os - Formatted output string holding the compared values.
+ * @param[in] metric_string - Name of the metric.
+ * @param[in] v_base - Base value of the metric.
+ * @param[in] v_current - Current value of the metric.
+ */
+ virtual void compareTestResults(llofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
+ virtual void compareTestResults(llofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
+
+ /**
+ * @brief Reset internal record count. Count starts with 1.
+ */
+ void resetCurrentCount() { mCount = 1; }
+ /**
+ * @brief Increment internal record count.
+ */
+ void incrementCurrentCount() { mCount++; }
+ /**
+ * @return Returns the label to be used for the current count. It's "TesterName"-"Count".
+ */
+ std::string getCurrentLabelName() const { return llformat("%s-%d", mName.c_str(), mCount) ;}
+
+ /**
+ * @brief Write a test record to the LLSD. Implementers need to overload this method.
+ * @param[out] sd - The LLSD record to store metric data into.
+ */
+ virtual void outputTestRecord(LLSD* sd) = 0 ;
private:
- void preOutputTestResults(LLSD* sd) ;
- void postOutputTestResults(LLSD* sd) ;
- static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
+ void preOutputTestResults(LLSD* sd) ;
+ void postOutputTestResults(LLSD* sd) ;
+ static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
- std::string mName ; // Name of this tester instance
- S32 mCount ; // Current record count
- BOOL mValidInstance; // TRUE if the instance is managed by the map
- std::vector< std::string > mMetricStrings ; // Metrics strings
+ std::string mName ; // Name of this tester instance
+ S32 mCount ; // Current record count
+ BOOL mValidInstance; // TRUE if the instance is managed by the map
+ std::vector< std::string > mMetricStrings ; // Metrics strings
// Static members managing the collection of testers
-public:
- // Map of all the tester instances in use
- typedef std::map< std::string, LLMetricPerformanceTesterBasic* > name_tester_map_t;
- static name_tester_map_t sTesterMap ;
-
- /**
- * @return Returns a pointer to the tester
- * @param[in] name - Name of the tester instance queried.
- */
- static LLMetricPerformanceTesterBasic* getTester(std::string name) ;
-
- /**
- * @return Delete the named tester from the list
- * @param[in] name - Name of the tester instance to delete.
- */
- static void deleteTester(std::string name);
-
- /**
- * @return Returns TRUE if that metric *or* the default catch all metric has been requested to be logged
- * @param[in] name - Name of the tester queried.
- */
- static BOOL isMetricLogRequested(std::string name);
-
- /**
- * @return Returns TRUE if there's a tester defined, FALSE otherwise.
- */
- static BOOL hasMetricPerformanceTesters() { return !sTesterMap.empty() ;}
- /**
- * @brief Delete all testers and reset the tester map
- */
- static void cleanupClass() ;
+public:
+ // Map of all the tester instances in use
+ typedef std::map< std::string, LLMetricPerformanceTesterBasic* > name_tester_map_t;
+ static name_tester_map_t sTesterMap ;
+
+ /**
+ * @return Returns a pointer to the tester
+ * @param[in] name - Name of the tester instance queried.
+ */
+ static LLMetricPerformanceTesterBasic* getTester(std::string name) ;
+
+ /**
+ * @return Delete the named tester from the list
+ * @param[in] name - Name of the tester instance to delete.
+ */
+ static void deleteTester(std::string name);
+
+ /**
+ * @return Returns TRUE if that metric *or* the default catch all metric has been requested to be logged
+ * @param[in] name - Name of the tester queried.
+ */
+ static BOOL isMetricLogRequested(std::string name);
+
+ /**
+ * @return Returns TRUE if there's a tester defined, FALSE otherwise.
+ */
+ static BOOL hasMetricPerformanceTesters() { return !sTesterMap.empty() ;}
+ /**
+ * @brief Delete all testers and reset the tester map
+ */
+ static void cleanupClass() ;
private:
- // Add a tester to the map. Returns false if adding fails.
- static BOOL addTester(LLMetricPerformanceTesterBasic* tester) ;
+ // Add a tester to the map. Returns false if adding fails.
+ static BOOL addTester(LLMetricPerformanceTesterBasic* tester) ;
};
/**
* @class LLMetricPerformanceTesterWithSession
- * @brief Performance Metric Class with custom session
+ * @brief Performance Metric Class with custom session
*/
class LL_COMMON_API LLMetricPerformanceTesterWithSession : public LLMetricPerformanceTesterBasic
{
public:
- /**
- * @param[in] name - Unique string identifying this tester instance.
- */
- LLMetricPerformanceTesterWithSession(std::string name);
- virtual ~LLMetricPerformanceTesterWithSession();
-
- /**
- * @brief Compare the test results.
- * This will be loading the base and current sessions and compare them using the virtual
- * abstract methods loadTestSession() and compareTestSessions()
- */
- virtual void analyzePerformance(llofstream* os, LLSD* base, LLSD* current) ;
+ /**
+ * @param[in] name - Unique string identifying this tester instance.
+ */
+ LLMetricPerformanceTesterWithSession(std::string name);
+ virtual ~LLMetricPerformanceTesterWithSession();
+
+ /**
+ * @brief Compare the test results.
+ * This will be loading the base and current sessions and compare them using the virtual
+ * abstract methods loadTestSession() and compareTestSessions()
+ */
+ virtual void analyzePerformance(llofstream* os, LLSD* base, LLSD* current) ;
protected:
- /**
- * @class LLMetricPerformanceTesterWithSession::LLTestSession
- * @brief Defines an interface for the two abstract virtual functions loadTestSession() and compareTestSessions()
- */
- class LL_COMMON_API LLTestSession
- {
- public:
- virtual ~LLTestSession() ;
- };
-
- /**
- * @brief Convert an LLSD log into a test session.
- * @param[in] log - The LLSD record
- * @return Returns the record as a test session
- */
- virtual LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) = 0;
-
- /**
- * @brief Compare the base session and the target session. Assumes base and current sessions have been loaded.
- * @param[out] os - The comparison result as a standard stream
- */
- virtual void compareTestSessions(llofstream* os) = 0;
-
- LLTestSession* mBaseSessionp;
- LLTestSession* mCurrentSessionp;
+ /**
+ * @class LLMetricPerformanceTesterWithSession::LLTestSession
+ * @brief Defines an interface for the two abstract virtual functions loadTestSession() and compareTestSessions()
+ */
+ class LL_COMMON_API LLTestSession
+ {
+ public:
+ virtual ~LLTestSession() ;
+ };
+
+ /**
+ * @brief Convert an LLSD log into a test session.
+ * @param[in] log - The LLSD record
+ * @return Returns the record as a test session
+ */
+ virtual LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) = 0;
+
+ /**
+ * @brief Compare the base session and the target session. Assumes base and current sessions have been loaded.
+ * @param[out] os - The comparison result as a standard stream
+ */
+ virtual void compareTestSessions(llofstream* os) = 0;
+
+ LLTestSession* mBaseSessionp;
+ LLTestSession* mCurrentSessionp;
};
#endif
diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp
index d40afe5160..7c37b18bab 100644
--- a/indra/llcommon/llmetrics.cpp
+++ b/indra/llcommon/llmetrics.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmetrics.cpp
* @author Kelly
* @date 2007-05-25
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2007&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,128 +36,128 @@
class LLMetricsImpl
{
public:
- LLMetricsImpl() { }
- ~LLMetricsImpl();
-
- void recordEvent(const std::string& location, const std::string& mesg, bool success);
- void printTotals(LLSD metadata);
- void recordEventDetails(const std::string& location,
- const std::string& mesg,
- bool success,
- LLSD stats);
+ LLMetricsImpl() { }
+ ~LLMetricsImpl();
+
+ void recordEvent(const std::string& location, const std::string& mesg, bool success);
+ void printTotals(LLSD metadata);
+ void recordEventDetails(const std::string& location,
+ const std::string& mesg,
+ bool success,
+ LLSD stats);
private:
- LLFrameTimer mLastPrintTimer;
- LLSD mMetricsMap;
+ LLFrameTimer mLastPrintTimer;
+ LLSD mMetricsMap;
};
LLMetricsImpl::~LLMetricsImpl()
{
}
-void LLMetricsImpl::recordEventDetails(const std::string& location,
- const std::string& mesg,
- bool success,
- LLSD stats)
+void LLMetricsImpl::recordEventDetails(const std::string& location,
+ const std::string& mesg,
+ bool success,
+ LLSD stats)
{
- recordEvent(location,mesg,success);
+ recordEvent(location,mesg,success);
- LLSD metrics = LLSD::emptyMap();
- metrics["location"] = location;
- metrics["stats"] = stats;
-
- LL_INFOS() << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << LL_ENDL;
+ LLSD metrics = LLSD::emptyMap();
+ metrics["location"] = location;
+ metrics["stats"] = stats;
+
+ LL_INFOS() << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << LL_ENDL;
}
// Store this:
// [ {'location_1':{'mesg_1':{'success':i10, 'fail':i0},
-// 'mesg_2':{'success':i10, 'fail':i0}},
+// 'mesg_2':{'success':i10, 'fail':i0}},
// {'location_2',{'mesg_3':{'success':i10, 'fail':i0}} ]
void LLMetricsImpl::recordEvent(const std::string& location, const std::string& mesg, bool success)
{
- LLSD& stats = mMetricsMap[location][mesg];
- if (success)
- {
- stats["success"] = stats["success"].asInteger() + 1;
- }
- else
- {
- stats["fail"] = stats["fail"].asInteger() + 1;
- }
+ LLSD& stats = mMetricsMap[location][mesg];
+ if (success)
+ {
+ stats["success"] = stats["success"].asInteger() + 1;
+ }
+ else
+ {
+ stats["fail"] = stats["fail"].asInteger() + 1;
+ }
}
// Print this:
// { 'meta':
-// { 'elapsed_time':r3600.000 }
+// { 'elapsed_time':r3600.000 }
// 'stats':
-// [ {'location':'location_1', 'mesg':'mesg_1', 'success':i10, 'fail':i0},
-// {'location':'location_1', 'mesg':'mesg_2', 'success':i10, 'fail':i0},
-// {'location':'location_2', 'mesg':'mesg_3', 'success':i10, 'fail':i0} ] }
+// [ {'location':'location_1', 'mesg':'mesg_1', 'success':i10, 'fail':i0},
+// {'location':'location_1', 'mesg':'mesg_2', 'success':i10, 'fail':i0},
+// {'location':'location_2', 'mesg':'mesg_3', 'success':i10, 'fail':i0} ] }
void LLMetricsImpl::printTotals(LLSD metadata)
{
- F32 elapsed_time = mLastPrintTimer.getElapsedTimeAndResetF32();
- metadata["elapsed_time"] = elapsed_time;
-
- LLSD out_sd = LLSD::emptyMap();
- out_sd["meta"] = metadata;
-
- LLSD stats = LLSD::emptyArray();
-
- LLSD::map_const_iterator loc_it = mMetricsMap.beginMap();
- LLSD::map_const_iterator loc_end = mMetricsMap.endMap();
- for ( ; loc_it != loc_end; ++loc_it)
- {
- const std::string& location = (*loc_it).first;
-
- const LLSD& loc_map = (*loc_it).second;
- LLSD::map_const_iterator mesg_it = loc_map.beginMap();
- LLSD::map_const_iterator mesg_end = loc_map.endMap();
- for ( ; mesg_it != mesg_end; ++mesg_it)
- {
- const std::string& mesg = (*mesg_it).first;
- const LLSD& mesg_map = (*mesg_it).second;
-
- LLSD entry = LLSD::emptyMap();
- entry["location"] = location;
- entry["mesg"] = mesg;
- entry["success"] = mesg_map["success"];
- entry["fail"] = mesg_map["fail"];
-
- stats.append(entry);
- }
- }
-
- out_sd["stats"] = stats;
-
- LL_INFOS() << "LLMETRICS: AGGREGATE: " << LLSDOStreamer<LLSDNotationFormatter>(out_sd) << LL_ENDL;
+ F32 elapsed_time = mLastPrintTimer.getElapsedTimeAndResetF32();
+ metadata["elapsed_time"] = elapsed_time;
+
+ LLSD out_sd = LLSD::emptyMap();
+ out_sd["meta"] = metadata;
+
+ LLSD stats = LLSD::emptyArray();
+
+ LLSD::map_const_iterator loc_it = mMetricsMap.beginMap();
+ LLSD::map_const_iterator loc_end = mMetricsMap.endMap();
+ for ( ; loc_it != loc_end; ++loc_it)
+ {
+ const std::string& location = (*loc_it).first;
+
+ const LLSD& loc_map = (*loc_it).second;
+ LLSD::map_const_iterator mesg_it = loc_map.beginMap();
+ LLSD::map_const_iterator mesg_end = loc_map.endMap();
+ for ( ; mesg_it != mesg_end; ++mesg_it)
+ {
+ const std::string& mesg = (*mesg_it).first;
+ const LLSD& mesg_map = (*mesg_it).second;
+
+ LLSD entry = LLSD::emptyMap();
+ entry["location"] = location;
+ entry["mesg"] = mesg;
+ entry["success"] = mesg_map["success"];
+ entry["fail"] = mesg_map["fail"];
+
+ stats.append(entry);
+ }
+ }
+
+ out_sd["stats"] = stats;
+
+ LL_INFOS() << "LLMETRICS: AGGREGATE: " << LLSDOStreamer<LLSDNotationFormatter>(out_sd) << LL_ENDL;
}
LLMetrics::LLMetrics()
{
- mImpl = new LLMetricsImpl();
+ mImpl = new LLMetricsImpl();
}
LLMetrics::~LLMetrics()
{
- delete mImpl;
- mImpl = NULL;
+ delete mImpl;
+ mImpl = NULL;
}
void LLMetrics::recordEvent(const std::string& location, const std::string& mesg, bool success)
{
- if (mImpl) mImpl->recordEvent(location,mesg,success);
+ if (mImpl) mImpl->recordEvent(location,mesg,success);
}
void LLMetrics::printTotals(LLSD meta)
{
- if (mImpl) mImpl->printTotals(meta);
+ if (mImpl) mImpl->printTotals(meta);
}
-void LLMetrics::recordEventDetails(const std::string& location,
- const std::string& mesg,
- bool success,
- LLSD stats)
+void LLMetrics::recordEventDetails(const std::string& location,
+ const std::string& mesg,
+ bool success,
+ LLSD stats)
{
- if (mImpl) mImpl->recordEventDetails(location,mesg,success,stats);
+ if (mImpl) mImpl->recordEventDetails(location,mesg,success,stats);
}
diff --git a/indra/llcommon/llmetrics.h b/indra/llcommon/llmetrics.h
index 85a6986049..a6df49fc6a 100644
--- a/indra/llcommon/llmetrics.h
+++ b/indra/llcommon/llmetrics.h
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2007&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,25 +35,25 @@ class LLSD;
class LL_COMMON_API LLMetrics
{
public:
- LLMetrics();
- virtual ~LLMetrics();
+ LLMetrics();
+ virtual ~LLMetrics();
- // Adds this event to aggregate totals and records details to syslog (LL_INFOS())
- virtual void recordEventDetails(const std::string& location,
- const std::string& mesg,
- bool success,
- LLSD stats);
+ // Adds this event to aggregate totals and records details to syslog (LL_INFOS())
+ virtual void recordEventDetails(const std::string& location,
+ const std::string& mesg,
+ bool success,
+ LLSD stats);
- // Adds this event to aggregate totals
- virtual void recordEvent(const std::string& location, const std::string& mesg, bool success);
+ // Adds this event to aggregate totals
+ virtual void recordEvent(const std::string& location, const std::string& mesg, bool success);
- // Prints aggregate totals and resets the counts.
- virtual void printTotals(LLSD meta);
+ // Prints aggregate totals and resets the counts.
+ virtual void printTotals(LLSD meta);
private:
-
- LLMetricsImpl* mImpl;
+
+ LLMetricsImpl* mImpl;
};
#endif
diff --git a/indra/llcommon/llmortician.cpp b/indra/llcommon/llmortician.cpp
index b6ad40c2af..00d4a32553 100644
--- a/indra/llcommon/llmortician.cpp
+++ b/indra/llcommon/llmortician.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llmortician.cpp
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -32,9 +32,9 @@ std::list<LLMortician*> LLMortician::sGraveyard;
BOOL LLMortician::sDestroyImmediate = FALSE;
-LLMortician::~LLMortician()
+LLMortician::~LLMortician()
{
- sGraveyard.remove(this);
+ sGraveyard.remove(this);
}
size_t LLMortician::logClass(std::stringstream &str)
@@ -73,34 +73,34 @@ size_t LLMortician::logClass(std::stringstream &str)
return size;
}
-void LLMortician::updateClass()
+void LLMortician::updateClass()
{
- while (!sGraveyard.empty())
- {
- LLMortician* dead = sGraveyard.front();
- delete dead;
- }
+ while (!sGraveyard.empty())
+ {
+ LLMortician* dead = sGraveyard.front();
+ delete dead;
+ }
}
-void LLMortician::die()
+void LLMortician::die()
{
- // It is valid to call die() more than once on something that hasn't died yet
- if (sDestroyImmediate)
- {
- // *NOTE: This is a hack to ensure destruction order on shutdown (relative to non-mortician controlled classes).
- mIsDead = TRUE;
- delete this;
- return;
- }
- else if (!mIsDead)
- {
- mIsDead = TRUE;
- sGraveyard.push_back(this);
- }
+ // It is valid to call die() more than once on something that hasn't died yet
+ if (sDestroyImmediate)
+ {
+ // *NOTE: This is a hack to ensure destruction order on shutdown (relative to non-mortician controlled classes).
+ mIsDead = TRUE;
+ delete this;
+ return;
+ }
+ else if (!mIsDead)
+ {
+ mIsDead = TRUE;
+ sGraveyard.push_back(this);
+ }
}
// static
void LLMortician::setZealous(BOOL b)
{
- sDestroyImmediate = b;
+ sDestroyImmediate = b;
}
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index f92c5a11db..6dca4da0c9 100644
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmortician.h
* @brief Base class for delayed deletions.
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -30,26 +30,26 @@
#include "stdtypes.h"
#include <list>
-class LL_COMMON_API LLMortician
+class LL_COMMON_API LLMortician
{
public:
- LLMortician() { mIsDead = FALSE; }
- static auto graveyardCount() { return sGraveyard.size(); };
- static size_t logClass(std::stringstream &str);
- static void updateClass();
- virtual ~LLMortician();
- void die();
- BOOL isDead() { return mIsDead; }
+ LLMortician() { mIsDead = FALSE; }
+ static auto graveyardCount() { return sGraveyard.size(); };
+ static size_t logClass(std::stringstream &str);
+ static void updateClass();
+ virtual ~LLMortician();
+ void die();
+ BOOL isDead() { return mIsDead; }
- // sets destroy immediate true
- static void setZealous(BOOL b);
+ // sets destroy immediate true
+ static void setZealous(BOOL b);
private:
- static BOOL sDestroyImmediate;
+ static BOOL sDestroyImmediate;
- BOOL mIsDead;
+ BOOL mIsDead;
- static std::list<LLMortician*> sGraveyard;
+ static std::list<LLMortician*> sGraveyard;
};
#endif
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index 0273dd5970..db14abb1fe 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llmutex.cpp
*
* $LicenseInfo:firstyear=2004&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,100 +45,100 @@ LLMutex::~LLMutex()
void LLMutex::lock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- if(isSelfLocked())
- { //redundant lock
- mCount++;
- return;
- }
-
- mMutex.lock();
-
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return;
+ }
+
+ mMutex.lock();
+
#if MUTEX_DEBUG
- // Have to have the lock before we can access the debug info
- auto id = LLThread::currentID();
- if (mIsLocked[id] != FALSE)
- LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
- mIsLocked[id] = TRUE;
+ // Have to have the lock before we can access the debug info
+ auto id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = TRUE;
#endif
- mLockingThread = LLThread::currentID();
+ mLockingThread = LLThread::currentID();
}
void LLMutex::unlock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- if (mCount > 0)
- { //not the root unlock
- mCount--;
- return;
- }
-
+ if (mCount > 0)
+ { //not the root unlock
+ mCount--;
+ return;
+ }
+
#if MUTEX_DEBUG
- // Access the debug info while we have the lock
- auto id = LLThread::currentID();
- if (mIsLocked[id] != TRUE)
- LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;
- mIsLocked[id] = FALSE;
+ // Access the debug info while we have the lock
+ auto id = LLThread::currentID();
+ if (mIsLocked[id] != TRUE)
+ LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = FALSE;
#endif
- mLockingThread = LLThread::id_t();
- mMutex.unlock();
+ mLockingThread = LLThread::id_t();
+ mMutex.unlock();
}
bool LLMutex::isLocked()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- if (!mMutex.try_lock())
- {
- return true;
- }
- else
- {
- mMutex.unlock();
- return false;
- }
+ if (!mMutex.try_lock())
+ {
+ return true;
+ }
+ else
+ {
+ mMutex.unlock();
+ return false;
+ }
}
bool LLMutex::isSelfLocked()
{
- return mLockingThread == LLThread::currentID();
+ return mLockingThread == LLThread::currentID();
}
LLThread::id_t LLMutex::lockingThread() const
{
- return mLockingThread;
+ return mLockingThread;
}
bool LLMutex::trylock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- if(isSelfLocked())
- { //redundant lock
- mCount++;
- return true;
- }
-
- if (!mMutex.try_lock())
- {
- return false;
- }
-
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return true;
+ }
+
+ if (!mMutex.try_lock())
+ {
+ return false;
+ }
+
#if MUTEX_DEBUG
- // Have to have the lock before we can access the debug info
- auto id = LLThread::currentID();
- if (mIsLocked[id] != FALSE)
- LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
- mIsLocked[id] = TRUE;
+ // Have to have the lock before we can access the debug info
+ auto id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = TRUE;
#endif
- mLockingThread = LLThread::currentID();
- return true;
+ mLockingThread = LLThread::currentID();
+ return true;
}
//============================================================================
LLCondition::LLCondition() :
- LLMutex()
+ LLMutex()
{
}
@@ -151,20 +151,20 @@ LLCondition::~LLCondition()
void LLCondition::wait()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- std::unique_lock< std::mutex > lock(mMutex);
- mCond.wait(lock);
+ std::unique_lock< std::mutex > lock(mMutex);
+ mCond.wait(lock);
}
void LLCondition::signal()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- mCond.notify_one();
+ mCond.notify_one();
}
void LLCondition::broadcast()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- mCond.notify_all();
+ mCond.notify_all();
}
@@ -210,30 +210,30 @@ LLMutexTrylock::~LLMutexTrylock()
LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- if(mutex)
- {
- mutex->lock();
- mLocked = true;
- }
- else
- {
- mLocked = false;
- }
+ if(mutex)
+ {
+ mutex->lock();
+ mLocked = true;
+ }
+ else
+ {
+ mLocked = false;
+ }
}
LLScopedLock::~LLScopedLock()
{
- unlock();
+ unlock();
}
void LLScopedLock::unlock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
- if(mLocked)
- {
- mMutex->unlock();
- mLocked = false;
- }
+ if(mLocked)
+ {
+ mMutex->unlock();
+ mLocked = false;
+ }
}
//============================================================================
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index 0d70da6178..9a888f1220 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmutex.h
* @brief Base classes for mutex and condition handling.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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$
*/
@@ -46,23 +46,23 @@
class LL_COMMON_API LLMutex
{
public:
- LLMutex();
- virtual ~LLMutex();
-
- void lock(); // blocks
- bool trylock(); // non-blocking, returns true if lock held.
- void unlock(); // undefined behavior when called on mutex not being held
- bool isLocked(); // non-blocking, but does do a lock/unlock so not free
- bool isSelfLocked(); //return true if locked in a same thread
- LLThread::id_t lockingThread() const; //get ID of locking thread
+ LLMutex();
+ virtual ~LLMutex();
+
+ void lock(); // blocks
+ bool trylock(); // non-blocking, returns true if lock held.
+ void unlock(); // undefined behavior when called on mutex not being held
+ bool isLocked(); // non-blocking, but does do a lock/unlock so not free
+ bool isSelfLocked(); //return true if locked in a same thread
+ LLThread::id_t lockingThread() const; //get ID of locking thread
protected:
- std::mutex mMutex;
- mutable U32 mCount;
- mutable LLThread::id_t mLockingThread;
-
+ std::mutex mMutex;
+ mutable U32 mCount;
+ mutable LLThread::id_t mLockingThread;
+
#if MUTEX_DEBUG
- std::unordered_map<LLThread::id_t, BOOL> mIsLocked;
+ std::unordered_map<LLThread::id_t, BOOL> mIsLocked;
#endif
};
@@ -70,34 +70,34 @@ protected:
class LL_COMMON_API LLCondition : public LLMutex
{
public:
- LLCondition();
- ~LLCondition();
-
- void wait(); // blocks
- void signal();
- void broadcast();
-
+ LLCondition();
+ ~LLCondition();
+
+ void wait(); // blocks
+ void signal();
+ void broadcast();
+
protected:
- std::condition_variable mCond;
+ std::condition_variable mCond;
};
class LLMutexLock
{
public:
- LLMutexLock(LLMutex* mutex)
- {
- mMutex = mutex;
-
- if(mMutex)
- mMutex->lock();
- }
- ~LLMutexLock()
- {
- if(mMutex)
- mMutex->unlock();
- }
+ LLMutexLock(LLMutex* mutex)
+ {
+ mMutex = mutex;
+
+ if(mMutex)
+ mMutex->lock();
+ }
+ ~LLMutexLock()
+ {
+ if(mMutex)
+ mMutex->unlock();
+ }
private:
- LLMutex* mMutex;
+ LLMutex* mMutex;
};
//============================================================================
@@ -113,18 +113,18 @@ private:
class LLMutexTrylock
{
public:
- LLMutexTrylock(LLMutex* mutex);
- LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms = 10);
- ~LLMutexTrylock();
-
- bool isLocked() const
- {
- return mLocked;
- }
-
+ LLMutexTrylock(LLMutex* mutex);
+ LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms = 10);
+ ~LLMutexTrylock();
+
+ bool isLocked() const
+ {
+ return mLocked;
+ }
+
private:
- LLMutex* mMutex;
- bool mLocked;
+ LLMutex* mMutex;
+ bool mLocked;
};
/**
diff --git a/indra/llcommon/llnametable.h b/indra/llcommon/llnametable.h
index 2c8e71263e..b3a9df8fc3 100644
--- a/indra/llcommon/llnametable.h
+++ b/indra/llcommon/llnametable.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llnametable.h
* @brief LLNameTable class is a table to associate pointers with string names
*
* $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$
*/
@@ -35,69 +35,69 @@ template <class DATA>
class LLNameTable
{
public:
- LLNameTable()
- : mNameMap()
- {
- }
+ LLNameTable()
+ : mNameMap()
+ {
+ }
- ~LLNameTable()
- {
- }
+ ~LLNameTable()
+ {
+ }
- void addEntry(const std::string& name, DATA data)
- {
- addEntry(name.c_str(), data);
- }
+ void addEntry(const std::string& name, DATA data)
+ {
+ addEntry(name.c_str(), data);
+ }
- void addEntry(const char *name, DATA data)
- {
- char *tablename = gStringTable.addString(name);
- mNameMap[tablename] = data;
- }
+ void addEntry(const char *name, DATA data)
+ {
+ char *tablename = gStringTable.addString(name);
+ mNameMap[tablename] = data;
+ }
- BOOL checkName(const std::string& name) const
- {
- return checkName(name.c_str());
- }
+ BOOL checkName(const std::string& name) const
+ {
+ return checkName(name.c_str());
+ }
- // "logically const" even though it modifies the global nametable
- BOOL checkName(const char *name) const
- {
- char *tablename = gStringTable.addString(name);
- return mNameMap.count(tablename) ? TRUE : FALSE;
- }
+ // "logically const" even though it modifies the global nametable
+ BOOL checkName(const char *name) const
+ {
+ char *tablename = gStringTable.addString(name);
+ return mNameMap.count(tablename) ? TRUE : FALSE;
+ }
- DATA resolveName(const std::string& name) const
- {
- return resolveName(name.c_str());
- }
+ DATA resolveName(const std::string& name) const
+ {
+ return resolveName(name.c_str());
+ }
- // "logically const" even though it modifies the global nametable
- DATA resolveName(const char *name) const
- {
- char *tablename = gStringTable.addString(name);
- const_iter_t iter = mNameMap.find(tablename);
- if (iter != mNameMap.end())
- return iter->second;
- else
- return 0;
- }
+ // "logically const" even though it modifies the global nametable
+ DATA resolveName(const char *name) const
+ {
+ char *tablename = gStringTable.addString(name);
+ const_iter_t iter = mNameMap.find(tablename);
+ if (iter != mNameMap.end())
+ return iter->second;
+ else
+ return 0;
+ }
- // O(N)! (currently only used in one place... (newsim/llstate.cpp))
- const char *resolveData(const DATA &data) const
- {
- for (const name_map_t::value_type& pair : mNameMap)
- {
- if (pair.second == data)
- return pair.first;
- }
- return NULL;
- }
+ // O(N)! (currently only used in one place... (newsim/llstate.cpp))
+ const char *resolveData(const DATA &data) const
+ {
+ for (const name_map_t::value_type& pair : mNameMap)
+ {
+ if (pair.second == data)
+ return pair.first;
+ }
+ return NULL;
+ }
- typedef std::map<const char *, DATA> name_map_t;
- typedef typename std::map<const char *,DATA>::iterator iter_t;
- typedef typename std::map<const char *,DATA>::const_iterator const_iter_t;
- name_map_t mNameMap;
+ typedef std::map<const char *, DATA> name_map_t;
+ typedef typename std::map<const char *,DATA>::iterator iter_t;
+ typedef typename std::map<const char *,DATA>::const_iterator const_iter_t;
+ name_map_t mNameMap;
};
#endif
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 64aceddf32..f5916f9d58 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -1,32 +1,32 @@
-/**
+/**
* @file llpointer.h
* @brief A reference-counted pointer for objects derived from LLRefCount
*
* $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$
*/
#ifndef LLPOINTER_H
#define LLPOINTER_H
-#include "llerror.h" // *TODO: consider eliminating this
+#include "llerror.h" // *TODO: consider eliminating this
#include "llmutex.h"
//----------------------------------------------------------------------------
@@ -46,299 +46,299 @@
template <class Type> class LLPointer
{
public:
- LLPointer() :
- mPointer(NULL)
- {
- }
-
- LLPointer(Type* ptr) :
- mPointer(ptr)
- {
- ref();
- }
-
- LLPointer(const LLPointer<Type>& ptr) :
- mPointer(ptr.mPointer)
- {
- ref();
- }
-
- // Support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLPointer(const LLPointer<Subclass>& ptr) :
- mPointer(ptr.get())
- {
- ref();
- }
-
- ~LLPointer()
- {
- unref();
- }
-
- Type* get() const { return mPointer; }
- const Type* operator->() const { return mPointer; }
- Type* operator->() { return mPointer; }
- const Type& operator*() const { return *mPointer; }
- Type& operator*() { return *mPointer; }
-
- operator BOOL() const { return (mPointer != NULL); }
- operator bool() const { return (mPointer != NULL); }
- bool operator!() const { return (mPointer == NULL); }
- bool isNull() const { return (mPointer == NULL); }
- bool notNull() const { return (mPointer != NULL); }
-
- operator Type*() const { return mPointer; }
- bool operator !=(Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
-
- LLPointer<Type>& operator =(Type* ptr)
- {
- assign(ptr);
- return *this;
- }
-
- LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
- {
- assign(ptr);
- return *this;
- }
-
- // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
- {
- assign(ptr.get());
- return *this;
- }
-
- // Just exchange the pointers, which will not change the reference counts.
- static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
- {
- Type* temp = a.mPointer;
- a.mPointer = b.mPointer;
- b.mPointer = temp;
- }
+ LLPointer() :
+ mPointer(NULL)
+ {
+ }
+
+ LLPointer(Type* ptr) :
+ mPointer(ptr)
+ {
+ ref();
+ }
+
+ LLPointer(const LLPointer<Type>& ptr) :
+ mPointer(ptr.mPointer)
+ {
+ ref();
+ }
+
+ // Support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLPointer(const LLPointer<Subclass>& ptr) :
+ mPointer(ptr.get())
+ {
+ ref();
+ }
+
+ ~LLPointer()
+ {
+ unref();
+ }
+
+ Type* get() const { return mPointer; }
+ const Type* operator->() const { return mPointer; }
+ Type* operator->() { return mPointer; }
+ const Type& operator*() const { return *mPointer; }
+ Type& operator*() { return *mPointer; }
+
+ operator BOOL() const { return (mPointer != NULL); }
+ operator bool() const { return (mPointer != NULL); }
+ bool operator!() const { return (mPointer == NULL); }
+ bool isNull() const { return (mPointer == NULL); }
+ bool notNull() const { return (mPointer != NULL); }
+
+ operator Type*() const { return mPointer; }
+ bool operator !=(Type* ptr) const { return (mPointer != ptr); }
+ bool operator ==(Type* ptr) const { return (mPointer == ptr); }
+ bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+
+ LLPointer<Type>& operator =(Type* ptr)
+ {
+ assign(ptr);
+ return *this;
+ }
+
+ LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
+ {
+ assign(ptr);
+ return *this;
+ }
+
+ // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
+ {
+ assign(ptr.get());
+ return *this;
+ }
+
+ // Just exchange the pointers, which will not change the reference counts.
+ static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
+ {
+ Type* temp = a.mPointer;
+ a.mPointer = b.mPointer;
+ b.mPointer = temp;
+ }
protected:
#ifdef LL_LIBRARY_INCLUDE
- void ref();
- void unref();
+ void ref();
+ void unref();
#else
- void ref()
- {
- if (mPointer)
- {
- mPointer->ref();
- }
- }
-
- void unref()
- {
- if (mPointer)
- {
- Type *temp = mPointer;
- mPointer = NULL;
- temp->unref();
- if (mPointer != NULL)
- {
- LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
- unref();
- }
- }
- }
+ void ref()
+ {
+ if (mPointer)
+ {
+ mPointer->ref();
+ }
+ }
+
+ void unref()
+ {
+ if (mPointer)
+ {
+ Type *temp = mPointer;
+ mPointer = NULL;
+ temp->unref();
+ if (mPointer != NULL)
+ {
+ LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+ unref();
+ }
+ }
+ }
#endif // LL_LIBRARY_INCLUDE
- void assign(const LLPointer<Type>& ptr)
- {
- if (mPointer != ptr.mPointer)
- {
- unref();
- mPointer = ptr.mPointer;
- ref();
- }
- }
+ void assign(const LLPointer<Type>& ptr)
+ {
+ if (mPointer != ptr.mPointer)
+ {
+ unref();
+ mPointer = ptr.mPointer;
+ ref();
+ }
+ }
protected:
- Type* mPointer;
+ Type* mPointer;
};
template <class Type> class LLConstPointer
{
public:
- LLConstPointer() :
- mPointer(NULL)
- {
- }
-
- LLConstPointer(const Type* ptr) :
- mPointer(ptr)
- {
- ref();
- }
-
- LLConstPointer(const LLConstPointer<Type>& ptr) :
- mPointer(ptr.mPointer)
- {
- ref();
- }
-
- // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLConstPointer(const LLConstPointer<Subclass>& ptr) :
- mPointer(ptr.get())
- {
- ref();
- }
-
- ~LLConstPointer()
- {
- unref();
- }
-
- const Type* get() const { return mPointer; }
- const Type* operator->() const { return mPointer; }
- const Type& operator*() const { return *mPointer; }
-
- operator BOOL() const { return (mPointer != NULL); }
- operator bool() const { return (mPointer != NULL); }
- bool operator!() const { return (mPointer == NULL); }
- bool isNull() const { return (mPointer == NULL); }
- bool notNull() const { return (mPointer != NULL); }
-
- operator const Type*() const { return mPointer; }
- bool operator !=(const Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(const Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
-
- LLConstPointer<Type>& operator =(const Type* ptr)
- {
- if( mPointer != ptr )
- {
- unref();
- mPointer = ptr;
- ref();
- }
-
- return *this;
- }
-
- LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)
- {
- if( mPointer != ptr.mPointer )
- {
- unref();
- mPointer = ptr.mPointer;
- ref();
- }
- return *this;
- }
-
- // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)
- {
- if( mPointer != ptr.get() )
- {
- unref();
- mPointer = ptr.get();
- ref();
- }
- return *this;
- }
-
- // Just exchange the pointers, which will not change the reference counts.
- static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
- {
- const Type* temp = a.mPointer;
- a.mPointer = b.mPointer;
- b.mPointer = temp;
- }
+ LLConstPointer() :
+ mPointer(NULL)
+ {
+ }
+
+ LLConstPointer(const Type* ptr) :
+ mPointer(ptr)
+ {
+ ref();
+ }
+
+ LLConstPointer(const LLConstPointer<Type>& ptr) :
+ mPointer(ptr.mPointer)
+ {
+ ref();
+ }
+
+ // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLConstPointer(const LLConstPointer<Subclass>& ptr) :
+ mPointer(ptr.get())
+ {
+ ref();
+ }
+
+ ~LLConstPointer()
+ {
+ unref();
+ }
+
+ const Type* get() const { return mPointer; }
+ const Type* operator->() const { return mPointer; }
+ const Type& operator*() const { return *mPointer; }
+
+ operator BOOL() const { return (mPointer != NULL); }
+ operator bool() const { return (mPointer != NULL); }
+ bool operator!() const { return (mPointer == NULL); }
+ bool isNull() const { return (mPointer == NULL); }
+ bool notNull() const { return (mPointer != NULL); }
+
+ operator const Type*() const { return mPointer; }
+ bool operator !=(const Type* ptr) const { return (mPointer != ptr); }
+ bool operator ==(const Type* ptr) const { return (mPointer == ptr); }
+ bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+
+ LLConstPointer<Type>& operator =(const Type* ptr)
+ {
+ if( mPointer != ptr )
+ {
+ unref();
+ mPointer = ptr;
+ ref();
+ }
+
+ return *this;
+ }
+
+ LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)
+ {
+ if( mPointer != ptr.mPointer )
+ {
+ unref();
+ mPointer = ptr.mPointer;
+ ref();
+ }
+ return *this;
+ }
+
+ // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)
+ {
+ if( mPointer != ptr.get() )
+ {
+ unref();
+ mPointer = ptr.get();
+ ref();
+ }
+ return *this;
+ }
+
+ // Just exchange the pointers, which will not change the reference counts.
+ static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
+ {
+ const Type* temp = a.mPointer;
+ a.mPointer = b.mPointer;
+ b.mPointer = temp;
+ }
protected:
#ifdef LL_LIBRARY_INCLUDE
- void ref();
- void unref();
+ void ref();
+ void unref();
#else // LL_LIBRARY_INCLUDE
- void ref()
- {
- if (mPointer)
- {
- mPointer->ref();
- }
- }
-
- void unref()
- {
- if (mPointer)
- {
- const Type *temp = mPointer;
- mPointer = NULL;
- temp->unref();
- if (mPointer != NULL)
- {
- LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
- unref();
- }
- }
- }
+ void ref()
+ {
+ if (mPointer)
+ {
+ mPointer->ref();
+ }
+ }
+
+ void unref()
+ {
+ if (mPointer)
+ {
+ const Type *temp = mPointer;
+ mPointer = NULL;
+ temp->unref();
+ if (mPointer != NULL)
+ {
+ LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+ unref();
+ }
+ }
+ }
#endif // LL_LIBRARY_INCLUDE
protected:
- const Type* mPointer;
+ const Type* mPointer;
};
template<typename Type>
class LLCopyOnWritePointer : public LLPointer<Type>
{
public:
- typedef LLCopyOnWritePointer<Type> self_t;
- typedef LLPointer<Type> pointer_t;
-
- LLCopyOnWritePointer()
- : mStayUnique(false)
- {}
-
- LLCopyOnWritePointer(Type* ptr)
- : LLPointer<Type>(ptr),
- mStayUnique(false)
- {}
-
- LLCopyOnWritePointer(LLPointer<Type>& ptr)
- : LLPointer<Type>(ptr),
- mStayUnique(false)
- {
- if (ptr.mForceUnique)
- {
- makeUnique();
- }
- }
-
- Type* write()
- {
- makeUnique();
- return pointer_t::mPointer;
- }
-
- void makeUnique()
- {
- if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1)
- {
- *(pointer_t* )(this) = new Type(*pointer_t::mPointer);
- }
- }
-
- const Type* operator->() const { return pointer_t::mPointer; }
- const Type& operator*() const { return *pointer_t::mPointer; }
-
- void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; }
+ typedef LLCopyOnWritePointer<Type> self_t;
+ typedef LLPointer<Type> pointer_t;
+
+ LLCopyOnWritePointer()
+ : mStayUnique(false)
+ {}
+
+ LLCopyOnWritePointer(Type* ptr)
+ : LLPointer<Type>(ptr),
+ mStayUnique(false)
+ {}
+
+ LLCopyOnWritePointer(LLPointer<Type>& ptr)
+ : LLPointer<Type>(ptr),
+ mStayUnique(false)
+ {
+ if (ptr.mForceUnique)
+ {
+ makeUnique();
+ }
+ }
+
+ Type* write()
+ {
+ makeUnique();
+ return pointer_t::mPointer;
+ }
+
+ void makeUnique()
+ {
+ if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1)
+ {
+ *(pointer_t* )(this) = new Type(*pointer_t::mPointer);
+ }
+ }
+
+ const Type* operator->() const { return pointer_t::mPointer; }
+ const Type& operator*() const { return *pointer_t::mPointer; }
+
+ void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; }
private:
- bool mStayUnique;
+ bool mStayUnique;
};
diff --git a/indra/llcommon/llpredicate.cpp b/indra/llcommon/llpredicate.cpp
index 1278948e24..fe80b77b63 100644
--- a/indra/llcommon/llpredicate.cpp
+++ b/indra/llcommon/llpredicate.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpredicate.cpp
* @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions
*
* $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$
*/
@@ -29,13 +29,13 @@
namespace LLPredicate
{
- const U32 cPredicateFlagsFromEnum[5] =
- {
- 0xAAAAaaaa, // 10101010101010101010101010101010
- 0xCCCCcccc, // 11001100110011001100110011001100
- 0xF0F0F0F0, // 11110000111100001111000011110000
- 0xFF00FF00, // 11111111000000001111111100000000
- 0xFFFF0000 // 11111111111111110000000000000000
- };
+ const U32 cPredicateFlagsFromEnum[5] =
+ {
+ 0xAAAAaaaa, // 10101010101010101010101010101010
+ 0xCCCCcccc, // 11001100110011001100110011001100
+ 0xF0F0F0F0, // 11110000111100001111000011110000
+ 0xFF00FF00, // 11111111000000001111111100000000
+ 0xFFFF0000 // 11111111111111110000000000000000
+ };
}
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index e6c56a5711..7c6874d279 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpredicate.h
* @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions
*
* $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$
*/
@@ -31,179 +31,179 @@
namespace LLPredicate
{
- template<typename ENUM> class Rule;
-
- extern const U32 cPredicateFlagsFromEnum[5];
-
- template<typename ENUM>
- class Value
- {
- public:
- typedef U32 predicate_flag_t;
- static const S32 cMaxEnum = 5;
-
- Value(ENUM e, bool predicate_value = true)
- : mPredicateFlags(predicate_value ? cPredicateFlagsFromEnum[e] : ~cPredicateFlagsFromEnum[e])
- {
- llassert(0 <= e && e < cMaxEnum);
- }
-
- Value()
- : mPredicateFlags(0xFFFFffff)
- {}
-
- Value operator!() const
- {
- Value new_value;
- new_value.mPredicateFlags = ~mPredicateFlags;
- return new_value;
- }
-
- Value operator &&(const Value other) const
- {
- Value new_value;
- new_value.mPredicateFlags = mPredicateFlags & other.mPredicateFlags;
- return new_value;
- }
-
- Value operator ||(const Value other) const
- {
- Value new_value;
- new_value.mPredicateFlags = mPredicateFlags | other.mPredicateFlags;
- return new_value;
- }
-
- void set(ENUM e, bool value = true)
- {
- llassert(0 <= e && e < cMaxEnum);
- predicate_flag_t flags_to_modify;
- predicate_flag_t mask = cPredicateFlagsFromEnum[e];
- if (value)
- { // add predicate "e" to flags that don't contain it already
- flags_to_modify = (mPredicateFlags & ~mask);
- // clear flags not containing e
- mPredicateFlags &= mask;
- // add back flags shifted to contain e
- mPredicateFlags |= flags_to_modify << (0x1 << e);
- }
- else
- { // remove predicate "e" from flags that contain it
- flags_to_modify = (mPredicateFlags & mask);
- // clear flags containing e
- mPredicateFlags &= ~mask;
- // add back flags shifted to not contain e
- mPredicateFlags |= flags_to_modify >> (0x1 << e);
- }
- }
-
- void forget(ENUM e)
- {
- set(e, true);
- U32 flags_with_predicate = mPredicateFlags;
- set(e, false);
- // ambiguous value is result of adding and removing predicate at the same time!
- mPredicateFlags |= flags_with_predicate;
- }
-
- bool allSet() const
- {
- return mPredicateFlags == ~0;
- }
-
- bool noneSet() const
- {
- return mPredicateFlags == 0;
- }
-
- bool someSet() const
- {
- return mPredicateFlags != 0;
- }
-
- private:
- predicate_flag_t mPredicateFlags;
- };
-
- template<typename ENUM>
- class Rule
- {
- public:
- Rule(ENUM value)
- : mRule(value)
- {}
-
- Rule(const Value<ENUM> other)
- : mRule(other)
- {}
-
- Rule()
- {}
-
- void require(ENUM e, bool match)
- {
- mRule.set(e, match);
- }
-
- void allow(ENUM e)
- {
- mRule.forget(e);
- }
-
- bool check(const Value<ENUM> value) const
- {
- return (mRule && value).someSet();
- }
-
- bool requires(const Value<ENUM> value) const
- {
- return (mRule && value).someSet() && (!mRule && value).noneSet();
- }
-
- bool isAmbivalent(const Value<ENUM> value) const
- {
- return (mRule && value).someSet() && (!mRule && value).someSet();
- }
-
- bool acceptsAll() const
- {
- return mRule.allSet();
- }
-
- bool acceptsNone() const
- {
- return mRule.noneSet();
- }
-
- Rule operator!() const
- {
- Rule new_rule;
- new_rule.mRule = !mRule;
- return new_rule;
- }
-
- Rule operator &&(const Rule other) const
- {
- Rule new_rule;
- new_rule.mRule = mRule && other.mRule;
- return new_rule;
- }
-
- Rule operator ||(const Rule other) const
- {
- Rule new_rule;
- new_rule.mRule = mRule || other.mRule;
- return new_rule;
- }
-
- private:
- Value<ENUM> mRule;
- };
+ template<typename ENUM> class Rule;
+
+ extern const U32 cPredicateFlagsFromEnum[5];
+
+ template<typename ENUM>
+ class Value
+ {
+ public:
+ typedef U32 predicate_flag_t;
+ static const S32 cMaxEnum = 5;
+
+ Value(ENUM e, bool predicate_value = true)
+ : mPredicateFlags(predicate_value ? cPredicateFlagsFromEnum[e] : ~cPredicateFlagsFromEnum[e])
+ {
+ llassert(0 <= e && e < cMaxEnum);
+ }
+
+ Value()
+ : mPredicateFlags(0xFFFFffff)
+ {}
+
+ Value operator!() const
+ {
+ Value new_value;
+ new_value.mPredicateFlags = ~mPredicateFlags;
+ return new_value;
+ }
+
+ Value operator &&(const Value other) const
+ {
+ Value new_value;
+ new_value.mPredicateFlags = mPredicateFlags & other.mPredicateFlags;
+ return new_value;
+ }
+
+ Value operator ||(const Value other) const
+ {
+ Value new_value;
+ new_value.mPredicateFlags = mPredicateFlags | other.mPredicateFlags;
+ return new_value;
+ }
+
+ void set(ENUM e, bool value = true)
+ {
+ llassert(0 <= e && e < cMaxEnum);
+ predicate_flag_t flags_to_modify;
+ predicate_flag_t mask = cPredicateFlagsFromEnum[e];
+ if (value)
+ { // add predicate "e" to flags that don't contain it already
+ flags_to_modify = (mPredicateFlags & ~mask);
+ // clear flags not containing e
+ mPredicateFlags &= mask;
+ // add back flags shifted to contain e
+ mPredicateFlags |= flags_to_modify << (0x1 << e);
+ }
+ else
+ { // remove predicate "e" from flags that contain it
+ flags_to_modify = (mPredicateFlags & mask);
+ // clear flags containing e
+ mPredicateFlags &= ~mask;
+ // add back flags shifted to not contain e
+ mPredicateFlags |= flags_to_modify >> (0x1 << e);
+ }
+ }
+
+ void forget(ENUM e)
+ {
+ set(e, true);
+ U32 flags_with_predicate = mPredicateFlags;
+ set(e, false);
+ // ambiguous value is result of adding and removing predicate at the same time!
+ mPredicateFlags |= flags_with_predicate;
+ }
+
+ bool allSet() const
+ {
+ return mPredicateFlags == ~0;
+ }
+
+ bool noneSet() const
+ {
+ return mPredicateFlags == 0;
+ }
+
+ bool someSet() const
+ {
+ return mPredicateFlags != 0;
+ }
+
+ private:
+ predicate_flag_t mPredicateFlags;
+ };
+
+ template<typename ENUM>
+ class Rule
+ {
+ public:
+ Rule(ENUM value)
+ : mRule(value)
+ {}
+
+ Rule(const Value<ENUM> other)
+ : mRule(other)
+ {}
+
+ Rule()
+ {}
+
+ void require(ENUM e, bool match)
+ {
+ mRule.set(e, match);
+ }
+
+ void allow(ENUM e)
+ {
+ mRule.forget(e);
+ }
+
+ bool check(const Value<ENUM> value) const
+ {
+ return (mRule && value).someSet();
+ }
+
+ bool requires(const Value<ENUM> value) const
+ {
+ return (mRule && value).someSet() && (!mRule && value).noneSet();
+ }
+
+ bool isAmbivalent(const Value<ENUM> value) const
+ {
+ return (mRule && value).someSet() && (!mRule && value).someSet();
+ }
+
+ bool acceptsAll() const
+ {
+ return mRule.allSet();
+ }
+
+ bool acceptsNone() const
+ {
+ return mRule.noneSet();
+ }
+
+ Rule operator!() const
+ {
+ Rule new_rule;
+ new_rule.mRule = !mRule;
+ return new_rule;
+ }
+
+ Rule operator &&(const Rule other) const
+ {
+ Rule new_rule;
+ new_rule.mRule = mRule && other.mRule;
+ return new_rule;
+ }
+
+ Rule operator ||(const Rule other) const
+ {
+ Rule new_rule;
+ new_rule.mRule = mRule || other.mRule;
+ return new_rule;
+ }
+
+ private:
+ Value<ENUM> mRule;
+ };
}
template<typename ENUM>
LLPredicate::Value<ENUM> ll_make_predicate(ENUM e, bool predicate_value = true)
{
- return LLPredicate::Value<ENUM>(e, predicate_value);
+ return LLPredicate::Value<ENUM>(e, predicate_value);
}
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index dc586b0008..a54408a852 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpreprocessor.h
* @brief This file should be included in all Linden Lab files and
* should only contain special preprocessor directives
@@ -6,21 +6,21 @@
* $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$
*/
@@ -32,7 +32,7 @@
#ifdef LL_LINUX
#define __ENABLE_WSTRING
#include <endian.h>
-#endif // LL_LINUX
+#endif // LL_LINUX
#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)))
#define LL_LITTLE_ENDIAN 1
@@ -64,31 +64,31 @@
// Figure out differences between compilers
#if defined(__GNUC__)
- #define GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
- #ifndef LL_GNUC
- #define LL_GNUC 1
- #endif
+ #define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+ #ifndef LL_GNUC
+ #define LL_GNUC 1
+ #endif
#elif defined(__MSVC_VER__) || defined(_MSC_VER)
- #ifndef LL_MSVC
- #define LL_MSVC 1
- #endif
- #if _MSC_VER < 1400
- #define LL_MSVC7 //Visual C++ 2003 or earlier
- #endif
+ #ifndef LL_MSVC
+ #define LL_MSVC 1
+ #endif
+ #if _MSC_VER < 1400
+ #define LL_MSVC7 //Visual C++ 2003 or earlier
+ #endif
#endif
// Deal with minor differences on Unixy OSes.
#if LL_DARWIN || LL_LINUX
- // Different name, same functionality.
- #define stricmp strcasecmp
- #define strnicmp strncasecmp
+ // Different name, same functionality.
+ #define stricmp strcasecmp
+ #define strnicmp strncasecmp
- // Not sure why this is different, but...
- #ifndef MAX_PATH
- #define MAX_PATH PATH_MAX
- #endif // not MAX_PATH
+ // Not sure why this is different, but...
+ #ifndef MAX_PATH
+ #define MAX_PATH PATH_MAX
+ #endif // not MAX_PATH
#endif
@@ -117,33 +117,33 @@
#ifndef XML_STATIC
#define XML_STATIC
#endif
-#endif // LL_WINDOWS
+#endif // LL_WINDOWS
// Deal with VC6 problems
#if LL_MSVC
-#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4.
-#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
-#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
-//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4.
-#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function
-#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
-#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
-#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
-#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
-//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
+#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4.
+#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
+#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
+//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4.
+#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function
+#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
+#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
+#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
+#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
+//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
#if ADDRESS_SIZE == 64
// That one is all over the place for x64 builds.
#pragma warning( disable : 4267 ) // 'var' : conversion from 'size_t' to 'type', possible loss of data)
#endif
-#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
-#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
-#pragma warning( disable : 4996 ) // warning: deprecated
+#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
+#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
+#pragma warning( disable : 4996 ) // warning: deprecated
// Linker optimization with "extern template" generates these warnings
-#pragma warning( disable : 4231 ) // nonstandard extension used : 'extern' before template explicit instantiation
+#pragma warning( disable : 4231 ) // nonstandard extension used : 'extern' before template explicit instantiation
#pragma warning( disable : 4506 ) // no definition for inline function
// level 4 warnings that we need to disable:
@@ -156,9 +156,9 @@
#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
-#pragma warning (disable : 4018) // '<' : signed/unsigned mismatch
+#pragma warning (disable : 4018) // '<' : signed/unsigned mismatch
-#endif // LL_MSVC
+#endif // LL_MSVC
#if LL_WINDOWS
#define LL_DLLEXPORT __declspec(dllexport)
@@ -232,4 +232,4 @@
#define LL_PRETTY_FUNCTION __PRETTY_FUNCTION__
#endif
-#endif // not LL_LINDEN_PREPROCESSOR_H
+#endif // not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llpriqueuemap.h b/indra/llcommon/llpriqueuemap.h
index 030e2e0f21..79934d094b 100644
--- a/indra/llcommon/llpriqueuemap.h
+++ b/indra/llcommon/llpriqueuemap.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpriqueuemap.h
* @brief Priority queue implementation
*
* $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$
*/
@@ -39,107 +39,107 @@ template <class DATA>
class LLPQMKey
{
public:
- LLPQMKey(const F32 priority, DATA data) : mPriority(priority), mData(data)
- {
- }
-
- bool operator<(const LLPQMKey &b) const
- {
- if (mPriority > b.mPriority)
- {
- return TRUE;
- }
- if (mPriority < b.mPriority)
- {
- return FALSE;
- }
- if (mData > b.mData)
- {
- return TRUE;
- }
- return FALSE;
- }
-
- F32 mPriority;
- DATA mData;
+ LLPQMKey(const F32 priority, DATA data) : mPriority(priority), mData(data)
+ {
+ }
+
+ bool operator<(const LLPQMKey &b) const
+ {
+ if (mPriority > b.mPriority)
+ {
+ return TRUE;
+ }
+ if (mPriority < b.mPriority)
+ {
+ return FALSE;
+ }
+ if (mData > b.mData)
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ F32 mPriority;
+ DATA mData;
};
template <class DATA_TYPE>
class LLPriQueueMap
{
public:
- typedef typename std::map<LLPQMKey<DATA_TYPE>, DATA_TYPE>::iterator pqm_iter;
- typedef std::pair<LLPQMKey<DATA_TYPE>, DATA_TYPE> pqm_pair;
- typedef void (*set_pri_fn)(DATA_TYPE &data, const F32 priority);
- typedef F32 (*get_pri_fn)(DATA_TYPE &data);
+ typedef typename std::map<LLPQMKey<DATA_TYPE>, DATA_TYPE>::iterator pqm_iter;
+ typedef std::pair<LLPQMKey<DATA_TYPE>, DATA_TYPE> pqm_pair;
+ typedef void (*set_pri_fn)(DATA_TYPE &data, const F32 priority);
+ typedef F32 (*get_pri_fn)(DATA_TYPE &data);
- LLPriQueueMap(set_pri_fn set_pri, get_pri_fn get_pri) : mSetPriority(set_pri), mGetPriority(get_pri)
- {
- }
+ LLPriQueueMap(set_pri_fn set_pri, get_pri_fn get_pri) : mSetPriority(set_pri), mGetPriority(get_pri)
+ {
+ }
- void push(const F32 priority, DATA_TYPE data)
- {
+ void push(const F32 priority, DATA_TYPE data)
+ {
#ifdef _DEBUG
- pqm_iter iter = mMap.find(LLPQMKey<DATA_TYPE>(priority, data));
- if (iter != mMap.end())
- {
- LL_ERRS() << "Pushing already existing data onto queue!" << LL_ENDL;
- }
+ pqm_iter iter = mMap.find(LLPQMKey<DATA_TYPE>(priority, data));
+ if (iter != mMap.end())
+ {
+ LL_ERRS() << "Pushing already existing data onto queue!" << LL_ENDL;
+ }
#endif
- mMap.insert(pqm_pair(LLPQMKey<DATA_TYPE>(priority, data), data));
- }
-
- BOOL pop(DATA_TYPE *datap)
- {
- pqm_iter iter;
- iter = mMap.begin();
- if (iter == mMap.end())
- {
- return FALSE;
- }
- *datap = (*(iter)).second;
- mMap.erase(iter);
-
- return TRUE;
- }
-
- void reprioritize(const F32 new_priority, DATA_TYPE data)
- {
- pqm_iter iter;
- F32 cur_priority = mGetPriority(data);
- LLPQMKey<DATA_TYPE> cur_key(cur_priority, data);
- iter = mMap.find(cur_key);
- if (iter == mMap.end())
- {
- LL_WARNS() << "Data not on priority queue!" << LL_ENDL;
- // OK, try iterating through all of the data and seeing if we just screwed up the priority
- // somehow.
- for (pqm_pair pair : mMap)
- {
- if (pair.second == data)
- {
- LL_ERRS() << "Data on priority queue but priority not matched!" << LL_ENDL;
- }
- }
- return;
- }
-
- mMap.erase(iter);
- mSetPriority(data, new_priority);
- push(new_priority, data);
- }
-
- S32 getLength() const
- {
- return (S32)mMap.size();
- }
-
- // Hack: public for use by the transfer manager, ugh.
- std::map<LLPQMKey<DATA_TYPE>, DATA_TYPE> mMap;
+ mMap.insert(pqm_pair(LLPQMKey<DATA_TYPE>(priority, data), data));
+ }
+
+ BOOL pop(DATA_TYPE *datap)
+ {
+ pqm_iter iter;
+ iter = mMap.begin();
+ if (iter == mMap.end())
+ {
+ return FALSE;
+ }
+ *datap = (*(iter)).second;
+ mMap.erase(iter);
+
+ return TRUE;
+ }
+
+ void reprioritize(const F32 new_priority, DATA_TYPE data)
+ {
+ pqm_iter iter;
+ F32 cur_priority = mGetPriority(data);
+ LLPQMKey<DATA_TYPE> cur_key(cur_priority, data);
+ iter = mMap.find(cur_key);
+ if (iter == mMap.end())
+ {
+ LL_WARNS() << "Data not on priority queue!" << LL_ENDL;
+ // OK, try iterating through all of the data and seeing if we just screwed up the priority
+ // somehow.
+ for (pqm_pair pair : mMap)
+ {
+ if (pair.second == data)
+ {
+ LL_ERRS() << "Data on priority queue but priority not matched!" << LL_ENDL;
+ }
+ }
+ return;
+ }
+
+ mMap.erase(iter);
+ mSetPriority(data, new_priority);
+ push(new_priority, data);
+ }
+
+ S32 getLength() const
+ {
+ return (S32)mMap.size();
+ }
+
+ // Hack: public for use by the transfer manager, ugh.
+ std::map<LLPQMKey<DATA_TYPE>, DATA_TYPE> mMap;
protected:
- void (*mSetPriority)(DATA_TYPE &data, const F32 priority);
- F32 (*mGetPriority)(DATA_TYPE &data);
+ void (*mSetPriority)(DATA_TYPE &data, const F32 priority);
+ F32 (*mGetPriority)(DATA_TYPE &data);
};
#endif // LL_LLPRIQUEUEMAP_H
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 0d6a147da3..2208b33b94 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llprocess.cpp
* @brief Utility class for launching, terminating, and tracking the state of processes.
*
* $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$
*/
@@ -57,9 +57,9 @@ static std::string getDesc(const LLProcess::Params& params);
static std::string whichfile(LLProcess::FILESLOT index)
{
- if (index < LL_ARRAY_SIZE(whichfile_))
- return whichfile_[index];
- return STRINGIZE("file slot " << index);
+ if (index < LL_ARRAY_SIZE(whichfile_))
+ return whichfile_[index];
+ return STRINGIZE("file slot " << index);
}
/**
@@ -69,64 +69,64 @@ static std::string whichfile(LLProcess::FILESLOT index)
*/
class LLProcessListener
{
- LOG_CLASS(LLProcessListener);
+ LOG_CLASS(LLProcessListener);
public:
- LLProcessListener():
- mCount(0)
- {}
-
- void addPoll(const LLProcess&)
- {
- // Unconditionally increment mCount. If it was zero before
- // incrementing, listen on "mainloop".
- if (mCount++ == 0)
- {
- LL_DEBUGS("LLProcess") << "listening on \"mainloop\"" << LL_ENDL;
- mConnection = LLEventPumps::instance().obtain("mainloop")
- .listen("LLProcessListener", boost::bind(&LLProcessListener::tick, this, _1));
- }
- }
-
- void dropPoll(const LLProcess&)
- {
- // Unconditionally decrement mCount. If it's zero after decrementing,
- // stop listening on "mainloop".
- if (--mCount == 0)
- {
- LL_DEBUGS("LLProcess") << "disconnecting from \"mainloop\"" << LL_ENDL;
- mConnection.disconnect();
- }
- }
+ LLProcessListener():
+ mCount(0)
+ {}
+
+ void addPoll(const LLProcess&)
+ {
+ // Unconditionally increment mCount. If it was zero before
+ // incrementing, listen on "mainloop".
+ if (mCount++ == 0)
+ {
+ LL_DEBUGS("LLProcess") << "listening on \"mainloop\"" << LL_ENDL;
+ mConnection = LLEventPumps::instance().obtain("mainloop")
+ .listen("LLProcessListener", boost::bind(&LLProcessListener::tick, this, _1));
+ }
+ }
+
+ void dropPoll(const LLProcess&)
+ {
+ // Unconditionally decrement mCount. If it's zero after decrementing,
+ // stop listening on "mainloop".
+ if (--mCount == 0)
+ {
+ LL_DEBUGS("LLProcess") << "disconnecting from \"mainloop\"" << LL_ENDL;
+ mConnection.disconnect();
+ }
+ }
private:
- /// called once per frame by the "mainloop" LLEventPump
- bool tick(const LLSD&)
- {
- // Tell APR to sense whether each registered LLProcess is still
- // running and call handle_status() appropriately. We should be able
- // to get the same info from an apr_proc_wait(APR_NOWAIT) call; but at
- // least in APR 1.4.2, testing suggests that even with APR_NOWAIT,
- // apr_proc_wait() blocks the caller. We can't have that in the
- // viewer. Hence the callback rigmarole. (Once we update APR, it's
- // probably worth testing again.) Also -- although there's an
- // apr_proc_other_child_refresh() call, i.e. get that information for
- // one specific child, it accepts an 'apr_other_child_rec_t*' that's
- // mentioned NOWHERE else in the documentation or header files! I
- // would use the specific call in LLProcess::getStatus() if I knew
- // how. As it is, each call to apr_proc_other_child_refresh_all() will
- // call callbacks for ALL still-running child processes. That's why we
- // centralize such calls, using "mainloop" to ensure it happens once
- // per frame, and refcounting running LLProcess objects to remain
- // registered only while needed.
- LL_DEBUGS("LLProcess") << "calling apr_proc_other_child_refresh_all()" << LL_ENDL;
- apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
- return false;
- }
-
- /// If this object is destroyed before mCount goes to zero, stop
- /// listening on "mainloop" anyway.
- LLTempBoundListener mConnection;
- unsigned mCount;
+ /// called once per frame by the "mainloop" LLEventPump
+ bool tick(const LLSD&)
+ {
+ // Tell APR to sense whether each registered LLProcess is still
+ // running and call handle_status() appropriately. We should be able
+ // to get the same info from an apr_proc_wait(APR_NOWAIT) call; but at
+ // least in APR 1.4.2, testing suggests that even with APR_NOWAIT,
+ // apr_proc_wait() blocks the caller. We can't have that in the
+ // viewer. Hence the callback rigmarole. (Once we update APR, it's
+ // probably worth testing again.) Also -- although there's an
+ // apr_proc_other_child_refresh() call, i.e. get that information for
+ // one specific child, it accepts an 'apr_other_child_rec_t*' that's
+ // mentioned NOWHERE else in the documentation or header files! I
+ // would use the specific call in LLProcess::getStatus() if I knew
+ // how. As it is, each call to apr_proc_other_child_refresh_all() will
+ // call callbacks for ALL still-running child processes. That's why we
+ // centralize such calls, using "mainloop" to ensure it happens once
+ // per frame, and refcounting running LLProcess objects to remain
+ // registered only while needed.
+ LL_DEBUGS("LLProcess") << "calling apr_proc_other_child_refresh_all()" << LL_ENDL;
+ apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING);
+ return false;
+ }
+
+ /// If this object is destroyed before mCount goes to zero, stop
+ /// listening on "mainloop" anyway.
+ LLTempBoundListener mConnection;
+ unsigned mCount;
};
static LLProcessListener sProcessListener;
@@ -135,141 +135,141 @@ static LLProcessListener sProcessListener;
*****************************************************************************/
LLProcess::BasePipe::~BasePipe() {}
const LLProcess::BasePipe::size_type
- // use funky syntax to call max() to avoid blighted max() macros
- LLProcess::BasePipe::npos((std::numeric_limits<LLProcess::BasePipe::size_type>::max)());
+ // use funky syntax to call max() to avoid blighted max() macros
+ LLProcess::BasePipe::npos((std::numeric_limits<LLProcess::BasePipe::size_type>::max)());
class WritePipeImpl: public LLProcess::WritePipe
{
- LOG_CLASS(WritePipeImpl);
+ LOG_CLASS(WritePipeImpl);
public:
- WritePipeImpl(const std::string& desc, apr_file_t* pipe):
- mDesc(desc),
- mPipe(pipe),
- // Essential to initialize our std::ostream with our special streambuf!
- mStream(&mStreambuf)
- {
- mConnection = LLEventPumps::instance().obtain("mainloop")
- .listen(LLEventPump::inventName("WritePipe"),
- boost::bind(&WritePipeImpl::tick, this, _1));
+ WritePipeImpl(const std::string& desc, apr_file_t* pipe):
+ mDesc(desc),
+ mPipe(pipe),
+ // Essential to initialize our std::ostream with our special streambuf!
+ mStream(&mStreambuf)
+ {
+ mConnection = LLEventPumps::instance().obtain("mainloop")
+ .listen(LLEventPump::inventName("WritePipe"),
+ boost::bind(&WritePipeImpl::tick, this, _1));
#if ! LL_WINDOWS
- // We can't count on every child process reading everything we try to
- // write to it. And if the child terminates with WritePipe data still
- // pending, unless we explicitly suppress it, Posix will hit us with
- // SIGPIPE. That would terminate the viewer, boom. "Ignoring" it means
- // APR gets the correct errno, passes it back to us, we log it, etc.
- signal(SIGPIPE, SIG_IGN);
+ // We can't count on every child process reading everything we try to
+ // write to it. And if the child terminates with WritePipe data still
+ // pending, unless we explicitly suppress it, Posix will hit us with
+ // SIGPIPE. That would terminate the viewer, boom. "Ignoring" it means
+ // APR gets the correct errno, passes it back to us, we log it, etc.
+ signal(SIGPIPE, SIG_IGN);
#endif
- }
-
- virtual std::ostream& get_ostream() { return mStream; }
- virtual size_type size() const { return mStreambuf.size(); }
-
- bool tick(const LLSD&)
- {
- typedef boost::asio::streambuf::const_buffers_type const_buffer_sequence;
- // If there's anything to send, try to send it.
- std::size_t total(mStreambuf.size()), consumed(0);
- if (total)
- {
- const_buffer_sequence bufs = mStreambuf.data();
- // In general, our streambuf might contain a number of different
- // physical buffers; iterate over those.
- bool keepwriting = true;
- for (const_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end());
- bufi != bufend && keepwriting; ++bufi)
- {
- // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
- // Although apr_file_write() accepts const void*, we
- // manipulate const char* so we can increment the pointer.
- const char* remainptr = boost::asio::buffer_cast<const char*>(*bufi);
- std::size_t remainlen = boost::asio::buffer_size(*bufi);
- while (remainlen)
- {
- // Tackle the current buffer in discrete chunks. On
- // Windows, we've observed strange failures when trying to
- // write big lengths (~1 MB) in a single operation. Even a
- // 32K chunk seems too large. At some point along the way
- // apr_file_write() returns 11 (Resource temporarily
- // unavailable, i.e. EAGAIN) and says it wrote 0 bytes --
- // even though it did write the chunk! Our next write
- // attempt retries with the same chunk, resulting in the
- // chunk being duplicated at the child end. Using smaller
- // chunks is empirically more reliable.
- std::size_t towrite((std::min)(remainlen, std::size_t(4*1024)));
- apr_size_t written(towrite);
- apr_status_t err = apr_file_write(mPipe, remainptr, &written);
- // EAGAIN is exactly what we want from a nonblocking pipe.
- // Rather than waiting for data, it should return immediately.
- if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err)))
- {
- LL_WARNS("LLProcess") << "apr_file_write(" << towrite << ") on " << mDesc
- << " got " << err << ":" << LL_ENDL;
- ll_apr_warn_status(err);
- }
-
- // 'written' is modified to reflect the number of bytes actually
- // written. Make sure we consume those later. (Don't consume them
- // now, that would invalidate the buffer iterator sequence!)
- consumed += written;
- // don't forget to advance to next chunk of current buffer
- remainptr += written;
- remainlen -= written;
-
- char msgbuf[512];
- LL_DEBUGS("LLProcess") << "wrote " << written << " of " << towrite
- << " bytes to " << mDesc
- << " (original " << total << "),"
- << " code " << err << ": "
- << apr_strerror(err, msgbuf, sizeof(msgbuf))
- << LL_ENDL;
-
- // The parent end of this pipe is nonblocking. If we weren't able
- // to write everything we wanted, don't keep banging on it -- that
- // won't change until the child reads some. Wait for next tick().
- if (written < towrite)
- {
- keepwriting = false; // break outer loop over buffers too
- break;
- }
- } // next chunk of current buffer
- } // next buffer
- // In all, we managed to write 'consumed' bytes. Remove them from the
- // streambuf so we don't keep trying to send them. This could be
- // anywhere from 0 up to mStreambuf.size(); anything we haven't yet
- // sent, we'll try again later.
- mStreambuf.consume(consumed);
- }
-
- return false;
- }
+ }
+
+ virtual std::ostream& get_ostream() { return mStream; }
+ virtual size_type size() const { return mStreambuf.size(); }
+
+ bool tick(const LLSD&)
+ {
+ typedef boost::asio::streambuf::const_buffers_type const_buffer_sequence;
+ // If there's anything to send, try to send it.
+ std::size_t total(mStreambuf.size()), consumed(0);
+ if (total)
+ {
+ const_buffer_sequence bufs = mStreambuf.data();
+ // In general, our streambuf might contain a number of different
+ // physical buffers; iterate over those.
+ bool keepwriting = true;
+ for (const_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end());
+ bufi != bufend && keepwriting; ++bufi)
+ {
+ // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
+ // Although apr_file_write() accepts const void*, we
+ // manipulate const char* so we can increment the pointer.
+ const char* remainptr = boost::asio::buffer_cast<const char*>(*bufi);
+ std::size_t remainlen = boost::asio::buffer_size(*bufi);
+ while (remainlen)
+ {
+ // Tackle the current buffer in discrete chunks. On
+ // Windows, we've observed strange failures when trying to
+ // write big lengths (~1 MB) in a single operation. Even a
+ // 32K chunk seems too large. At some point along the way
+ // apr_file_write() returns 11 (Resource temporarily
+ // unavailable, i.e. EAGAIN) and says it wrote 0 bytes --
+ // even though it did write the chunk! Our next write
+ // attempt retries with the same chunk, resulting in the
+ // chunk being duplicated at the child end. Using smaller
+ // chunks is empirically more reliable.
+ std::size_t towrite((std::min)(remainlen, std::size_t(4*1024)));
+ apr_size_t written(towrite);
+ apr_status_t err = apr_file_write(mPipe, remainptr, &written);
+ // EAGAIN is exactly what we want from a nonblocking pipe.
+ // Rather than waiting for data, it should return immediately.
+ if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err)))
+ {
+ LL_WARNS("LLProcess") << "apr_file_write(" << towrite << ") on " << mDesc
+ << " got " << err << ":" << LL_ENDL;
+ ll_apr_warn_status(err);
+ }
+
+ // 'written' is modified to reflect the number of bytes actually
+ // written. Make sure we consume those later. (Don't consume them
+ // now, that would invalidate the buffer iterator sequence!)
+ consumed += written;
+ // don't forget to advance to next chunk of current buffer
+ remainptr += written;
+ remainlen -= written;
+
+ char msgbuf[512];
+ LL_DEBUGS("LLProcess") << "wrote " << written << " of " << towrite
+ << " bytes to " << mDesc
+ << " (original " << total << "),"
+ << " code " << err << ": "
+ << apr_strerror(err, msgbuf, sizeof(msgbuf))
+ << LL_ENDL;
+
+ // The parent end of this pipe is nonblocking. If we weren't able
+ // to write everything we wanted, don't keep banging on it -- that
+ // won't change until the child reads some. Wait for next tick().
+ if (written < towrite)
+ {
+ keepwriting = false; // break outer loop over buffers too
+ break;
+ }
+ } // next chunk of current buffer
+ } // next buffer
+ // In all, we managed to write 'consumed' bytes. Remove them from the
+ // streambuf so we don't keep trying to send them. This could be
+ // anywhere from 0 up to mStreambuf.size(); anything we haven't yet
+ // sent, we'll try again later.
+ mStreambuf.consume(consumed);
+ }
+
+ return false;
+ }
private:
- std::string mDesc;
- apr_file_t* mPipe;
- LLTempBoundListener mConnection;
- boost::asio::streambuf mStreambuf;
- std::ostream mStream;
+ std::string mDesc;
+ apr_file_t* mPipe;
+ LLTempBoundListener mConnection;
+ boost::asio::streambuf mStreambuf;
+ std::ostream mStream;
};
class ReadPipeImpl: public LLProcess::ReadPipe
{
- LOG_CLASS(ReadPipeImpl);
+ LOG_CLASS(ReadPipeImpl);
public:
- ReadPipeImpl(const std::string& desc, apr_file_t* pipe, LLProcess::FILESLOT index):
- mDesc(desc),
- mPipe(pipe),
- mIndex(index),
- // Essential to initialize our std::istream with our special streambuf!
- mStream(&mStreambuf),
- mPump("ReadPipe", true), // tweak name as needed to avoid collisions
- mLimit(0),
- mEOF(false)
- {
- mConnection = LLEventPumps::instance().obtain("mainloop")
- .listen(LLEventPump::inventName("ReadPipe"),
- boost::bind(&ReadPipeImpl::tick, this, _1));
- }
+ ReadPipeImpl(const std::string& desc, apr_file_t* pipe, LLProcess::FILESLOT index):
+ mDesc(desc),
+ mPipe(pipe),
+ mIndex(index),
+ // Essential to initialize our std::istream with our special streambuf!
+ mStream(&mStreambuf),
+ mPump("ReadPipe", true), // tweak name as needed to avoid collisions
+ mLimit(0),
+ mEOF(false)
+ {
+ mConnection = LLEventPumps::instance().obtain("mainloop")
+ .listen(LLEventPump::inventName("ReadPipe"),
+ boost::bind(&ReadPipeImpl::tick, this, _1));
+ }
~ReadPipeImpl()
{
@@ -279,200 +279,200 @@ public:
}
}
- // Much of the implementation is simply connecting the abstract virtual
- // methods with implementation data concealed from the base class.
- virtual std::istream& get_istream() { return mStream; }
- virtual std::string getline() { return LLProcess::getline(mStream); }
- virtual LLEventPump& getPump() { return mPump; }
- virtual void setLimit(size_type limit) { mLimit = limit; }
- virtual size_type getLimit() const { return mLimit; }
- virtual size_type size() const { return mStreambuf.size(); }
-
- virtual std::string read(size_type len)
- {
- // Read specified number of bytes into a buffer.
- size_type readlen((std::min)(size(), len));
- // Formally, &buffer[0] is invalid for a vector of size() 0. Exit
- // early in that situation.
- if (! readlen)
- return "";
- // Make a buffer big enough.
- std::vector<char> buffer(readlen);
- mStream.read(&buffer[0], readlen);
- // Since we've already clamped 'readlen', we can think of no reason
- // why mStream.read() should read fewer than 'readlen' bytes.
- // Nonetheless, use the actual retrieved length.
- return std::string(&buffer[0], mStream.gcount());
- }
-
- virtual std::string peek(size_type offset=0, size_type len=npos) const
- {
- // Constrain caller's offset and len to overlap actual buffer content.
- std::size_t real_offset = (std::min)(mStreambuf.size(), std::size_t(offset));
- size_type want_end = (len == npos)? npos : (real_offset + len);
- std::size_t real_end = (std::min)(mStreambuf.size(), std::size_t(want_end));
- boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
- return std::string(boost::asio::buffers_begin(cbufs) + real_offset,
- boost::asio::buffers_begin(cbufs) + real_end);
- }
-
- virtual size_type find(const std::string& seek, size_type offset=0) const
- {
- // If we're passing a string of length 1, use find(char), which can
- // use an O(n) std::find() rather than the O(n^2) std::search().
- if (seek.length() == 1)
- {
- return find(seek[0], offset);
- }
-
- // If offset is beyond the whole buffer, can't even construct a valid
- // iterator range; can't possibly find the string we seek.
- if (offset > mStreambuf.size())
- {
- return npos;
- }
-
- boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
- boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type>
- begin(boost::asio::buffers_begin(cbufs)),
- end (boost::asio::buffers_end(cbufs)),
- found(std::search(begin + offset, end, seek.begin(), seek.end()));
- return (found == end)? npos : (found - begin);
- }
-
- virtual size_type find(char seek, size_type offset=0) const
- {
- // If offset is beyond the whole buffer, can't even construct a valid
- // iterator range; can't possibly find the char we seek.
- if (offset > mStreambuf.size())
- {
- return npos;
- }
-
- boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
- boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type>
- begin(boost::asio::buffers_begin(cbufs)),
- end (boost::asio::buffers_end(cbufs)),
- found(std::find(begin + offset, end, seek));
- return (found == end)? npos : (found - begin);
- }
-
- bool tick(const LLSD&)
- {
- // Once we've hit EOF, skip all the rest of this.
- if (mEOF)
- return false;
-
- typedef boost::asio::streambuf::mutable_buffers_type mutable_buffer_sequence;
- // Try, every time, to read into our streambuf. In fact, we have no
- // idea how much data the child might be trying to send: keep trying
- // until we're convinced we've temporarily exhausted the pipe.
- enum PipeState { RETRY, EXHAUSTED, CLOSED };
- PipeState state = RETRY;
- std::size_t committed(0);
- do
- {
- // attempt to read an arbitrary size
- mutable_buffer_sequence bufs = mStreambuf.prepare(4096);
- // In general, the mutable_buffer_sequence returned by prepare() might
- // contain a number of different physical buffers; iterate over those.
- std::size_t tocommit(0);
- for (mutable_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end());
- bufi != bufend; ++bufi)
- {
- // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
- std::size_t toread(boost::asio::buffer_size(*bufi));
- apr_size_t gotten(toread);
- apr_status_t err = apr_file_read(mPipe,
- boost::asio::buffer_cast<void*>(*bufi),
- &gotten);
- // EAGAIN is exactly what we want from a nonblocking pipe.
- // Rather than waiting for data, it should return immediately.
- if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err)))
- {
- // Handle EOF specially: it's part of normal-case processing.
- if (err == APR_EOF)
- {
- LL_DEBUGS("LLProcess") << "EOF on " << mDesc << LL_ENDL;
- }
- else
- {
- LL_WARNS("LLProcess") << "apr_file_read(" << toread << ") on " << mDesc
- << " got " << err << ":" << LL_ENDL;
- ll_apr_warn_status(err);
- }
- // Either way, though, we won't need any more tick() calls.
- mConnection.disconnect();
- // Ignore any subsequent calls we might get anyway.
- mEOF = true;
- state = CLOSED; // also break outer retry loop
- break;
- }
-
- // 'gotten' was modified to reflect the number of bytes actually
- // received. Make sure we commit those later. (Don't commit them
- // now, that would invalidate the buffer iterator sequence!)
- tocommit += gotten;
- LL_DEBUGS("LLProcess") << "filled " << gotten << " of " << toread
- << " bytes from " << mDesc << LL_ENDL;
-
- // The parent end of this pipe is nonblocking. If we weren't even
- // able to fill this buffer, don't loop to try to fill the next --
- // that won't change until the child writes more. Wait for next
- // tick().
- if (gotten < toread)
- {
- // break outer retry loop too
- state = EXHAUSTED;
- break;
- }
- }
-
- // Don't forget to "commit" the data!
- mStreambuf.commit(tocommit);
- committed += tocommit;
-
- // state is changed from RETRY when we can't fill any one buffer
- // of the mutable_buffer_sequence established by the current
- // prepare() call -- whether due to error or not enough bytes.
- // That is, if state is still RETRY, we've filled every physical
- // buffer in the mutable_buffer_sequence. In that case, for all we
- // know, the child might have still more data pending -- go for it!
- } while (state == RETRY);
-
- // Once we recognize that the pipe is closed, make one more call to
- // listener. The listener might be waiting for a particular substring
- // to arrive, or a particular length of data or something. The event
- // with "eof" == true announces that nothing further will arrive, so
- // use it or lose it.
- if (committed || state == CLOSED)
- {
- // If we actually received new data, publish it on our LLEventPump
- // as advertised. Constrain it by mLimit. But show listener the
- // actual accumulated buffer size, regardless of mLimit.
- size_type datasize((std::min)(mLimit, size_type(mStreambuf.size())));
- mPump.post(LLSDMap
- ("data", peek(0, datasize))
- ("len", LLSD::Integer(mStreambuf.size()))
- ("slot", LLSD::Integer(mIndex))
- ("name", whichfile(mIndex))
- ("desc", mDesc)
- ("eof", state == CLOSED));
- }
-
- return false;
- }
+ // Much of the implementation is simply connecting the abstract virtual
+ // methods with implementation data concealed from the base class.
+ virtual std::istream& get_istream() { return mStream; }
+ virtual std::string getline() { return LLProcess::getline(mStream); }
+ virtual LLEventPump& getPump() { return mPump; }
+ virtual void setLimit(size_type limit) { mLimit = limit; }
+ virtual size_type getLimit() const { return mLimit; }
+ virtual size_type size() const { return mStreambuf.size(); }
+
+ virtual std::string read(size_type len)
+ {
+ // Read specified number of bytes into a buffer.
+ size_type readlen((std::min)(size(), len));
+ // Formally, &buffer[0] is invalid for a vector of size() 0. Exit
+ // early in that situation.
+ if (! readlen)
+ return "";
+ // Make a buffer big enough.
+ std::vector<char> buffer(readlen);
+ mStream.read(&buffer[0], readlen);
+ // Since we've already clamped 'readlen', we can think of no reason
+ // why mStream.read() should read fewer than 'readlen' bytes.
+ // Nonetheless, use the actual retrieved length.
+ return std::string(&buffer[0], mStream.gcount());
+ }
+
+ virtual std::string peek(size_type offset=0, size_type len=npos) const
+ {
+ // Constrain caller's offset and len to overlap actual buffer content.
+ std::size_t real_offset = (std::min)(mStreambuf.size(), std::size_t(offset));
+ size_type want_end = (len == npos)? npos : (real_offset + len);
+ std::size_t real_end = (std::min)(mStreambuf.size(), std::size_t(want_end));
+ boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+ return std::string(boost::asio::buffers_begin(cbufs) + real_offset,
+ boost::asio::buffers_begin(cbufs) + real_end);
+ }
+
+ virtual size_type find(const std::string& seek, size_type offset=0) const
+ {
+ // If we're passing a string of length 1, use find(char), which can
+ // use an O(n) std::find() rather than the O(n^2) std::search().
+ if (seek.length() == 1)
+ {
+ return find(seek[0], offset);
+ }
+
+ // If offset is beyond the whole buffer, can't even construct a valid
+ // iterator range; can't possibly find the string we seek.
+ if (offset > mStreambuf.size())
+ {
+ return npos;
+ }
+
+ boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+ boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type>
+ begin(boost::asio::buffers_begin(cbufs)),
+ end (boost::asio::buffers_end(cbufs)),
+ found(std::search(begin + offset, end, seek.begin(), seek.end()));
+ return (found == end)? npos : (found - begin);
+ }
+
+ virtual size_type find(char seek, size_type offset=0) const
+ {
+ // If offset is beyond the whole buffer, can't even construct a valid
+ // iterator range; can't possibly find the char we seek.
+ if (offset > mStreambuf.size())
+ {
+ return npos;
+ }
+
+ boost::asio::streambuf::const_buffers_type cbufs = mStreambuf.data();
+ boost::asio::buffers_iterator<boost::asio::streambuf::const_buffers_type>
+ begin(boost::asio::buffers_begin(cbufs)),
+ end (boost::asio::buffers_end(cbufs)),
+ found(std::find(begin + offset, end, seek));
+ return (found == end)? npos : (found - begin);
+ }
+
+ bool tick(const LLSD&)
+ {
+ // Once we've hit EOF, skip all the rest of this.
+ if (mEOF)
+ return false;
+
+ typedef boost::asio::streambuf::mutable_buffers_type mutable_buffer_sequence;
+ // Try, every time, to read into our streambuf. In fact, we have no
+ // idea how much data the child might be trying to send: keep trying
+ // until we're convinced we've temporarily exhausted the pipe.
+ enum PipeState { RETRY, EXHAUSTED, CLOSED };
+ PipeState state = RETRY;
+ std::size_t committed(0);
+ do
+ {
+ // attempt to read an arbitrary size
+ mutable_buffer_sequence bufs = mStreambuf.prepare(4096);
+ // In general, the mutable_buffer_sequence returned by prepare() might
+ // contain a number of different physical buffers; iterate over those.
+ std::size_t tocommit(0);
+ for (mutable_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end());
+ bufi != bufend; ++bufi)
+ {
+ // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents
+ std::size_t toread(boost::asio::buffer_size(*bufi));
+ apr_size_t gotten(toread);
+ apr_status_t err = apr_file_read(mPipe,
+ boost::asio::buffer_cast<void*>(*bufi),
+ &gotten);
+ // EAGAIN is exactly what we want from a nonblocking pipe.
+ // Rather than waiting for data, it should return immediately.
+ if (! (err == APR_SUCCESS || APR_STATUS_IS_EAGAIN(err)))
+ {
+ // Handle EOF specially: it's part of normal-case processing.
+ if (err == APR_EOF)
+ {
+ LL_DEBUGS("LLProcess") << "EOF on " << mDesc << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("LLProcess") << "apr_file_read(" << toread << ") on " << mDesc
+ << " got " << err << ":" << LL_ENDL;
+ ll_apr_warn_status(err);
+ }
+ // Either way, though, we won't need any more tick() calls.
+ mConnection.disconnect();
+ // Ignore any subsequent calls we might get anyway.
+ mEOF = true;
+ state = CLOSED; // also break outer retry loop
+ break;
+ }
+
+ // 'gotten' was modified to reflect the number of bytes actually
+ // received. Make sure we commit those later. (Don't commit them
+ // now, that would invalidate the buffer iterator sequence!)
+ tocommit += gotten;
+ LL_DEBUGS("LLProcess") << "filled " << gotten << " of " << toread
+ << " bytes from " << mDesc << LL_ENDL;
+
+ // The parent end of this pipe is nonblocking. If we weren't even
+ // able to fill this buffer, don't loop to try to fill the next --
+ // that won't change until the child writes more. Wait for next
+ // tick().
+ if (gotten < toread)
+ {
+ // break outer retry loop too
+ state = EXHAUSTED;
+ break;
+ }
+ }
+
+ // Don't forget to "commit" the data!
+ mStreambuf.commit(tocommit);
+ committed += tocommit;
+
+ // state is changed from RETRY when we can't fill any one buffer
+ // of the mutable_buffer_sequence established by the current
+ // prepare() call -- whether due to error or not enough bytes.
+ // That is, if state is still RETRY, we've filled every physical
+ // buffer in the mutable_buffer_sequence. In that case, for all we
+ // know, the child might have still more data pending -- go for it!
+ } while (state == RETRY);
+
+ // Once we recognize that the pipe is closed, make one more call to
+ // listener. The listener might be waiting for a particular substring
+ // to arrive, or a particular length of data or something. The event
+ // with "eof" == true announces that nothing further will arrive, so
+ // use it or lose it.
+ if (committed || state == CLOSED)
+ {
+ // If we actually received new data, publish it on our LLEventPump
+ // as advertised. Constrain it by mLimit. But show listener the
+ // actual accumulated buffer size, regardless of mLimit.
+ size_type datasize((std::min)(mLimit, size_type(mStreambuf.size())));
+ mPump.post(LLSDMap
+ ("data", peek(0, datasize))
+ ("len", LLSD::Integer(mStreambuf.size()))
+ ("slot", LLSD::Integer(mIndex))
+ ("name", whichfile(mIndex))
+ ("desc", mDesc)
+ ("eof", state == CLOSED));
+ }
+
+ return false;
+ }
private:
- std::string mDesc;
- apr_file_t* mPipe;
- LLProcess::FILESLOT mIndex;
- LLTempBoundListener mConnection;
- boost::asio::streambuf mStreambuf;
- std::istream mStream;
- LLEventStream mPump;
- size_type mLimit;
- bool mEOF;
+ std::string mDesc;
+ apr_file_t* mPipe;
+ LLProcess::FILESLOT mIndex;
+ LLTempBoundListener mConnection;
+ boost::asio::streambuf mStreambuf;
+ std::istream mStream;
+ LLEventStream mPump;
+ size_type mLimit;
+ bool mEOF;
};
/*****************************************************************************
@@ -482,72 +482,72 @@ private:
/// internal use only
struct LLProcessError: public LLException
{
- LLProcessError(const std::string& msg): LLException(msg) {}
+ LLProcessError(const std::string& msg): LLException(msg) {}
};
LLProcessPtr LLProcess::create(const LLSDOrParams& params)
{
- try
- {
- return LLProcessPtr(new LLProcess(params));
- }
- catch (const LLProcessError& e)
- {
- LL_WARNS("LLProcess") << e.what() << LL_ENDL;
-
- // If caller is requesting an event on process termination, send one
- // indicating bad launch. This may prevent someone waiting forever for
- // a termination post that can't arrive because the child never
- // started.
- if (params.postend.isProvided())
- {
- LLEventPumps::instance().obtain(params.postend)
- .post(LLSDMap
- // no "id"
- ("desc", getDesc(params))
- ("state", LLProcess::UNSTARTED)
- // no "data"
- ("string", e.what())
- );
- }
-
- return LLProcessPtr();
- }
+ try
+ {
+ return LLProcessPtr(new LLProcess(params));
+ }
+ catch (const LLProcessError& e)
+ {
+ LL_WARNS("LLProcess") << e.what() << LL_ENDL;
+
+ // If caller is requesting an event on process termination, send one
+ // indicating bad launch. This may prevent someone waiting forever for
+ // a termination post that can't arrive because the child never
+ // started.
+ if (params.postend.isProvided())
+ {
+ LLEventPumps::instance().obtain(params.postend)
+ .post(LLSDMap
+ // no "id"
+ ("desc", getDesc(params))
+ ("state", LLProcess::UNSTARTED)
+ // no "data"
+ ("string", e.what())
+ );
+ }
+
+ return LLProcessPtr();
+ }
}
/// Call an apr function returning apr_status_t. On failure, log warning and
/// throw LLProcessError mentioning the function call that produced that
/// result.
#define chkapr(func) \
- if (ll_apr_warn_status(func)) \
- throw LLProcessError(#func " failed")
+ if (ll_apr_warn_status(func)) \
+ throw LLProcessError(#func " failed")
LLProcess::LLProcess(const LLSDOrParams& params):
- mAutokill(params.autokill),
- // Because 'autokill' originally meant both 'autokill' and 'attached', to
- // preserve existing semantics, we promise that mAttached defaults to the
- // same setting as mAutokill.
- mAttached(params.attached.isProvided()? params.attached : params.autokill),
+ mAutokill(params.autokill),
+ // Because 'autokill' originally meant both 'autokill' and 'attached', to
+ // preserve existing semantics, we promise that mAttached defaults to the
+ // same setting as mAutokill.
+ mAttached(params.attached.isProvided()? params.attached : params.autokill),
mPool(NULL),
- mPipes(NSLOTS)
+ mPipes(NSLOTS)
{
- // Hmm, when you construct a ptr_vector with a size, it merely reserves
- // space, it doesn't actually make it that big. Explicitly make it bigger.
- // Because of ptr_vector's odd semantics, have to push_back(0) the right
- // number of times! resize() wants to default-construct new BasePipe
- // instances, which fails because it's pure virtual. But because of the
- // constructor call, these push_back() calls should require no new
- // allocation.
- for (size_t i = 0; i < mPipes.capacity(); ++i)
- mPipes.push_back(0);
-
- if (! params.validateBlock(true))
- {
- LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
- << LLSDNotationStreamer(params))));
- }
-
- mPostend = params.postend;
+ // Hmm, when you construct a ptr_vector with a size, it merely reserves
+ // space, it doesn't actually make it that big. Explicitly make it bigger.
+ // Because of ptr_vector's odd semantics, have to push_back(0) the right
+ // number of times! resize() wants to default-construct new BasePipe
+ // instances, which fails because it's pure virtual. But because of the
+ // constructor call, these push_back() calls should require no new
+ // allocation.
+ for (size_t i = 0; i < mPipes.capacity(); ++i)
+ mPipes.push_back(0);
+
+ if (! params.validateBlock(true))
+ {
+ LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
+ << LLSDNotationStreamer(params))));
+ }
+
+ mPostend = params.postend;
apr_pool_create(&mPool, gAPRPoolp);
if (!mPool)
@@ -555,272 +555,272 @@ LLProcess::LLProcess(const LLSDOrParams& params):
LLTHROW(LLProcessError(STRINGIZE("failed to create apr pool")));
}
- apr_procattr_t *procattr = NULL;
- chkapr(apr_procattr_create(&procattr, mPool));
-
- // IQA-490, CHOP-900: On Windows, ask APR to jump through hoops to
- // constrain the set of handles passed to the child process. Before we
- // changed to APR, the Windows implementation of LLProcessLauncher called
- // CreateProcess(bInheritHandles=FALSE), meaning to pass NO open handles
- // to the child process. Now that we support pipes, though, we must allow
- // apr_proc_create() to pass bInheritHandles=TRUE. But without taking
- // special pains, that causes trouble in a number of ways, due to the fact
- // that the viewer is constantly opening and closing files -- most of
- // which CreateProcess() passes to every child process!
+ apr_procattr_t *procattr = NULL;
+ chkapr(apr_procattr_create(&procattr, mPool));
+
+ // IQA-490, CHOP-900: On Windows, ask APR to jump through hoops to
+ // constrain the set of handles passed to the child process. Before we
+ // changed to APR, the Windows implementation of LLProcessLauncher called
+ // CreateProcess(bInheritHandles=FALSE), meaning to pass NO open handles
+ // to the child process. Now that we support pipes, though, we must allow
+ // apr_proc_create() to pass bInheritHandles=TRUE. But without taking
+ // special pains, that causes trouble in a number of ways, due to the fact
+ // that the viewer is constantly opening and closing files -- most of
+ // which CreateProcess() passes to every child process!
#if ! defined(APR_HAS_PROCATTR_CONSTRAIN_HANDLE_SET)
- // Our special preprocessor symbol isn't even defined -- wrong APR
- LL_WARNS("LLProcess") << "This version of APR lacks Linden "
- << "apr_procattr_constrain_handle_set() extension" << LL_ENDL;
+ // Our special preprocessor symbol isn't even defined -- wrong APR
+ LL_WARNS("LLProcess") << "This version of APR lacks Linden "
+ << "apr_procattr_constrain_handle_set() extension" << LL_ENDL;
#else
- chkapr(apr_procattr_constrain_handle_set(procattr, 1));
+ chkapr(apr_procattr_constrain_handle_set(procattr, 1));
#endif
- // For which of stdin, stdout, stderr should we create a pipe to the
- // child? In the viewer, there are only a couple viable
- // apr_procattr_io_set() alternatives: inherit the viewer's own stdxxx
- // handle (APR_NO_PIPE, e.g. for stdout, stderr), or create a pipe that's
- // blocking on the child end but nonblocking at the viewer end
- // (APR_CHILD_BLOCK).
- // Other major options could include explicitly creating a single APR pipe
- // and passing it as both stdout and stderr (apr_procattr_child_out_set(),
- // apr_procattr_child_err_set()), or accepting a filename, opening it and
- // passing that apr_file_t (simple <, >, 2> redirect emulation).
- std::vector<apr_int32_t> select;
- for (const FileParam& fparam : params.files)
- {
- // Every iteration, we're going to append an item to 'select'. At the
- // top of the loop, its size() is, in effect, an index. Use that to
- // pick a string description for messages.
- std::string which(whichfile(FILESLOT(select.size())));
- if (fparam.type().empty()) // inherit our file descriptor
- {
- select.push_back(APR_NO_PIPE);
- }
- else if (fparam.type() == "pipe") // anonymous pipe
- {
- if (! fparam.name().empty())
- {
- LL_WARNS("LLProcess") << "For " << params.executable()
- << ": internal names for reusing pipes ('"
- << fparam.name() << "' for " << which
- << ") are not yet supported -- creating distinct pipe"
- << LL_ENDL;
- }
- // The viewer can't block for anything: the parent end MUST be
- // nonblocking. As the APR documentation itself points out, it
- // makes very little sense to set nonblocking I/O for the child
- // end of a pipe: only a specially-written child could deal with
- // that.
- select.push_back(APR_CHILD_BLOCK);
- }
- else
- {
- LLTHROW(LLProcessError(STRINGIZE("For " << params.executable()
- << ": unsupported FileParam for " << which
- << ": type='" << fparam.type()
- << "', name='" << fparam.name() << "'")));
- }
- }
- // By default, pass APR_NO_PIPE for unspecified slots.
- while (select.size() < NSLOTS)
- {
- select.push_back(APR_NO_PIPE);
- }
- chkapr(apr_procattr_io_set(procattr, select[STDIN], select[STDOUT], select[STDERR]));
-
- // Thumbs down on implicitly invoking the shell to invoke the child. From
- // our point of view, the other major alternative to APR_PROGRAM_PATH
- // would be APR_PROGRAM_ENV: still copy environment, but require full
- // executable pathname. I don't see a downside to searching the PATH,
- // though: if our caller wants (e.g.) a specific Python interpreter, s/he
- // can still pass the full pathname.
- chkapr(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
- // YES, do extra work if necessary to report child exec() failures back to
- // parent process.
- chkapr(apr_procattr_error_check_set(procattr, 1));
- // Do not start a non-autokill child in detached state. On Posix
- // platforms, this setting attempts to daemonize the new child, closing
- // std handles and the like, and that's a bit more detachment than we
- // want. autokill=false just means not to implicitly kill the child when
- // the parent terminates!
-// chkapr(apr_procattr_detach_set(procattr, mAutokill? 0 : 1));
-
- if (mAutokill)
- {
+ // For which of stdin, stdout, stderr should we create a pipe to the
+ // child? In the viewer, there are only a couple viable
+ // apr_procattr_io_set() alternatives: inherit the viewer's own stdxxx
+ // handle (APR_NO_PIPE, e.g. for stdout, stderr), or create a pipe that's
+ // blocking on the child end but nonblocking at the viewer end
+ // (APR_CHILD_BLOCK).
+ // Other major options could include explicitly creating a single APR pipe
+ // and passing it as both stdout and stderr (apr_procattr_child_out_set(),
+ // apr_procattr_child_err_set()), or accepting a filename, opening it and
+ // passing that apr_file_t (simple <, >, 2> redirect emulation).
+ std::vector<apr_int32_t> select;
+ for (const FileParam& fparam : params.files)
+ {
+ // Every iteration, we're going to append an item to 'select'. At the
+ // top of the loop, its size() is, in effect, an index. Use that to
+ // pick a string description for messages.
+ std::string which(whichfile(FILESLOT(select.size())));
+ if (fparam.type().empty()) // inherit our file descriptor
+ {
+ select.push_back(APR_NO_PIPE);
+ }
+ else if (fparam.type() == "pipe") // anonymous pipe
+ {
+ if (! fparam.name().empty())
+ {
+ LL_WARNS("LLProcess") << "For " << params.executable()
+ << ": internal names for reusing pipes ('"
+ << fparam.name() << "' for " << which
+ << ") are not yet supported -- creating distinct pipe"
+ << LL_ENDL;
+ }
+ // The viewer can't block for anything: the parent end MUST be
+ // nonblocking. As the APR documentation itself points out, it
+ // makes very little sense to set nonblocking I/O for the child
+ // end of a pipe: only a specially-written child could deal with
+ // that.
+ select.push_back(APR_CHILD_BLOCK);
+ }
+ else
+ {
+ LLTHROW(LLProcessError(STRINGIZE("For " << params.executable()
+ << ": unsupported FileParam for " << which
+ << ": type='" << fparam.type()
+ << "', name='" << fparam.name() << "'")));
+ }
+ }
+ // By default, pass APR_NO_PIPE for unspecified slots.
+ while (select.size() < NSLOTS)
+ {
+ select.push_back(APR_NO_PIPE);
+ }
+ chkapr(apr_procattr_io_set(procattr, select[STDIN], select[STDOUT], select[STDERR]));
+
+ // Thumbs down on implicitly invoking the shell to invoke the child. From
+ // our point of view, the other major alternative to APR_PROGRAM_PATH
+ // would be APR_PROGRAM_ENV: still copy environment, but require full
+ // executable pathname. I don't see a downside to searching the PATH,
+ // though: if our caller wants (e.g.) a specific Python interpreter, s/he
+ // can still pass the full pathname.
+ chkapr(apr_procattr_cmdtype_set(procattr, APR_PROGRAM_PATH));
+ // YES, do extra work if necessary to report child exec() failures back to
+ // parent process.
+ chkapr(apr_procattr_error_check_set(procattr, 1));
+ // Do not start a non-autokill child in detached state. On Posix
+ // platforms, this setting attempts to daemonize the new child, closing
+ // std handles and the like, and that's a bit more detachment than we
+ // want. autokill=false just means not to implicitly kill the child when
+ // the parent terminates!
+// chkapr(apr_procattr_detach_set(procattr, mAutokill? 0 : 1));
+
+ if (mAutokill)
+ {
#if ! defined(APR_HAS_PROCATTR_AUTOKILL_SET)
- // Our special preprocessor symbol isn't even defined -- wrong APR
- LL_WARNS("LLProcess") << "This version of APR lacks Linden apr_procattr_autokill_set() extension" << LL_ENDL;
+ // Our special preprocessor symbol isn't even defined -- wrong APR
+ LL_WARNS("LLProcess") << "This version of APR lacks Linden apr_procattr_autokill_set() extension" << LL_ENDL;
#elif ! APR_HAS_PROCATTR_AUTOKILL_SET
- // Symbol is defined, but to 0: expect apr_procattr_autokill_set() to
- // return APR_ENOTIMPL.
+ // Symbol is defined, but to 0: expect apr_procattr_autokill_set() to
+ // return APR_ENOTIMPL.
#else // APR_HAS_PROCATTR_AUTOKILL_SET nonzero
- ll_apr_warn_status(apr_procattr_autokill_set(procattr, 1));
+ ll_apr_warn_status(apr_procattr_autokill_set(procattr, 1));
#endif
- }
-
- // In preparation for calling apr_proc_create(), we collect a number of
- // const char* pointers obtained from std::string::c_str(). Turns out
- // LLInitParam::Block's helpers Optional, Mandatory, Multiple et al.
- // guarantee that converting to the wrapped type (std::string in our
- // case), e.g. by calling operator(), returns a reference to *the same
- // instance* of the wrapped type that's stored in our Block subclass.
- // That's important! We know 'params' persists throughout this method
- // call; but without that guarantee, we'd have to assume that converting
- // one of its members to std::string might return a different (temp)
- // instance. Capturing the c_str() from a temporary std::string is Bad Bad
- // Bad. But armed with this knowledge, when you see params.cwd().c_str(),
- // grit your teeth and smile and carry on.
-
- if (params.cwd.isProvided())
- {
- chkapr(apr_procattr_dir_set(procattr, params.cwd().c_str()));
- }
-
- // create an argv vector for the child process
- std::vector<const char*> argv;
-
- // Add the executable path. See above remarks about c_str().
- argv.push_back(params.executable().c_str());
-
- // Add arguments. See above remarks about c_str().
- for (const std::string& arg : params.args)
- {
- argv.push_back(arg.c_str());
- }
-
- // terminate with a null pointer
- argv.push_back(NULL);
-
- // Launch! The NULL would be the environment block, if we were passing
- // one. Hand-expand chkapr() macro so we can fill in the actual command
- // string instead of the variable names.
- if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
- mPool)))
- {
- LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
- }
-
- // arrange to call status_callback()
- apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
+ }
+
+ // In preparation for calling apr_proc_create(), we collect a number of
+ // const char* pointers obtained from std::string::c_str(). Turns out
+ // LLInitParam::Block's helpers Optional, Mandatory, Multiple et al.
+ // guarantee that converting to the wrapped type (std::string in our
+ // case), e.g. by calling operator(), returns a reference to *the same
+ // instance* of the wrapped type that's stored in our Block subclass.
+ // That's important! We know 'params' persists throughout this method
+ // call; but without that guarantee, we'd have to assume that converting
+ // one of its members to std::string might return a different (temp)
+ // instance. Capturing the c_str() from a temporary std::string is Bad Bad
+ // Bad. But armed with this knowledge, when you see params.cwd().c_str(),
+ // grit your teeth and smile and carry on.
+
+ if (params.cwd.isProvided())
+ {
+ chkapr(apr_procattr_dir_set(procattr, params.cwd().c_str()));
+ }
+
+ // create an argv vector for the child process
+ std::vector<const char*> argv;
+
+ // Add the executable path. See above remarks about c_str().
+ argv.push_back(params.executable().c_str());
+
+ // Add arguments. See above remarks about c_str().
+ for (const std::string& arg : params.args)
+ {
+ argv.push_back(arg.c_str());
+ }
+
+ // terminate with a null pointer
+ argv.push_back(NULL);
+
+ // Launch! The NULL would be the environment block, if we were passing
+ // one. Hand-expand chkapr() macro so we can fill in the actual command
+ // string instead of the variable names.
+ if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
+ mPool)))
+ {
+ LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
+ }
+
+ // arrange to call status_callback()
+ apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
mPool);
- // and make sure we poll it once per "mainloop" tick
- sProcessListener.addPoll(*this);
- mStatus.mState = RUNNING;
-
- mDesc = STRINGIZE(getDesc(params) << " (" << mProcess.pid << ')');
- LL_INFOS("LLProcess") << mDesc << ": launched " << params << LL_ENDL;
-
- // Unless caller explicitly turned off autokill (child should persist),
- // take steps to terminate the child. This is all suspenders-and-belt: in
- // theory our destructor should kill an autokill child, but in practice
- // that doesn't always work (e.g. VWR-21538).
- if (mAutokill)
- {
+ // and make sure we poll it once per "mainloop" tick
+ sProcessListener.addPoll(*this);
+ mStatus.mState = RUNNING;
+
+ mDesc = STRINGIZE(getDesc(params) << " (" << mProcess.pid << ')');
+ LL_INFOS("LLProcess") << mDesc << ": launched " << params << LL_ENDL;
+
+ // Unless caller explicitly turned off autokill (child should persist),
+ // take steps to terminate the child. This is all suspenders-and-belt: in
+ // theory our destructor should kill an autokill child, but in practice
+ // that doesn't always work (e.g. VWR-21538).
+ if (mAutokill)
+ {
/*==========================================================================*|
- // NO: There may be an APR bug, not sure -- but at least on Mac, when
- // gAPRPoolp is destroyed, OUR process receives SIGTERM! Apparently
- // either our own PID is getting into the list of processes to kill()
- // (unlikely), or somehow one of those PIDs is getting zeroed first,
- // so that kill() sends SIGTERM to the whole process group -- this
- // process included. I'd have to build and link with a debug version
- // of APR to know for sure. It's too bad: this mechanism would be just
- // right for dealing with static autokill LLProcessPtr variables,
- // which aren't destroyed until after APR is no longer available.
-
- // Tie the lifespan of this child process to the lifespan of our APR
- // pool: on destruction of the pool, forcibly kill the process. Tell
- // APR to try SIGTERM and suspend 3 seconds. If that didn't work, use
- // SIGKILL.
- apr_pool_note_subprocess(gAPRPoolp, &mProcess, APR_KILL_AFTER_TIMEOUT);
+ // NO: There may be an APR bug, not sure -- but at least on Mac, when
+ // gAPRPoolp is destroyed, OUR process receives SIGTERM! Apparently
+ // either our own PID is getting into the list of processes to kill()
+ // (unlikely), or somehow one of those PIDs is getting zeroed first,
+ // so that kill() sends SIGTERM to the whole process group -- this
+ // process included. I'd have to build and link with a debug version
+ // of APR to know for sure. It's too bad: this mechanism would be just
+ // right for dealing with static autokill LLProcessPtr variables,
+ // which aren't destroyed until after APR is no longer available.
+
+ // Tie the lifespan of this child process to the lifespan of our APR
+ // pool: on destruction of the pool, forcibly kill the process. Tell
+ // APR to try SIGTERM and suspend 3 seconds. If that didn't work, use
+ // SIGKILL.
+ apr_pool_note_subprocess(gAPRPoolp, &mProcess, APR_KILL_AFTER_TIMEOUT);
|*==========================================================================*/
- // On Windows, associate the new child process with our Job Object.
- autokill();
- }
-
- // Instantiate the proper pipe I/O machinery
- // want to be able to point to apr_proc_t::in, out, err by index
- typedef apr_file_t* apr_proc_t::*apr_proc_file_ptr;
- static apr_proc_file_ptr members[] =
- { &apr_proc_t::in, &apr_proc_t::out, &apr_proc_t::err };
- for (size_t i = 0; i < NSLOTS; ++i)
- {
- if (select[i] != APR_CHILD_BLOCK)
- continue;
- std::string desc(STRINGIZE(mDesc << ' ' << whichfile(FILESLOT(i))));
- apr_file_t* pipe(mProcess.*(members[i]));
- if (i == STDIN)
- {
- mPipes.replace(i, new WritePipeImpl(desc, pipe));
- }
- else
- {
- mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i)));
- }
- // Removed temporaily for Xcode 7 build tests: error was:
- // "error: expression with side effects will be evaluated despite
- // being used as an operand to 'typeid' [-Werror,-Wpotentially-evaluated-expression]""
- //LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
- // << "('" << desc << "')" << LL_ENDL;
- }
+ // On Windows, associate the new child process with our Job Object.
+ autokill();
+ }
+
+ // Instantiate the proper pipe I/O machinery
+ // want to be able to point to apr_proc_t::in, out, err by index
+ typedef apr_file_t* apr_proc_t::*apr_proc_file_ptr;
+ static apr_proc_file_ptr members[] =
+ { &apr_proc_t::in, &apr_proc_t::out, &apr_proc_t::err };
+ for (size_t i = 0; i < NSLOTS; ++i)
+ {
+ if (select[i] != APR_CHILD_BLOCK)
+ continue;
+ std::string desc(STRINGIZE(mDesc << ' ' << whichfile(FILESLOT(i))));
+ apr_file_t* pipe(mProcess.*(members[i]));
+ if (i == STDIN)
+ {
+ mPipes.replace(i, new WritePipeImpl(desc, pipe));
+ }
+ else
+ {
+ mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i)));
+ }
+ // Removed temporaily for Xcode 7 build tests: error was:
+ // "error: expression with side effects will be evaluated despite
+ // being used as an operand to 'typeid' [-Werror,-Wpotentially-evaluated-expression]""
+ //LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
+ // << "('" << desc << "')" << LL_ENDL;
+ }
}
// Helper to obtain a description string, given a Params block
static std::string getDesc(const LLProcess::Params& params)
{
- // If caller specified a description string, by all means use it.
- if (params.desc.isProvided())
- return params.desc;
+ // If caller specified a description string, by all means use it.
+ if (params.desc.isProvided())
+ return params.desc;
- // Caller didn't say. Use the executable name -- but use just the filename
- // part. On Mac, for instance, full pathnames get cumbersome.
- return LLProcess::basename(params.executable);
+ // Caller didn't say. Use the executable name -- but use just the filename
+ // part. On Mac, for instance, full pathnames get cumbersome.
+ return LLProcess::basename(params.executable);
}
//static
std::string LLProcess::basename(const std::string& path)
{
- // If there are Linden utility functions to manipulate pathnames, I
- // haven't found them -- and for this usage, Boost.Filesystem seems kind
- // of heavyweight.
- std::string::size_type delim = path.find_last_of("\\/");
- // If path contains no pathname delimiters, return the whole thing.
- if (delim == std::string::npos)
- return path;
-
- // Return just the part beyond the last delimiter.
- return path.substr(delim + 1);
+ // If there are Linden utility functions to manipulate pathnames, I
+ // haven't found them -- and for this usage, Boost.Filesystem seems kind
+ // of heavyweight.
+ std::string::size_type delim = path.find_last_of("\\/");
+ // If path contains no pathname delimiters, return the whole thing.
+ if (delim == std::string::npos)
+ return path;
+
+ // Return just the part beyond the last delimiter.
+ return path.substr(delim + 1);
}
LLProcess::~LLProcess()
{
- // In the Linden viewer, there's at least one static LLProcessPtr. Its
- // destructor will be called *after* ll_cleanup_apr(). In such a case,
- // unregistering is pointless (and fatal!) -- and kill(), which also
- // relies on APR, is impossible.
- if (! gAPRPoolp)
- return;
-
- // Only in state RUNNING are we registered for callback. In UNSTARTED we
- // haven't yet registered. And since receiving the callback is the only
- // way we detect child termination, we only change from state RUNNING at
- // the same time we unregister.
- if (mStatus.mState == RUNNING)
- {
- // We're still registered for a callback: unregister. Do it before
- // we even issue the kill(): even if kill() somehow prompted an
- // instantaneous callback (unlikely), this object is going away! Any
- // information updated in this object by such a callback is no longer
- // available to any consumer anyway.
- apr_proc_other_child_unregister(this);
- // One less LLProcess to poll for
- sProcessListener.dropPoll(*this);
- }
-
- if (mAttached)
- {
- kill("destructor");
- }
+ // In the Linden viewer, there's at least one static LLProcessPtr. Its
+ // destructor will be called *after* ll_cleanup_apr(). In such a case,
+ // unregistering is pointless (and fatal!) -- and kill(), which also
+ // relies on APR, is impossible.
+ if (! gAPRPoolp)
+ return;
+
+ // Only in state RUNNING are we registered for callback. In UNSTARTED we
+ // haven't yet registered. And since receiving the callback is the only
+ // way we detect child termination, we only change from state RUNNING at
+ // the same time we unregister.
+ if (mStatus.mState == RUNNING)
+ {
+ // We're still registered for a callback: unregister. Do it before
+ // we even issue the kill(): even if kill() somehow prompted an
+ // instantaneous callback (unlikely), this object is going away! Any
+ // information updated in this object by such a callback is no longer
+ // available to any consumer anyway.
+ apr_proc_other_child_unregister(this);
+ // One less LLProcess to poll for
+ sProcessListener.dropPoll(*this);
+ }
+
+ if (mAttached)
+ {
+ kill("destructor");
+ }
if (mPool)
{
@@ -831,330 +831,330 @@ LLProcess::~LLProcess()
bool LLProcess::kill(const std::string& who)
{
- if (isRunning())
- {
- LL_INFOS("LLProcess") << who << " killing " << mDesc << LL_ENDL;
+ if (isRunning())
+ {
+ LL_INFOS("LLProcess") << who << " killing " << mDesc << LL_ENDL;
#if LL_WINDOWS
- int sig = -1;
+ int sig = -1;
#else // Posix
- int sig = SIGTERM;
+ int sig = SIGTERM;
#endif
- ll_apr_warn_status(apr_proc_kill(&mProcess, sig));
- }
+ ll_apr_warn_status(apr_proc_kill(&mProcess, sig));
+ }
- return ! isRunning();
+ return ! isRunning();
}
//static
bool LLProcess::kill(const LLProcessPtr& p, const std::string& who)
{
- if (! p)
- return true; // process dead! (was never running)
- return p->kill(who);
+ if (! p)
+ return true; // process dead! (was never running)
+ return p->kill(who);
}
bool LLProcess::isRunning() const
{
- return getStatus().mState == RUNNING;
+ return getStatus().mState == RUNNING;
}
//static
bool LLProcess::isRunning(const LLProcessPtr& p)
{
- if (! p)
- return false;
- return p->isRunning();
+ if (! p)
+ return false;
+ return p->isRunning();
}
LLProcess::Status LLProcess::getStatus() const
{
- return mStatus;
+ return mStatus;
}
//static
LLProcess::Status LLProcess::getStatus(const LLProcessPtr& p)
{
- if (! p)
- {
- // default-constructed Status has mState == UNSTARTED
- return Status();
- }
- return p->getStatus();
+ if (! p)
+ {
+ // default-constructed Status has mState == UNSTARTED
+ return Status();
+ }
+ return p->getStatus();
}
std::string LLProcess::getStatusString() const
{
- return getStatusString(getStatus());
+ return getStatusString(getStatus());
}
std::string LLProcess::getStatusString(const Status& status) const
{
- return getStatusString(mDesc, status);
+ return getStatusString(mDesc, status);
}
//static
std::string LLProcess::getStatusString(const std::string& desc, const LLProcessPtr& p)
{
- if (! p)
- {
- // default-constructed Status has mState == UNSTARTED
- return getStatusString(desc, Status());
- }
- return desc + " " + p->getStatusString();
+ if (! p)
+ {
+ // default-constructed Status has mState == UNSTARTED
+ return getStatusString(desc, Status());
+ }
+ return desc + " " + p->getStatusString();
}
//static
std::string LLProcess::getStatusString(const std::string& desc, const Status& status)
{
- if (status.mState == UNSTARTED)
- return desc + " was never launched";
+ if (status.mState == UNSTARTED)
+ return desc + " was never launched";
- if (status.mState == RUNNING)
- return desc + " running";
+ if (status.mState == RUNNING)
+ return desc + " running";
- if (status.mState == EXITED)
- return STRINGIZE(desc << " exited with code " << status.mData);
+ if (status.mState == EXITED)
+ return STRINGIZE(desc << " exited with code " << status.mData);
- if (status.mState == KILLED)
+ if (status.mState == KILLED)
#if LL_WINDOWS
- return STRINGIZE(desc << " killed with exception " << std::hex << status.mData);
+ return STRINGIZE(desc << " killed with exception " << std::hex << status.mData);
#else
- return STRINGIZE(desc << " killed by signal " << status.mData
- << " (" << apr_signal_description_get(status.mData) << ")");
+ return STRINGIZE(desc << " killed by signal " << status.mData
+ << " (" << apr_signal_description_get(status.mData) << ")");
#endif
- return STRINGIZE(desc << " in unknown state " << status.mState << " (" << status.mData << ")");
+ return STRINGIZE(desc << " in unknown state " << status.mState << " (" << status.mData << ")");
}
// Classic-C-style APR callback
void LLProcess::status_callback(int reason, void* data, int status)
{
- // Our only role is to bounce this static method call back into object
- // space.
- static_cast<LLProcess*>(data)->handle_status(reason, status);
+ // Our only role is to bounce this static method call back into object
+ // space.
+ static_cast<LLProcess*>(data)->handle_status(reason, status);
}
#define tabent(symbol) { symbol, #symbol }
static struct ReasonCode
{
- int code;
- const char* name;
+ int code;
+ const char* name;
} reasons[] =
{
- tabent(APR_OC_REASON_DEATH),
- tabent(APR_OC_REASON_UNWRITABLE),
- tabent(APR_OC_REASON_RESTART),
- tabent(APR_OC_REASON_UNREGISTER),
- tabent(APR_OC_REASON_LOST),
- tabent(APR_OC_REASON_RUNNING)
+ tabent(APR_OC_REASON_DEATH),
+ tabent(APR_OC_REASON_UNWRITABLE),
+ tabent(APR_OC_REASON_RESTART),
+ tabent(APR_OC_REASON_UNREGISTER),
+ tabent(APR_OC_REASON_LOST),
+ tabent(APR_OC_REASON_RUNNING)
};
#undef tabent
// Object-oriented callback
void LLProcess::handle_status(int reason, int status)
{
- {
- // This odd appearance of LL_DEBUGS is just to bracket a lookup that will
- // only be performed if in fact we're going to produce the log message.
- LL_DEBUGS("LLProcess") << empty;
- std::string reason_str;
- for (const ReasonCode& rcp : reasons)
- {
- if (reason == rcp.code)
- {
- reason_str = rcp.name;
- break;
- }
- }
- if (reason_str.empty())
- {
- reason_str = STRINGIZE("unknown reason " << reason);
- }
- LL_CONT << mDesc << ": handle_status(" << reason_str << ", " << status << ")" << LL_ENDL;
- }
-
- if (! (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST))
- {
- // We're only interested in the call when the child terminates.
- return;
- }
-
- // Somewhat oddly, APR requires that you explicitly unregister even when
- // it already knows the child has terminated. We must pass the same 'data'
- // pointer as for the register() call, which was our 'this'.
- apr_proc_other_child_unregister(this);
- // don't keep polling for a terminated process
- sProcessListener.dropPoll(*this);
- // We overload mStatus.mState to indicate whether the child is registered
- // for APR callback: only RUNNING means registered. Track that we've
- // unregistered. We know the child has terminated; might be EXITED or
- // KILLED; refine below.
- mStatus.mState = EXITED;
-
- // Make last-gasp calls for each of the ReadPipes we have on hand. Since
- // they're listening on "mainloop", we can be sure they'll eventually
- // collect all pending data from the child. But we want to be able to
- // guarantee to our consumer that by the time we post on the "postend"
- // LLEventPump, our ReadPipes are already buffering all the data there
- // will ever be from the child. That lets the "postend" listener decide
- // what to do with that final data.
- for (size_t i = 0; i < mPipes.size(); ++i)
- {
- std::string error;
- ReadPipeImpl* ppipe = getPipePtr<ReadPipeImpl>(error, FILESLOT(i));
- if (ppipe)
- {
- static LLSD trivial;
- ppipe->tick(trivial);
- }
- }
-
-// wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
- // It's just wrong to call apr_proc_wait() here. The only way APR knows to
- // call us with APR_OC_REASON_DEATH is that it's already reaped this child
- // process, so calling wait() will only produce "huh?" from the OS. We
- // must rely on the status param passed in, which unfortunately comes
- // straight from the OS wait() call, which means we have to decode it by
- // hand.
- mStatus = interpret_status(status);
- LL_INFOS("LLProcess") << getStatusString() << LL_ENDL;
-
- // If caller requested notification on child termination, send it.
- if (! mPostend.empty())
- {
- LLEventPumps::instance().obtain(mPostend)
- .post(LLSDMap
- ("id", getProcessID())
- ("desc", mDesc)
- ("state", mStatus.mState)
- ("data", mStatus.mData)
- ("string", getStatusString())
- );
- }
+ {
+ // This odd appearance of LL_DEBUGS is just to bracket a lookup that will
+ // only be performed if in fact we're going to produce the log message.
+ LL_DEBUGS("LLProcess") << empty;
+ std::string reason_str;
+ for (const ReasonCode& rcp : reasons)
+ {
+ if (reason == rcp.code)
+ {
+ reason_str = rcp.name;
+ break;
+ }
+ }
+ if (reason_str.empty())
+ {
+ reason_str = STRINGIZE("unknown reason " << reason);
+ }
+ LL_CONT << mDesc << ": handle_status(" << reason_str << ", " << status << ")" << LL_ENDL;
+ }
+
+ if (! (reason == APR_OC_REASON_DEATH || reason == APR_OC_REASON_LOST))
+ {
+ // We're only interested in the call when the child terminates.
+ return;
+ }
+
+ // Somewhat oddly, APR requires that you explicitly unregister even when
+ // it already knows the child has terminated. We must pass the same 'data'
+ // pointer as for the register() call, which was our 'this'.
+ apr_proc_other_child_unregister(this);
+ // don't keep polling for a terminated process
+ sProcessListener.dropPoll(*this);
+ // We overload mStatus.mState to indicate whether the child is registered
+ // for APR callback: only RUNNING means registered. Track that we've
+ // unregistered. We know the child has terminated; might be EXITED or
+ // KILLED; refine below.
+ mStatus.mState = EXITED;
+
+ // Make last-gasp calls for each of the ReadPipes we have on hand. Since
+ // they're listening on "mainloop", we can be sure they'll eventually
+ // collect all pending data from the child. But we want to be able to
+ // guarantee to our consumer that by the time we post on the "postend"
+ // LLEventPump, our ReadPipes are already buffering all the data there
+ // will ever be from the child. That lets the "postend" listener decide
+ // what to do with that final data.
+ for (size_t i = 0; i < mPipes.size(); ++i)
+ {
+ std::string error;
+ ReadPipeImpl* ppipe = getPipePtr<ReadPipeImpl>(error, FILESLOT(i));
+ if (ppipe)
+ {
+ static LLSD trivial;
+ ppipe->tick(trivial);
+ }
+ }
+
+// wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
+ // It's just wrong to call apr_proc_wait() here. The only way APR knows to
+ // call us with APR_OC_REASON_DEATH is that it's already reaped this child
+ // process, so calling wait() will only produce "huh?" from the OS. We
+ // must rely on the status param passed in, which unfortunately comes
+ // straight from the OS wait() call, which means we have to decode it by
+ // hand.
+ mStatus = interpret_status(status);
+ LL_INFOS("LLProcess") << getStatusString() << LL_ENDL;
+
+ // If caller requested notification on child termination, send it.
+ if (! mPostend.empty())
+ {
+ LLEventPumps::instance().obtain(mPostend)
+ .post(LLSDMap
+ ("id", getProcessID())
+ ("desc", mDesc)
+ ("state", mStatus.mState)
+ ("data", mStatus.mData)
+ ("string", getStatusString())
+ );
+ }
}
LLProcess::id LLProcess::getProcessID() const
{
- return mProcess.pid;
+ return mProcess.pid;
}
LLProcess::handle LLProcess::getProcessHandle() const
{
#if LL_WINDOWS
- return mProcess.hproc;
+ return mProcess.hproc;
#else
- return mProcess.pid;
+ return mProcess.pid;
#endif
}
std::string LLProcess::getPipeName(FILESLOT) const
{
- // LLProcess::FileParam::type "npipe" is not yet implemented
- return "";
+ // LLProcess::FileParam::type "npipe" is not yet implemented
+ return "";
}
template<class PIPETYPE>
PIPETYPE* LLProcess::getPipePtr(std::string& error, FILESLOT slot)
{
- if (slot >= NSLOTS)
- {
- error = STRINGIZE(mDesc << " has no slot " << slot);
- return NULL;
- }
- if (mPipes.is_null(slot))
- {
- error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a monitored pipe");
- return NULL;
- }
- // Make sure we dynamic_cast in pointer domain so we can test, rather than
- // accepting runtime's exception.
- PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]);
- if (! ppipe)
- {
- error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a " << typeid(PIPETYPE).name());
- return NULL;
- }
-
- error.clear();
- return ppipe;
+ if (slot >= NSLOTS)
+ {
+ error = STRINGIZE(mDesc << " has no slot " << slot);
+ return NULL;
+ }
+ if (mPipes.is_null(slot))
+ {
+ error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a monitored pipe");
+ return NULL;
+ }
+ // Make sure we dynamic_cast in pointer domain so we can test, rather than
+ // accepting runtime's exception.
+ PIPETYPE* ppipe = dynamic_cast<PIPETYPE*>(&mPipes[slot]);
+ if (! ppipe)
+ {
+ error = STRINGIZE(mDesc << ' ' << whichfile(slot) << " not a " << typeid(PIPETYPE).name());
+ return NULL;
+ }
+
+ error.clear();
+ return ppipe;
}
template <class PIPETYPE>
PIPETYPE& LLProcess::getPipe(FILESLOT slot)
{
- std::string error;
- PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
- if (! wp)
- {
- LLTHROW(NoPipe(error));
- }
- return *wp;
+ std::string error;
+ PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
+ if (! wp)
+ {
+ LLTHROW(NoPipe(error));
+ }
+ return *wp;
}
template <class PIPETYPE>
boost::optional<PIPETYPE&> LLProcess::getOptPipe(FILESLOT slot)
{
- std::string error;
- PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
- if (! wp)
- {
- LL_DEBUGS("LLProcess") << error << LL_ENDL;
- return boost::optional<PIPETYPE&>();
- }
- return *wp;
+ std::string error;
+ PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
+ if (! wp)
+ {
+ LL_DEBUGS("LLProcess") << error << LL_ENDL;
+ return boost::optional<PIPETYPE&>();
+ }
+ return *wp;
}
LLProcess::WritePipe& LLProcess::getWritePipe(FILESLOT slot)
{
- return getPipe<WritePipe>(slot);
+ return getPipe<WritePipe>(slot);
}
boost::optional<LLProcess::WritePipe&> LLProcess::getOptWritePipe(FILESLOT slot)
{
- return getOptPipe<WritePipe>(slot);
+ return getOptPipe<WritePipe>(slot);
}
LLProcess::ReadPipe& LLProcess::getReadPipe(FILESLOT slot)
{
- return getPipe<ReadPipe>(slot);
+ return getPipe<ReadPipe>(slot);
}
boost::optional<LLProcess::ReadPipe&> LLProcess::getOptReadPipe(FILESLOT slot)
{
- return getOptPipe<ReadPipe>(slot);
+ return getOptPipe<ReadPipe>(slot);
}
//static
std::string LLProcess::getline(std::istream& in)
{
- std::string line;
- std::getline(in, line);
- // Blur the distinction between "\r\n" and plain "\n". std::getline() will
- // have eaten the "\n", but we could still end up with a trailing "\r".
- std::string::size_type lastpos = line.find_last_not_of("\r");
- if (lastpos != std::string::npos)
- {
- // Found at least one character that's not a trailing '\r'. SKIP OVER
- // IT and erase the rest of the line.
- line.erase(lastpos+1);
- }
- return line;
+ std::string line;
+ std::getline(in, line);
+ // Blur the distinction between "\r\n" and plain "\n". std::getline() will
+ // have eaten the "\n", but we could still end up with a trailing "\r".
+ std::string::size_type lastpos = line.find_last_not_of("\r");
+ if (lastpos != std::string::npos)
+ {
+ // Found at least one character that's not a trailing '\r'. SKIP OVER
+ // IT and erase the rest of the line.
+ line.erase(lastpos+1);
+ }
+ return line;
}
std::ostream& operator<<(std::ostream& out, const LLProcess::Params& params)
{
- if (params.cwd.isProvided())
- {
- out << "cd " << LLStringUtil::quote(params.cwd) << ": ";
- }
- out << LLStringUtil::quote(params.executable);
- for (const std::string& arg : params.args)
- {
- out << ' ' << LLStringUtil::quote(arg);
- }
- return out;
+ if (params.cwd.isProvided())
+ {
+ out << "cd " << LLStringUtil::quote(params.cwd) << ": ";
+ }
+ out << LLStringUtil::quote(params.executable);
+ for (const std::string& arg : params.args)
+ {
+ out << ' ' << LLStringUtil::quote(arg);
+ }
+ return out;
}
/*****************************************************************************
@@ -1166,68 +1166,68 @@ static std::string WindowsErrorString(const std::string& operation);
void LLProcess::autokill()
{
- // hopefully now handled by apr_procattr_autokill_set()
+ // hopefully now handled by apr_procattr_autokill_set()
}
LLProcess::handle LLProcess::isRunning(handle h, const std::string& desc)
{
- // This direct Windows implementation is because we have no access to the
- // apr_proc_t struct: we expect it's been destroyed.
- if (! h)
- return 0;
-
- DWORD waitresult = WaitForSingleObject(h, 0);
- if(waitresult == WAIT_OBJECT_0)
- {
- // the process has completed.
- if (! desc.empty())
- {
- DWORD status = 0;
- if (! GetExitCodeProcess(h, &status))
- {
- LL_WARNS("LLProcess") << desc << " terminated, but "
- << WindowsErrorString("GetExitCodeProcess()") << LL_ENDL;
- }
- {
- LL_INFOS("LLProcess") << getStatusString(desc, interpret_status(status))
- << LL_ENDL;
- }
- }
- CloseHandle(h);
- return 0;
- }
-
- return h;
+ // This direct Windows implementation is because we have no access to the
+ // apr_proc_t struct: we expect it's been destroyed.
+ if (! h)
+ return 0;
+
+ DWORD waitresult = WaitForSingleObject(h, 0);
+ if(waitresult == WAIT_OBJECT_0)
+ {
+ // the process has completed.
+ if (! desc.empty())
+ {
+ DWORD status = 0;
+ if (! GetExitCodeProcess(h, &status))
+ {
+ LL_WARNS("LLProcess") << desc << " terminated, but "
+ << WindowsErrorString("GetExitCodeProcess()") << LL_ENDL;
+ }
+ {
+ LL_INFOS("LLProcess") << getStatusString(desc, interpret_status(status))
+ << LL_ENDL;
+ }
+ }
+ CloseHandle(h);
+ return 0;
+ }
+
+ return h;
}
static LLProcess::Status interpret_status(int status)
{
- LLProcess::Status result;
-
- // This bit of code is cribbed from apr/threadproc/win32/proc.c, a
- // function (unfortunately static) called why_from_exit_code():
- /* See WinNT.h STATUS_ACCESS_VIOLATION and family for how
- * this class of failures was determined
- */
- if ((status & 0xFFFF0000) == 0xC0000000)
- {
- result.mState = LLProcess::KILLED;
- }
- else
- {
- result.mState = LLProcess::EXITED;
- }
- result.mData = status;
-
- return result;
+ LLProcess::Status result;
+
+ // This bit of code is cribbed from apr/threadproc/win32/proc.c, a
+ // function (unfortunately static) called why_from_exit_code():
+ /* See WinNT.h STATUS_ACCESS_VIOLATION and family for how
+ * this class of failures was determined
+ */
+ if ((status & 0xFFFF0000) == 0xC0000000)
+ {
+ result.mState = LLProcess::KILLED;
+ }
+ else
+ {
+ result.mState = LLProcess::EXITED;
+ }
+ result.mData = status;
+
+ return result;
}
/// GetLastError()/FormatMessage() boilerplate
static std::string WindowsErrorString(const std::string& operation)
{
- auto result = GetLastError();
- return STRINGIZE(operation << " failed (" << result << "): "
- << windows_message<std::string>(result));
+ auto result = GetLastError();
+ return STRINGIZE(operation << " failed (" << result << "): "
+ << windows_message<std::string>(result));
}
/*****************************************************************************
@@ -1242,117 +1242,117 @@ static std::string WindowsErrorString(const std::string& operation)
void LLProcess::autokill()
{
- // What we ought to do here is to:
- // 1. create a unique process group and run all autokill children in that
- // group (see https://jira.secondlife.com/browse/SWAT-563);
- // 2. figure out a way to intercept control when the viewer exits --
- // gracefully or not;
- // 3. when the viewer exits, kill off the aforementioned process group.
-
- // It's point 2 that's troublesome. Although I've seen some signal-
- // handling logic in the Posix viewer code, I haven't yet found any bit of
- // code that's run no matter how the viewer exits (a try/finally for the
- // whole process, as it were).
+ // What we ought to do here is to:
+ // 1. create a unique process group and run all autokill children in that
+ // group (see https://jira.secondlife.com/browse/SWAT-563);
+ // 2. figure out a way to intercept control when the viewer exits --
+ // gracefully or not;
+ // 3. when the viewer exits, kill off the aforementioned process group.
+
+ // It's point 2 that's troublesome. Although I've seen some signal-
+ // handling logic in the Posix viewer code, I haven't yet found any bit of
+ // code that's run no matter how the viewer exits (a try/finally for the
+ // whole process, as it were).
}
// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
static bool reap_pid(pid_t pid, LLProcess::Status* pstatus=NULL)
{
- LLProcess::Status dummy;
- if (! pstatus)
- {
- // If caller doesn't want to see Status, give us a target anyway so we
- // don't have to have a bunch of conditionals.
- pstatus = &dummy;
- }
-
- int status = 0;
- pid_t wait_result = ::waitpid(pid, &status, WNOHANG);
- if (wait_result == pid)
- {
- *pstatus = interpret_status(status);
- return true;
- }
- if (wait_result == 0)
- {
- pstatus->mState = LLProcess::RUNNING;
- pstatus->mData = 0;
- return false;
- }
-
- // Clear caller's Status block; caller must interpret UNSTARTED to mean
- // "if this PID was ever valid, it no longer is."
- *pstatus = LLProcess::Status();
-
- // We've dealt with the success cases: we were able to reap the child
- // (wait_result == pid) or it's still running (wait_result == 0). It may
- // be that the child terminated but didn't hang around long enough for us
- // to reap. In that case we still have no Status to report, but we can at
- // least state that it's not running.
- if (wait_result == -1 && errno == ECHILD)
- {
- // No such process -- this may mean we're ignoring SIGCHILD.
- return true;
- }
-
- // Uh, should never happen?!
- LL_WARNS("LLProcess") << "LLProcess::reap_pid(): waitpid(" << pid << ") returned "
- << wait_result << "; not meaningful?" << LL_ENDL;
- // If caller is looping until this pid terminates, and if we can't find
- // out, better to break the loop than to claim it's still running.
- return true;
+ LLProcess::Status dummy;
+ if (! pstatus)
+ {
+ // If caller doesn't want to see Status, give us a target anyway so we
+ // don't have to have a bunch of conditionals.
+ pstatus = &dummy;
+ }
+
+ int status = 0;
+ pid_t wait_result = ::waitpid(pid, &status, WNOHANG);
+ if (wait_result == pid)
+ {
+ *pstatus = interpret_status(status);
+ return true;
+ }
+ if (wait_result == 0)
+ {
+ pstatus->mState = LLProcess::RUNNING;
+ pstatus->mData = 0;
+ return false;
+ }
+
+ // Clear caller's Status block; caller must interpret UNSTARTED to mean
+ // "if this PID was ever valid, it no longer is."
+ *pstatus = LLProcess::Status();
+
+ // We've dealt with the success cases: we were able to reap the child
+ // (wait_result == pid) or it's still running (wait_result == 0). It may
+ // be that the child terminated but didn't hang around long enough for us
+ // to reap. In that case we still have no Status to report, but we can at
+ // least state that it's not running.
+ if (wait_result == -1 && errno == ECHILD)
+ {
+ // No such process -- this may mean we're ignoring SIGCHILD.
+ return true;
+ }
+
+ // Uh, should never happen?!
+ LL_WARNS("LLProcess") << "LLProcess::reap_pid(): waitpid(" << pid << ") returned "
+ << wait_result << "; not meaningful?" << LL_ENDL;
+ // If caller is looping until this pid terminates, and if we can't find
+ // out, better to break the loop than to claim it's still running.
+ return true;
}
LLProcess::id LLProcess::isRunning(id pid, const std::string& desc)
{
- // This direct Posix implementation is because we have no access to the
- // apr_proc_t struct: we expect it's been destroyed.
- if (! pid)
- return 0;
-
- // Check whether the process has exited, and reap it if it has.
- LLProcess::Status status;
- if(reap_pid(pid, &status))
- {
- // the process has exited.
- if (! desc.empty())
- {
- std::string statstr(desc + " apparently terminated: no status available");
- // We don't just pass UNSTARTED to getStatusString() because, in
- // the context of reap_pid(), that state has special meaning.
- if (status.mState != UNSTARTED)
- {
- statstr = getStatusString(desc, status);
- }
- LL_INFOS("LLProcess") << statstr << LL_ENDL;
- }
- return 0;
- }
-
- return pid;
+ // This direct Posix implementation is because we have no access to the
+ // apr_proc_t struct: we expect it's been destroyed.
+ if (! pid)
+ return 0;
+
+ // Check whether the process has exited, and reap it if it has.
+ LLProcess::Status status;
+ if(reap_pid(pid, &status))
+ {
+ // the process has exited.
+ if (! desc.empty())
+ {
+ std::string statstr(desc + " apparently terminated: no status available");
+ // We don't just pass UNSTARTED to getStatusString() because, in
+ // the context of reap_pid(), that state has special meaning.
+ if (status.mState != UNSTARTED)
+ {
+ statstr = getStatusString(desc, status);
+ }
+ LL_INFOS("LLProcess") << statstr << LL_ENDL;
+ }
+ return 0;
+ }
+
+ return pid;
}
static LLProcess::Status interpret_status(int status)
{
- LLProcess::Status result;
-
- if (WIFEXITED(status))
- {
- result.mState = LLProcess::EXITED;
- result.mData = WEXITSTATUS(status);
- }
- else if (WIFSIGNALED(status))
- {
- result.mState = LLProcess::KILLED;
- result.mData = WTERMSIG(status);
- }
- else // uh, shouldn't happen?
- {
- result.mState = LLProcess::EXITED;
- result.mData = status; // someone else will have to decode
- }
-
- return result;
+ LLProcess::Status result;
+
+ if (WIFEXITED(status))
+ {
+ result.mState = LLProcess::EXITED;
+ result.mData = WEXITSTATUS(status);
+ }
+ else if (WIFSIGNALED(status))
+ {
+ result.mState = LLProcess::KILLED;
+ result.mData = WTERMSIG(status);
+ }
+ else // uh, shouldn't happen?
+ {
+ result.mState = LLProcess::EXITED;
+ result.mData = status; // someone else will have to decode
+ }
+
+ return result;
}
#endif // Posix
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index c57821bf52..166da8f424 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -1,29 +1,29 @@
-/**
+/**
* @file llprocess.h
* @brief Utility class for launching, terminating, and tracking child processes.
*
* $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$
*/
-
+
#ifndef LL_LLPROCESS_H
#define LL_LLPROCESS_H
@@ -39,7 +39,7 @@
#include <iosfwd> // std::ostream
#if LL_WINDOWS
-#include "llwin32headerslean.h" // for HANDLE
+#include "llwin32headerslean.h" // for HANDLE
#elif LL_LINUX
#if defined(Status)
#undef Status
@@ -71,503 +71,503 @@ typedef std::shared_ptr<LLProcess> LLProcessPtr;
*/
class LL_COMMON_API LLProcess: public boost::noncopyable
{
- LOG_CLASS(LLProcess);
+ LOG_CLASS(LLProcess);
public:
- /**
- * Specify what to pass for each of child stdin, stdout, stderr.
- * @see LLProcess::Params::files.
- */
- struct FileParam: public LLInitParam::Block<FileParam>
- {
- /**
- * type of file handle to pass to child process
- *
- * - "" (default): let the child inherit the same file handle used by
- * this process. For instance, if passed as stdout, child stdout
- * will be interleaved with stdout from this process. In this case,
- * @a name is moot and should be left "".
- *
- * - "file": open an OS filesystem file with the specified @a name.
- * <i>Not yet implemented.</i>
- *
- * - "pipe" or "tpipe" or "npipe": depends on @a name
- *
- * - @a name.empty(): construct an OS pipe used only for this slot
- * of the forthcoming child process.
- *
- * - ! @a name.empty(): in a global registry, find or create (using
- * the specified @a name) an OS pipe. The point of the (purely
- * internal) @a name is that passing the same @a name in more than
- * one slot for a given LLProcess -- or for slots in different
- * LLProcess instances -- means the same pipe. For example, you
- * might pass the same @a name value as both stdout and stderr to
- * make the child process produce both on the same actual pipe. Or
- * you might pass the same @a name as the stdout for one LLProcess
- * and the stdin for another to connect the two child processes.
- * Use LLProcess::getPipeName() to generate a unique name
- * guaranteed not to already exist in the registry. <i>Not yet
- * implemented.</i>
- *
- * The difference between "pipe", "tpipe" and "npipe" is as follows.
- *
- * - "pipe": direct LLProcess to monitor the parent end of the pipe,
- * pumping nonblocking I/O every frame. The expectation (at least
- * for stdout or stderr) is that the caller will listen for
- * incoming data and consume it as it arrives. It's important not
- * to neglect such a pipe, because it's buffered in memory. If you
- * suspect the child may produce a great volume of output between
- * frames, consider directing the child to write to a filesystem
- * file instead, then read the file later.
- *
- * - "tpipe": do not engage LLProcess machinery to monitor the
- * parent end of the pipe. A "tpipe" is used only to connect
- * different child processes. As such, it makes little sense to
- * pass an empty @a name. <i>Not yet implemented.</i>
- *
- * - "npipe": like "tpipe", but use an OS named pipe with a
- * generated name. Note that @a name is the @em internal name of
- * the pipe in our global registry -- it doesn't necessarily have
- * anything to do with the pipe's name in the OS filesystem. Use
- * LLProcess::getPipeName() to obtain the named pipe's OS
- * filesystem name, e.g. to pass it as the @a name to another
- * LLProcess instance using @a type "file". This supports usage
- * like bash's &lt;(subcommand...) or &gt;(subcommand...)
- * constructs. <i>Not yet implemented.</i>
- *
- * In all cases the open mode (read, write) is determined by the child
- * slot you're filling. Child stdin means select the "read" end of a
- * pipe, or open a filesystem file for reading; child stdout or stderr
- * means select the "write" end of a pipe, or open a filesystem file
- * for writing.
- *
- * Confusion such as passing the same pipe as the stdin of two
- * processes (rather than stdout for one and stdin for the other) is
- * explicitly permitted: it's up to the caller to construct meaningful
- * LLProcess pipe graphs.
- */
- Optional<std::string> type;
- Optional<std::string> name;
-
- FileParam(const std::string& tp="", const std::string& nm=""):
- type("type"),
- name("name")
- {
- // If caller wants to specify values, use explicit assignment to
- // set them rather than initialization.
- if (! tp.empty()) type = tp;
- if (! nm.empty()) name = nm;
- }
- };
-
- /// Param block definition
- struct Params: public LLInitParam::Block<Params>
- {
- Params():
- executable("executable"),
- args("args"),
- cwd("cwd"),
- autokill("autokill", true),
- attached("attached", true),
- files("files"),
- postend("postend"),
- desc("desc")
- {}
-
- /// pathname of executable
- Mandatory<std::string> executable;
- /**
- * zero or more additional command-line arguments. Arguments are
- * passed through as exactly as we can manage, whitespace and all.
- * @note On Windows we manage this by implicitly double-quoting each
- * argument while assembling the command line.
- */
- Multiple<std::string> args;
- /// current working directory, if need it changed
- Optional<std::string> cwd;
- /// implicitly kill child process on termination of parent, whether
- /// voluntary or crash (default true)
- Optional<bool> autokill;
- /// implicitly kill process on destruction of LLProcess object
- /// (default same as autokill)
- ///
- /// Originally, 'autokill' conflated two concepts: kill child process on
- /// - destruction of its LLProcess object, and
- /// - termination of parent process, voluntary or otherwise.
- ///
- /// It's useful to tease these apart. Some child processes are sent a
- /// "clean up and terminate" message before the associated LLProcess
- /// object is destroyed. A child process launched with attached=false
- /// has an extra time window from the destruction of its LLProcess
- /// until parent-process termination in which to perform its own
- /// orderly shutdown, yet autokill=true still guarantees that we won't
- /// accumulate orphan instances of such processes indefinitely. With
- /// attached=true, if a child process cannot clean up between the
- /// shutdown message and LLProcess destruction (presumably very soon
- /// thereafter), it's forcibly killed anyway -- which can lead to
- /// distressing user-visible crash indications.
- ///
- /// (The usefulness of attached=true with autokill=false is less
- /// clear, but we don't prohibit that combination.)
- Optional<bool> attached;
- /**
- * Up to three FileParam items: for child stdin, stdout, stderr.
- * Passing two FileParam entries means default treatment for stderr,
- * and so forth.
- *
- * @note LLInitParam::Block permits usage like this:
- * @code
- * LLProcess::Params params;
- * ...
- * params.files
- * .add(LLProcess::FileParam()) // stdin
- * .add(LLProcess::FileParam().type("pipe") // stdout
- * .add(LLProcess::FileParam().type("file").name("error.log"));
- * @endcode
- *
- * @note While it's theoretically plausible to pass additional open
- * file handles to a child specifically written to expect them, our
- * underlying implementation doesn't yet support that.
- */
- Multiple<FileParam, AtMost<3> > files;
- /**
- * On child-process termination, if this LLProcess object still
- * exists, post LLSD event to LLEventPump with specified name (default
- * no event). Event contains at least:
- *
- * - "id" as obtained from getProcessID()
- * - "desc" short string description of child (executable + pid)
- * - "state" @c state enum value, from Status.mState
- * - "data" if "state" is EXITED, exit code; if KILLED, on Posix,
- * signal number
- * - "string" English text describing "state" and "data" (e.g. "exited
- * with code 0")
- */
- Optional<std::string> postend;
- /**
- * Description of child process for logging purposes. It need not be
- * unique; the logged description string will contain the PID as well.
- * If this is omitted, a description will be derived from the
- * executable name.
- */
- Optional<std::string> desc;
- };
- typedef LLSDParamAdapter<Params> LLSDOrParams;
-
- /**
- * Factory accepting either plain LLSD::Map or Params block.
- * MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid!
- */
- static LLProcessPtr create(const LLSDOrParams& params);
- virtual ~LLProcess();
-
- /// Is child process still running?
- bool isRunning() const;
- // static isRunning(LLProcessPtr), getStatus(LLProcessPtr),
- // getStatusString(LLProcessPtr), kill(LLProcessPtr) handle the case in
- // which the passed LLProcessPtr might be NULL (default-constructed).
- static bool isRunning(const LLProcessPtr&);
-
- /**
- * State of child process
- */
- enum state
- {
- UNSTARTED, ///< initial value, invisible to consumer
- RUNNING, ///< child process launched
- EXITED, ///< child process terminated voluntarily
- KILLED ///< child process terminated involuntarily
- };
-
- /**
- * Status info
- */
- struct Status
- {
- Status():
- mState(UNSTARTED),
- mData(0)
- {}
-
- state mState; ///< @see state
- /**
- * - for mState == EXITED: mData is exit() code
- * - for mState == KILLED: mData is signal number (Posix)
- * - otherwise: mData is undefined
- */
- int mData;
- };
-
- /// Status query
- Status getStatus() const;
- static Status getStatus(const LLProcessPtr&);
- /// English Status string query, for logging etc.
- std::string getStatusString() const;
- static std::string getStatusString(const std::string& desc, const LLProcessPtr&);
- /// English Status string query for previously-captured Status
- std::string getStatusString(const Status& status) const;
- /// static English Status string query
- static std::string getStatusString(const std::string& desc, const Status& status);
-
- // Attempt to kill the process -- returns true if the process is no longer running when it returns.
- // Note that even if this returns false, the process may exit some time after it's called.
- bool kill(const std::string& who="");
- static bool kill(const LLProcessPtr& p, const std::string& who="");
+ /**
+ * Specify what to pass for each of child stdin, stdout, stderr.
+ * @see LLProcess::Params::files.
+ */
+ struct FileParam: public LLInitParam::Block<FileParam>
+ {
+ /**
+ * type of file handle to pass to child process
+ *
+ * - "" (default): let the child inherit the same file handle used by
+ * this process. For instance, if passed as stdout, child stdout
+ * will be interleaved with stdout from this process. In this case,
+ * @a name is moot and should be left "".
+ *
+ * - "file": open an OS filesystem file with the specified @a name.
+ * <i>Not yet implemented.</i>
+ *
+ * - "pipe" or "tpipe" or "npipe": depends on @a name
+ *
+ * - @a name.empty(): construct an OS pipe used only for this slot
+ * of the forthcoming child process.
+ *
+ * - ! @a name.empty(): in a global registry, find or create (using
+ * the specified @a name) an OS pipe. The point of the (purely
+ * internal) @a name is that passing the same @a name in more than
+ * one slot for a given LLProcess -- or for slots in different
+ * LLProcess instances -- means the same pipe. For example, you
+ * might pass the same @a name value as both stdout and stderr to
+ * make the child process produce both on the same actual pipe. Or
+ * you might pass the same @a name as the stdout for one LLProcess
+ * and the stdin for another to connect the two child processes.
+ * Use LLProcess::getPipeName() to generate a unique name
+ * guaranteed not to already exist in the registry. <i>Not yet
+ * implemented.</i>
+ *
+ * The difference between "pipe", "tpipe" and "npipe" is as follows.
+ *
+ * - "pipe": direct LLProcess to monitor the parent end of the pipe,
+ * pumping nonblocking I/O every frame. The expectation (at least
+ * for stdout or stderr) is that the caller will listen for
+ * incoming data and consume it as it arrives. It's important not
+ * to neglect such a pipe, because it's buffered in memory. If you
+ * suspect the child may produce a great volume of output between
+ * frames, consider directing the child to write to a filesystem
+ * file instead, then read the file later.
+ *
+ * - "tpipe": do not engage LLProcess machinery to monitor the
+ * parent end of the pipe. A "tpipe" is used only to connect
+ * different child processes. As such, it makes little sense to
+ * pass an empty @a name. <i>Not yet implemented.</i>
+ *
+ * - "npipe": like "tpipe", but use an OS named pipe with a
+ * generated name. Note that @a name is the @em internal name of
+ * the pipe in our global registry -- it doesn't necessarily have
+ * anything to do with the pipe's name in the OS filesystem. Use
+ * LLProcess::getPipeName() to obtain the named pipe's OS
+ * filesystem name, e.g. to pass it as the @a name to another
+ * LLProcess instance using @a type "file". This supports usage
+ * like bash's &lt;(subcommand...) or &gt;(subcommand...)
+ * constructs. <i>Not yet implemented.</i>
+ *
+ * In all cases the open mode (read, write) is determined by the child
+ * slot you're filling. Child stdin means select the "read" end of a
+ * pipe, or open a filesystem file for reading; child stdout or stderr
+ * means select the "write" end of a pipe, or open a filesystem file
+ * for writing.
+ *
+ * Confusion such as passing the same pipe as the stdin of two
+ * processes (rather than stdout for one and stdin for the other) is
+ * explicitly permitted: it's up to the caller to construct meaningful
+ * LLProcess pipe graphs.
+ */
+ Optional<std::string> type;
+ Optional<std::string> name;
+
+ FileParam(const std::string& tp="", const std::string& nm=""):
+ type("type"),
+ name("name")
+ {
+ // If caller wants to specify values, use explicit assignment to
+ // set them rather than initialization.
+ if (! tp.empty()) type = tp;
+ if (! nm.empty()) name = nm;
+ }
+ };
+
+ /// Param block definition
+ struct Params: public LLInitParam::Block<Params>
+ {
+ Params():
+ executable("executable"),
+ args("args"),
+ cwd("cwd"),
+ autokill("autokill", true),
+ attached("attached", true),
+ files("files"),
+ postend("postend"),
+ desc("desc")
+ {}
+
+ /// pathname of executable
+ Mandatory<std::string> executable;
+ /**
+ * zero or more additional command-line arguments. Arguments are
+ * passed through as exactly as we can manage, whitespace and all.
+ * @note On Windows we manage this by implicitly double-quoting each
+ * argument while assembling the command line.
+ */
+ Multiple<std::string> args;
+ /// current working directory, if need it changed
+ Optional<std::string> cwd;
+ /// implicitly kill child process on termination of parent, whether
+ /// voluntary or crash (default true)
+ Optional<bool> autokill;
+ /// implicitly kill process on destruction of LLProcess object
+ /// (default same as autokill)
+ ///
+ /// Originally, 'autokill' conflated two concepts: kill child process on
+ /// - destruction of its LLProcess object, and
+ /// - termination of parent process, voluntary or otherwise.
+ ///
+ /// It's useful to tease these apart. Some child processes are sent a
+ /// "clean up and terminate" message before the associated LLProcess
+ /// object is destroyed. A child process launched with attached=false
+ /// has an extra time window from the destruction of its LLProcess
+ /// until parent-process termination in which to perform its own
+ /// orderly shutdown, yet autokill=true still guarantees that we won't
+ /// accumulate orphan instances of such processes indefinitely. With
+ /// attached=true, if a child process cannot clean up between the
+ /// shutdown message and LLProcess destruction (presumably very soon
+ /// thereafter), it's forcibly killed anyway -- which can lead to
+ /// distressing user-visible crash indications.
+ ///
+ /// (The usefulness of attached=true with autokill=false is less
+ /// clear, but we don't prohibit that combination.)
+ Optional<bool> attached;
+ /**
+ * Up to three FileParam items: for child stdin, stdout, stderr.
+ * Passing two FileParam entries means default treatment for stderr,
+ * and so forth.
+ *
+ * @note LLInitParam::Block permits usage like this:
+ * @code
+ * LLProcess::Params params;
+ * ...
+ * params.files
+ * .add(LLProcess::FileParam()) // stdin
+ * .add(LLProcess::FileParam().type("pipe") // stdout
+ * .add(LLProcess::FileParam().type("file").name("error.log"));
+ * @endcode
+ *
+ * @note While it's theoretically plausible to pass additional open
+ * file handles to a child specifically written to expect them, our
+ * underlying implementation doesn't yet support that.
+ */
+ Multiple<FileParam, AtMost<3> > files;
+ /**
+ * On child-process termination, if this LLProcess object still
+ * exists, post LLSD event to LLEventPump with specified name (default
+ * no event). Event contains at least:
+ *
+ * - "id" as obtained from getProcessID()
+ * - "desc" short string description of child (executable + pid)
+ * - "state" @c state enum value, from Status.mState
+ * - "data" if "state" is EXITED, exit code; if KILLED, on Posix,
+ * signal number
+ * - "string" English text describing "state" and "data" (e.g. "exited
+ * with code 0")
+ */
+ Optional<std::string> postend;
+ /**
+ * Description of child process for logging purposes. It need not be
+ * unique; the logged description string will contain the PID as well.
+ * If this is omitted, a description will be derived from the
+ * executable name.
+ */
+ Optional<std::string> desc;
+ };
+ typedef LLSDParamAdapter<Params> LLSDOrParams;
+
+ /**
+ * Factory accepting either plain LLSD::Map or Params block.
+ * MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid!
+ */
+ static LLProcessPtr create(const LLSDOrParams& params);
+ virtual ~LLProcess();
+
+ /// Is child process still running?
+ bool isRunning() const;
+ // static isRunning(LLProcessPtr), getStatus(LLProcessPtr),
+ // getStatusString(LLProcessPtr), kill(LLProcessPtr) handle the case in
+ // which the passed LLProcessPtr might be NULL (default-constructed).
+ static bool isRunning(const LLProcessPtr&);
+
+ /**
+ * State of child process
+ */
+ enum state
+ {
+ UNSTARTED, ///< initial value, invisible to consumer
+ RUNNING, ///< child process launched
+ EXITED, ///< child process terminated voluntarily
+ KILLED ///< child process terminated involuntarily
+ };
+
+ /**
+ * Status info
+ */
+ struct Status
+ {
+ Status():
+ mState(UNSTARTED),
+ mData(0)
+ {}
+
+ state mState; ///< @see state
+ /**
+ * - for mState == EXITED: mData is exit() code
+ * - for mState == KILLED: mData is signal number (Posix)
+ * - otherwise: mData is undefined
+ */
+ int mData;
+ };
+
+ /// Status query
+ Status getStatus() const;
+ static Status getStatus(const LLProcessPtr&);
+ /// English Status string query, for logging etc.
+ std::string getStatusString() const;
+ static std::string getStatusString(const std::string& desc, const LLProcessPtr&);
+ /// English Status string query for previously-captured Status
+ std::string getStatusString(const Status& status) const;
+ /// static English Status string query
+ static std::string getStatusString(const std::string& desc, const Status& status);
+
+ // Attempt to kill the process -- returns true if the process is no longer running when it returns.
+ // Note that even if this returns false, the process may exit some time after it's called.
+ bool kill(const std::string& who="");
+ static bool kill(const LLProcessPtr& p, const std::string& who="");
#if LL_WINDOWS
- typedef int id; ///< as returned by getProcessID()
- typedef HANDLE handle; ///< as returned by getProcessHandle()
+ typedef int id; ///< as returned by getProcessID()
+ typedef HANDLE handle; ///< as returned by getProcessHandle()
#else
- typedef pid_t id;
- typedef pid_t handle;
+ typedef pid_t id;
+ typedef pid_t handle;
#endif
- /**
- * Get an int-like id value. This is primarily intended for a human reader
- * to differentiate processes.
- */
- id getProcessID() const;
- /**
- * Get a "handle" of a kind that you might pass to platform-specific API
- * functions to engage features not directly supported by LLProcess.
- */
- handle getProcessHandle() const;
-
- /**
- * Test if a process (@c handle obtained from getProcessHandle()) is still
- * running. Return same nonzero @c handle value if still running, else
- * zero, so you can test it like a bool. But if you want to update a
- * stored variable as a side effect, you can write code like this:
- * @code
- * hchild = LLProcess::isRunning(hchild);
- * @endcode
- * @note This method is intended as a unit-test hook, not as the first of
- * a whole set of operations supported on freestanding @c handle values.
- * New functionality should be added as nonstatic members operating on
- * the same data as getProcessHandle().
- *
- * In particular, if child termination is detected by this static isRunning()
- * rather than by nonstatic isRunning(), the LLProcess object won't be
- * aware of the child's changed status and may encounter OS errors trying
- * to obtain it. This static isRunning() is only intended for after the
- * launching LLProcess object has been destroyed.
- */
- static handle isRunning(handle, const std::string& desc="");
-
- /// Provide symbolic access to child's file slots
- enum FILESLOT { STDIN=0, STDOUT=1, STDERR=2, NSLOTS=3 };
-
- /**
- * For a pipe constructed with @a type "npipe", obtain the generated OS
- * filesystem name for the specified pipe. Otherwise returns the empty
- * string. @see LLProcess::FileParam::type
- */
- std::string getPipeName(FILESLOT) const;
-
- /// base of ReadPipe, WritePipe
- class LL_COMMON_API BasePipe
- {
- public:
- virtual ~BasePipe() = 0;
-
- typedef std::size_t size_type;
- static const size_type npos;
-
- /**
- * Get accumulated buffer length.
- *
- * For WritePipe, is there still pending data to send to child?
- *
- * For ReadPipe, we often need to refrain from actually reading the
- * std::istream returned by get_istream() until we've accumulated
- * enough data to make it worthwhile. For instance, if we're expecting
- * a number from the child, but the child happens to flush "12" before
- * emitting "3\n", get_istream() >> myint could return 12 rather than
- * 123!
- */
- virtual size_type size() const = 0;
- };
-
- /// As returned by getWritePipe() or getOptWritePipe()
- class WritePipe: public BasePipe
- {
- public:
- /**
- * Get ostream& on which to write to child's stdin.
- *
- * @usage
- * @code
- * myProcess->getWritePipe().get_ostream() << "Hello, child!" << std::endl;
- * @endcode
- */
- virtual std::ostream& get_ostream() = 0;
- };
-
- /// As returned by getReadPipe() or getOptReadPipe()
- class ReadPipe: public BasePipe
- {
- public:
- /**
- * Get istream& on which to read from child's stdout or stderr.
- *
- * @usage
- * @code
- * std::string stuff;
- * myProcess->getReadPipe().get_istream() >> stuff;
- * @endcode
- *
- * You should be sure in advance that the ReadPipe in question can
- * fill the request. @see getPump()
- */
- virtual std::istream& get_istream() = 0;
-
- /**
- * Like std::getline(get_istream(), line), but trims off trailing '\r'
- * to make calling code less platform-sensitive.
- */
- virtual std::string getline() = 0;
-
- /**
- * Like get_istream().read(buffer, n), but returns std::string rather
- * than requiring caller to construct a buffer, etc.
- */
- virtual std::string read(size_type len) = 0;
-
- /**
- * Peek at accumulated buffer data without consuming it. Optional
- * parameters give you substr() functionality.
- *
- * @note You can discard buffer data using get_istream().ignore(n).
- */
- virtual std::string peek(size_type offset=0, size_type len=npos) const = 0;
-
- /**
- * Detect presence of a substring (or char) in accumulated buffer data
- * without retrieving it. Optional offset allows you to search from
- * specified position.
- */
- template <typename SEEK>
- bool contains(SEEK seek, size_type offset=0) const
- { return find(seek, offset) != npos; }
-
- /**
- * Search for a substring in accumulated buffer data without
- * retrieving it. Returns size_type position at which found, or npos
- * meaning not found. Optional offset allows you to search from
- * specified position.
- */
- virtual size_type find(const std::string& seek, size_type offset=0) const = 0;
-
- /**
- * Search for a char in accumulated buffer data without retrieving it.
- * Returns size_type position at which found, or npos meaning not
- * found. Optional offset allows you to search from specified
- * position.
- */
- virtual size_type find(char seek, size_type offset=0) const = 0;
-
- /**
- * Get LLEventPump& on which to listen for incoming data. The posted
- * LLSD::Map event will contain:
- *
- * - "data" part of pending data; see setLimit()
- * - "len" entire length of pending data, regardless of setLimit()
- * - "slot" this ReadPipe's FILESLOT, e.g. LLProcess::STDOUT
- * - "name" e.g. "stdout"
- * - "desc" e.g. "SLPlugin (pid) stdout"
- * - "eof" @c true means there no more data will arrive on this pipe,
- * therefore no more events on this pump
- *
- * If the child sends "abc", and this ReadPipe posts "data"="abc", but
- * you don't consume it by reading the std::istream returned by
- * get_istream(), and the child next sends "def", ReadPipe will post
- * "data"="abcdef".
- */
- virtual LLEventPump& getPump() = 0;
-
- /**
- * Set maximum length of buffer data that will be posted in the LLSD
- * announcing arrival of new data from the child. If you call
- * setLimit(5), and the child sends "abcdef", the LLSD event will
- * contain "data"="abcde". However, you may still read the entire
- * "abcdef" from get_istream(): this limit affects only the size of
- * the data posted with the LLSD event. If you don't call this method,
- * @em no data will be posted: the default is 0 bytes.
- */
- virtual void setLimit(size_type limit) = 0;
-
- /**
- * Query the current setLimit() limit.
- */
- virtual size_type getLimit() const = 0;
- };
-
- /// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
- /// create a pipe at the corresponding FILESLOT.
- struct NoPipe: public LLException
- {
- NoPipe(const std::string& what): LLException(what) {}
- };
-
- /**
- * Get a reference to the (only) WritePipe for this LLProcess. @a slot, if
- * specified, must be STDIN. Throws NoPipe if you did not request a "pipe"
- * for child stdin. Use this method when you know how you created the
- * LLProcess in hand.
- */
- WritePipe& getWritePipe(FILESLOT slot=STDIN);
-
- /**
- * Get a boost::optional<WritePipe&> to the (only) WritePipe for this
- * LLProcess. @a slot, if specified, must be STDIN. The return value is
- * empty if you did not request a "pipe" for child stdin. Use this method
- * for inspecting an LLProcess you did not create.
- */
- boost::optional<WritePipe&> getOptWritePipe(FILESLOT slot=STDIN);
-
- /**
- * Get a reference to one of the ReadPipes for this LLProcess. @a slot, if
- * specified, must be STDOUT or STDERR. Throws NoPipe if you did not
- * request a "pipe" for child stdout or stderr. Use this method when you
- * know how you created the LLProcess in hand.
- */
- ReadPipe& getReadPipe(FILESLOT slot);
-
- /**
- * Get a boost::optional<ReadPipe&> to one of the ReadPipes for this
- * LLProcess. @a slot, if specified, must be STDOUT or STDERR. The return
- * value is empty if you did not request a "pipe" for child stdout or
- * stderr. Use this method for inspecting an LLProcess you did not create.
- */
- boost::optional<ReadPipe&> getOptReadPipe(FILESLOT slot);
-
- /// little utilities that really should already be somewhere else in the
- /// code base
- static std::string basename(const std::string& path);
- static std::string getline(std::istream&);
+ /**
+ * Get an int-like id value. This is primarily intended for a human reader
+ * to differentiate processes.
+ */
+ id getProcessID() const;
+ /**
+ * Get a "handle" of a kind that you might pass to platform-specific API
+ * functions to engage features not directly supported by LLProcess.
+ */
+ handle getProcessHandle() const;
+
+ /**
+ * Test if a process (@c handle obtained from getProcessHandle()) is still
+ * running. Return same nonzero @c handle value if still running, else
+ * zero, so you can test it like a bool. But if you want to update a
+ * stored variable as a side effect, you can write code like this:
+ * @code
+ * hchild = LLProcess::isRunning(hchild);
+ * @endcode
+ * @note This method is intended as a unit-test hook, not as the first of
+ * a whole set of operations supported on freestanding @c handle values.
+ * New functionality should be added as nonstatic members operating on
+ * the same data as getProcessHandle().
+ *
+ * In particular, if child termination is detected by this static isRunning()
+ * rather than by nonstatic isRunning(), the LLProcess object won't be
+ * aware of the child's changed status and may encounter OS errors trying
+ * to obtain it. This static isRunning() is only intended for after the
+ * launching LLProcess object has been destroyed.
+ */
+ static handle isRunning(handle, const std::string& desc="");
+
+ /// Provide symbolic access to child's file slots
+ enum FILESLOT { STDIN=0, STDOUT=1, STDERR=2, NSLOTS=3 };
+
+ /**
+ * For a pipe constructed with @a type "npipe", obtain the generated OS
+ * filesystem name for the specified pipe. Otherwise returns the empty
+ * string. @see LLProcess::FileParam::type
+ */
+ std::string getPipeName(FILESLOT) const;
+
+ /// base of ReadPipe, WritePipe
+ class LL_COMMON_API BasePipe
+ {
+ public:
+ virtual ~BasePipe() = 0;
+
+ typedef std::size_t size_type;
+ static const size_type npos;
+
+ /**
+ * Get accumulated buffer length.
+ *
+ * For WritePipe, is there still pending data to send to child?
+ *
+ * For ReadPipe, we often need to refrain from actually reading the
+ * std::istream returned by get_istream() until we've accumulated
+ * enough data to make it worthwhile. For instance, if we're expecting
+ * a number from the child, but the child happens to flush "12" before
+ * emitting "3\n", get_istream() >> myint could return 12 rather than
+ * 123!
+ */
+ virtual size_type size() const = 0;
+ };
+
+ /// As returned by getWritePipe() or getOptWritePipe()
+ class WritePipe: public BasePipe
+ {
+ public:
+ /**
+ * Get ostream& on which to write to child's stdin.
+ *
+ * @usage
+ * @code
+ * myProcess->getWritePipe().get_ostream() << "Hello, child!" << std::endl;
+ * @endcode
+ */
+ virtual std::ostream& get_ostream() = 0;
+ };
+
+ /// As returned by getReadPipe() or getOptReadPipe()
+ class ReadPipe: public BasePipe
+ {
+ public:
+ /**
+ * Get istream& on which to read from child's stdout or stderr.
+ *
+ * @usage
+ * @code
+ * std::string stuff;
+ * myProcess->getReadPipe().get_istream() >> stuff;
+ * @endcode
+ *
+ * You should be sure in advance that the ReadPipe in question can
+ * fill the request. @see getPump()
+ */
+ virtual std::istream& get_istream() = 0;
+
+ /**
+ * Like std::getline(get_istream(), line), but trims off trailing '\r'
+ * to make calling code less platform-sensitive.
+ */
+ virtual std::string getline() = 0;
+
+ /**
+ * Like get_istream().read(buffer, n), but returns std::string rather
+ * than requiring caller to construct a buffer, etc.
+ */
+ virtual std::string read(size_type len) = 0;
+
+ /**
+ * Peek at accumulated buffer data without consuming it. Optional
+ * parameters give you substr() functionality.
+ *
+ * @note You can discard buffer data using get_istream().ignore(n).
+ */
+ virtual std::string peek(size_type offset=0, size_type len=npos) const = 0;
+
+ /**
+ * Detect presence of a substring (or char) in accumulated buffer data
+ * without retrieving it. Optional offset allows you to search from
+ * specified position.
+ */
+ template <typename SEEK>
+ bool contains(SEEK seek, size_type offset=0) const
+ { return find(seek, offset) != npos; }
+
+ /**
+ * Search for a substring in accumulated buffer data without
+ * retrieving it. Returns size_type position at which found, or npos
+ * meaning not found. Optional offset allows you to search from
+ * specified position.
+ */
+ virtual size_type find(const std::string& seek, size_type offset=0) const = 0;
+
+ /**
+ * Search for a char in accumulated buffer data without retrieving it.
+ * Returns size_type position at which found, or npos meaning not
+ * found. Optional offset allows you to search from specified
+ * position.
+ */
+ virtual size_type find(char seek, size_type offset=0) const = 0;
+
+ /**
+ * Get LLEventPump& on which to listen for incoming data. The posted
+ * LLSD::Map event will contain:
+ *
+ * - "data" part of pending data; see setLimit()
+ * - "len" entire length of pending data, regardless of setLimit()
+ * - "slot" this ReadPipe's FILESLOT, e.g. LLProcess::STDOUT
+ * - "name" e.g. "stdout"
+ * - "desc" e.g. "SLPlugin (pid) stdout"
+ * - "eof" @c true means there no more data will arrive on this pipe,
+ * therefore no more events on this pump
+ *
+ * If the child sends "abc", and this ReadPipe posts "data"="abc", but
+ * you don't consume it by reading the std::istream returned by
+ * get_istream(), and the child next sends "def", ReadPipe will post
+ * "data"="abcdef".
+ */
+ virtual LLEventPump& getPump() = 0;
+
+ /**
+ * Set maximum length of buffer data that will be posted in the LLSD
+ * announcing arrival of new data from the child. If you call
+ * setLimit(5), and the child sends "abcdef", the LLSD event will
+ * contain "data"="abcde". However, you may still read the entire
+ * "abcdef" from get_istream(): this limit affects only the size of
+ * the data posted with the LLSD event. If you don't call this method,
+ * @em no data will be posted: the default is 0 bytes.
+ */
+ virtual void setLimit(size_type limit) = 0;
+
+ /**
+ * Query the current setLimit() limit.
+ */
+ virtual size_type getLimit() const = 0;
+ };
+
+ /// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
+ /// create a pipe at the corresponding FILESLOT.
+ struct NoPipe: public LLException
+ {
+ NoPipe(const std::string& what): LLException(what) {}
+ };
+
+ /**
+ * Get a reference to the (only) WritePipe for this LLProcess. @a slot, if
+ * specified, must be STDIN. Throws NoPipe if you did not request a "pipe"
+ * for child stdin. Use this method when you know how you created the
+ * LLProcess in hand.
+ */
+ WritePipe& getWritePipe(FILESLOT slot=STDIN);
+
+ /**
+ * Get a boost::optional<WritePipe&> to the (only) WritePipe for this
+ * LLProcess. @a slot, if specified, must be STDIN. The return value is
+ * empty if you did not request a "pipe" for child stdin. Use this method
+ * for inspecting an LLProcess you did not create.
+ */
+ boost::optional<WritePipe&> getOptWritePipe(FILESLOT slot=STDIN);
+
+ /**
+ * Get a reference to one of the ReadPipes for this LLProcess. @a slot, if
+ * specified, must be STDOUT or STDERR. Throws NoPipe if you did not
+ * request a "pipe" for child stdout or stderr. Use this method when you
+ * know how you created the LLProcess in hand.
+ */
+ ReadPipe& getReadPipe(FILESLOT slot);
+
+ /**
+ * Get a boost::optional<ReadPipe&> to one of the ReadPipes for this
+ * LLProcess. @a slot, if specified, must be STDOUT or STDERR. The return
+ * value is empty if you did not request a "pipe" for child stdout or
+ * stderr. Use this method for inspecting an LLProcess you did not create.
+ */
+ boost::optional<ReadPipe&> getOptReadPipe(FILESLOT slot);
+
+ /// little utilities that really should already be somewhere else in the
+ /// code base
+ static std::string basename(const std::string& path);
+ static std::string getline(std::istream&);
private:
- /// constructor is private: use create() instead
- LLProcess(const LLSDOrParams& params);
- void autokill();
- // Classic-C-style APR callback
- static void status_callback(int reason, void* data, int status);
- // Object-oriented callback
- void handle_status(int reason, int status);
- // implementation for get[Opt][Read|Write]Pipe()
- template <class PIPETYPE>
- PIPETYPE& getPipe(FILESLOT slot);
- template <class PIPETYPE>
- boost::optional<PIPETYPE&> getOptPipe(FILESLOT slot);
- template <class PIPETYPE>
- PIPETYPE* getPipePtr(std::string& error, FILESLOT slot);
-
- std::string mDesc;
- std::string mPostend;
- apr_proc_t mProcess;
- bool mAutokill, mAttached;
- Status mStatus;
- // explicitly want this ptr_vector to be able to store NULLs
- typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector;
- PipeVector mPipes;
+ /// constructor is private: use create() instead
+ LLProcess(const LLSDOrParams& params);
+ void autokill();
+ // Classic-C-style APR callback
+ static void status_callback(int reason, void* data, int status);
+ // Object-oriented callback
+ void handle_status(int reason, int status);
+ // implementation for get[Opt][Read|Write]Pipe()
+ template <class PIPETYPE>
+ PIPETYPE& getPipe(FILESLOT slot);
+ template <class PIPETYPE>
+ boost::optional<PIPETYPE&> getOptPipe(FILESLOT slot);
+ template <class PIPETYPE>
+ PIPETYPE* getPipePtr(std::string& error, FILESLOT slot);
+
+ std::string mDesc;
+ std::string mPostend;
+ apr_proc_t mProcess;
+ bool mAutokill, mAttached;
+ Status mStatus;
+ // explicitly want this ptr_vector to be able to store NULLs
+ typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector;
+ PipeVector mPipes;
apr_pool_t* mPool;
};
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 4cdc3d7519..3a05407dd0 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llprocessor.cpp
* @brief Code to figure out the processor. Originally by Benjamin Jurke.
*
* $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$
*/
@@ -34,199 +34,199 @@
//#include <memory>
#if LL_WINDOWS
-# include "llwin32headerslean.h"
-# define _interlockedbittestandset _renamed_interlockedbittestandset
-# define _interlockedbittestandreset _renamed_interlockedbittestandreset
-# include <intrin.h>
-# undef _interlockedbittestandset
-# undef _interlockedbittestandreset
+# include "llwin32headerslean.h"
+# define _interlockedbittestandset _renamed_interlockedbittestandset
+# define _interlockedbittestandreset _renamed_interlockedbittestandreset
+# include <intrin.h>
+# undef _interlockedbittestandset
+# undef _interlockedbittestandreset
#endif
#include "llsd.h"
class LLProcessorInfoImpl; // foward declaration for the mImpl;
-namespace
+namespace
{
- enum cpu_info
- {
- eBrandName = 0,
- eFrequency,
- eVendor,
- eStepping,
- eFamily,
- eExtendedFamily,
- eModel,
- eExtendedModel,
- eType,
- eBrandID,
- eFamilyName
- };
-
-
- const char* cpu_info_names[] =
- {
- "Processor Name",
- "Frequency",
- "Vendor",
- "Stepping",
- "Family",
- "Extended Family",
- "Model",
- "Extended Model",
- "Type",
- "Brand ID",
- "Family Name"
- };
-
- enum cpu_config
- {
- eMaxID,
- eMaxExtID,
- eCLFLUSHCacheLineSize,
- eAPICPhysicalID,
- eCacheLineSize,
- eL2Associativity,
- eCacheSizeK,
- eFeatureBits,
- eExtFeatureBits
- };
-
- const char* cpu_config_names[] =
- {
- "Max Supported CPUID level",
- "Max Supported Ext. CPUID level",
- "CLFLUSH cache line size",
- "APIC Physical ID",
- "Cache Line Size",
- "L2 Associativity",
- "Cache Size",
- "Feature Bits",
- "Ext. Feature Bits"
- };
-
-
-
- // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32.
- // The rest of the names are referenced by bit maks returned from cpuid.
- enum cpu_features
- {
- eSSE_Ext=25,
- eSSE2_Ext=26,
-
- eSSE3_Features=32,
- eMONTIOR_MWAIT=33,
- eCPLDebugStore=34,
- eThermalMonitor2=35,
- eAltivec=36,
+ enum cpu_info
+ {
+ eBrandName = 0,
+ eFrequency,
+ eVendor,
+ eStepping,
+ eFamily,
+ eExtendedFamily,
+ eModel,
+ eExtendedModel,
+ eType,
+ eBrandID,
+ eFamilyName
+ };
+
+
+ const char* cpu_info_names[] =
+ {
+ "Processor Name",
+ "Frequency",
+ "Vendor",
+ "Stepping",
+ "Family",
+ "Extended Family",
+ "Model",
+ "Extended Model",
+ "Type",
+ "Brand ID",
+ "Family Name"
+ };
+
+ enum cpu_config
+ {
+ eMaxID,
+ eMaxExtID,
+ eCLFLUSHCacheLineSize,
+ eAPICPhysicalID,
+ eCacheLineSize,
+ eL2Associativity,
+ eCacheSizeK,
+ eFeatureBits,
+ eExtFeatureBits
+ };
+
+ const char* cpu_config_names[] =
+ {
+ "Max Supported CPUID level",
+ "Max Supported Ext. CPUID level",
+ "CLFLUSH cache line size",
+ "APIC Physical ID",
+ "Cache Line Size",
+ "L2 Associativity",
+ "Cache Size",
+ "Feature Bits",
+ "Ext. Feature Bits"
+ };
+
+
+
+ // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32.
+ // The rest of the names are referenced by bit maks returned from cpuid.
+ enum cpu_features
+ {
+ eSSE_Ext=25,
+ eSSE2_Ext=26,
+
+ eSSE3_Features=32,
+ eMONTIOR_MWAIT=33,
+ eCPLDebugStore=34,
+ eThermalMonitor2=35,
+ eAltivec=36,
eSSE3S_Features = 37,
eSSE4_1_Features = 38,
eSSE4_2_Features = 39,
eSSE4a_Features = 40,
- };
-
- const char* cpu_feature_names[] =
- {
- "x87 FPU On Chip",
- "Virtual-8086 Mode Enhancement",
- "Debugging Extensions",
- "Page Size Extensions",
- "Time Stamp Counter",
- "RDMSR and WRMSR Support",
- "Physical Address Extensions",
- "Machine Check Exception",
- "CMPXCHG8B Instruction",
- "APIC On Chip",
- "Unknown1",
- "SYSENTER and SYSEXIT",
- "Memory Type Range Registers",
- "PTE Global Bit",
- "Machine Check Architecture",
- "Conditional Move/Compare Instruction",
- "Page Attribute Table",
- "Page Size Extension",
- "Processor Serial Number",
- "CFLUSH Extension",
- "Unknown2",
- "Debug Store",
- "Thermal Monitor and Clock Ctrl",
- "MMX Technology",
- "FXSAVE/FXRSTOR",
- "SSE Extensions",
- "SSE2 Extensions",
- "Self Snoop",
- "Hyper-threading Technology",
- "Thermal Monitor",
- "Unknown4",
- "Pend. Brk. EN.", // 31 End of FeatureInfo bits
-
- "SSE3 New Instructions", // 32
- "MONITOR/MWAIT",
- "CPL Qualified Debug Store",
- "Thermal Monitor 2",
-
- "Altivec",
+ };
+
+ const char* cpu_feature_names[] =
+ {
+ "x87 FPU On Chip",
+ "Virtual-8086 Mode Enhancement",
+ "Debugging Extensions",
+ "Page Size Extensions",
+ "Time Stamp Counter",
+ "RDMSR and WRMSR Support",
+ "Physical Address Extensions",
+ "Machine Check Exception",
+ "CMPXCHG8B Instruction",
+ "APIC On Chip",
+ "Unknown1",
+ "SYSENTER and SYSEXIT",
+ "Memory Type Range Registers",
+ "PTE Global Bit",
+ "Machine Check Architecture",
+ "Conditional Move/Compare Instruction",
+ "Page Attribute Table",
+ "Page Size Extension",
+ "Processor Serial Number",
+ "CFLUSH Extension",
+ "Unknown2",
+ "Debug Store",
+ "Thermal Monitor and Clock Ctrl",
+ "MMX Technology",
+ "FXSAVE/FXRSTOR",
+ "SSE Extensions",
+ "SSE2 Extensions",
+ "Self Snoop",
+ "Hyper-threading Technology",
+ "Thermal Monitor",
+ "Unknown4",
+ "Pend. Brk. EN.", // 31 End of FeatureInfo bits
+
+ "SSE3 New Instructions", // 32
+ "MONITOR/MWAIT",
+ "CPL Qualified Debug Store",
+ "Thermal Monitor 2",
+
+ "Altivec",
"SSE3S Instructions",
"SSE4.1 Instructions",
"SSE4.2 Instructions",
"SSE4a Instructions",
- };
-
- std::string intel_CPUFamilyName(int composed_family)
- {
- switch(composed_family)
- {
- case 3: return "Intel i386";
- case 4: return "Intel i486";
- case 5: return "Intel Pentium";
- case 6: return "Intel Pentium Pro/2/3, Core";
- case 7: return "Intel Itanium (IA-64)";
- case 0xF: return "Intel Pentium 4";
- case 0x10: return "Intel Itanium 2 (IA-64)";
- }
- return STRINGIZE("Intel <unknown 0x" << std::hex << composed_family << ">");
- }
-
- std::string amd_CPUFamilyName(int composed_family)
- {
+ };
+
+ std::string intel_CPUFamilyName(int composed_family)
+ {
+ switch(composed_family)
+ {
+ case 3: return "Intel i386";
+ case 4: return "Intel i486";
+ case 5: return "Intel Pentium";
+ case 6: return "Intel Pentium Pro/2/3, Core";
+ case 7: return "Intel Itanium (IA-64)";
+ case 0xF: return "Intel Pentium 4";
+ case 0x10: return "Intel Itanium 2 (IA-64)";
+ }
+ return STRINGIZE("Intel <unknown 0x" << std::hex << composed_family << ">");
+ }
+
+ std::string amd_CPUFamilyName(int composed_family)
+ {
// https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
// https://developer.amd.com/resources/developer-guides-manuals/
- switch(composed_family)
- {
- case 4: return "AMD 80486/5x86";
- case 5: return "AMD K5/K6";
- case 6: return "AMD K7";
- case 0xF: return "AMD K8";
- case 0x10: return "AMD K8L";
- case 0x12: return "AMD K10";
- case 0x14: return "AMD Bobcat";
- case 0x15: return "AMD Bulldozer";
- case 0x16: return "AMD Jaguar";
- case 0x17: return "AMD Zen/Zen+/Zen2";
- case 0x18: return "AMD Hygon Dhyana";
- case 0x19: return "AMD Zen 3";
- }
- return STRINGIZE("AMD <unknown 0x" << std::hex << composed_family << ">");
- }
-
- std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family)
- {
- const char* intel_string = "GenuineIntel";
- const char* amd_string = "AuthenticAMD";
- if (LLStringUtil::startsWith(cpu_vendor, intel_string))
- {
- U32 composed_family = family + ext_family;
- return intel_CPUFamilyName(composed_family);
- }
- else if (LLStringUtil::startsWith(cpu_vendor, amd_string))
- {
- U32 composed_family = (family == 0xF)
- ? family + ext_family
- : family;
- return amd_CPUFamilyName(composed_family);
- }
- return STRINGIZE("Unrecognized CPU vendor <" << cpu_vendor << ">");
- }
+ switch(composed_family)
+ {
+ case 4: return "AMD 80486/5x86";
+ case 5: return "AMD K5/K6";
+ case 6: return "AMD K7";
+ case 0xF: return "AMD K8";
+ case 0x10: return "AMD K8L";
+ case 0x12: return "AMD K10";
+ case 0x14: return "AMD Bobcat";
+ case 0x15: return "AMD Bulldozer";
+ case 0x16: return "AMD Jaguar";
+ case 0x17: return "AMD Zen/Zen+/Zen2";
+ case 0x18: return "AMD Hygon Dhyana";
+ case 0x19: return "AMD Zen 3";
+ }
+ return STRINGIZE("AMD <unknown 0x" << std::hex << composed_family << ">");
+ }
+
+ std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family)
+ {
+ const char* intel_string = "GenuineIntel";
+ const char* amd_string = "AuthenticAMD";
+ if (LLStringUtil::startsWith(cpu_vendor, intel_string))
+ {
+ U32 composed_family = family + ext_family;
+ return intel_CPUFamilyName(composed_family);
+ }
+ else if (LLStringUtil::startsWith(cpu_vendor, amd_string))
+ {
+ U32 composed_family = (family == 0xF)
+ ? family + ext_family
+ : family;
+ return amd_CPUFamilyName(composed_family);
+ }
+ return STRINGIZE("Unrecognized CPU vendor <" << cpu_vendor << ">");
+ }
} // end unnamed namespace
@@ -235,28 +235,28 @@ namespace
class LLProcessorInfoImpl
{
public:
- LLProcessorInfoImpl()
- {
- mProcessorInfo["info"] = LLSD::emptyMap();
- mProcessorInfo["config"] = LLSD::emptyMap();
- mProcessorInfo["extension"] = LLSD::emptyMap();
- }
- virtual ~LLProcessorInfoImpl() {}
-
- F64 getCPUFrequency() const
- {
- return getInfo(eFrequency, 0).asReal();
- }
-
- bool hasSSE() const
- {
- return hasExtension(cpu_feature_names[eSSE_Ext]);
- }
-
- bool hasSSE2() const
- {
- return hasExtension(cpu_feature_names[eSSE2_Ext]);
- }
+ LLProcessorInfoImpl()
+ {
+ mProcessorInfo["info"] = LLSD::emptyMap();
+ mProcessorInfo["config"] = LLSD::emptyMap();
+ mProcessorInfo["extension"] = LLSD::emptyMap();
+ }
+ virtual ~LLProcessorInfoImpl() {}
+
+ F64 getCPUFrequency() const
+ {
+ return getInfo(eFrequency, 0).asReal();
+ }
+
+ bool hasSSE() const
+ {
+ return hasExtension(cpu_feature_names[eSSE_Ext]);
+ }
+
+ bool hasSSE2() const
+ {
+ return hasExtension(cpu_feature_names[eSSE2_Ext]);
+ }
bool hasSSE3() const
{
@@ -283,229 +283,229 @@ public:
return hasExtension(cpu_feature_names[eSSE4a_Features]);
}
- bool hasAltivec() const
- {
- return hasExtension("Altivec");
- }
-
- std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unset family").asString(); }
- std::string getCPUBrandName() const { return getInfo(eBrandName, "Unset brand").asString(); }
-
- // This is virtual to support a different linux format.
- // *NOTE:Mani - I didn't want to screw up server use of this data...
- virtual std::string getCPUFeatureDescription() const
- {
- std::ostringstream out;
- out << std::endl << std::endl;
- out << "// CPU General Information" << std::endl;
- out << "//////////////////////////" << std::endl;
- out << "Processor Name: " << getCPUBrandName() << std::endl;
- out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl;
- out << "Vendor: " << getInfo(eVendor, "Unset vendor").asString() << std::endl;
- out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl;
- out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl;
- out << "Model: " << getInfo(eModel, 0) << std::endl;
- out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl;
- out << "Type: " << getInfo(eType, 0) << std::endl;
- out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl;
- out << std::endl;
- out << "// CPU Configuration" << std::endl;
- out << "//////////////////////////" << std::endl;
-
- // Iterate through the dictionary of configuration options.
- LLSD configs = mProcessorInfo["config"];
- for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr)
- {
- out << cfgItr->first << " = " << cfgItr->second << std::endl;
- }
- out << std::endl;
-
- out << "// CPU Extensions" << std::endl;
- out << "//////////////////////////" << std::endl;
-
- for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr)
- {
- out << " " << itr->first << std::endl;
- }
- return out.str();
- }
+ bool hasAltivec() const
+ {
+ return hasExtension("Altivec");
+ }
+
+ std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unset family").asString(); }
+ std::string getCPUBrandName() const { return getInfo(eBrandName, "Unset brand").asString(); }
+
+ // This is virtual to support a different linux format.
+ // *NOTE:Mani - I didn't want to screw up server use of this data...
+ virtual std::string getCPUFeatureDescription() const
+ {
+ std::ostringstream out;
+ out << std::endl << std::endl;
+ out << "// CPU General Information" << std::endl;
+ out << "//////////////////////////" << std::endl;
+ out << "Processor Name: " << getCPUBrandName() << std::endl;
+ out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl;
+ out << "Vendor: " << getInfo(eVendor, "Unset vendor").asString() << std::endl;
+ out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl;
+ out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl;
+ out << "Model: " << getInfo(eModel, 0) << std::endl;
+ out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl;
+ out << "Type: " << getInfo(eType, 0) << std::endl;
+ out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl;
+ out << std::endl;
+ out << "// CPU Configuration" << std::endl;
+ out << "//////////////////////////" << std::endl;
+
+ // Iterate through the dictionary of configuration options.
+ LLSD configs = mProcessorInfo["config"];
+ for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr)
+ {
+ out << cfgItr->first << " = " << cfgItr->second << std::endl;
+ }
+ out << std::endl;
+
+ out << "// CPU Extensions" << std::endl;
+ out << "//////////////////////////" << std::endl;
+
+ for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr)
+ {
+ out << " " << itr->first << std::endl;
+ }
+ return out.str();
+ }
protected:
- void setInfo(cpu_info info_type, const LLSD& value)
- {
- setInfo(cpu_info_names[info_type], value);
- }
+ void setInfo(cpu_info info_type, const LLSD& value)
+ {
+ setInfo(cpu_info_names[info_type], value);
+ }
LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const
- {
- return getInfo(cpu_info_names[info_type], defaultVal);
- }
-
- void setConfig(cpu_config config_type, const LLSD& value)
- {
- setConfig(cpu_config_names[config_type], value);
- }
- LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const
- {
- return getConfig(cpu_config_names[config_type], defaultVal);
- }
-
- void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; }
- bool hasExtension(const std::string& name) const
- {
- return mProcessorInfo["extension"].has(name);
- }
+ {
+ return getInfo(cpu_info_names[info_type], defaultVal);
+ }
+
+ void setConfig(cpu_config config_type, const LLSD& value)
+ {
+ setConfig(cpu_config_names[config_type], value);
+ }
+ LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const
+ {
+ return getConfig(cpu_config_names[config_type], defaultVal);
+ }
+
+ void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; }
+ bool hasExtension(const std::string& name) const
+ {
+ return mProcessorInfo["extension"].has(name);
+ }
private:
- void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; }
- LLSD getInfo(const std::string& name, const LLSD& defaultVal) const
- {
- if(mProcessorInfo["info"].has(name))
- {
- return mProcessorInfo["info"][name];
- }
- return defaultVal;
- }
- void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; }
- LLSD getConfig(const std::string& name, const LLSD& defaultVal) const
- {
- LLSD r = mProcessorInfo["config"].get(name);
- return r.isDefined() ? r : defaultVal;
- }
+ void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; }
+ LLSD getInfo(const std::string& name, const LLSD& defaultVal) const
+ {
+ if(mProcessorInfo["info"].has(name))
+ {
+ return mProcessorInfo["info"][name];
+ }
+ return defaultVal;
+ }
+ void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; }
+ LLSD getConfig(const std::string& name, const LLSD& defaultVal) const
+ {
+ LLSD r = mProcessorInfo["config"].get(name);
+ return r.isDefined() ? r : defaultVal;
+ }
private:
- LLSD mProcessorInfo;
+ LLSD mProcessorInfo;
};
#ifdef LL_MSVC
-// LL_MSVC and not LLWINDOWS because some of the following code
+// LL_MSVC and not LLWINDOWS because some of the following code
// uses the MSVC compiler intrinsics __cpuid() and __rdtsc().
// Delays for the specified amount of milliseconds
static void _Delay(unsigned int ms)
{
- LARGE_INTEGER freq, c1, c2;
- __int64 x;
-
- // Get High-Res Timer frequency
- if (!QueryPerformanceFrequency(&freq))
- return;
-
- // Convert ms to High-Res Timer value
- x = freq.QuadPart/1000*ms;
-
- // Get first snapshot of High-Res Timer value
- QueryPerformanceCounter(&c1);
- do
- {
- // Get second snapshot
- QueryPerformanceCounter(&c2);
- }while(c2.QuadPart-c1.QuadPart < x);
- // Loop while (second-first < x)
+ LARGE_INTEGER freq, c1, c2;
+ __int64 x;
+
+ // Get High-Res Timer frequency
+ if (!QueryPerformanceFrequency(&freq))
+ return;
+
+ // Convert ms to High-Res Timer value
+ x = freq.QuadPart/1000*ms;
+
+ // Get first snapshot of High-Res Timer value
+ QueryPerformanceCounter(&c1);
+ do
+ {
+ // Get second snapshot
+ QueryPerformanceCounter(&c2);
+ }while(c2.QuadPart-c1.QuadPart < x);
+ // Loop while (second-first < x)
}
static F64 calculate_cpu_frequency(U32 measure_msecs)
{
- if(measure_msecs == 0)
- {
- return 0;
- }
-
- // After that we declare some vars and check the frequency of the high
- // resolution timer for the measure process.
- // If there"s no high-res timer, we exit.
- unsigned __int64 starttime, endtime, timedif, freq, start, end, dif;
- if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
- {
- return 0;
- }
-
- // Now we can init the measure process. We set the process and thread priority
- // to the highest available level (Realtime priority). Also we focus the
- // first processor in the multiprocessor system.
- HANDLE hProcess = GetCurrentProcess();
- HANDLE hThread = GetCurrentThread();
- unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
- int iCurThreadPriority = GetThreadPriority(hThread);
- DWORD_PTR dwProcessMask, dwSystemMask, dwNewMask = 1;
- GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
-
- SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
- SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
- SetProcessAffinityMask(hProcess, dwNewMask);
-
- //// Now we call a CPUID to ensure, that all other prior called functions are
- //// completed now (serialization)
- //__asm cpuid
- int cpu_info[4] = {-1};
- __cpuid(cpu_info, 0);
-
- // We ask the high-res timer for the start time
- QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
-
- // Then we get the current cpu clock and store it
- start = __rdtsc();
-
- // Now we wart for some msecs
- _Delay(measure_msecs);
- // Sleep(uiMeasureMSecs);
-
- // We ask for the end time
- QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
-
- // And also for the end cpu clock
- end = __rdtsc();
-
- // Now we can restore the default process and thread priorities
- SetProcessAffinityMask(hProcess, dwProcessMask);
- SetThreadPriority(hThread, iCurThreadPriority);
- SetPriorityClass(hProcess, dwCurPriorityClass);
-
- // Then we calculate the time and clock differences
- dif = end - start;
- timedif = endtime - starttime;
-
- // And finally the frequency is the clock difference divided by the time
- // difference.
- F64 frequency = (F64)dif / (((F64)timedif) / freq);
-
- // At last we just return the frequency that is also stored in the call
- // member var uqwFrequency - converted to MHz
- return frequency / (F64)1000000;
+ if(measure_msecs == 0)
+ {
+ return 0;
+ }
+
+ // After that we declare some vars and check the frequency of the high
+ // resolution timer for the measure process.
+ // If there"s no high-res timer, we exit.
+ unsigned __int64 starttime, endtime, timedif, freq, start, end, dif;
+ if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
+ {
+ return 0;
+ }
+
+ // Now we can init the measure process. We set the process and thread priority
+ // to the highest available level (Realtime priority). Also we focus the
+ // first processor in the multiprocessor system.
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hThread = GetCurrentThread();
+ unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
+ int iCurThreadPriority = GetThreadPriority(hThread);
+ DWORD_PTR dwProcessMask, dwSystemMask, dwNewMask = 1;
+ GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
+
+ SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
+ SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
+ SetProcessAffinityMask(hProcess, dwNewMask);
+
+ //// Now we call a CPUID to ensure, that all other prior called functions are
+ //// completed now (serialization)
+ //__asm cpuid
+ int cpu_info[4] = {-1};
+ __cpuid(cpu_info, 0);
+
+ // We ask the high-res timer for the start time
+ QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
+
+ // Then we get the current cpu clock and store it
+ start = __rdtsc();
+
+ // Now we wart for some msecs
+ _Delay(measure_msecs);
+ // Sleep(uiMeasureMSecs);
+
+ // We ask for the end time
+ QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
+
+ // And also for the end cpu clock
+ end = __rdtsc();
+
+ // Now we can restore the default process and thread priorities
+ SetProcessAffinityMask(hProcess, dwProcessMask);
+ SetThreadPriority(hThread, iCurThreadPriority);
+ SetPriorityClass(hProcess, dwCurPriorityClass);
+
+ // Then we calculate the time and clock differences
+ dif = end - start;
+ timedif = endtime - starttime;
+
+ // And finally the frequency is the clock difference divided by the time
+ // difference.
+ F64 frequency = (F64)dif / (((F64)timedif) / freq);
+
+ // At last we just return the frequency that is also stored in the call
+ // member var uqwFrequency - converted to MHz
+ return frequency / (F64)1000000;
}
// Windows implementation
class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl
{
public:
- LLProcessorInfoWindowsImpl()
- {
- getCPUIDInfo();
- setInfo(eFrequency, calculate_cpu_frequency(50));
- }
+ LLProcessorInfoWindowsImpl()
+ {
+ getCPUIDInfo();
+ setInfo(eFrequency, calculate_cpu_frequency(50));
+ }
private:
- void getCPUIDInfo()
- {
- // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx
-
- // __cpuid with an InfoType argument of 0 returns the number of
- // valid Ids in cpu_info[0] and the CPU identification string in
- // the other three array elements. The CPU identification string is
- // not in linear order. The code below arranges the information
- // in a human readable form.
- int cpu_info[4] = {-1};
- __cpuid(cpu_info, 0);
- unsigned int ids = (unsigned int)cpu_info[0];
- setConfig(eMaxID, (S32)ids);
-
- char cpu_vendor[0x20];
- memset(cpu_vendor, 0, sizeof(cpu_vendor));
- *((int*)cpu_vendor) = cpu_info[1];
- *((int*)(cpu_vendor+4)) = cpu_info[3];
- *((int*)(cpu_vendor+8)) = cpu_info[2];
- setInfo(eVendor, cpu_vendor);
+ void getCPUIDInfo()
+ {
+ // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx
+
+ // __cpuid with an InfoType argument of 0 returns the number of
+ // valid Ids in cpu_info[0] and the CPU identification string in
+ // the other three array elements. The CPU identification string is
+ // not in linear order. The code below arranges the information
+ // in a human readable form.
+ int cpu_info[4] = {-1};
+ __cpuid(cpu_info, 0);
+ unsigned int ids = (unsigned int)cpu_info[0];
+ setConfig(eMaxID, (S32)ids);
+
+ char cpu_vendor[0x20];
+ memset(cpu_vendor, 0, sizeof(cpu_vendor));
+ *((int*)cpu_vendor) = cpu_info[1];
+ *((int*)(cpu_vendor+4)) = cpu_info[3];
+ *((int*)(cpu_vendor+8)) = cpu_info[2];
+ setInfo(eVendor, cpu_vendor);
std::string cmp_vendor(cpu_vendor);
bool is_amd = false;
if (cmp_vendor == "AuthenticAMD")
@@ -513,49 +513,49 @@ private:
is_amd = true;
}
- // Get the information associated with each valid Id
- for(unsigned int i=0; i<=ids; ++i)
- {
- __cpuid(cpu_info, i);
-
- // Interpret CPU feature information.
- if (i == 1)
- {
- setInfo(eStepping, cpu_info[0] & 0xf);
- setInfo(eModel, (cpu_info[0] >> 4) & 0xf);
- int family = (cpu_info[0] >> 8) & 0xf;
- setInfo(eFamily, family);
- setInfo(eType, (cpu_info[0] >> 12) & 0x3);
- setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf);
- int ext_family = (cpu_info[0] >> 20) & 0xff;
- setInfo(eExtendedFamily, ext_family);
- setInfo(eBrandID, cpu_info[1] & 0xff);
-
- setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
-
- setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
- setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
-
- if(cpu_info[2] & 0x1)
- {
- setExtension(cpu_feature_names[eSSE3_Features]);
- }
-
- if(cpu_info[2] & 0x8)
- {
+ // Get the information associated with each valid Id
+ for(unsigned int i=0; i<=ids; ++i)
+ {
+ __cpuid(cpu_info, i);
+
+ // Interpret CPU feature information.
+ if (i == 1)
+ {
+ setInfo(eStepping, cpu_info[0] & 0xf);
+ setInfo(eModel, (cpu_info[0] >> 4) & 0xf);
+ int family = (cpu_info[0] >> 8) & 0xf;
+ setInfo(eFamily, family);
+ setInfo(eType, (cpu_info[0] >> 12) & 0x3);
+ setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf);
+ int ext_family = (cpu_info[0] >> 20) & 0xff;
+ setInfo(eExtendedFamily, ext_family);
+ setInfo(eBrandID, cpu_info[1] & 0xff);
+
+ setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+
+ setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+ setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+
+ if(cpu_info[2] & 0x1)
+ {
+ setExtension(cpu_feature_names[eSSE3_Features]);
+ }
+
+ if(cpu_info[2] & 0x8)
+ {
// intel specific SSE3 suplements
- setExtension(cpu_feature_names[eMONTIOR_MWAIT]);
- }
-
- if(cpu_info[2] & 0x10)
- {
- setExtension(cpu_feature_names[eCPLDebugStore]);
- }
-
- if(cpu_info[2] & 0x100)
- {
- setExtension(cpu_feature_names[eThermalMonitor2]);
- }
+ setExtension(cpu_feature_names[eMONTIOR_MWAIT]);
+ }
+
+ if(cpu_info[2] & 0x10)
+ {
+ setExtension(cpu_feature_names[eCPLDebugStore]);
+ }
+
+ if(cpu_info[2] & 0x100)
+ {
+ setExtension(cpu_feature_names[eThermalMonitor2]);
+ }
if (cpu_info[2] & 0x200)
{
@@ -572,32 +572,32 @@ private:
setExtension(cpu_feature_names[eSSE4_2_Features]);
}
- unsigned int feature_info = (unsigned int) cpu_info[3];
- for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
- {
- if(feature_info & bit)
- {
- setExtension(cpu_feature_names[index]);
- }
- }
- }
- }
-
- // Calling __cpuid with 0x80000000 as the InfoType argument
- // gets the number of valid extended IDs.
- __cpuid(cpu_info, 0x80000000);
- unsigned int ext_ids = cpu_info[0];
- setConfig(eMaxExtID, 0);
-
- char cpu_brand_string[0x40];
- memset(cpu_brand_string, 0, sizeof(cpu_brand_string));
-
- // Get the information associated with each extended ID.
- for(unsigned int i=0x80000000; i<=ext_ids; ++i)
- {
- __cpuid(cpu_info, i);
-
- // Interpret CPU brand string and cache information.
+ unsigned int feature_info = (unsigned int) cpu_info[3];
+ for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
+ {
+ if(feature_info & bit)
+ {
+ setExtension(cpu_feature_names[index]);
+ }
+ }
+ }
+ }
+
+ // Calling __cpuid with 0x80000000 as the InfoType argument
+ // gets the number of valid extended IDs.
+ __cpuid(cpu_info, 0x80000000);
+ unsigned int ext_ids = cpu_info[0];
+ setConfig(eMaxExtID, 0);
+
+ char cpu_brand_string[0x40];
+ memset(cpu_brand_string, 0, sizeof(cpu_brand_string));
+
+ // Get the information associated with each extended ID.
+ for(unsigned int i=0x80000000; i<=ext_ids; ++i)
+ {
+ __cpuid(cpu_info, i);
+
+ // Interpret CPU brand string and cache information.
if (i == 0x80000001)
{
if (is_amd)
@@ -609,21 +609,21 @@ private:
{
memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info));
}
- else if (i == 0x80000003)
- memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info));
- else if (i == 0x80000004)
- {
- memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info));
- setInfo(eBrandName, cpu_brand_string);
- }
- else if (i == 0x80000006)
- {
- setConfig(eCacheLineSize, cpu_info[2] & 0xff);
- setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf);
- setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);
- }
- }
- }
+ else if (i == 0x80000003)
+ memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info));
+ else if (i == 0x80000004)
+ {
+ memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info));
+ setInfo(eBrandName, cpu_brand_string);
+ }
+ else if (i == 0x80000006)
+ {
+ setConfig(eCacheLineSize, cpu_info[2] & 0xff);
+ setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf);
+ setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);
+ }
+ }
+ }
};
#elif LL_DARWIN
@@ -634,126 +634,126 @@ private:
class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl
{
public:
- LLProcessorInfoDarwinImpl()
- {
- getCPUIDInfo();
- uint64_t frequency = getSysctlInt64("hw.cpufrequency");
- setInfo(eFrequency, (F64)frequency / (F64)1000000);
- }
+ LLProcessorInfoDarwinImpl()
+ {
+ getCPUIDInfo();
+ uint64_t frequency = getSysctlInt64("hw.cpufrequency");
+ setInfo(eFrequency, (F64)frequency / (F64)1000000);
+ }
- virtual ~LLProcessorInfoDarwinImpl() {}
+ virtual ~LLProcessorInfoDarwinImpl() {}
private:
- int getSysctlInt(const char* name)
- {
- int result = 0;
- size_t len = sizeof(int);
- int error = sysctlbyname(name, (void*)&result, &len, NULL, 0);
- return error == -1 ? 0 : result;
- }
-
- uint64_t getSysctlInt64(const char* name)
- {
- uint64_t value = 0;
- size_t size = sizeof(value);
- int result = sysctlbyname(name, (void*)&value, &size, NULL, 0);
- if ( result == 0 )
- {
- if ( size == sizeof( uint64_t ) )
- ;
- else if ( size == sizeof( uint32_t ) )
- value = (uint64_t)(( uint32_t *)&value);
- else if ( size == sizeof( uint16_t ) )
- value = (uint64_t)(( uint16_t *)&value);
- else if ( size == sizeof( uint8_t ) )
- value = (uint64_t)(( uint8_t *)&value);
- else
- {
- LL_WARNS() << "Unknown type returned from sysctl" << LL_ENDL;
- }
- }
-
- return result == -1 ? 0 : value;
- }
-
- void getCPUIDInfo()
- {
- size_t len = 0;
-
- char cpu_brand_string[0x40];
- len = sizeof(cpu_brand_string);
- memset(cpu_brand_string, 0, len);
- sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0);
- cpu_brand_string[0x3f] = 0;
- setInfo(eBrandName, cpu_brand_string);
-
- char cpu_vendor[0x20];
- len = sizeof(cpu_vendor);
- memset(cpu_vendor, 0, len);
- sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0);
- cpu_vendor[0x1f] = 0;
- setInfo(eVendor, cpu_vendor);
-
- setInfo(eStepping, getSysctlInt("machdep.cpu.stepping"));
- setInfo(eModel, getSysctlInt("machdep.cpu.model"));
- int family = getSysctlInt("machdep.cpu.family");
- int ext_family = getSysctlInt("machdep.cpu.extfamily");
- setInfo(eFamily, family);
- setInfo(eExtendedFamily, ext_family);
- setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
- setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
- setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
- setInfo(eType, 0); // ? where to find this?
-
- //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
- //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
- setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
- setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
- setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
-
- uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits");
- S32 *feature_infos = (S32*)(&feature_info);
-
- setConfig(eFeatureBits, feature_infos[0]);
-
- for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
- {
- if(feature_info & bit)
- {
- setExtension(cpu_feature_names[index]);
- }
- }
-
- // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be
- // The feature bits I think it is. Here's a test:
+ int getSysctlInt(const char* name)
+ {
+ int result = 0;
+ size_t len = sizeof(int);
+ int error = sysctlbyname(name, (void*)&result, &len, NULL, 0);
+ return error == -1 ? 0 : result;
+ }
+
+ uint64_t getSysctlInt64(const char* name)
+ {
+ uint64_t value = 0;
+ size_t size = sizeof(value);
+ int result = sysctlbyname(name, (void*)&value, &size, NULL, 0);
+ if ( result == 0 )
+ {
+ if ( size == sizeof( uint64_t ) )
+ ;
+ else if ( size == sizeof( uint32_t ) )
+ value = (uint64_t)(( uint32_t *)&value);
+ else if ( size == sizeof( uint16_t ) )
+ value = (uint64_t)(( uint16_t *)&value);
+ else if ( size == sizeof( uint8_t ) )
+ value = (uint64_t)(( uint8_t *)&value);
+ else
+ {
+ LL_WARNS() << "Unknown type returned from sysctl" << LL_ENDL;
+ }
+ }
+
+ return result == -1 ? 0 : value;
+ }
+
+ void getCPUIDInfo()
+ {
+ size_t len = 0;
+
+ char cpu_brand_string[0x40];
+ len = sizeof(cpu_brand_string);
+ memset(cpu_brand_string, 0, len);
+ sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0);
+ cpu_brand_string[0x3f] = 0;
+ setInfo(eBrandName, cpu_brand_string);
+
+ char cpu_vendor[0x20];
+ len = sizeof(cpu_vendor);
+ memset(cpu_vendor, 0, len);
+ sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0);
+ cpu_vendor[0x1f] = 0;
+ setInfo(eVendor, cpu_vendor);
+
+ setInfo(eStepping, getSysctlInt("machdep.cpu.stepping"));
+ setInfo(eModel, getSysctlInt("machdep.cpu.model"));
+ int family = getSysctlInt("machdep.cpu.family");
+ int ext_family = getSysctlInt("machdep.cpu.extfamily");
+ setInfo(eFamily, family);
+ setInfo(eExtendedFamily, ext_family);
+ setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+ setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+ setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+ setInfo(eType, 0); // ? where to find this?
+
+ //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+ //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+ setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
+ setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
+ setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
+
+ uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits");
+ S32 *feature_infos = (S32*)(&feature_info);
+
+ setConfig(eFeatureBits, feature_infos[0]);
+
+ for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
+ {
+ if(feature_info & bit)
+ {
+ setExtension(cpu_feature_names[index]);
+ }
+ }
+
+ // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be
+ // The feature bits I think it is. Here's a test:
#ifndef LL_RELEASE_FOR_DOWNLOAD
- #if defined(__i386__) && defined(__PIC__)
- /* %ebx may be the PIC register. */
- #define __cpuid(level, a, b, c, d) \
- __asm__ ("xchgl\t%%ebx, %1\n\t" \
- "cpuid\n\t" \
- "xchgl\t%%ebx, %1\n\t" \
- : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
- : "0" (level))
- #else
- #define __cpuid(level, a, b, c, d) \
- __asm__ ("cpuid\n\t" \
- : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
- : "0" (level))
- #endif
-
- unsigned int eax, ebx, ecx, edx;
- __cpuid(0x1, eax, ebx, ecx, edx);
- if(feature_infos[0] != (S32)edx)
- {
- LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
- }
-#endif // LL_RELEASE_FOR_DOWNLOAD
-
-
- uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits");
- S32 *ext_feature_infos = (S32*)(&ext_feature_info);
- setConfig(eExtFeatureBits, ext_feature_infos[0]);
+ #if defined(__i386__) && defined(__PIC__)
+ /* %ebx may be the PIC register. */
+ #define __cpuid(level, a, b, c, d) \
+ __asm__ ("xchgl\t%%ebx, %1\n\t" \
+ "cpuid\n\t" \
+ "xchgl\t%%ebx, %1\n\t" \
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "0" (level))
+ #else
+ #define __cpuid(level, a, b, c, d) \
+ __asm__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level))
+ #endif
+
+ unsigned int eax, ebx, ecx, edx;
+ __cpuid(0x1, eax, ebx, ecx, edx);
+ if(feature_infos[0] != (S32)edx)
+ {
+ LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
+ }
+#endif // LL_RELEASE_FOR_DOWNLOAD
+
+
+ uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits");
+ S32 *ext_feature_infos = (S32*)(&ext_feature_info);
+ setConfig(eExtFeatureBits, ext_feature_infos[0]);
char cpu_features[1024];
@@ -789,23 +789,23 @@ private:
// Not supposed to happen?
setExtension(cpu_feature_names[eSSE4a_Features]);
}
- }
+ }
};
#elif LL_LINUX
// *NOTE:Mani - eww, macros! srry.
#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \
- if (!cpuinfo[cpuinfo_id].empty()) \
- { setInfo(llpi_id, cpuinfo[cpuinfo_id]);}
+ if (!cpuinfo[cpuinfo_id].empty()) \
+ { setInfo(llpi_id, cpuinfo[cpuinfo_id]);}
#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \
- {\
- S32 result; \
- if (!cpuinfo[cpuinfo_id].empty() \
- && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \
- { setInfo(llpi_id, result);} \
- }
+ {\
+ S32 result; \
+ if (!cpuinfo[cpuinfo_id].empty() \
+ && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \
+ { setInfo(llpi_id, result);} \
+ }
const char CPUINFO_FILE[] = "/proc/cpuinfo";
@@ -842,38 +842,38 @@ private:
return mhz;
}
- void get_proc_cpuinfo()
- {
- std::map< std::string, std::string > cpuinfo;
- LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
- if(cpuinfo_fp)
- {
- char line[MAX_STRING];
- memset(line, 0, MAX_STRING);
- while(fgets(line, MAX_STRING, cpuinfo_fp))
- {
- // /proc/cpuinfo on Linux looks like:
- // name\t*: value\n
- char* tabspot = strchr( line, '\t' );
- if (tabspot == NULL)
- continue;
- char* colspot = strchr( tabspot, ':' );
- if (colspot == NULL)
- continue;
- char* spacespot = strchr( colspot, ' ' );
- if (spacespot == NULL)
- continue;
- char* nlspot = strchr( line, '\n' );
- if (nlspot == NULL)
- nlspot = line + strlen( line ); // Fallback to terminating NUL
- std::string linename( line, tabspot );
- std::string llinename(linename);
- LLStringUtil::toLower(llinename);
- std::string lineval( spacespot + 1, nlspot );
+ void get_proc_cpuinfo()
+ {
+ std::map< std::string, std::string > cpuinfo;
+ LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
+ if(cpuinfo_fp)
+ {
+ char line[MAX_STRING];
+ memset(line, 0, MAX_STRING);
+ while(fgets(line, MAX_STRING, cpuinfo_fp))
+ {
+ // /proc/cpuinfo on Linux looks like:
+ // name\t*: value\n
+ char* tabspot = strchr( line, '\t' );
+ if (tabspot == NULL)
+ continue;
+ char* colspot = strchr( tabspot, ':' );
+ if (colspot == NULL)
+ continue;
+ char* spacespot = strchr( colspot, ' ' );
+ if (spacespot == NULL)
+ continue;
+ char* nlspot = strchr( line, '\n' );
+ if (nlspot == NULL)
+ nlspot = line + strlen( line ); // Fallback to terminating NUL
+ std::string linename( line, tabspot );
+ std::string llinename(linename);
+ LLStringUtil::toLower(llinename);
+ std::string lineval( spacespot + 1, nlspot );
cpuinfo[ llinename ] = lineval;
- }
- fclose(cpuinfo_fp);
- }
+ }
+ fclose(cpuinfo_fp);
+ }
# if LL_X86
F64 mhzFromSys = getCPUMaxMHZ();
@@ -889,45 +889,45 @@ private:
setInfo(eFrequency,(F64)(mhzFromProc));
}
- LLPI_SET_INFO_STRING(eBrandName, "model name");
- LLPI_SET_INFO_STRING(eVendor, "vendor_id");
-
- LLPI_SET_INFO_INT(eStepping, "stepping");
- LLPI_SET_INFO_INT(eModel, "model");
-
-
- S32 family{};
- if (!cpuinfo["cpu family"].empty()
- && LLStringUtil::convertToS32(cpuinfo["cpu family"], family))
- {
- setInfo(eFamily, family);
- }
-
- setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family, 0));
-
- // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
- // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
- // setInfo(eType, 0); // ? where to find this?
-
- //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
- //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
- //setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
- //setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
- //setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
-
- // Read extensions
- std::string flags = " " + cpuinfo["flags"] + " ";
- LLStringUtil::toLower(flags);
-
- if( flags.find( " sse " ) != std::string::npos )
- {
- setExtension(cpu_feature_names[eSSE_Ext]);
- }
-
- if( flags.find( " sse2 " ) != std::string::npos )
- {
- setExtension(cpu_feature_names[eSSE2_Ext]);
- }
+ LLPI_SET_INFO_STRING(eBrandName, "model name");
+ LLPI_SET_INFO_STRING(eVendor, "vendor_id");
+
+ LLPI_SET_INFO_INT(eStepping, "stepping");
+ LLPI_SET_INFO_INT(eModel, "model");
+
+
+ S32 family{};
+ if (!cpuinfo["cpu family"].empty()
+ && LLStringUtil::convertToS32(cpuinfo["cpu family"], family))
+ {
+ setInfo(eFamily, family);
+ }
+
+ setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family, 0));
+
+ // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+ // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+ // setInfo(eType, 0); // ? where to find this?
+
+ //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+ //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+ //setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
+ //setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
+ //setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
+
+ // Read extensions
+ std::string flags = " " + cpuinfo["flags"] + " ";
+ LLStringUtil::toLower(flags);
+
+ if( flags.find( " sse " ) != std::string::npos )
+ {
+ setExtension(cpu_feature_names[eSSE_Ext]);
+ }
+
+ if( flags.find( " sse2 " ) != std::string::npos )
+ {
+ setExtension(cpu_feature_names[eSSE2_Ext]);
+ }
if (flags.find(" pni ") != std::string::npos)
{
@@ -953,36 +953,36 @@ private:
{
setExtension(cpu_feature_names[eSSE4a_Features]);
}
-
+
# endif // LL_X86
- }
-
- std::string getCPUFeatureDescription() const
- {
- std::ostringstream s;
-
- // *NOTE:Mani - This is for linux only.
- LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
- if(cpuinfo)
- {
- char line[MAX_STRING];
- memset(line, 0, MAX_STRING);
- while(fgets(line, MAX_STRING, cpuinfo))
- {
- line[strlen(line)-1] = ' ';
- s << line;
- s << std::endl;
- }
- fclose(cpuinfo);
- s << std::endl;
- }
- else
- {
- s << "Unable to collect processor information" << std::endl;
- }
- return s.str();
- }
-
+ }
+
+ std::string getCPUFeatureDescription() const
+ {
+ std::ostringstream s;
+
+ // *NOTE:Mani - This is for linux only.
+ LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
+ if(cpuinfo)
+ {
+ char line[MAX_STRING];
+ memset(line, 0, MAX_STRING);
+ while(fgets(line, MAX_STRING, cpuinfo))
+ {
+ line[strlen(line)-1] = ' ';
+ s << line;
+ s << std::endl;
+ }
+ fclose(cpuinfo);
+ s << std::endl;
+ }
+ else
+ {
+ s << "Unable to collect processor information" << std::endl;
+ }
+ return s.str();
+ }
+
};
@@ -992,20 +992,20 @@ private:
// Interface definition
LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
{
- // *NOTE:Mani - not thread safe.
- if(!mImpl)
- {
+ // *NOTE:Mani - not thread safe.
+ if(!mImpl)
+ {
#ifdef LL_MSVC
- static LLProcessorInfoWindowsImpl the_impl;
- mImpl = &the_impl;
+ static LLProcessorInfoWindowsImpl the_impl;
+ mImpl = &the_impl;
#elif LL_DARWIN
- static LLProcessorInfoDarwinImpl the_impl;
- mImpl = &the_impl;
+ static LLProcessorInfoDarwinImpl the_impl;
+ mImpl = &the_impl;
#else
- static LLProcessorInfoLinuxImpl the_impl;
- mImpl = &the_impl;
+ static LLProcessorInfoLinuxImpl the_impl;
+ mImpl = &the_impl;
#endif // LL_MSVC
- }
+ }
}
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index 1a473ddc97..f8ccf686c8 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llprocessor.h
* @brief Code to figure out the processor. Originally by Benjamin Jurke.
*
* $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$
*/
@@ -48,23 +48,23 @@ class LLProcessorInfoImpl;
class LL_COMMON_API LLProcessorInfo
{
public:
- LLProcessorInfo();
- ~LLProcessorInfo();
+ LLProcessorInfo();
+ ~LLProcessorInfo();
- F64MegahertzImplicit getCPUFrequency() const;
- bool hasSSE() const;
- bool hasSSE2() const;
+ F64MegahertzImplicit getCPUFrequency() const;
+ bool hasSSE() const;
+ bool hasSSE2() const;
bool hasSSE3() const;
bool hasSSE3S() const;
bool hasSSE41() const;
bool hasSSE42() const;
bool hasSSE4a() const;
- bool hasAltivec() const;
- std::string getCPUFamilyName() const;
- std::string getCPUBrandName() const;
- std::string getCPUFeatureDescription() const;
+ bool hasAltivec() const;
+ std::string getCPUFamilyName() const;
+ std::string getCPUBrandName() const;
+ std::string getCPUFeatureDescription() const;
private:
- LLProcessorInfoImpl* mImpl;
+ LLProcessorInfoImpl* mImpl;
};
#endif // LLPROCESSOR_H
diff --git a/indra/llcommon/llprocinfo.cpp b/indra/llcommon/llprocinfo.cpp
index c00f979b0b..69be00e14a 100644
--- a/indra/llcommon/llprocinfo.cpp
+++ b/indra/llcommon/llprocinfo.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llprocinfo.cpp
* @brief Process, cpu and resource usage information APIs.
* @author monty@lindenlab.com
@@ -30,7 +30,7 @@
#if LL_WINDOWS
-#define PSAPI_VERSION 1
+#define PSAPI_VERSION 1
#include "windows.h"
#include "psapi.h"
@@ -38,7 +38,7 @@
#include <sys/resource.h>
#include <mach/mach.h>
-
+
#else
#include <sys/time.h>
@@ -52,42 +52,42 @@ void LLProcInfo::getCPUUsage(time_type & user_time, time_type & system_time)
{
#if LL_WINDOWS
- HANDLE self(GetCurrentProcess()); // Does not have to be closed
- FILETIME ft_dummy, ft_system, ft_user;
-
- GetProcessTimes(self, &ft_dummy, &ft_dummy, &ft_system, &ft_user);
- ULARGE_INTEGER uli;
- uli.u.LowPart = ft_system.dwLowDateTime;
- uli.u.HighPart = ft_system.dwHighDateTime;
- system_time = uli.QuadPart / U64L(10); // Convert to uS
- uli.u.LowPart = ft_user.dwLowDateTime;
- uli.u.HighPart = ft_user.dwHighDateTime;
- user_time = uli.QuadPart / U64L(10);
-
+ HANDLE self(GetCurrentProcess()); // Does not have to be closed
+ FILETIME ft_dummy, ft_system, ft_user;
+
+ GetProcessTimes(self, &ft_dummy, &ft_dummy, &ft_system, &ft_user);
+ ULARGE_INTEGER uli;
+ uli.u.LowPart = ft_system.dwLowDateTime;
+ uli.u.HighPart = ft_system.dwHighDateTime;
+ system_time = uli.QuadPart / U64L(10); // Convert to uS
+ uli.u.LowPart = ft_user.dwLowDateTime;
+ uli.u.HighPart = ft_user.dwHighDateTime;
+ user_time = uli.QuadPart / U64L(10);
+
#elif LL_DARWIN
- struct rusage usage;
+ struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage))
- {
- user_time = system_time = time_type(0U);
- return;
- }
- user_time = U64(usage.ru_utime.tv_sec) * U64L(1000000) + usage.ru_utime.tv_usec;
- system_time = U64(usage.ru_stime.tv_sec) * U64L(1000000) + usage.ru_stime.tv_usec;
+ if (getrusage(RUSAGE_SELF, &usage))
+ {
+ user_time = system_time = time_type(0U);
+ return;
+ }
+ user_time = U64(usage.ru_utime.tv_sec) * U64L(1000000) + usage.ru_utime.tv_usec;
+ system_time = U64(usage.ru_stime.tv_sec) * U64L(1000000) + usage.ru_stime.tv_usec;
#else // Linux
- struct rusage usage;
+ struct rusage usage;
+
+ if (getrusage(RUSAGE_SELF, &usage))
+ {
+ user_time = system_time = time_type(0U);
+ return;
+ }
+ user_time = U64(usage.ru_utime.tv_sec) * U64L(1000000) + usage.ru_utime.tv_usec;
+ system_time = U64(usage.ru_stime.tv_sec) * U64L(1000000) + usage.ru_stime.tv_usec;
- if (getrusage(RUSAGE_SELF, &usage))
- {
- user_time = system_time = time_type(0U);
- return;
- }
- user_time = U64(usage.ru_utime.tv_sec) * U64L(1000000) + usage.ru_utime.tv_usec;
- system_time = U64(usage.ru_stime.tv_sec) * U64L(1000000) + usage.ru_stime.tv_usec;
-
#endif // LL_WINDOWS/LL_DARWIN/Linux
}
diff --git a/indra/llcommon/llprocinfo.h b/indra/llcommon/llprocinfo.h
index e78bcf490a..5955799812 100644
--- a/indra/llcommon/llprocinfo.h
+++ b/indra/llcommon/llprocinfo.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llprocinfo.h
* @brief Interface to process/cpu/resource information services.
* @author monty@lindenlab.com
@@ -25,8 +25,8 @@
* $/LicenseInfo$
*/
-#ifndef LL_PROCINFO_H
-#define LL_PROCINFO_H
+#ifndef LL_PROCINFO_H
+#define LL_PROCINFO_H
#include "linden_common.h"
@@ -46,23 +46,23 @@
class LL_COMMON_API LLProcInfo
{
public:
- /// Public types
+ /// Public types
+
+ typedef U64 time_type; /// Relative microseconds
- typedef U64 time_type; /// Relative microseconds
-
private:
- LLProcInfo(); // Not defined
- ~LLProcInfo(); // Not defined
- LLProcInfo(const LLProcInfo &); // Not defined
- void operator=(const LLProcInfo &); // Not defined
+ LLProcInfo(); // Not defined
+ ~LLProcInfo(); // Not defined
+ LLProcInfo(const LLProcInfo &); // Not defined
+ void operator=(const LLProcInfo &); // Not defined
public:
- /// Get accumulated system and user CPU time in
- /// microseconds. Syscalls involved in every invocation.
- ///
- /// Threading: expected to be safe.
- static void getCPUUsage(time_type & user_time, time_type & system_time);
+ /// Get accumulated system and user CPU time in
+ /// microseconds. Syscalls involved in every invocation.
+ ///
+ /// Threading: expected to be safe.
+ static void getCPUUsage(time_type & user_time, time_type & system_time);
};
-
-#endif // LL_PROCINFO_H
+
+#endif // LL_PROCINFO_H
diff --git a/indra/llcommon/llptrto.cpp b/indra/llcommon/llptrto.cpp
index b270291bd6..c4528a47a7 100644
--- a/indra/llcommon/llptrto.cpp
+++ b/indra/llcommon/llptrto.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-08-20
* @brief Test for llptrto.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$
*/
diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h
index 9ef279fdbf..b57a1ee7f4 100644
--- a/indra/llcommon/llptrto.h
+++ b/indra/llcommon/llptrto.h
@@ -5,25 +5,25 @@
* @brief LLPtrTo<TARGET> is a template helper to pick either TARGET* or -- when
* TARGET is a subclass of LLRefCount or LLThreadSafeRefCount --
* LLPointer<TARGET>. LLPtrTo<> chooses whichever pointer type is best.
- *
+ *
* $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$
*/
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 394212ee0d..aaf13ac796 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llqueuedthread.cpp
*
* $LicenseInfo:firstyear=2004&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 @@
#include <chrono>
#include "llstl.h"
-#include "lltimer.h" // ms_sleep()
+#include "lltimer.h" // ms_sleep()
#include "llmutex.h"
//============================================================================
@@ -46,75 +46,75 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool shou
llassert(threaded); // not threaded implementation is deprecated
mMainQueue = LL::WorkQueue::getInstance("mainloop");
- if (mThreaded)
- {
- if(should_pause)
- {
- pause() ; //call this before start the thread.
- }
+ if (mThreaded)
+ {
+ if(should_pause)
+ {
+ pause() ; //call this before start the thread.
+ }
- start();
- }
+ start();
+ }
}
// MAIN THREAD
LLQueuedThread::~LLQueuedThread()
{
- if (!mThreaded)
- {
- endThread();
- }
- shutdown();
- // ~LLThread() will be called here
+ if (!mThreaded)
+ {
+ endThread();
+ }
+ shutdown();
+ // ~LLThread() will be called here
}
void LLQueuedThread::shutdown()
{
- setQuitting();
+ setQuitting();
- unpause(); // MAIN THREAD
- if (mThreaded)
- {
+ unpause(); // MAIN THREAD
+ if (mThreaded)
+ {
if (mRequestQueue.size() == 0)
{
mRequestQueue.close();
}
- S32 timeout = 100;
- for ( ; timeout>0; timeout--)
- {
- if (isStopped())
- {
- break;
- }
- ms_sleep(100);
- LLThread::yield();
- }
- if (timeout == 0)
- {
- LL_WARNS() << "~LLQueuedThread (" << mName << ") timed out!" << LL_ENDL;
- }
- }
- else
- {
- mStatus = STOPPED;
- }
-
- QueuedRequest* req;
- S32 active_count = 0;
- while ( (req = (QueuedRequest*)mRequestHash.pop_element()) )
- {
- if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
- {
- ++active_count;
- req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest
- }
- req->deleteRequest();
- }
- if (active_count)
- {
- LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;
- }
+ S32 timeout = 100;
+ for ( ; timeout>0; timeout--)
+ {
+ if (isStopped())
+ {
+ break;
+ }
+ ms_sleep(100);
+ LLThread::yield();
+ }
+ if (timeout == 0)
+ {
+ LL_WARNS() << "~LLQueuedThread (" << mName << ") timed out!" << LL_ENDL;
+ }
+ }
+ else
+ {
+ mStatus = STOPPED;
+ }
+
+ QueuedRequest* req;
+ S32 active_count = 0;
+ while ( (req = (QueuedRequest*)mRequestHash.pop_element()) )
+ {
+ if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
+ {
+ ++active_count;
+ req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest
+ }
+ req->deleteRequest();
+ }
+ if (active_count)
+ {
+ LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;
+ }
mRequestQueue.close();
}
@@ -126,23 +126,23 @@ void LLQueuedThread::shutdown()
size_t LLQueuedThread::update(F32 max_time_ms)
{
LL_PROFILE_ZONE_SCOPED;
- if (!mStarted)
- {
- if (!mThreaded)
- {
- startThread();
- mStarted = TRUE;
- }
- }
- return updateQueue(max_time_ms);
+ if (!mStarted)
+ {
+ if (!mThreaded)
+ {
+ startThread();
+ mStarted = TRUE;
+ }
+ }
+ return updateQueue(max_time_ms);
}
size_t LLQueuedThread::updateQueue(F32 max_time_ms)
{
LL_PROFILE_ZONE_SCOPED;
- // Frame Update
- if (mThreaded)
- {
+ // Frame Update
+ if (mThreaded)
+ {
// schedule a call to threadedUpdate for every call to updateQueue
if (!isQuitting())
{
@@ -156,29 +156,29 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms)
);
}
- if(getPending() > 0)
- {
- unpause();
- }
- }
- else
- {
+ if(getPending() > 0)
+ {
+ unpause();
+ }
+ }
+ else
+ {
mRequestQueue.runFor(std::chrono::microseconds((int) (max_time_ms*1000.f)));
threadedUpdate();
- }
- return getPending();
+ }
+ return getPending();
}
void LLQueuedThread::incQueue()
{
- // Something has been added to the queue
- if (!isPaused())
- {
- if (mThreaded)
- {
- wake(); // Wake the thread up if necessary.
- }
- }
+ // Something has been added to the queue
+ if (!isPaused())
+ {
+ if (mThreaded)
+ {
+ wake(); // Wake the thread up if necessary.
+ }
+ }
}
//virtual
@@ -191,200 +191,200 @@ size_t LLQueuedThread::getPending()
// MAIN thread
void LLQueuedThread::waitOnPending()
{
- while(1)
- {
- update(0);
-
- if (mIdleThread)
- {
- break;
- }
- if (mThreaded)
- {
- yield();
- }
- }
- return;
+ while(1)
+ {
+ update(0);
+
+ if (mIdleThread)
+ {
+ break;
+ }
+ if (mThreaded)
+ {
+ yield();
+ }
+ }
+ return;
}
// MAIN thread
void LLQueuedThread::printQueueStats()
{
U32 size = mRequestQueue.size();
- if (size > 0)
- {
- LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Queued Thread Idle" << LL_ENDL;
- }
+ if (size > 0)
+ {
+ LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Queued Thread Idle" << LL_ENDL;
+ }
}
// MAIN thread
LLQueuedThread::handle_t LLQueuedThread::generateHandle()
{
U32 res = ++mNextHandle;
- return res;
+ return res;
}
// MAIN thread
bool LLQueuedThread::addRequest(QueuedRequest* req)
{
LL_PROFILE_ZONE_SCOPED;
- if (mStatus == QUITTING)
- {
- return false;
- }
-
- lockData();
- req->setStatus(STATUS_QUEUED);
+ if (mStatus == QUITTING)
+ {
+ return false;
+ }
+
+ lockData();
+ req->setStatus(STATUS_QUEUED);
mRequestHash.insert(req);
#if _DEBUG
-// LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
+// LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
#endif
- unlockData();
+ unlockData();
llassert(!mDataLock->isSelfLocked());
mRequestQueue.post([this, req]() { processRequest(req); });
- return true;
+ return true;
}
// MAIN thread
bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
{
LL_PROFILE_ZONE_SCOPED;
- llassert (handle != nullHandle());
- bool res = false;
- bool waspaused = isPaused();
- bool done = false;
- while(!done)
- {
- update(0); // unpauses
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (!req)
- {
- done = true; // request does not exist
- }
- else if (req->getStatus() == STATUS_COMPLETE)
- {
- res = true;
- if (auto_complete)
- {
- mRequestHash.erase(handle);
- req->deleteRequest();
-// check();
- }
- done = true;
- }
- unlockData();
-
- if (!done && mThreaded)
- {
- yield();
- }
- }
- if (waspaused)
- {
- pause();
- }
- return res;
+ llassert (handle != nullHandle());
+ bool res = false;
+ bool waspaused = isPaused();
+ bool done = false;
+ while(!done)
+ {
+ update(0); // unpauses
+ lockData();
+ QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
+ if (!req)
+ {
+ done = true; // request does not exist
+ }
+ else if (req->getStatus() == STATUS_COMPLETE)
+ {
+ res = true;
+ if (auto_complete)
+ {
+ mRequestHash.erase(handle);
+ req->deleteRequest();
+// check();
+ }
+ done = true;
+ }
+ unlockData();
+
+ if (!done && mThreaded)
+ {
+ yield();
+ }
+ }
+ if (waspaused)
+ {
+ pause();
+ }
+ return res;
}
// MAIN thread
LLQueuedThread::QueuedRequest* LLQueuedThread::getRequest(handle_t handle)
{
- if (handle == nullHandle())
- {
- return 0;
- }
- lockData();
- QueuedRequest* res = (QueuedRequest*)mRequestHash.find(handle);
- unlockData();
- return res;
+ if (handle == nullHandle())
+ {
+ return 0;
+ }
+ lockData();
+ QueuedRequest* res = (QueuedRequest*)mRequestHash.find(handle);
+ unlockData();
+ return res;
}
LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle)
{
- status_t res = STATUS_EXPIRED;
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req)
- {
- res = req->getStatus();
- }
- unlockData();
- return res;
+ status_t res = STATUS_EXPIRED;
+ lockData();
+ QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
+ if (req)
+ {
+ res = req->getStatus();
+ }
+ unlockData();
+ return res;
}
void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req)
- {
- req->setFlags(FLAG_ABORT | (autocomplete ? FLAG_AUTO_COMPLETE : 0));
- }
- unlockData();
+ lockData();
+ QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
+ if (req)
+ {
+ req->setFlags(FLAG_ABORT | (autocomplete ? FLAG_AUTO_COMPLETE : 0));
+ }
+ unlockData();
}
// MAIN thread
void LLQueuedThread::setFlags(handle_t handle, U32 flags)
{
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req)
- {
- req->setFlags(flags);
- }
- unlockData();
+ lockData();
+ QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
+ if (req)
+ {
+ req->setFlags(flags);
+ }
+ unlockData();
}
bool LLQueuedThread::completeRequest(handle_t handle)
{
LL_PROFILE_ZONE_SCOPED;
- bool res = false;
- lockData();
- QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
- if (req)
- {
- llassert_always(req->getStatus() != STATUS_QUEUED);
- llassert_always(req->getStatus() != STATUS_INPROGRESS);
+ bool res = false;
+ lockData();
+ QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
+ if (req)
+ {
+ llassert_always(req->getStatus() != STATUS_QUEUED);
+ llassert_always(req->getStatus() != STATUS_INPROGRESS);
#if _DEBUG
-// LL_INFOS() << llformat("LLQueuedThread::Completed req [%08d]",handle) << LL_ENDL;
+// LL_INFOS() << llformat("LLQueuedThread::Completed req [%08d]",handle) << LL_ENDL;
#endif
- mRequestHash.erase(handle);
- req->deleteRequest();
-// check();
- res = true;
- }
- unlockData();
- return res;
+ mRequestHash.erase(handle);
+ req->deleteRequest();
+// check();
+ res = true;
+ }
+ unlockData();
+ return res;
}
bool LLQueuedThread::check()
{
#if 0 // not a reliable check once mNextHandle wraps, just for quick and dirty debugging
- for (int i=0; i<REQUEST_HASH_SIZE; i++)
- {
- LLSimpleHashEntry<handle_t>* entry = mRequestHash.get_element_at_index(i);
- while (entry)
- {
- if (entry->getHashKey() > mNextHandle)
- {
- LL_ERRS() << "Hash Error" << LL_ENDL;
- return false;
- }
- entry = entry->getNextEntry();
- }
- }
+ for (int i=0; i<REQUEST_HASH_SIZE; i++)
+ {
+ LLSimpleHashEntry<handle_t>* entry = mRequestHash.get_element_at_index(i);
+ while (entry)
+ {
+ if (entry->getHashKey() > mNextHandle)
+ {
+ LL_ERRS() << "Hash Error" << LL_ENDL;
+ return false;
+ }
+ entry = entry->getNextEntry();
+ }
+ }
#endif
- return true;
-}
-
+ return true;
+}
+
//============================================================================
// Runs on its OWN thread
@@ -395,22 +395,22 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
mIdleThread = FALSE;
//threadedUpdate();
- // Get next request from pool
- lockData();
-
- if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
- {
+ // Get next request from pool
+ lockData();
+
+ if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qtpr - abort");
- req->setStatus(STATUS_ABORTED);
- req->finishRequest(false);
- if (req->getFlags() & FLAG_AUTO_COMPLETE)
- {
- mRequestHash.erase(req);
- req->deleteRequest();
-// check();
- }
+ req->setStatus(STATUS_ABORTED);
+ req->finishRequest(false);
+ if (req->getFlags() & FLAG_AUTO_COMPLETE)
+ {
+ mRequestHash.erase(req);
+ req->deleteRequest();
+// check();
+ }
unlockData();
- }
+ }
else
{
llassert_always(req->getStatus() == STATUS_QUEUED);
@@ -426,7 +426,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
// safe to access req.
if (req)
{
- // process request
+ // process request
bool complete = req->processRequest();
if (complete)
@@ -439,7 +439,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
{
mRequestHash.erase(req);
req->deleteRequest();
- // check();
+ // check();
}
unlockData();
}
@@ -449,7 +449,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
//put back on queue and try again in 0.1ms
lockData();
req->setStatus(STATUS_QUEUED);
-
+
unlockData();
llassert(!mDataLock->isSelfLocked());
@@ -480,8 +480,8 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
if (LL::WorkQueue::TimePoint::clock::now() < retry_time)
{
auto sleep_time = std::chrono::duration_cast<std::chrono::milliseconds>(retry_time - LL::WorkQueue::TimePoint::clock::now());
-
- if (sleep_time.count() > 0)
+
+ if (sleep_time.count() > 0)
{
ms_sleep(sleep_time.count());
}
@@ -489,7 +489,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
processRequest(req);
});
#endif
-
+
}
}
}
@@ -500,48 +500,48 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
// virtual
bool LLQueuedThread::runCondition()
{
- // mRunCondition must be locked here
- if (mRequestQueue.size() == 0 && mIdleThread)
- return false;
- else
- return true;
+ // mRunCondition must be locked here
+ if (mRequestQueue.size() == 0 && mIdleThread)
+ return false;
+ else
+ return true;
}
// virtual
void LLQueuedThread::run()
{
- // call checPause() immediately so we don't try to do anything before the class is fully constructed
- checkPause();
- startThread();
- mStarted = TRUE;
-
-
- /*while (1)
- {
+ // call checPause() immediately so we don't try to do anything before the class is fully constructed
+ checkPause();
+ startThread();
+ mStarted = TRUE;
+
+
+ /*while (1)
+ {
LL_PROFILE_ZONE_SCOPED;
- // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
- checkPause();
-
- mIdleThread = FALSE;
+ // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
+ checkPause();
- threadedUpdate();
-
- auto pending_work = processNextRequest();
+ mIdleThread = FALSE;
- if (pending_work == 0)
- {
+ threadedUpdate();
+
+ auto pending_work = processNextRequest();
+
+ if (pending_work == 0)
+ {
//LL_PROFILE_ZONE_NAMED("LLQueuedThread - sleep");
- mIdleThread = TRUE;
- //ms_sleep(1);
- }
- //LLThread::yield(); // thread should yield after each request
- }*/
+ mIdleThread = TRUE;
+ //ms_sleep(1);
+ }
+ //LLThread::yield(); // thread should yield after each request
+ }*/
mRequestQueue.runUntilClose();
endThread();
- LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL;
+ LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL;
+
-
}
// virtual
@@ -562,15 +562,15 @@ void LLQueuedThread::threadedUpdate()
//============================================================================
LLQueuedThread::QueuedRequest::QueuedRequest(LLQueuedThread::handle_t handle, U32 flags) :
- LLSimpleHashEntry<LLQueuedThread::handle_t>(handle),
- mStatus(STATUS_UNKNOWN),
- mFlags(flags)
+ LLSimpleHashEntry<LLQueuedThread::handle_t>(handle),
+ mStatus(STATUS_UNKNOWN),
+ mFlags(flags)
{
}
LLQueuedThread::QueuedRequest::~QueuedRequest()
{
- llassert_always(mStatus == STATUS_DELETE);
+ llassert_always(mStatus == STATUS_DELETE);
}
//virtual
@@ -581,7 +581,7 @@ void LLQueuedThread::QueuedRequest::finishRequest(bool completed)
//virtual
void LLQueuedThread::QueuedRequest::deleteRequest()
{
- llassert_always(mStatus != STATUS_INPROGRESS);
- setStatus(STATUS_DELETE);
- delete this;
+ llassert_always(mStatus != STATUS_INPROGRESS);
+ setStatus(STATUS_DELETE);
+ delete this;
}
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 814dbc4c38..339299f081 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llqueuedthread.h
* @brief
*
* $LicenseInfo:firstyear=2004&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,135 +44,135 @@
class LL_COMMON_API LLQueuedThread : public LLThread
{
- //------------------------------------------------------------------------
+ //------------------------------------------------------------------------
public:
- enum status_t {
- STATUS_EXPIRED = -1,
- STATUS_UNKNOWN = 0,
- STATUS_QUEUED = 1,
- STATUS_INPROGRESS = 2,
- STATUS_COMPLETE = 3,
- STATUS_ABORTED = 4,
- STATUS_DELETE = 5
- };
- enum flags_t {
- FLAG_AUTO_COMPLETE = 1,
- FLAG_AUTO_DELETE = 2, // child-class dependent
- FLAG_ABORT = 4
- };
-
- typedef U32 handle_t;
-
- //------------------------------------------------------------------------
+ enum status_t {
+ STATUS_EXPIRED = -1,
+ STATUS_UNKNOWN = 0,
+ STATUS_QUEUED = 1,
+ STATUS_INPROGRESS = 2,
+ STATUS_COMPLETE = 3,
+ STATUS_ABORTED = 4,
+ STATUS_DELETE = 5
+ };
+ enum flags_t {
+ FLAG_AUTO_COMPLETE = 1,
+ FLAG_AUTO_DELETE = 2, // child-class dependent
+ FLAG_ABORT = 4
+ };
+
+ typedef U32 handle_t;
+
+ //------------------------------------------------------------------------
public:
- class LL_COMMON_API QueuedRequest : public LLSimpleHashEntry<handle_t>
- {
- friend class LLQueuedThread;
-
- protected:
- virtual ~QueuedRequest(); // use deleteRequest()
-
- public:
- QueuedRequest(handle_t handle, U32 flags = 0);
-
- status_t getStatus()
- {
- return mStatus;
- }
- U32 getFlags() const
- {
- return mFlags;
- }
-
- protected:
- status_t setStatus(status_t newstatus)
- {
- status_t oldstatus = mStatus;
- mStatus = newstatus;
- return oldstatus;
- }
- void setFlags(U32 flags)
- {
- // NOTE: flags are |'d
- mFlags |= flags;
- }
-
- virtual bool processRequest() = 0; // Return true when request has completed
- virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
- virtual void deleteRequest(); // Only method to delete a request
-
- protected:
- LLAtomicBase<status_t> mStatus;
- U32 mFlags;
- };
-
- //------------------------------------------------------------------------
-
+ class LL_COMMON_API QueuedRequest : public LLSimpleHashEntry<handle_t>
+ {
+ friend class LLQueuedThread;
+
+ protected:
+ virtual ~QueuedRequest(); // use deleteRequest()
+
+ public:
+ QueuedRequest(handle_t handle, U32 flags = 0);
+
+ status_t getStatus()
+ {
+ return mStatus;
+ }
+ U32 getFlags() const
+ {
+ return mFlags;
+ }
+
+ protected:
+ status_t setStatus(status_t newstatus)
+ {
+ status_t oldstatus = mStatus;
+ mStatus = newstatus;
+ return oldstatus;
+ }
+ void setFlags(U32 flags)
+ {
+ // NOTE: flags are |'d
+ mFlags |= flags;
+ }
+
+ virtual bool processRequest() = 0; // Return true when request has completed
+ virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
+ virtual void deleteRequest(); // Only method to delete a request
+
+ protected:
+ LLAtomicBase<status_t> mStatus;
+ U32 mFlags;
+ };
+
+ //------------------------------------------------------------------------
+
public:
- static handle_t nullHandle() { return handle_t(0); }
-
+ static handle_t nullHandle() { return handle_t(0); }
+
public:
- LLQueuedThread(const std::string& name, bool threaded = true, bool should_pause = false);
- virtual ~LLQueuedThread();
- virtual void shutdown();
-
+ LLQueuedThread(const std::string& name, bool threaded = true, bool should_pause = false);
+ virtual ~LLQueuedThread();
+ virtual void shutdown();
+
private:
- // No copy constructor or copy assignment
- LLQueuedThread(const LLQueuedThread&);
- LLQueuedThread& operator=(const LLQueuedThread&);
+ // No copy constructor or copy assignment
+ LLQueuedThread(const LLQueuedThread&);
+ LLQueuedThread& operator=(const LLQueuedThread&);
- virtual bool runCondition(void);
- virtual void run(void);
- virtual void startThread(void);
- virtual void endThread(void);
- virtual void threadedUpdate(void);
+ virtual bool runCondition(void);
+ virtual void run(void);
+ virtual void startThread(void);
+ virtual void endThread(void);
+ virtual void threadedUpdate(void);
protected:
- handle_t generateHandle();
- bool addRequest(QueuedRequest* req);
- void processRequest(QueuedRequest* req);
- void incQueue();
+ handle_t generateHandle();
+ bool addRequest(QueuedRequest* req);
+ void processRequest(QueuedRequest* req);
+ void incQueue();
public:
- bool waitForResult(handle_t handle, bool auto_complete = true);
+ bool waitForResult(handle_t handle, bool auto_complete = true);
- virtual size_t update(F32 max_time_ms);
- size_t updateQueue(F32 max_time_ms);
+ virtual size_t update(F32 max_time_ms);
+ size_t updateQueue(F32 max_time_ms);
- void waitOnPending();
- void printQueueStats();
+ void waitOnPending();
+ void printQueueStats();
- virtual size_t getPending();
- bool getThreaded() { return mThreaded ? true : false; }
+ virtual size_t getPending();
+ bool getThreaded() { return mThreaded ? true : false; }
- // Request accessors
- status_t getRequestStatus(handle_t handle);
- void abortRequest(handle_t handle, bool autocomplete);
- void setFlags(handle_t handle, U32 flags);
- bool completeRequest(handle_t handle);
- // This is public for support classes like LLWorkerThread,
- // but generally the methods above should be used.
- QueuedRequest* getRequest(handle_t handle);
+ // Request accessors
+ status_t getRequestStatus(handle_t handle);
+ void abortRequest(handle_t handle, bool autocomplete);
+ void setFlags(handle_t handle, U32 flags);
+ bool completeRequest(handle_t handle);
+ // This is public for support classes like LLWorkerThread,
+ // but generally the methods above should be used.
+ QueuedRequest* getRequest(handle_t handle);
+
+ // debug (see source)
+ bool check();
- // debug (see source)
- bool check();
-
protected:
- BOOL mThreaded; // if false, run on main thread and do updates during update()
- BOOL mStarted; // required when mThreaded is false to call startThread() from update()
- LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
-
- //typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
- //request_queue_t mRequestQueue;
+ BOOL mThreaded; // if false, run on main thread and do updates during update()
+ BOOL mStarted; // required when mThreaded is false to call startThread() from update()
+ LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
+
+ //typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
+ //request_queue_t mRequestQueue;
LL::WorkQueue mRequestQueue;
LL::WorkQueue::weak_t mMainQueue;
- enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
- typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t;
- request_hash_t mRequestHash;
+ enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
+ typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t;
+ request_hash_t mRequestHash;
- handle_t mNextHandle;
+ handle_t mNextHandle;
};
#endif // LL_LLQUEUEDTHREAD_H
diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp
index 0192111574..25d75af568 100644
--- a/indra/llcommon/llrand.cpp
+++ b/indra/llcommon/llrand.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrand.cpp
* @brief Global random generator.
*
* $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$
*/
@@ -69,25 +69,25 @@ inline REAL ll_internal_random();
template <>
inline F64 ll_internal_random<F64>()
{
- // *HACK: Through experimentation, we have found that dual core
- // CPUs (or at least multi-threaded processes) seem to
- // occasionally give an obviously incorrect random number -- like
- // 5^15 or something. Sooooo, clamp it as described above.
- F64 rv{ gRandomGenerator() };
- if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0);
- return rv;
+ // *HACK: Through experimentation, we have found that dual core
+ // CPUs (or at least multi-threaded processes) seem to
+ // occasionally give an obviously incorrect random number -- like
+ // 5^15 or something. Sooooo, clamp it as described above.
+ F64 rv{ gRandomGenerator() };
+ if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0);
+ return rv;
}
template <>
inline F32 ll_internal_random<F32>()
{
- // *HACK: clamp the result as described above.
- // Per Monty, it's important to clamp using the correct fmodf() rather
- // than expanding to F64 for fmod() and then truncating back to F32. Prior
- // to this change, we were getting sporadic ll_frand() == 1.0 results.
- F32 rv{ narrow<F32>(gRandomGenerator()) };
- if(!((rv >= 0.0f) && (rv < 1.0f))) return fmodf(rv, 1.0f);
- return rv;
+ // *HACK: clamp the result as described above.
+ // Per Monty, it's important to clamp using the correct fmodf() rather
+ // than expanding to F64 for fmod() and then truncating back to F32. Prior
+ // to this change, we were getting sporadic ll_frand() == 1.0 results.
+ F32 rv{ narrow<F32>(gRandomGenerator()) };
+ if(!((rv >= 0.0f) && (rv < 1.0f))) return fmodf(rv, 1.0f);
+ return rv;
}
/*------------------------------ F64 aliases -------------------------------*/
@@ -98,7 +98,7 @@ inline F64 ll_internal_random_double()
F64 ll_drand()
{
- return ll_internal_random_double();
+ return ll_internal_random_double();
}
/*------------------------------ F32 aliases -------------------------------*/
@@ -109,37 +109,37 @@ inline F32 ll_internal_random_float()
F32 ll_frand()
{
- return ll_internal_random_float();
+ return ll_internal_random_float();
}
/*-------------------------- clamped random range --------------------------*/
S32 ll_rand()
{
- return ll_rand(RAND_MAX);
+ return ll_rand(RAND_MAX);
}
S32 ll_rand(S32 val)
{
- // The clamping rules are described above.
- S32 rv = (S32)(ll_internal_random_double() * val);
- if(rv == val) return 0;
- return rv;
+ // The clamping rules are described above.
+ S32 rv = (S32)(ll_internal_random_double() * val);
+ if(rv == val) return 0;
+ return rv;
}
template <typename REAL>
REAL ll_grand(REAL val)
{
- // The clamping rules are described above.
- REAL rv = ll_internal_random<REAL>() * val;
- if(val > 0)
- {
- if(rv >= val) return REAL();
- }
- else
- {
- if(rv <= val) return REAL();
- }
- return rv;
+ // The clamping rules are described above.
+ REAL rv = ll_internal_random<REAL>() * val;
+ if(val > 0)
+ {
+ if(rv >= val) return REAL();
+ }
+ else
+ {
+ if(rv <= val) return REAL();
+ }
+ return rv;
}
F32 ll_frand(F32 val)
diff --git a/indra/llcommon/llrand.h b/indra/llcommon/llrand.h
index ad317d5bf7..625ae0f5f4 100644
--- a/indra/llcommon/llrand.h
+++ b/indra/llcommon/llrand.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrand.h
* @brief Information, functions, and typedefs for randomness.
*
* $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$
*/
@@ -42,18 +42,18 @@
* fairly trivial operations to try to limit compiler optimizations,
* so these numbers are only good for relative comparisons.
*
- * usec/inter algorithm
- * 0.21 boost::minstd_rand0
- * 0.039 boost:lagged_fibonacci19937
- * 0.036 boost:lagged_fibonacci607
- * 0.44 boost::hellekalek1995
- * 0.44 boost::ecuyer1988
- * 0.042 boost::rand48
- * 0.043 boost::mt11213b
- * 0.028 stdlib random()
- * 0.05 stdlib lrand48()
- * 0.034 stdlib rand()
- * 0.020 the old & lame LLRand
+ * usec/inter algorithm
+ * 0.21 boost::minstd_rand0
+ * 0.039 boost:lagged_fibonacci19937
+ * 0.036 boost:lagged_fibonacci607
+ * 0.44 boost::hellekalek1995
+ * 0.44 boost::ecuyer1988
+ * 0.042 boost::rand48
+ * 0.043 boost::mt11213b
+ * 0.028 stdlib random()
+ * 0.05 stdlib lrand48()
+ * 0.034 stdlib rand()
+ * 0.020 the old & lame LLRand
*/
/**
@@ -100,13 +100,13 @@ F64 LL_COMMON_API ll_drand(F64 val);
*/
typedef boost::lagged_fibonacci607 LLRandLagFib607;
-/**<
+/**<
* lengh of cycle: 2^32,000
* memory: 607*sizeof(double) (about 5K)
*/
typedef boost::lagged_fibonacci2281 LLRandLagFib2281;
-/**<
+/**<
* lengh of cycle: 2^120,000
* memory: 2281*sizeof(double) (about 17K)
*/
diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
index 3da94e7a8d..6b546aac63 100644
--- a/indra/llcommon/llrefcount.cpp
+++ b/indra/llcommon/llrefcount.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrefcount.cpp
* @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$
*/
@@ -33,26 +33,26 @@
const S32 gMaxRefCount = LL_REFCOUNT_FREE;
LLRefCount::LLRefCount(const LLRefCount& other)
-: mRef(0)
+: mRef(0)
{
}
LLRefCount& LLRefCount::operator=(const LLRefCount&)
{
- // do nothing, since ref count is specific to *this* reference
- return *this;
+ // do nothing, since ref count is specific to *this* reference
+ return *this;
}
LLRefCount::LLRefCount() :
- mRef(0)
+ mRef(0)
{
}
LLRefCount::~LLRefCount()
{
- if (mRef != LL_REFCOUNT_FREE && mRef != 0)
- {
- LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
- }
+ if (mRef != LL_REFCOUNT_FREE && mRef != 0)
+ {
+ LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
+ }
}
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 15e7175fc8..33c9e956b1 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$
*/
@@ -44,42 +44,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;
};
@@ -90,50 +90,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;
};
/**
@@ -142,12 +142,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();
}
/**
@@ -156,12 +156,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/llregex.h b/indra/llcommon/llregex.h
index 2b7f5e47c2..18da304aee 100644
--- a/indra/llcommon/llregex.h
+++ b/indra/llcommon/llregex.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llregex.h
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2021, 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$
*/
@@ -30,60 +30,60 @@
template <typename S, typename M, typename R>
LL_COMMON_API bool ll_regex_match(const S& string, M& match, const R& regex)
{
- try
- {
- return boost::regex_match(string, match, regex);
- }
- catch (const std::runtime_error& e)
- {
- LL_WARNS() << "error matching with '" << regex.str() << "': "
- << e.what() << ":\n'" << string << "'" << LL_ENDL;
- return false;
- }
+ try
+ {
+ return boost::regex_match(string, match, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error matching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
}
template <typename S, typename R>
LL_COMMON_API bool ll_regex_match(const S& string, const R& regex)
{
- try
- {
- return boost::regex_match(string, regex);
- }
- catch (const std::runtime_error& e)
- {
- LL_WARNS() << "error matching with '" << regex.str() << "': "
- << e.what() << ":\n'" << string << "'" << LL_ENDL;
- return false;
- }
+ try
+ {
+ return boost::regex_match(string, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error matching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
}
template <typename S, typename M, typename R>
bool ll_regex_search(const S& string, M& match, const R& regex)
{
- try
- {
- return boost::regex_search(string, match, regex);
- }
- catch (const std::runtime_error& e)
- {
- LL_WARNS() << "error searching with '" << regex.str() << "': "
- << e.what() << ":\n'" << string << "'" << LL_ENDL;
- return false;
- }
+ try
+ {
+ return boost::regex_search(string, match, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error searching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
}
template <typename S, typename R>
bool ll_regex_search(const S& string, const R& regex)
{
- try
- {
- return boost::regex_search(string, regex);
- }
- catch (const std::runtime_error& e)
- {
- LL_WARNS() << "error searching with '" << regex.str() << "': "
- << e.what() << ":\n'" << string << "'" << LL_ENDL;
- return false;
- }
+ try
+ {
+ return boost::regex_search(string, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error searching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
}
#endif // LLREGEX_H
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index e272d7a9b8..55dabd57a2 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llregistry.h
* @brief template classes for registering name, value pairs in nested scopes, statically, etc.
*
* $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$
*/
@@ -35,314 +35,314 @@
template <typename T>
struct LLRegistryDefaultComparator
{
- bool operator()(const T& lhs, const T& rhs) const
- {
- using std::less;
- return less<T>()(lhs, rhs);
- }
+ bool operator()(const T& lhs, const T& rhs) const
+ {
+ using std::less;
+ return less<T>()(lhs, rhs);
+ }
};
template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
class LLRegistry
{
public:
- typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
- typedef const KEY& ref_const_key_t;
- typedef const VALUE& ref_const_value_t;
- typedef const VALUE* ptr_const_value_t;
- typedef VALUE* ptr_value_t;
-
- class Registrar
- {
- friend class LLRegistry<KEY, VALUE, COMPARATOR>;
- public:
- typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
-
- bool add(ref_const_key_t key, ref_const_value_t value)
- {
- if (mMap.insert(std::make_pair(key, value)).second == false)
- {
- LL_WARNS() << "Tried to register " << key << " but it was already registered!" << LL_ENDL;
- return false;
- }
- return true;
- }
-
- void remove(ref_const_key_t key)
- {
- mMap.erase(key);
- }
-
- void replace(ref_const_key_t key, ref_const_value_t value)
- {
- mMap[key] = value;
- }
-
- typename registry_map_t::const_iterator beginItems() const
- {
- return mMap.begin();
- }
-
- typename registry_map_t::const_iterator endItems() const
- {
- return mMap.end();
- }
-
- protected:
- ptr_value_t getValue(ref_const_key_t key)
- {
- typename registry_map_t::iterator found_it = mMap.find(key);
- if (found_it != mMap.end())
- {
- return &(found_it->second);
- }
- return NULL;
- }
-
- ptr_const_value_t getValue(ref_const_key_t key) const
- {
- typename registry_map_t::const_iterator found_it = mMap.find(key);
- if (found_it != mMap.end())
- {
- return &(found_it->second);
- }
- return NULL;
- }
-
- // if the registry is used to store pointers, and null values are valid entries
- // then use this function to check the existence of an entry
- bool exists(ref_const_key_t key) const
- {
- return mMap.find(key) != mMap.end();
- }
-
- bool empty() const
- {
- return mMap.empty();
- }
-
- protected:
- // use currentRegistrar() or defaultRegistrar()
- Registrar() {}
- ~Registrar() {}
-
- private:
- registry_map_t mMap;
- };
-
- typedef typename std::list<Registrar*> scope_list_t;
- typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
- typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
-
- LLRegistry()
- {}
-
- ~LLRegistry() {}
-
- ptr_value_t getValue(ref_const_key_t key)
- {
- for(Registrar* scope : mActiveScopes)
- {
- ptr_value_t valuep = scope->getValue(key);
- if (valuep != NULL) return valuep;
- }
- return mDefaultRegistrar.getValue(key);
- }
-
- ptr_const_value_t getValue(ref_const_key_t key) const
- {
- for(const Registrar* scope : mActiveScopes)
- {
- ptr_const_value_t valuep = scope->getValue(key);
- if (valuep != NULL) return valuep;
- }
- return mDefaultRegistrar.getValue(key);
- }
-
- bool exists(ref_const_key_t key) const
- {
- for(const Registrar* scope : mActiveScopes)
- {
- if (scope->exists(key)) return true;
- }
-
- return mDefaultRegistrar.exists(key);
- }
-
- bool empty() const
- {
- for(const Registrar* scope : mActiveScopes)
- {
- if (!scope->empty()) return false;
- }
-
- return mDefaultRegistrar.empty();
- }
-
-
- Registrar& defaultRegistrar()
- {
- return mDefaultRegistrar;
- }
-
- const Registrar& defaultRegistrar() const
- {
- return mDefaultRegistrar;
- }
-
-
- Registrar& currentRegistrar()
- {
- if (!mActiveScopes.empty())
- {
- return *mActiveScopes.front();
- }
-
- return mDefaultRegistrar;
- }
-
- const Registrar& currentRegistrar() const
- {
- if (!mActiveScopes.empty())
- {
- return *mActiveScopes.front();
- }
-
- return mDefaultRegistrar;
- }
+ typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef const KEY& ref_const_key_t;
+ typedef const VALUE& ref_const_value_t;
+ typedef const VALUE* ptr_const_value_t;
+ typedef VALUE* ptr_value_t;
+
+ class Registrar
+ {
+ friend class LLRegistry<KEY, VALUE, COMPARATOR>;
+ public:
+ typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
+
+ bool add(ref_const_key_t key, ref_const_value_t value)
+ {
+ if (mMap.insert(std::make_pair(key, value)).second == false)
+ {
+ LL_WARNS() << "Tried to register " << key << " but it was already registered!" << LL_ENDL;
+ return false;
+ }
+ return true;
+ }
+
+ void remove(ref_const_key_t key)
+ {
+ mMap.erase(key);
+ }
+
+ void replace(ref_const_key_t key, ref_const_value_t value)
+ {
+ mMap[key] = value;
+ }
+
+ typename registry_map_t::const_iterator beginItems() const
+ {
+ return mMap.begin();
+ }
+
+ typename registry_map_t::const_iterator endItems() const
+ {
+ return mMap.end();
+ }
+
+ protected:
+ ptr_value_t getValue(ref_const_key_t key)
+ {
+ typename registry_map_t::iterator found_it = mMap.find(key);
+ if (found_it != mMap.end())
+ {
+ return &(found_it->second);
+ }
+ return NULL;
+ }
+
+ ptr_const_value_t getValue(ref_const_key_t key) const
+ {
+ typename registry_map_t::const_iterator found_it = mMap.find(key);
+ if (found_it != mMap.end())
+ {
+ return &(found_it->second);
+ }
+ return NULL;
+ }
+
+ // if the registry is used to store pointers, and null values are valid entries
+ // then use this function to check the existence of an entry
+ bool exists(ref_const_key_t key) const
+ {
+ return mMap.find(key) != mMap.end();
+ }
+
+ bool empty() const
+ {
+ return mMap.empty();
+ }
+
+ protected:
+ // use currentRegistrar() or defaultRegistrar()
+ Registrar() {}
+ ~Registrar() {}
+
+ private:
+ registry_map_t mMap;
+ };
+
+ typedef typename std::list<Registrar*> scope_list_t;
+ typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
+ typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
+
+ LLRegistry()
+ {}
+
+ ~LLRegistry() {}
+
+ ptr_value_t getValue(ref_const_key_t key)
+ {
+ for(Registrar* scope : mActiveScopes)
+ {
+ ptr_value_t valuep = scope->getValue(key);
+ if (valuep != NULL) return valuep;
+ }
+ return mDefaultRegistrar.getValue(key);
+ }
+
+ ptr_const_value_t getValue(ref_const_key_t key) const
+ {
+ for(const Registrar* scope : mActiveScopes)
+ {
+ ptr_const_value_t valuep = scope->getValue(key);
+ if (valuep != NULL) return valuep;
+ }
+ return mDefaultRegistrar.getValue(key);
+ }
+
+ bool exists(ref_const_key_t key) const
+ {
+ for(const Registrar* scope : mActiveScopes)
+ {
+ if (scope->exists(key)) return true;
+ }
+
+ return mDefaultRegistrar.exists(key);
+ }
+
+ bool empty() const
+ {
+ for(const Registrar* scope : mActiveScopes)
+ {
+ if (!scope->empty()) return false;
+ }
+
+ return mDefaultRegistrar.empty();
+ }
+
+
+ Registrar& defaultRegistrar()
+ {
+ return mDefaultRegistrar;
+ }
+
+ const Registrar& defaultRegistrar() const
+ {
+ return mDefaultRegistrar;
+ }
+
+
+ Registrar& currentRegistrar()
+ {
+ if (!mActiveScopes.empty())
+ {
+ return *mActiveScopes.front();
+ }
+
+ return mDefaultRegistrar;
+ }
+
+ const Registrar& currentRegistrar() const
+ {
+ if (!mActiveScopes.empty())
+ {
+ return *mActiveScopes.front();
+ }
+
+ return mDefaultRegistrar;
+ }
protected:
- void addScope(Registrar* scope)
- {
- // newer scopes go up front
- mActiveScopes.insert(mActiveScopes.begin(), scope);
- }
-
- void removeScope(Registrar* scope)
- {
- // O(N) but should be near the beggining and N should be small and this is safer than storing iterators
- scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
- if (iter != mActiveScopes.end())
- {
- mActiveScopes.erase(iter);
- }
- }
+ void addScope(Registrar* scope)
+ {
+ // newer scopes go up front
+ mActiveScopes.insert(mActiveScopes.begin(), scope);
+ }
+
+ void removeScope(Registrar* scope)
+ {
+ // O(N) but should be near the beggining and N should be small and this is safer than storing iterators
+ scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
+ if (iter != mActiveScopes.end())
+ {
+ mActiveScopes.erase(iter);
+ }
+ }
private:
- scope_list_t mActiveScopes;
- Registrar mDefaultRegistrar;
+ scope_list_t mActiveScopes;
+ Registrar mDefaultRegistrar;
};
template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
class LLRegistrySingleton
- : public LLRegistry<KEY, VALUE, COMPARATOR>,
- public LLSingleton<DERIVED_TYPE>
+ : public LLRegistry<KEY, VALUE, COMPARATOR>,
+ public LLSingleton<DERIVED_TYPE>
{
- // This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton)
- // because the concrete class is actually DERIVED_TYPE, not
- // LLRegistrySingleton. So each concrete subclass needs
- // LLSINGLETON(whatever) -- not this intermediate base class.
+ // This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton)
+ // because the concrete class is actually DERIVED_TYPE, not
+ // LLRegistrySingleton. So each concrete subclass needs
+ // LLSINGLETON(whatever) -- not this intermediate base class.
public:
- typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
- typedef const KEY& ref_const_key_t;
- typedef const VALUE& ref_const_value_t;
- typedef VALUE* ptr_value_t;
- typedef const VALUE* ptr_const_value_t;
- typedef LLSingleton<DERIVED_TYPE> singleton_t;
-
- class ScopedRegistrar : public registry_t::Registrar
- {
- public:
- ScopedRegistrar(bool push_scope = true)
- {
- if (push_scope)
- {
- pushScope();
- }
- }
-
- ~ScopedRegistrar()
- {
- if (singleton_t::instanceExists())
- {
- popScope();
- }
- }
-
- void pushScope()
- {
- singleton_t::instance().addScope(this);
- }
-
- void popScope()
- {
- singleton_t::instance().removeScope(this);
- }
-
- ptr_value_t getValueFromScope(ref_const_key_t key)
- {
- return getValue(key);
- }
-
- ptr_const_value_t getValueFromScope(ref_const_key_t key) const
- {
- return getValue(key);
- }
-
- private:
- typename std::list<typename registry_t::Registrar*>::iterator mListIt;
- };
-
- class StaticRegistrar : public registry_t::Registrar
- {
- public:
- virtual ~StaticRegistrar() {}
- StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
- {
- if (singleton_t::instance().exists(key))
- {
- LL_ERRS() << "Duplicate registry entry under key \"" << key << "\"" << LL_ENDL;
- }
- singleton_t::instance().mStaticScope->add(key, value);
- }
- };
-
- // convenience functions
- typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
- static ref_registrar_t currentRegistrar()
- {
- return singleton_t::instance().registry_t::currentRegistrar();
- }
-
- static ref_registrar_t defaultRegistrar()
- {
- return singleton_t::instance().registry_t::defaultRegistrar();
- }
-
- static ptr_value_t getValue(ref_const_key_t key)
- {
- return singleton_t::instance().registry_t::getValue(key);
- }
+ typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef const KEY& ref_const_key_t;
+ typedef const VALUE& ref_const_value_t;
+ typedef VALUE* ptr_value_t;
+ typedef const VALUE* ptr_const_value_t;
+ typedef LLSingleton<DERIVED_TYPE> singleton_t;
+
+ class ScopedRegistrar : public registry_t::Registrar
+ {
+ public:
+ ScopedRegistrar(bool push_scope = true)
+ {
+ if (push_scope)
+ {
+ pushScope();
+ }
+ }
+
+ ~ScopedRegistrar()
+ {
+ if (singleton_t::instanceExists())
+ {
+ popScope();
+ }
+ }
+
+ void pushScope()
+ {
+ singleton_t::instance().addScope(this);
+ }
+
+ void popScope()
+ {
+ singleton_t::instance().removeScope(this);
+ }
+
+ ptr_value_t getValueFromScope(ref_const_key_t key)
+ {
+ return getValue(key);
+ }
+
+ ptr_const_value_t getValueFromScope(ref_const_key_t key) const
+ {
+ return getValue(key);
+ }
+
+ private:
+ typename std::list<typename registry_t::Registrar*>::iterator mListIt;
+ };
+
+ class StaticRegistrar : public registry_t::Registrar
+ {
+ public:
+ virtual ~StaticRegistrar() {}
+ StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
+ {
+ if (singleton_t::instance().exists(key))
+ {
+ LL_ERRS() << "Duplicate registry entry under key \"" << key << "\"" << LL_ENDL;
+ }
+ singleton_t::instance().mStaticScope->add(key, value);
+ }
+ };
+
+ // convenience functions
+ typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
+ static ref_registrar_t currentRegistrar()
+ {
+ return singleton_t::instance().registry_t::currentRegistrar();
+ }
+
+ static ref_registrar_t defaultRegistrar()
+ {
+ return singleton_t::instance().registry_t::defaultRegistrar();
+ }
+
+ static ptr_value_t getValue(ref_const_key_t key)
+ {
+ return singleton_t::instance().registry_t::getValue(key);
+ }
protected:
- // DERIVED_TYPE needs to derive from LLRegistrySingleton
- LLRegistrySingleton()
- : mStaticScope(NULL)
- {}
+ // DERIVED_TYPE needs to derive from LLRegistrySingleton
+ LLRegistrySingleton()
+ : mStaticScope(NULL)
+ {}
- virtual void initSingleton()
- {
- mStaticScope = new ScopedRegistrar();
- }
+ virtual void initSingleton()
+ {
+ mStaticScope = new ScopedRegistrar();
+ }
- virtual ~LLRegistrySingleton()
- {
- delete mStaticScope;
- }
+ virtual ~LLRegistrySingleton()
+ {
+ delete mStaticScope;
+ }
private:
- ScopedRegistrar* mStaticScope;
+ ScopedRegistrar* mStaticScope;
};
// helper macro for doing static registration
diff --git a/indra/llcommon/llrun.cpp b/indra/llcommon/llrun.cpp
index a3b3fccf4b..82005b16bc 100644
--- a/indra/llcommon/llrun.cpp
+++ b/indra/llcommon/llrun.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llrun.cpp
* @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$
*/
@@ -33,136 +33,136 @@
static const LLRunner::run_handle_t INVALID_RUN_HANDLE = 0;
-/**
+/**
* LLRunner
*/
LLRunner::LLRunner() :
- mNextHandle(1)
+ mNextHandle(1)
{
}
LLRunner::~LLRunner()
{
- mRunOnce.clear();
- mRunEvery.clear();
+ mRunOnce.clear();
+ mRunEvery.clear();
}
size_t LLRunner::run()
{
- // We collect all of the runnables which should be run. Since the
- // runnables are allowed to adjust the run list, we need to copy
- // them into a temporary structure which then iterates over them
- // to call out of this method into the runnables.
- F64 now = LLFrameTimer::getTotalSeconds();
- run_list_t run_now;
+ // We collect all of the runnables which should be run. Since the
+ // runnables are allowed to adjust the run list, we need to copy
+ // them into a temporary structure which then iterates over them
+ // to call out of this method into the runnables.
+ F64 now = LLFrameTimer::getTotalSeconds();
+ run_list_t run_now;
- // Collect the run once. We erase the matching ones now because
- // it's easier. If we find a reason to keep them around for a
- // while, we can restructure this method.
- LLRunner::run_list_t::iterator iter = mRunOnce.begin();
- for( ; iter != mRunOnce.end(); )
- {
- if(now > (*iter).mNextRunAt)
- {
- run_now.push_back(*iter);
- iter = mRunOnce.erase(iter);
- }
- else
- {
- ++iter;
- }
- }
+ // Collect the run once. We erase the matching ones now because
+ // it's easier. If we find a reason to keep them around for a
+ // while, we can restructure this method.
+ LLRunner::run_list_t::iterator iter = mRunOnce.begin();
+ for( ; iter != mRunOnce.end(); )
+ {
+ if(now > (*iter).mNextRunAt)
+ {
+ run_now.push_back(*iter);
+ iter = mRunOnce.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
- // Collect the ones that repeat.
- iter = mRunEvery.begin();
- LLRunner::run_list_t::iterator end = mRunEvery.end();
- for( ; iter != end; ++iter )
- {
- if(now > (*iter).mNextRunAt)
- {
- (*iter).mNextRunAt = now + (*iter).mIncrement;
- run_now.push_back(*iter);
- }
- }
+ // Collect the ones that repeat.
+ iter = mRunEvery.begin();
+ LLRunner::run_list_t::iterator end = mRunEvery.end();
+ for( ; iter != end; ++iter )
+ {
+ if(now > (*iter).mNextRunAt)
+ {
+ (*iter).mNextRunAt = now + (*iter).mIncrement;
+ run_now.push_back(*iter);
+ }
+ }
- // Now, run them.
- iter = run_now.begin();
- end = run_now.end();
- for( ; iter != end; ++iter )
- {
- (*iter).mRunnable->run(this, (*iter).mHandle);
- }
- return run_now.size();
+ // Now, run them.
+ iter = run_now.begin();
+ end = run_now.end();
+ for( ; iter != end; ++iter )
+ {
+ (*iter).mRunnable->run(this, (*iter).mHandle);
+ }
+ return run_now.size();
}
LLRunner::run_handle_t LLRunner::addRunnable(
- run_ptr_t runnable,
- ERunSchedule schedule,
- F64 seconds)
+ run_ptr_t runnable,
+ ERunSchedule schedule,
+ F64 seconds)
{
- if(!runnable) return INVALID_RUN_HANDLE;
- run_handle_t handle = mNextHandle++;
- F64 next_run = LLFrameTimer::getTotalSeconds() + seconds;
- LLRunInfo info(handle, runnable, schedule, next_run, seconds);
- switch(schedule)
- {
- case RUN_IN:
- // We could optimize this a bit by sorting this on entry.
- mRunOnce.push_back(info);
- break;
- case RUN_EVERY:
- mRunEvery.push_back(info);
- break;
- default:
- handle = INVALID_RUN_HANDLE;
- break;
- }
- return handle;
+ if(!runnable) return INVALID_RUN_HANDLE;
+ run_handle_t handle = mNextHandle++;
+ F64 next_run = LLFrameTimer::getTotalSeconds() + seconds;
+ LLRunInfo info(handle, runnable, schedule, next_run, seconds);
+ switch(schedule)
+ {
+ case RUN_IN:
+ // We could optimize this a bit by sorting this on entry.
+ mRunOnce.push_back(info);
+ break;
+ case RUN_EVERY:
+ mRunEvery.push_back(info);
+ break;
+ default:
+ handle = INVALID_RUN_HANDLE;
+ break;
+ }
+ return handle;
}
LLRunner::run_ptr_t LLRunner::removeRunnable(LLRunner::run_handle_t handle)
{
- LLRunner::run_ptr_t rv;
- LLRunner::run_list_t::iterator iter = mRunOnce.begin();
- LLRunner::run_list_t::iterator end = mRunOnce.end();
- for( ; iter != end; ++iter)
- {
- if((*iter).mHandle == handle)
- {
- rv = (*iter).mRunnable;
- mRunOnce.erase(iter);
- return rv;
- }
- }
+ LLRunner::run_ptr_t rv;
+ LLRunner::run_list_t::iterator iter = mRunOnce.begin();
+ LLRunner::run_list_t::iterator end = mRunOnce.end();
+ for( ; iter != end; ++iter)
+ {
+ if((*iter).mHandle == handle)
+ {
+ rv = (*iter).mRunnable;
+ mRunOnce.erase(iter);
+ return rv;
+ }
+ }
- iter = mRunEvery.begin();
- end = mRunEvery.end();
- for( ; iter != end; ++iter)
- {
- if((*iter).mHandle == handle)
- {
- rv = (*iter).mRunnable;
- mRunEvery.erase(iter);
- return rv;
- }
- }
- return rv;
+ iter = mRunEvery.begin();
+ end = mRunEvery.end();
+ for( ; iter != end; ++iter)
+ {
+ if((*iter).mHandle == handle)
+ {
+ rv = (*iter).mRunnable;
+ mRunEvery.erase(iter);
+ return rv;
+ }
+ }
+ return rv;
}
-/**
+/**
* LLRunner::LLRunInfo
*/
LLRunner::LLRunInfo::LLRunInfo(
- run_handle_t handle,
- run_ptr_t runnable,
- ERunSchedule schedule,
- F64 next_run_after,
- F64 increment) :
- mHandle(handle),
- mRunnable(runnable),
- mSchedule(schedule),
- mNextRunAt(next_run_after),
- mIncrement(increment)
+ run_handle_t handle,
+ run_ptr_t runnable,
+ ERunSchedule schedule,
+ F64 next_run_after,
+ F64 increment) :
+ mHandle(handle),
+ mRunnable(runnable),
+ mSchedule(schedule),
+ mNextRunAt(next_run_after),
+ mIncrement(increment)
{
}
diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h
index 42e3d9b47a..8061117ad5 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$
*/
@@ -34,7 +34,7 @@
class LLRunnable;
-/**
+/**
* @class LLRunner
* @brief This class manages a set of LLRunnable objects.
*
@@ -45,96 +45,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.
*
@@ -146,17 +146,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/llsafehandle.h b/indra/llcommon/llsafehandle.h
index 9550e6253e..1d7e4f8220 100644
--- a/indra/llcommon/llsafehandle.h
+++ b/indra/llcommon/llsafehandle.h
@@ -1,32 +1,32 @@
-/**
+/**
* @file llsafehandle.h
* @brief Reference-counted object where Object() is valid, not NULL.
*
* $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$
*/
#ifndef LLSAFEHANDLE_H
#define LLSAFEHANDLE_H
-#include "llerror.h" // *TODO: consider eliminating this
+#include "llerror.h" // *TODO: consider eliminating this
#include "llsingleton.h"
/*==========================================================================*|
@@ -57,142 +57,142 @@ not ever affect subsequent computations.
// when error checking occurs at a different granularity or in a different part of the code
// than when referencing an object via a LLSafeHandle.
-template <class Type>
+template <class Type>
class LLSafeHandle
{
public:
- LLSafeHandle() :
- mPointer(NULL)
- {
- }
-
- LLSafeHandle(Type* ptr) :
- mPointer(NULL)
- {
- assign(ptr);
- }
-
- LLSafeHandle(const LLSafeHandle<Type>& ptr) :
- mPointer(NULL)
- {
- assign(ptr.mPointer);
- }
-
- // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
- mPointer(NULL)
- {
- assign(ptr.get());
- }
-
- ~LLSafeHandle()
- {
- unref();
- }
-
- const Type* operator->() const { return nonNull(mPointer); }
- Type* operator->() { return nonNull(mPointer); }
-
- Type* get() const { return mPointer; }
- void clear() { assign(NULL); }
- // we disallow these operations as they expose our null objects to direct manipulation
- // and bypass the reference counting semantics
- //const Type& operator*() const { return *nonNull(mPointer); }
- //Type& operator*() { return *nonNull(mPointer); }
-
- operator BOOL() const { return mPointer != NULL; }
- operator bool() const { return mPointer != NULL; }
- bool operator!() const { return mPointer == NULL; }
- bool isNull() const { return mPointer == NULL; }
- bool notNull() const { return mPointer != NULL; }
-
-
- operator Type*() const { return mPointer; }
- operator const Type*() const { return mPointer; }
- bool operator !=(Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
-
- LLSafeHandle<Type>& operator =(Type* ptr)
- {
- assign(ptr);
- return *this;
- }
-
- LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
- {
- assign(ptr.mPointer);
- return *this;
- }
-
- // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
- {
- assign(ptr.get());
- return *this;
- }
+ LLSafeHandle() :
+ mPointer(NULL)
+ {
+ }
+
+ LLSafeHandle(Type* ptr) :
+ mPointer(NULL)
+ {
+ assign(ptr);
+ }
+
+ LLSafeHandle(const LLSafeHandle<Type>& ptr) :
+ mPointer(NULL)
+ {
+ assign(ptr.mPointer);
+ }
+
+ // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
+ mPointer(NULL)
+ {
+ assign(ptr.get());
+ }
+
+ ~LLSafeHandle()
+ {
+ unref();
+ }
+
+ const Type* operator->() const { return nonNull(mPointer); }
+ Type* operator->() { return nonNull(mPointer); }
+
+ Type* get() const { return mPointer; }
+ void clear() { assign(NULL); }
+ // we disallow these operations as they expose our null objects to direct manipulation
+ // and bypass the reference counting semantics
+ //const Type& operator*() const { return *nonNull(mPointer); }
+ //Type& operator*() { return *nonNull(mPointer); }
+
+ operator BOOL() const { return mPointer != NULL; }
+ operator bool() const { return mPointer != NULL; }
+ bool operator!() const { return mPointer == NULL; }
+ bool isNull() const { return mPointer == NULL; }
+ bool notNull() const { return mPointer != NULL; }
+
+
+ operator Type*() const { return mPointer; }
+ operator const Type*() const { return mPointer; }
+ bool operator !=(Type* ptr) const { return (mPointer != ptr); }
+ bool operator ==(Type* ptr) const { return (mPointer == ptr); }
+ bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+
+ LLSafeHandle<Type>& operator =(Type* ptr)
+ {
+ assign(ptr);
+ return *this;
+ }
+
+ LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
+ {
+ assign(ptr.mPointer);
+ return *this;
+ }
+
+ // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
+ {
+ assign(ptr.get());
+ return *this;
+ }
protected:
- void ref()
- {
- if (mPointer)
- {
- mPointer->ref();
- }
- }
-
- void unref()
- {
- if (mPointer)
- {
- Type *tempp = mPointer;
- mPointer = NULL;
- tempp->unref();
- if (mPointer != NULL)
- {
- LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
- unref();
- }
- }
- }
-
- void assign(Type* ptr)
- {
- if( mPointer != ptr )
- {
- unref();
- mPointer = ptr;
- ref();
- }
- }
-
- // Define an LLSingleton whose sole purpose is to hold a "null instance"
- // of the subject Type: the canonical instance to dereference if this
- // LLSafeHandle actually holds a null pointer. We use LLSingleton
- // specifically so that the "null instance" can be cleaned up at a well-
- // defined time, specifically LLSingletonBase::deleteAll().
- // Of course, as with any LLSingleton, the "null instance" is only
- // instantiated on demand -- in this case, if you actually try to
- // dereference an LLSafeHandle containing null.
- class NullInstanceHolder: public LLSingleton<NullInstanceHolder>
- {
- LLSINGLETON_EMPTY_CTOR(NullInstanceHolder);
- ~NullInstanceHolder() {}
- public:
- Type mNullInstance;
- };
-
- static Type* nonNull(Type* ptr)
- {
- return ptr? ptr : &NullInstanceHolder::instance().mNullInstance;
- }
+ void ref()
+ {
+ if (mPointer)
+ {
+ mPointer->ref();
+ }
+ }
+
+ void unref()
+ {
+ if (mPointer)
+ {
+ Type *tempp = mPointer;
+ mPointer = NULL;
+ tempp->unref();
+ if (mPointer != NULL)
+ {
+ LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+ unref();
+ }
+ }
+ }
+
+ void assign(Type* ptr)
+ {
+ if( mPointer != ptr )
+ {
+ unref();
+ mPointer = ptr;
+ ref();
+ }
+ }
+
+ // Define an LLSingleton whose sole purpose is to hold a "null instance"
+ // of the subject Type: the canonical instance to dereference if this
+ // LLSafeHandle actually holds a null pointer. We use LLSingleton
+ // specifically so that the "null instance" can be cleaned up at a well-
+ // defined time, specifically LLSingletonBase::deleteAll().
+ // Of course, as with any LLSingleton, the "null instance" is only
+ // instantiated on demand -- in this case, if you actually try to
+ // dereference an LLSafeHandle containing null.
+ class NullInstanceHolder: public LLSingleton<NullInstanceHolder>
+ {
+ LLSINGLETON_EMPTY_CTOR(NullInstanceHolder);
+ ~NullInstanceHolder() {}
+ public:
+ Type mNullInstance;
+ };
+
+ static Type* nonNull(Type* ptr)
+ {
+ return ptr? ptr : &NullInstanceHolder::instance().mNullInstance;
+ }
protected:
- Type* mPointer;
+ Type* mPointer;
};
#endif
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 590915e9d2..663ceac22b 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsd.cpp
* @brief LLSD flexible data system
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -53,13 +53,13 @@ bool was_negative(size_t i)
#endif
#ifdef NAME_UNNAMED_NAMESPACE
-namespace LLSDUnnamedNamespace
+namespace LLSDUnnamedNamespace
#else
-namespace
+namespace
#endif
{
- class ImplMap;
- class ImplArray;
+ class ImplMap;
+ class ImplArray;
}
#ifdef NAME_UNNAMED_NAMESPACE
@@ -70,740 +70,740 @@ namespace llsd
{
// statics
-S32 sLLSDAllocationCount = 0;
+S32 sLLSDAllocationCount = 0;
S32 sLLSDNetObjects = 0;
} // namespace llsd
-#define ALLOC_LLSD_OBJECT { llsd::sLLSDNetObjects++; llsd::sLLSDAllocationCount++; }
-#define FREE_LLSD_OBJECT { llsd::sLLSDNetObjects--; }
+#define ALLOC_LLSD_OBJECT { llsd::sLLSDNetObjects++; llsd::sLLSDAllocationCount++; }
+#define FREE_LLSD_OBJECT { llsd::sLLSDNetObjects--; }
class LLSD::Impl
- /**< This class is the abstract base class of the implementation of LLSD
- It provides the reference counting implementation, and the default
- implementation of most methods for most data types. It also serves
- as a working implementation of the Undefined type.
-
- */
+ /**< This class is the abstract base class of the implementation of LLSD
+ It provides the reference counting implementation, and the default
+ implementation of most methods for most data types. It also serves
+ as a working implementation of the Undefined type.
+
+ */
{
protected:
- Impl();
-
- enum StaticAllocationMarker { STATIC_USAGE_COUNT = 0xFFFFFFFF };
- Impl(StaticAllocationMarker);
- ///< This constructor is used for static objects and causes the
- // suppresses adjusting the debugging counters when they are
- // finally initialized.
-
- virtual ~Impl();
-
- bool shared() const { return (mUseCount > 1) && (mUseCount != STATIC_USAGE_COUNT); }
-
- U32 mUseCount;
+ Impl();
+
+ enum StaticAllocationMarker { STATIC_USAGE_COUNT = 0xFFFFFFFF };
+ Impl(StaticAllocationMarker);
+ ///< This constructor is used for static objects and causes the
+ // suppresses adjusting the debugging counters when they are
+ // finally initialized.
+
+ virtual ~Impl();
+
+ bool shared() const { return (mUseCount > 1) && (mUseCount != STATIC_USAGE_COUNT); }
+
+ U32 mUseCount;
public:
- static void reset(Impl*& var, Impl* impl);
- ///< safely set var to refer to the new impl (possibly shared)
-
- static Impl& safe( Impl*);
- static const Impl& safe(const Impl*);
- ///< since a NULL Impl* is used for undefined, this ensures there is
- // always an object you call virtual member functions on
-
- virtual ImplMap& makeMap(Impl*& var);
- virtual ImplArray& makeArray(Impl*& var);
- ///< sure var is a modifiable, non-shared map or array
-
- virtual LLSD::Type type() const { return LLSD::TypeUndefined; }
-
- static void assignUndefined(LLSD::Impl*& var);
- static void assign(LLSD::Impl*& var, const LLSD::Impl* other);
-
- virtual void assign(Impl*& var, LLSD::Boolean);
- virtual void assign(Impl*& var, LLSD::Integer);
- virtual void assign(Impl*& var, LLSD::Real);
- virtual void assign(Impl*& var, const LLSD::String&);
- virtual void assign(Impl*& var, const LLSD::UUID&);
- virtual void assign(Impl*& var, const LLSD::Date&);
- virtual void assign(Impl*& var, const LLSD::URI&);
- virtual void assign(Impl*& var, const LLSD::Binary&);
- ///< If the receiver is the right type and unshared, these are simple
- // data assignments, othewise the default implementation handless
- // constructing the proper Impl subclass
-
- virtual Boolean asBoolean() const { return false; }
- virtual Integer asInteger() const { return 0; }
- virtual Real asReal() const { return 0.0; }
- virtual String asString() const { return std::string(); }
- virtual UUID asUUID() const { return LLUUID(); }
- virtual Date asDate() const { return LLDate(); }
- virtual URI asURI() const { return LLURI(); }
- virtual const Binary& asBinary() const { static const std::vector<U8> empty; return empty; }
-
- virtual const String& asStringRef() const { static const std::string empty; return empty; }
-
- virtual bool has(const String&) const { return false; }
- virtual LLSD get(const String&) const { return LLSD(); }
- virtual LLSD getKeys() const { return LLSD::emptyArray(); }
- virtual void erase(const String&) { }
- virtual const LLSD& ref(const String&) const{ return undef(); }
-
- virtual size_t size() const { return 0; }
- virtual LLSD get(size_t) const { return LLSD(); }
- virtual void erase(size_t) { }
- virtual const LLSD& ref(size_t) const { return undef(); }
-
- virtual LLSD::map_const_iterator beginMap() const { return endMap(); }
- virtual LLSD::map_const_iterator endMap() const { static const std::map<String, LLSD> empty; return empty.end(); }
- virtual LLSD::array_const_iterator beginArray() const { return endArray(); }
- virtual LLSD::array_const_iterator endArray() const { static const std::vector<LLSD> empty; return empty.end(); }
-
- virtual void dumpStats() const;
- virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
- // Container subclasses contain LLSD objects, rather than directly
- // containing Impl objects. This helper forwards through LLSD.
- void calcStats(const LLSD& llsd, S32 type_counts[], S32 share_counts[]) const
- {
- safe(llsd.impl).calcStats(type_counts, share_counts);
- }
-
- static const Impl& getImpl(const LLSD& llsd) { return safe(llsd.impl); }
- static Impl& getImpl(LLSD& llsd) { return safe(llsd.impl); }
-
- static const LLSD& undef();
-
- static U32 sAllocationCount;
- static U32 sOutstandingCount;
+ static void reset(Impl*& var, Impl* impl);
+ ///< safely set var to refer to the new impl (possibly shared)
+
+ static Impl& safe( Impl*);
+ static const Impl& safe(const Impl*);
+ ///< since a NULL Impl* is used for undefined, this ensures there is
+ // always an object you call virtual member functions on
+
+ virtual ImplMap& makeMap(Impl*& var);
+ virtual ImplArray& makeArray(Impl*& var);
+ ///< sure var is a modifiable, non-shared map or array
+
+ virtual LLSD::Type type() const { return LLSD::TypeUndefined; }
+
+ static void assignUndefined(LLSD::Impl*& var);
+ static void assign(LLSD::Impl*& var, const LLSD::Impl* other);
+
+ virtual void assign(Impl*& var, LLSD::Boolean);
+ virtual void assign(Impl*& var, LLSD::Integer);
+ virtual void assign(Impl*& var, LLSD::Real);
+ virtual void assign(Impl*& var, const LLSD::String&);
+ virtual void assign(Impl*& var, const LLSD::UUID&);
+ virtual void assign(Impl*& var, const LLSD::Date&);
+ virtual void assign(Impl*& var, const LLSD::URI&);
+ virtual void assign(Impl*& var, const LLSD::Binary&);
+ ///< If the receiver is the right type and unshared, these are simple
+ // data assignments, othewise the default implementation handless
+ // constructing the proper Impl subclass
+
+ virtual Boolean asBoolean() const { return false; }
+ virtual Integer asInteger() const { return 0; }
+ virtual Real asReal() const { return 0.0; }
+ virtual String asString() const { return std::string(); }
+ virtual UUID asUUID() const { return LLUUID(); }
+ virtual Date asDate() const { return LLDate(); }
+ virtual URI asURI() const { return LLURI(); }
+ virtual const Binary& asBinary() const { static const std::vector<U8> empty; return empty; }
+
+ virtual const String& asStringRef() const { static const std::string empty; return empty; }
+
+ virtual bool has(const String&) const { return false; }
+ virtual LLSD get(const String&) const { return LLSD(); }
+ virtual LLSD getKeys() const { return LLSD::emptyArray(); }
+ virtual void erase(const String&) { }
+ virtual const LLSD& ref(const String&) const{ return undef(); }
+
+ virtual size_t size() const { return 0; }
+ virtual LLSD get(size_t) const { return LLSD(); }
+ virtual void erase(size_t) { }
+ virtual const LLSD& ref(size_t) const { return undef(); }
+
+ virtual LLSD::map_const_iterator beginMap() const { return endMap(); }
+ virtual LLSD::map_const_iterator endMap() const { static const std::map<String, LLSD> empty; return empty.end(); }
+ virtual LLSD::array_const_iterator beginArray() const { return endArray(); }
+ virtual LLSD::array_const_iterator endArray() const { static const std::vector<LLSD> empty; return empty.end(); }
+
+ virtual void dumpStats() const;
+ virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
+ // Container subclasses contain LLSD objects, rather than directly
+ // containing Impl objects. This helper forwards through LLSD.
+ void calcStats(const LLSD& llsd, S32 type_counts[], S32 share_counts[]) const
+ {
+ safe(llsd.impl).calcStats(type_counts, share_counts);
+ }
+
+ static const Impl& getImpl(const LLSD& llsd) { return safe(llsd.impl); }
+ static Impl& getImpl(LLSD& llsd) { return safe(llsd.impl); }
+
+ static const LLSD& undef();
+
+ static U32 sAllocationCount;
+ static U32 sOutstandingCount;
};
#ifdef NAME_UNNAMED_NAMESPACE
-namespace LLSDUnnamedNamespace
+namespace LLSDUnnamedNamespace
#else
-namespace
+namespace
#endif
{
- template<LLSD::Type T, class Data, class DataRef = Data>
- class ImplBase : public LLSD::Impl
- ///< This class handles most of the work for a subclass of Impl
- // for a given simple data type. Subclasses of this provide the
- // conversion functions and a constructor.
- {
- protected:
- Data mValue;
-
- typedef ImplBase Base;
-
- public:
- ImplBase(DataRef value) : mValue(value) { }
-
- virtual LLSD::Type type() const { return T; }
-
- using LLSD::Impl::assign; // Unhiding base class virtuals...
- virtual void assign(LLSD::Impl*& var, DataRef value) {
- if (shared())
- {
- Impl::assign(var, value);
- }
- else
- {
- mValue = value;
- }
- }
- };
-
-
- class ImplBoolean
- : public ImplBase<LLSD::TypeBoolean, LLSD::Boolean>
- {
- public:
- ImplBoolean(LLSD::Boolean v) : Base(v) { }
-
- virtual LLSD::Boolean asBoolean() const { return mValue; }
- virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; }
- virtual LLSD::Real asReal() const { return mValue ? 1 : 0; }
- virtual LLSD::String asString() const;
- };
-
- LLSD::String ImplBoolean::asString() const
- // *NOTE: The reason that false is not converted to "false" is
- // because that would break roundtripping,
- // e.g. LLSD(false).asString().asBoolean(). There are many
- // reasons for wanting LLSD("false").asBoolean() == true, such
- // as "everything else seems to work that way".
- { return mValue ? "true" : ""; }
-
-
- class ImplInteger
- : public ImplBase<LLSD::TypeInteger, LLSD::Integer>
- {
- public:
- ImplInteger(LLSD::Integer v) : Base(v) { }
-
- virtual LLSD::Boolean asBoolean() const { return mValue != 0; }
- virtual LLSD::Integer asInteger() const { return mValue; }
- virtual LLSD::Real asReal() const { return mValue; }
- virtual LLSD::String asString() const;
- };
-
- LLSD::String ImplInteger::asString() const
- { return llformat("%d", mValue); }
-
-
- class ImplReal
- : public ImplBase<LLSD::TypeReal, LLSD::Real>
- {
- public:
- ImplReal(LLSD::Real v) : Base(v) { }
-
- virtual LLSD::Boolean asBoolean() const;
- virtual LLSD::Integer asInteger() const;
- virtual LLSD::Real asReal() const { return mValue; }
- virtual LLSD::String asString() const;
- };
-
- LLSD::Boolean ImplReal::asBoolean() const
- { return !llisnan(mValue) && mValue != 0.0; }
-
- LLSD::Integer ImplReal::asInteger() const
- { return !llisnan(mValue) ? (LLSD::Integer)mValue : 0; }
-
- LLSD::String ImplReal::asString() const
- { return llformat("%lg", mValue); }
-
-
- class ImplString
- : public ImplBase<LLSD::TypeString, LLSD::String, const LLSD::String&>
- {
- public:
- ImplString(const LLSD::String& v) : Base(v) { }
-
- virtual LLSD::Boolean asBoolean() const { return !mValue.empty(); }
- virtual LLSD::Integer asInteger() const;
- virtual LLSD::Real asReal() const;
- virtual LLSD::String asString() const { return mValue; }
- virtual LLSD::UUID asUUID() const { return LLUUID(mValue); }
- virtual LLSD::Date asDate() const { return LLDate(mValue); }
- virtual LLSD::URI asURI() const { return LLURI(mValue); }
- virtual size_t size() const { return mValue.size(); }
- virtual const LLSD::String& asStringRef() const { return mValue; }
- };
-
- LLSD::Integer ImplString::asInteger() const
- {
- // This must treat "1.23" not as an error, but as a number, which is
- // then truncated down to an integer. Hence, this code doesn't call
- // std::istringstream::operator>>(int&), which would not consume the
- // ".23" portion.
-
- return (int)asReal();
- }
-
- LLSD::Real ImplString::asReal() const
- {
- F64 v = 0.0;
- std::istringstream i_stream(mValue);
- i_stream >> v;
-
- // we would probably like to ignore all trailing whitespace as
- // well, but for now, simply eat the next character, and make
- // sure we reached the end of the string.
- // *NOTE: gcc 2.95 does not generate an eof() event on the
- // stream operation above, so we manually get here to force it
- // across platforms.
- int c = i_stream.get();
- return ((EOF ==c) ? v : 0.0);
- }
-
-
- class ImplUUID
- : public ImplBase<LLSD::TypeUUID, LLSD::UUID, const LLSD::UUID&>
- {
- public:
- ImplUUID(const LLSD::UUID& v) : Base(v) { }
-
- virtual LLSD::String asString() const{ return mValue.asString(); }
- virtual LLSD::UUID asUUID() const { return mValue; }
- };
-
-
- class ImplDate
- : public ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>
- {
- public:
- ImplDate(const LLSD::Date& v)
- : ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>(v)
- { }
-
- virtual LLSD::Integer asInteger() const
- {
- return (LLSD::Integer)(mValue.secondsSinceEpoch());
- }
- virtual LLSD::Real asReal() const
- {
- return mValue.secondsSinceEpoch();
- }
- virtual LLSD::String asString() const{ return mValue.asString(); }
- virtual LLSD::Date asDate() const { return mValue; }
- };
-
-
- class ImplURI
- : public ImplBase<LLSD::TypeURI, LLSD::URI, const LLSD::URI&>
- {
- public:
- ImplURI(const LLSD::URI& v) : Base(v) { }
-
- virtual LLSD::String asString() const{ return mValue.asString(); }
- virtual LLSD::URI asURI() const { return mValue; }
- };
-
-
- class ImplBinary
- : public ImplBase<LLSD::TypeBinary, LLSD::Binary, const LLSD::Binary&>
- {
- public:
- ImplBinary(const LLSD::Binary& v) : Base(v) { }
-
- virtual const LLSD::Binary& asBinary() const{ return mValue; }
- };
-
-
- class ImplMap : public LLSD::Impl
- {
- private:
- typedef std::map<LLSD::String, LLSD> DataMap;
-
- DataMap mData;
-
- protected:
- ImplMap(const DataMap& data) : mData(data) { }
-
- public:
- ImplMap() { }
-
- virtual ImplMap& makeMap(LLSD::Impl*&);
-
- virtual LLSD::Type type() const { return LLSD::TypeMap; }
-
- virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
-
- virtual bool has(const LLSD::String&) const;
-
- using LLSD::Impl::get; // Unhiding get(size_t)
- using LLSD::Impl::erase; // Unhiding erase(size_t)
- using LLSD::Impl::ref; // Unhiding ref(size_t)
- virtual LLSD get(const LLSD::String&) const;
- virtual LLSD getKeys() const;
- void insert(const LLSD::String& k, const LLSD& v);
- virtual void erase(const LLSD::String&);
- LLSD& ref(const LLSD::String&);
- virtual const LLSD& ref(const LLSD::String&) const;
-
- virtual size_t size() const { return mData.size(); }
-
- LLSD::map_iterator beginMap() { return mData.begin(); }
- LLSD::map_iterator endMap() { return mData.end(); }
- virtual LLSD::map_const_iterator beginMap() const { return mData.begin(); }
- virtual LLSD::map_const_iterator endMap() const { return mData.end(); }
-
- virtual void dumpStats() const;
- virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
- };
-
- ImplMap& ImplMap::makeMap(LLSD::Impl*& var)
- {
+ template<LLSD::Type T, class Data, class DataRef = Data>
+ class ImplBase : public LLSD::Impl
+ ///< This class handles most of the work for a subclass of Impl
+ // for a given simple data type. Subclasses of this provide the
+ // conversion functions and a constructor.
+ {
+ protected:
+ Data mValue;
+
+ typedef ImplBase Base;
+
+ public:
+ ImplBase(DataRef value) : mValue(value) { }
+
+ virtual LLSD::Type type() const { return T; }
+
+ using LLSD::Impl::assign; // Unhiding base class virtuals...
+ virtual void assign(LLSD::Impl*& var, DataRef value) {
+ if (shared())
+ {
+ Impl::assign(var, value);
+ }
+ else
+ {
+ mValue = value;
+ }
+ }
+ };
+
+
+ class ImplBoolean
+ : public ImplBase<LLSD::TypeBoolean, LLSD::Boolean>
+ {
+ public:
+ ImplBoolean(LLSD::Boolean v) : Base(v) { }
+
+ virtual LLSD::Boolean asBoolean() const { return mValue; }
+ virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; }
+ virtual LLSD::Real asReal() const { return mValue ? 1 : 0; }
+ virtual LLSD::String asString() const;
+ };
+
+ LLSD::String ImplBoolean::asString() const
+ // *NOTE: The reason that false is not converted to "false" is
+ // because that would break roundtripping,
+ // e.g. LLSD(false).asString().asBoolean(). There are many
+ // reasons for wanting LLSD("false").asBoolean() == true, such
+ // as "everything else seems to work that way".
+ { return mValue ? "true" : ""; }
+
+
+ class ImplInteger
+ : public ImplBase<LLSD::TypeInteger, LLSD::Integer>
+ {
+ public:
+ ImplInteger(LLSD::Integer v) : Base(v) { }
+
+ virtual LLSD::Boolean asBoolean() const { return mValue != 0; }
+ virtual LLSD::Integer asInteger() const { return mValue; }
+ virtual LLSD::Real asReal() const { return mValue; }
+ virtual LLSD::String asString() const;
+ };
+
+ LLSD::String ImplInteger::asString() const
+ { return llformat("%d", mValue); }
+
+
+ class ImplReal
+ : public ImplBase<LLSD::TypeReal, LLSD::Real>
+ {
+ public:
+ ImplReal(LLSD::Real v) : Base(v) { }
+
+ virtual LLSD::Boolean asBoolean() const;
+ virtual LLSD::Integer asInteger() const;
+ virtual LLSD::Real asReal() const { return mValue; }
+ virtual LLSD::String asString() const;
+ };
+
+ LLSD::Boolean ImplReal::asBoolean() const
+ { return !llisnan(mValue) && mValue != 0.0; }
+
+ LLSD::Integer ImplReal::asInteger() const
+ { return !llisnan(mValue) ? (LLSD::Integer)mValue : 0; }
+
+ LLSD::String ImplReal::asString() const
+ { return llformat("%lg", mValue); }
+
+
+ class ImplString
+ : public ImplBase<LLSD::TypeString, LLSD::String, const LLSD::String&>
+ {
+ public:
+ ImplString(const LLSD::String& v) : Base(v) { }
+
+ virtual LLSD::Boolean asBoolean() const { return !mValue.empty(); }
+ virtual LLSD::Integer asInteger() const;
+ virtual LLSD::Real asReal() const;
+ virtual LLSD::String asString() const { return mValue; }
+ virtual LLSD::UUID asUUID() const { return LLUUID(mValue); }
+ virtual LLSD::Date asDate() const { return LLDate(mValue); }
+ virtual LLSD::URI asURI() const { return LLURI(mValue); }
+ virtual size_t size() const { return mValue.size(); }
+ virtual const LLSD::String& asStringRef() const { return mValue; }
+ };
+
+ LLSD::Integer ImplString::asInteger() const
+ {
+ // This must treat "1.23" not as an error, but as a number, which is
+ // then truncated down to an integer. Hence, this code doesn't call
+ // std::istringstream::operator>>(int&), which would not consume the
+ // ".23" portion.
+
+ return (int)asReal();
+ }
+
+ LLSD::Real ImplString::asReal() const
+ {
+ F64 v = 0.0;
+ std::istringstream i_stream(mValue);
+ i_stream >> v;
+
+ // we would probably like to ignore all trailing whitespace as
+ // well, but for now, simply eat the next character, and make
+ // sure we reached the end of the string.
+ // *NOTE: gcc 2.95 does not generate an eof() event on the
+ // stream operation above, so we manually get here to force it
+ // across platforms.
+ int c = i_stream.get();
+ return ((EOF ==c) ? v : 0.0);
+ }
+
+
+ class ImplUUID
+ : public ImplBase<LLSD::TypeUUID, LLSD::UUID, const LLSD::UUID&>
+ {
+ public:
+ ImplUUID(const LLSD::UUID& v) : Base(v) { }
+
+ virtual LLSD::String asString() const{ return mValue.asString(); }
+ virtual LLSD::UUID asUUID() const { return mValue; }
+ };
+
+
+ class ImplDate
+ : public ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>
+ {
+ public:
+ ImplDate(const LLSD::Date& v)
+ : ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>(v)
+ { }
+
+ virtual LLSD::Integer asInteger() const
+ {
+ return (LLSD::Integer)(mValue.secondsSinceEpoch());
+ }
+ virtual LLSD::Real asReal() const
+ {
+ return mValue.secondsSinceEpoch();
+ }
+ virtual LLSD::String asString() const{ return mValue.asString(); }
+ virtual LLSD::Date asDate() const { return mValue; }
+ };
+
+
+ class ImplURI
+ : public ImplBase<LLSD::TypeURI, LLSD::URI, const LLSD::URI&>
+ {
+ public:
+ ImplURI(const LLSD::URI& v) : Base(v) { }
+
+ virtual LLSD::String asString() const{ return mValue.asString(); }
+ virtual LLSD::URI asURI() const { return mValue; }
+ };
+
+
+ class ImplBinary
+ : public ImplBase<LLSD::TypeBinary, LLSD::Binary, const LLSD::Binary&>
+ {
+ public:
+ ImplBinary(const LLSD::Binary& v) : Base(v) { }
+
+ virtual const LLSD::Binary& asBinary() const{ return mValue; }
+ };
+
+
+ class ImplMap : public LLSD::Impl
+ {
+ private:
+ typedef std::map<LLSD::String, LLSD> DataMap;
+
+ DataMap mData;
+
+ protected:
+ ImplMap(const DataMap& data) : mData(data) { }
+
+ public:
+ ImplMap() { }
+
+ virtual ImplMap& makeMap(LLSD::Impl*&);
+
+ virtual LLSD::Type type() const { return LLSD::TypeMap; }
+
+ virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+
+ virtual bool has(const LLSD::String&) const;
+
+ using LLSD::Impl::get; // Unhiding get(size_t)
+ using LLSD::Impl::erase; // Unhiding erase(size_t)
+ using LLSD::Impl::ref; // Unhiding ref(size_t)
+ virtual LLSD get(const LLSD::String&) const;
+ virtual LLSD getKeys() const;
+ void insert(const LLSD::String& k, const LLSD& v);
+ virtual void erase(const LLSD::String&);
+ LLSD& ref(const LLSD::String&);
+ virtual const LLSD& ref(const LLSD::String&) const;
+
+ virtual size_t size() const { return mData.size(); }
+
+ LLSD::map_iterator beginMap() { return mData.begin(); }
+ LLSD::map_iterator endMap() { return mData.end(); }
+ virtual LLSD::map_const_iterator beginMap() const { return mData.begin(); }
+ virtual LLSD::map_const_iterator endMap() const { return mData.end(); }
+
+ virtual void dumpStats() const;
+ virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
+ };
+
+ ImplMap& ImplMap::makeMap(LLSD::Impl*& var)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- if (shared())
- {
- ImplMap* i = new ImplMap(mData);
- Impl::assign(var, i);
- return *i;
- }
- else
- {
- return *this;
- }
- }
-
- bool ImplMap::has(const LLSD::String& k) const
- {
+ if (shared())
+ {
+ ImplMap* i = new ImplMap(mData);
+ Impl::assign(var, i);
+ return *i;
+ }
+ else
+ {
+ return *this;
+ }
+ }
+
+ bool ImplMap::has(const LLSD::String& k) const
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- DataMap::const_iterator i = mData.find(k);
- return i != mData.end();
- }
-
- LLSD ImplMap::get(const LLSD::String& k) const
- {
+ DataMap::const_iterator i = mData.find(k);
+ return i != mData.end();
+ }
+
+ LLSD ImplMap::get(const LLSD::String& k) const
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- DataMap::const_iterator i = mData.find(k);
- return (i != mData.end()) ? i->second : LLSD();
- }
+ DataMap::const_iterator i = mData.find(k);
+ return (i != mData.end()) ? i->second : LLSD();
+ }
- LLSD ImplMap::getKeys() const
- {
+ LLSD ImplMap::getKeys() const
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- LLSD keys = LLSD::emptyArray();
- DataMap::const_iterator iter = mData.begin();
- while (iter != mData.end())
- {
- keys.append((*iter).first);
- iter++;
- }
- return keys;
- }
-
- void ImplMap::insert(const LLSD::String& k, const LLSD& v)
- {
+ LLSD keys = LLSD::emptyArray();
+ DataMap::const_iterator iter = mData.begin();
+ while (iter != mData.end())
+ {
+ keys.append((*iter).first);
+ iter++;
+ }
+ return keys;
+ }
+
+ void ImplMap::insert(const LLSD::String& k, const LLSD& v)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- mData.insert(DataMap::value_type(k, v));
- }
-
- void ImplMap::erase(const LLSD::String& k)
- {
+ mData.insert(DataMap::value_type(k, v));
+ }
+
+ void ImplMap::erase(const LLSD::String& k)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- mData.erase(k);
- }
-
- LLSD& ImplMap::ref(const LLSD::String& k)
- {
- return mData[k];
- }
-
- const LLSD& ImplMap::ref(const LLSD::String& k) const
- {
- DataMap::const_iterator i = mData.lower_bound(k);
- if (i == mData.end() || mData.key_comp()(k, i->first))
- {
- return undef();
- }
-
- return i->second;
- }
-
- void ImplMap::dumpStats() const
- {
- std::cout << "Map size: " << mData.size() << std::endl;
-
- std::cout << "LLSD Net Objects: " << llsd::sLLSDNetObjects << std::endl;
- std::cout << "LLSD allocations: " << llsd::sLLSDAllocationCount << std::endl;
-
- std::cout << "LLSD::Impl Net Objects: " << sOutstandingCount << std::endl;
- std::cout << "LLSD::Impl allocations: " << sAllocationCount << std::endl;
-
- Impl::dumpStats();
- }
-
- void ImplMap::calcStats(S32 type_counts[], S32 share_counts[]) const
- {
- LLSD::map_const_iterator iter = beginMap();
- while (iter != endMap())
- {
- //std::cout << " " << (*iter).first << ": " << (*iter).second << std::endl;
- Impl::calcStats((*iter).second, type_counts, share_counts);
- iter++;
- }
-
- // Add in the values for this map
- Impl::calcStats(type_counts, share_counts);
- }
-
-
- class ImplArray : public LLSD::Impl
- {
- private:
- typedef std::vector<LLSD> DataVector;
-
- DataVector mData;
-
- protected:
- ImplArray(const DataVector& data) : mData(data) { }
-
- public:
- ImplArray() { }
-
- virtual ImplArray& makeArray(Impl*&);
-
- virtual LLSD::Type type() const { return LLSD::TypeArray; }
-
- virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
-
- using LLSD::Impl::get; // Unhiding get(LLSD::String)
- using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
- using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
- virtual size_t size() const;
- virtual LLSD get(size_t) const;
- void set(size_t, const LLSD&);
- void insert(size_t, const LLSD&);
- LLSD& append(const LLSD&);
- virtual void erase(size_t);
- LLSD& ref(size_t);
- virtual const LLSD& ref(size_t) const;
-
- LLSD::array_iterator beginArray() { return mData.begin(); }
- LLSD::array_iterator endArray() { return mData.end(); }
- LLSD::reverse_array_iterator rbeginArray() { return mData.rbegin(); }
- LLSD::reverse_array_iterator rendArray() { return mData.rend(); }
- virtual LLSD::array_const_iterator beginArray() const { return mData.begin(); }
- virtual LLSD::array_const_iterator endArray() const { return mData.end(); }
-
- virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
- };
-
- ImplArray& ImplArray::makeArray(Impl*& var)
- {
- if (shared())
- {
- ImplArray* i = new ImplArray(mData);
- Impl::assign(var, i);
- return *i;
- }
- else
- {
- return *this;
- }
- }
-
- size_t ImplArray::size() const { return mData.size(); }
-
- LLSD ImplArray::get(size_t i) const
- {
- NEGATIVE_RETURN(i, LLSD());
- DataVector::size_type index = i;
-
- return (index < mData.size()) ? mData[index] : LLSD();
- }
-
- void ImplArray::set(size_t i, const LLSD& v)
- {
- NEGATIVE_EXIT(i);
- DataVector::size_type index = i;
-
- if (index >= mData.size())
- {
- mData.resize(index + 1);
- }
-
- mData[index] = v;
- }
-
- void ImplArray::insert(size_t i, const LLSD& v)
- {
- NEGATIVE_EXIT(i);
- DataVector::size_type index = i;
-
- if (index >= mData.size()) // tbd - sanity check limit for index ?
- {
- mData.resize(index + 1);
- }
-
- mData.insert(mData.begin() + index, v);
- }
-
- LLSD& ImplArray::append(const LLSD& v)
- {
- mData.push_back(v);
- return mData.back();
- }
-
- void ImplArray::erase(size_t i)
- {
- NEGATIVE_EXIT(i);
- DataVector::size_type index = i;
-
- if (index < mData.size())
- {
- mData.erase(mData.begin() + index);
- }
- }
-
- LLSD& ImplArray::ref(size_t i)
- {
- DataVector::size_type index = was_negative(i)? 0 : i;
-
- if (index >= mData.size())
- {
- mData.resize(index + 1);
- }
-
- return mData[index];
- }
-
- const LLSD& ImplArray::ref(size_t i) const
- {
- NEGATIVE_RETURN(i, undef());
- DataVector::size_type index = i;
-
- if (index >= mData.size())
- {
- return undef();
- }
-
- return mData[index];
- }
-
- void ImplArray::calcStats(S32 type_counts[], S32 share_counts[]) const
- {
- LLSD::array_const_iterator iter = beginArray();
- while (iter != endArray())
- { // Add values for all items held in the array
- Impl::calcStats((*iter), type_counts, share_counts);
- iter++;
- }
-
- // Add in the values for this array
- Impl::calcStats(type_counts, share_counts);
- }
+ mData.erase(k);
+ }
+
+ LLSD& ImplMap::ref(const LLSD::String& k)
+ {
+ return mData[k];
+ }
+
+ const LLSD& ImplMap::ref(const LLSD::String& k) const
+ {
+ DataMap::const_iterator i = mData.lower_bound(k);
+ if (i == mData.end() || mData.key_comp()(k, i->first))
+ {
+ return undef();
+ }
+
+ return i->second;
+ }
+
+ void ImplMap::dumpStats() const
+ {
+ std::cout << "Map size: " << mData.size() << std::endl;
+
+ std::cout << "LLSD Net Objects: " << llsd::sLLSDNetObjects << std::endl;
+ std::cout << "LLSD allocations: " << llsd::sLLSDAllocationCount << std::endl;
+
+ std::cout << "LLSD::Impl Net Objects: " << sOutstandingCount << std::endl;
+ std::cout << "LLSD::Impl allocations: " << sAllocationCount << std::endl;
+
+ Impl::dumpStats();
+ }
+
+ void ImplMap::calcStats(S32 type_counts[], S32 share_counts[]) const
+ {
+ LLSD::map_const_iterator iter = beginMap();
+ while (iter != endMap())
+ {
+ //std::cout << " " << (*iter).first << ": " << (*iter).second << std::endl;
+ Impl::calcStats((*iter).second, type_counts, share_counts);
+ iter++;
+ }
+
+ // Add in the values for this map
+ Impl::calcStats(type_counts, share_counts);
+ }
+
+
+ class ImplArray : public LLSD::Impl
+ {
+ private:
+ typedef std::vector<LLSD> DataVector;
+
+ DataVector mData;
+
+ protected:
+ ImplArray(const DataVector& data) : mData(data) { }
+
+ public:
+ ImplArray() { }
+
+ virtual ImplArray& makeArray(Impl*&);
+
+ virtual LLSD::Type type() const { return LLSD::TypeArray; }
+
+ virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+
+ using LLSD::Impl::get; // Unhiding get(LLSD::String)
+ using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
+ using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
+ virtual size_t size() const;
+ virtual LLSD get(size_t) const;
+ void set(size_t, const LLSD&);
+ void insert(size_t, const LLSD&);
+ LLSD& append(const LLSD&);
+ virtual void erase(size_t);
+ LLSD& ref(size_t);
+ virtual const LLSD& ref(size_t) const;
+
+ LLSD::array_iterator beginArray() { return mData.begin(); }
+ LLSD::array_iterator endArray() { return mData.end(); }
+ LLSD::reverse_array_iterator rbeginArray() { return mData.rbegin(); }
+ LLSD::reverse_array_iterator rendArray() { return mData.rend(); }
+ virtual LLSD::array_const_iterator beginArray() const { return mData.begin(); }
+ virtual LLSD::array_const_iterator endArray() const { return mData.end(); }
+
+ virtual void calcStats(S32 type_counts[], S32 share_counts[]) const;
+ };
+
+ ImplArray& ImplArray::makeArray(Impl*& var)
+ {
+ if (shared())
+ {
+ ImplArray* i = new ImplArray(mData);
+ Impl::assign(var, i);
+ return *i;
+ }
+ else
+ {
+ return *this;
+ }
+ }
+
+ size_t ImplArray::size() const { return mData.size(); }
+
+ LLSD ImplArray::get(size_t i) const
+ {
+ NEGATIVE_RETURN(i, LLSD());
+ DataVector::size_type index = i;
+
+ return (index < mData.size()) ? mData[index] : LLSD();
+ }
+
+ void ImplArray::set(size_t i, const LLSD& v)
+ {
+ NEGATIVE_EXIT(i);
+ DataVector::size_type index = i;
+
+ if (index >= mData.size())
+ {
+ mData.resize(index + 1);
+ }
+
+ mData[index] = v;
+ }
+
+ void ImplArray::insert(size_t i, const LLSD& v)
+ {
+ NEGATIVE_EXIT(i);
+ DataVector::size_type index = i;
+
+ if (index >= mData.size()) // tbd - sanity check limit for index ?
+ {
+ mData.resize(index + 1);
+ }
+
+ mData.insert(mData.begin() + index, v);
+ }
+
+ LLSD& ImplArray::append(const LLSD& v)
+ {
+ mData.push_back(v);
+ return mData.back();
+ }
+
+ void ImplArray::erase(size_t i)
+ {
+ NEGATIVE_EXIT(i);
+ DataVector::size_type index = i;
+
+ if (index < mData.size())
+ {
+ mData.erase(mData.begin() + index);
+ }
+ }
+
+ LLSD& ImplArray::ref(size_t i)
+ {
+ DataVector::size_type index = was_negative(i)? 0 : i;
+
+ if (index >= mData.size())
+ {
+ mData.resize(index + 1);
+ }
+
+ return mData[index];
+ }
+
+ const LLSD& ImplArray::ref(size_t i) const
+ {
+ NEGATIVE_RETURN(i, undef());
+ DataVector::size_type index = i;
+
+ if (index >= mData.size())
+ {
+ return undef();
+ }
+
+ return mData[index];
+ }
+
+ void ImplArray::calcStats(S32 type_counts[], S32 share_counts[]) const
+ {
+ LLSD::array_const_iterator iter = beginArray();
+ while (iter != endArray())
+ { // Add values for all items held in the array
+ Impl::calcStats((*iter), type_counts, share_counts);
+ iter++;
+ }
+
+ // Add in the values for this array
+ Impl::calcStats(type_counts, share_counts);
+ }
}
LLSD::Impl::Impl()
- : mUseCount(0)
+ : mUseCount(0)
{
- ++sAllocationCount;
- ++sOutstandingCount;
+ ++sAllocationCount;
+ ++sOutstandingCount;
}
LLSD::Impl::Impl(StaticAllocationMarker)
- : mUseCount(0)
+ : mUseCount(0)
{
}
LLSD::Impl::~Impl()
{
- --sOutstandingCount;
+ --sOutstandingCount;
}
void LLSD::Impl::reset(Impl*& var, Impl* impl)
{
- if (impl && impl->mUseCount != STATIC_USAGE_COUNT)
- {
- ++impl->mUseCount;
- }
- if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0)
- {
- delete var;
- }
- var = impl;
+ if (impl && impl->mUseCount != STATIC_USAGE_COUNT)
+ {
+ ++impl->mUseCount;
+ }
+ if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0)
+ {
+ delete var;
+ }
+ var = impl;
}
LLSD::Impl& LLSD::Impl::safe(Impl* impl)
{
- static Impl theUndefined(STATIC_USAGE_COUNT);
- return impl ? *impl : theUndefined;
+ static Impl theUndefined(STATIC_USAGE_COUNT);
+ return impl ? *impl : theUndefined;
}
const LLSD::Impl& LLSD::Impl::safe(const Impl* impl)
{
- static Impl theUndefined(STATIC_USAGE_COUNT);
- return impl ? *impl : theUndefined;
+ static Impl theUndefined(STATIC_USAGE_COUNT);
+ return impl ? *impl : theUndefined;
}
ImplMap& LLSD::Impl::makeMap(Impl*& var)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- ImplMap* im = new ImplMap;
- reset(var, im);
- return *im;
+ ImplMap* im = new ImplMap;
+ reset(var, im);
+ return *im;
}
ImplArray& LLSD::Impl::makeArray(Impl*& var)
{
- ImplArray* ia = new ImplArray;
- reset(var, ia);
- return *ia;
+ ImplArray* ia = new ImplArray;
+ reset(var, ia);
+ return *ia;
}
void LLSD::Impl::assign(Impl*& var, const Impl* other)
{
- reset(var, const_cast<Impl*>(other));
+ reset(var, const_cast<Impl*>(other));
}
void LLSD::Impl::assignUndefined(Impl*& var)
{
- reset(var, 0);
+ reset(var, 0);
}
void LLSD::Impl::assign(Impl*& var, LLSD::Boolean v)
{
- reset(var, new ImplBoolean(v));
+ reset(var, new ImplBoolean(v));
}
void LLSD::Impl::assign(Impl*& var, LLSD::Integer v)
{
- reset(var, new ImplInteger(v));
+ reset(var, new ImplInteger(v));
}
void LLSD::Impl::assign(Impl*& var, LLSD::Real v)
{
- reset(var, new ImplReal(v));
+ reset(var, new ImplReal(v));
}
void LLSD::Impl::assign(Impl*& var, const LLSD::String& v)
{
- reset(var, new ImplString(v));
+ reset(var, new ImplString(v));
}
void LLSD::Impl::assign(Impl*& var, const LLSD::UUID& v)
{
- reset(var, new ImplUUID(v));
+ reset(var, new ImplUUID(v));
}
void LLSD::Impl::assign(Impl*& var, const LLSD::Date& v)
{
- reset(var, new ImplDate(v));
+ reset(var, new ImplDate(v));
}
void LLSD::Impl::assign(Impl*& var, const LLSD::URI& v)
{
- reset(var, new ImplURI(v));
+ reset(var, new ImplURI(v));
}
void LLSD::Impl::assign(Impl*& var, const LLSD::Binary& v)
{
- reset(var, new ImplBinary(v));
+ reset(var, new ImplBinary(v));
}
const LLSD& LLSD::Impl::undef()
{
- static const LLSD immutableUndefined;
- return immutableUndefined;
+ static const LLSD immutableUndefined;
+ return immutableUndefined;
}
void LLSD::Impl::dumpStats() const
{
- S32 type_counts[LLSD::TypeLLSDNumTypes + 1];
- memset(&type_counts, 0, sizeof(type_counts));
-
- S32 share_counts[LLSD::TypeLLSDNumTypes + 1];
- memset(&share_counts, 0, sizeof(share_counts));
-
- // Add info from all the values this object has
- calcStats(type_counts, share_counts);
-
- S32 type_index = LLSD::TypeLLSDTypeBegin;
- while (type_index != LLSD::TypeLLSDTypeEnd)
- {
- std::cout << LLSD::typeString((LLSD::Type)type_index) << " type "
- << type_counts[type_index] << " objects, "
- << share_counts[type_index] << " shared"
- << std::endl;
- type_index++;
- }
+ S32 type_counts[LLSD::TypeLLSDNumTypes + 1];
+ memset(&type_counts, 0, sizeof(type_counts));
+
+ S32 share_counts[LLSD::TypeLLSDNumTypes + 1];
+ memset(&share_counts, 0, sizeof(share_counts));
+
+ // Add info from all the values this object has
+ calcStats(type_counts, share_counts);
+
+ S32 type_index = LLSD::TypeLLSDTypeBegin;
+ while (type_index != LLSD::TypeLLSDTypeEnd)
+ {
+ std::cout << LLSD::typeString((LLSD::Type)type_index) << " type "
+ << type_counts[type_index] << " objects, "
+ << share_counts[type_index] << " shared"
+ << std::endl;
+ type_index++;
+ }
}
void LLSD::Impl::calcStats(S32 type_counts[], S32 share_counts[]) const
{
- S32 tp = S32(type());
- if (0 <= tp && tp < LLSD::TypeLLSDNumTypes)
- {
- type_counts[tp]++;
- if (shared())
- {
- share_counts[tp]++;
- }
- }
+ S32 tp = S32(type());
+ if (0 <= tp && tp < LLSD::TypeLLSDNumTypes)
+ {
+ type_counts[tp]++;
+ if (shared())
+ {
+ share_counts[tp]++;
+ }
+ }
}
@@ -813,218 +813,218 @@ U32 LLSD::Impl::sOutstandingCount = 0;
#ifdef NAME_UNNAMED_NAMESPACE
-namespace LLSDUnnamedNamespace
+namespace LLSDUnnamedNamespace
#else
-namespace
+namespace
#endif
{
- inline LLSD::Impl& safe(LLSD::Impl* impl)
- { return LLSD::Impl::safe(impl); }
-
- inline ImplMap& makeMap(LLSD::Impl*& var)
- { return safe(var).makeMap(var); }
-
- inline ImplArray& makeArray(LLSD::Impl*& var)
- { return safe(var).makeArray(var); }
+ inline LLSD::Impl& safe(LLSD::Impl* impl)
+ { return LLSD::Impl::safe(impl); }
+
+ inline ImplMap& makeMap(LLSD::Impl*& var)
+ { return safe(var).makeMap(var); }
+
+ inline ImplArray& makeArray(LLSD::Impl*& var)
+ { return safe(var).makeArray(var); }
}
-LLSD::LLSD() : impl(0) { ALLOC_LLSD_OBJECT; }
-LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0); }
+LLSD::LLSD() : impl(0) { ALLOC_LLSD_OBJECT; }
+LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0); }
LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); }
-void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); }
+void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); }
-void LLSD::clear() { Impl::assignUndefined(impl); }
+void LLSD::clear() { Impl::assignUndefined(impl); }
-LLSD::Type LLSD::type() const { return safe(impl).type(); }
+LLSD::Type LLSD::type() const { return safe(impl).type(); }
// Scalar Constructors
-LLSD::LLSD(Boolean v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(Integer v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(Real v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(const UUID& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(const String& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(const Date& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(const URI& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
-LLSD::LLSD(const Binary& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(Boolean v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(Integer v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(Real v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(const UUID& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(const String& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(const Date& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(const URI& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(const Binary& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
// Scalar Assignment
-void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); }
-void LLSD::assign(Integer v) { safe(impl).assign(impl, v); }
-void LLSD::assign(Real v) { safe(impl).assign(impl, v); }
-void LLSD::assign(const String& v) { safe(impl).assign(impl, v); }
-void LLSD::assign(const UUID& v) { safe(impl).assign(impl, v); }
-void LLSD::assign(const Date& v) { safe(impl).assign(impl, v); }
-void LLSD::assign(const URI& v) { safe(impl).assign(impl, v); }
-void LLSD::assign(const Binary& v) { safe(impl).assign(impl, v); }
+void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); }
+void LLSD::assign(Integer v) { safe(impl).assign(impl, v); }
+void LLSD::assign(Real v) { safe(impl).assign(impl, v); }
+void LLSD::assign(const String& v) { safe(impl).assign(impl, v); }
+void LLSD::assign(const UUID& v) { safe(impl).assign(impl, v); }
+void LLSD::assign(const Date& v) { safe(impl).assign(impl, v); }
+void LLSD::assign(const URI& v) { safe(impl).assign(impl, v); }
+void LLSD::assign(const Binary& v) { safe(impl).assign(impl, v); }
// Scalar Accessors
-LLSD::Boolean LLSD::asBoolean() const { return safe(impl).asBoolean(); }
-LLSD::Integer LLSD::asInteger() const { return safe(impl).asInteger(); }
-LLSD::Real LLSD::asReal() const { return safe(impl).asReal(); }
-LLSD::String LLSD::asString() const { return safe(impl).asString(); }
-LLSD::UUID LLSD::asUUID() const { return safe(impl).asUUID(); }
-LLSD::Date LLSD::asDate() const { return safe(impl).asDate(); }
-LLSD::URI LLSD::asURI() const { return safe(impl).asURI(); }
-const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); }
+LLSD::Boolean LLSD::asBoolean() const { return safe(impl).asBoolean(); }
+LLSD::Integer LLSD::asInteger() const { return safe(impl).asInteger(); }
+LLSD::Real LLSD::asReal() const { return safe(impl).asReal(); }
+LLSD::String LLSD::asString() const { return safe(impl).asString(); }
+LLSD::UUID LLSD::asUUID() const { return safe(impl).asUUID(); }
+LLSD::Date LLSD::asDate() const { return safe(impl).asDate(); }
+LLSD::URI LLSD::asURI() const { return safe(impl).asURI(); }
+const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); }
const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
// const char * helpers
-LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
+LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
void LLSD::assign(const char* v)
{
- if(v) assign(std::string(v));
- else assign(std::string());
+ if(v) assign(std::string(v));
+ else assign(std::string());
}
LLSD LLSD::emptyMap()
{
- LLSD v;
- makeMap(v.impl);
- return v;
+ LLSD v;
+ makeMap(v.impl);
+ return v;
}
-bool LLSD::has(const String& k) const { return safe(impl).has(k); }
-LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
-LLSD LLSD::getKeys() const { return safe(impl).getKeys(); }
-void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); }
+bool LLSD::has(const String& k) const { return safe(impl).has(k); }
+LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
+LLSD LLSD::getKeys() const { return safe(impl).getKeys(); }
+void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); }
LLSD& LLSD::with(const String& k, const LLSD& v)
- {
- makeMap(impl).insert(k, v);
- return *this;
- }
-void LLSD::erase(const String& k) { makeMap(impl).erase(k); }
+ {
+ makeMap(impl).insert(k, v);
+ return *this;
+ }
+void LLSD::erase(const String& k) { makeMap(impl).erase(k); }
LLSD& LLSD::operator[](const String& k)
-{
+{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- return makeMap(impl).ref(k);
+ return makeMap(impl).ref(k);
}
const LLSD& LLSD::operator[](const String& k) const
-{
+{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- return safe(impl).ref(k);
+ return safe(impl).ref(k);
}
LLSD LLSD::emptyArray()
{
- LLSD v;
- makeArray(v.impl);
- return v;
+ LLSD v;
+ makeArray(v.impl);
+ return v;
}
-size_t LLSD::size() const { return safe(impl).size(); }
-
-LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
+size_t LLSD::size() const { return safe(impl).size(); }
+
+LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); }
void LLSD::insert(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); }
LLSD& LLSD::with(Integer i, const LLSD& v)
- {
- makeArray(impl).insert(i, v);
- return *this;
- }
-LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); }
-void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
+ {
+ makeArray(impl).insert(i, v);
+ return *this;
+ }
+LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); }
+void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
LLSD& LLSD::operator[](size_t i)
-{
+{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
- return makeArray(impl).ref(i);
+ return makeArray(impl).ref(i);
}
const LLSD& LLSD::operator[](size_t i) const
-{
+{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
return safe(impl).ref(i);
}
static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat)
{
- // sStorage is used to hold the string representation of the llsd last
- // passed into this function. If this function is never called (the
- // normal case when not debugging), nothing is allocated. Otherwise
- // sStorage will point to the result of the last call. This will actually
- // be one leak, but since this is used only when running under the
- // debugger, it should not be an issue.
- static char *sStorage = NULL;
- delete[] sStorage;
- std::string out_string;
- {
- std::ostringstream out;
- if (useXMLFormat)
- out << LLSDXMLStreamer(llsd);
- else
- out << LLSDNotationStreamer(llsd);
- out_string = out.str();
- }
- auto len = out_string.length();
- sStorage = new char[len + 1];
- memcpy(sStorage, out_string.c_str(), len);
- sStorage[len] = '\0';
- return sStorage;
+ // sStorage is used to hold the string representation of the llsd last
+ // passed into this function. If this function is never called (the
+ // normal case when not debugging), nothing is allocated. Otherwise
+ // sStorage will point to the result of the last call. This will actually
+ // be one leak, but since this is used only when running under the
+ // debugger, it should not be an issue.
+ static char *sStorage = NULL;
+ delete[] sStorage;
+ std::string out_string;
+ {
+ std::ostringstream out;
+ if (useXMLFormat)
+ out << LLSDXMLStreamer(llsd);
+ else
+ out << LLSDNotationStreamer(llsd);
+ out_string = out.str();
+ }
+ auto len = out_string.length();
+ sStorage = new char[len + 1];
+ memcpy(sStorage, out_string.c_str(), len);
+ sStorage[len] = '\0';
+ return sStorage;
}
/// Returns XML version of llsd -- only to be called from debugger
const char *LLSD::dumpXML(const LLSD &llsd)
{
- return llsd_dump(llsd, true);
+ return llsd_dump(llsd, true);
}
/// Returns Notation version of llsd -- only to be called from debugger
const char *LLSD::dump(const LLSD &llsd)
{
- return llsd_dump(llsd, false);
+ return llsd_dump(llsd, false);
}
-LLSD::map_iterator LLSD::beginMap() { return makeMap(impl).beginMap(); }
-LLSD::map_iterator LLSD::endMap() { return makeMap(impl).endMap(); }
-LLSD::map_const_iterator LLSD::beginMap() const { return safe(impl).beginMap(); }
-LLSD::map_const_iterator LLSD::endMap() const { return safe(impl).endMap(); }
+LLSD::map_iterator LLSD::beginMap() { return makeMap(impl).beginMap(); }
+LLSD::map_iterator LLSD::endMap() { return makeMap(impl).endMap(); }
+LLSD::map_const_iterator LLSD::beginMap() const { return safe(impl).beginMap(); }
+LLSD::map_const_iterator LLSD::endMap() const { return safe(impl).endMap(); }
-LLSD::array_iterator LLSD::beginArray() { return makeArray(impl).beginArray(); }
-LLSD::array_iterator LLSD::endArray() { return makeArray(impl).endArray(); }
-LLSD::array_const_iterator LLSD::beginArray() const{ return safe(impl).beginArray(); }
-LLSD::array_const_iterator LLSD::endArray() const { return safe(impl).endArray(); }
+LLSD::array_iterator LLSD::beginArray() { return makeArray(impl).beginArray(); }
+LLSD::array_iterator LLSD::endArray() { return makeArray(impl).endArray(); }
+LLSD::array_const_iterator LLSD::beginArray() const{ return safe(impl).beginArray(); }
+LLSD::array_const_iterator LLSD::endArray() const { return safe(impl).endArray(); }
-LLSD::reverse_array_iterator LLSD::rbeginArray() { return makeArray(impl).rbeginArray(); }
-LLSD::reverse_array_iterator LLSD::rendArray() { return makeArray(impl).rendArray(); }
+LLSD::reverse_array_iterator LLSD::rbeginArray() { return makeArray(impl).rbeginArray(); }
+LLSD::reverse_array_iterator LLSD::rendArray() { return makeArray(impl).rendArray(); }
namespace llsd
{
-U32 allocationCount() { return LLSD::Impl::sAllocationCount; }
-U32 outstandingCount() { return LLSD::Impl::sOutstandingCount; }
+U32 allocationCount() { return LLSD::Impl::sAllocationCount; }
+U32 outstandingCount() { return LLSD::Impl::sOutstandingCount; }
// Diagnostic dump of contents in an LLSD object
-void dumpStats(const LLSD& llsd) { LLSD::Impl::getImpl(llsd).dumpStats(); }
+void dumpStats(const LLSD& llsd) { LLSD::Impl::getImpl(llsd).dumpStats(); }
} // namespace llsd
// static
-std::string LLSD::typeString(Type type)
+std::string LLSD::typeString(Type type)
{
- static const char * sTypeNameArray[] = {
- "Undefined",
- "Boolean",
- "Integer",
- "Real",
- "String",
- "UUID",
- "Date",
- "URI",
- "Binary",
- "Map",
- "Array"
- };
-
- if (0 <= type && type < LL_ARRAY_SIZE(sTypeNameArray))
- {
- return sTypeNameArray[type];
- }
- return STRINGIZE("** invalid type value " << type);
+ static const char * sTypeNameArray[] = {
+ "Undefined",
+ "Boolean",
+ "Integer",
+ "Real",
+ "String",
+ "UUID",
+ "Date",
+ "URI",
+ "Binary",
+ "Map",
+ "Array"
+ };
+
+ if (0 <= type && type < LL_ARRAY_SIZE(sTypeNameArray))
+ {
+ return sTypeNameArray[type];
+ }
+ return STRINGIZE("** invalid type value " << type);
}
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 8ed254919c..a5e735b561 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsd.h
* @brief LLSD flexible data system.
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -38,450 +38,450 @@
#include "lluuid.h"
/**
- LLSD provides a flexible data system similar to the data facilities of
- dynamic languages like Perl and Python. It is created to support exchange
- of structured data between loosely coupled systems. (Here, "loosely coupled"
- means not compiled together into the same module.)
-
- Data in such exchanges must be highly tolerant of changes on either side
- such as:
- - recompilation
- - implementation in a different langauge
- - addition of extra parameters
- - execution of older versions (with fewer parameters)
-
- To this aim, the C++ API of LLSD strives to be very easy to use, and to
- default to "the right thing" wherever possible. It is extremely tolerant
- of errors and unexpected situations.
-
- The fundamental class is LLSD. LLSD is a value holding object. It holds
- one value that is either undefined, one of the scalar types, or a map or an
- array. LLSD objects have value semantics (copying them copies the value,
- though it can be considered efficient, due to sharing), and mutable.
-
- Undefined is the singular value given to LLSD objects that are not
- initialized with any data. It is also used as the return value for
- operations that return an LLSD.
-
- The scalar data types are:
- - Boolean - true or false
- - Integer - a 32 bit signed integer
- - Real - a 64 IEEE 754 floating point value
- - UUID - a 128 unique value
- - String - a sequence of zero or more Unicode chracters
- - Date - an absolute point in time, UTC,
- with resolution to the second
- - URI - a String that is a URI
- - Binary - a sequence of zero or more octets (unsigned bytes)
-
- A map is a dictionary mapping String keys to LLSD values. The keys are
- unique within a map, and have only one value (though that value could be
- an LLSD array).
-
- An array is a sequence of zero or more LLSD values.
-
- Thread Safety
-
- In general, these LLSD classes offer *less* safety than STL container
- classes. Implementations prior to this one were unsafe even when
- completely unrelated LLSD trees were in two threads due to reference
- sharing of special 'undefined' values that participated in the reference
- counting mechanism.
-
- The dereference-before-refcount and aggressive tree sharing also make
- it impractical to share an LLSD across threads. A strategy of passing
- ownership or a copy to another thread is still difficult due to a lack
- of a cloning interface but it can be done with some care.
-
- One way of transferring ownership is as follows:
-
- void method(const LLSD input) {
- ...
- LLSD * xfer_tree = new LLSD();
- {
- // Top-level values
- (* xfer_tree)['label'] = "Some text";
- (* xfer_tree)['mode'] = APP_MODE_CONSTANT;
-
- // There will be a second-level
- LLSD subtree(LLSD::emptyMap());
- (* xfer_tree)['subtree'] = subtree;
-
- // Do *not* copy from LLSD objects via LLSD
- // intermediaries. Only use plain-old-data
- // types as intermediaries to prevent reference
- // sharing.
- subtree['value1'] = input['value1'].asInteger();
- subtree['value2'] = input['value2'].asString();
-
- // Close scope and drop 'subtree's reference.
- // Only xfer_tree has a reference to the second
- // level data.
- }
- ...
- // Transfer the LLSD pointer to another thread. Ownership
- // transfers, this thread no longer has a reference to any
- // part of the xfer_tree and there's nothing to free or
- // release here. Receiving thread does need to delete the
- // pointer when it is done with the LLSD. Transfer
- // mechanism must perform correct data ordering operations
- // as dictated by architecture.
- other_thread.sendMessageAndPointer("Take This", xfer_tree);
- xfer_tree = NULL;
-
-
- Avoid this pattern which provides half of a race condition:
-
- void method(const LLSD input) {
- ...
- LLSD xfer_tree(LLSD::emptyMap());
- xfer_tree['label'] = "Some text";
- xfer_tree['mode'] = APP_MODE_CONSTANT;
- ...
- other_thread.sendMessageAndPointer("Take This", xfer_tree);
-
-
- @nosubgrouping
+ LLSD provides a flexible data system similar to the data facilities of
+ dynamic languages like Perl and Python. It is created to support exchange
+ of structured data between loosely coupled systems. (Here, "loosely coupled"
+ means not compiled together into the same module.)
+
+ Data in such exchanges must be highly tolerant of changes on either side
+ such as:
+ - recompilation
+ - implementation in a different langauge
+ - addition of extra parameters
+ - execution of older versions (with fewer parameters)
+
+ To this aim, the C++ API of LLSD strives to be very easy to use, and to
+ default to "the right thing" wherever possible. It is extremely tolerant
+ of errors and unexpected situations.
+
+ The fundamental class is LLSD. LLSD is a value holding object. It holds
+ one value that is either undefined, one of the scalar types, or a map or an
+ array. LLSD objects have value semantics (copying them copies the value,
+ though it can be considered efficient, due to sharing), and mutable.
+
+ Undefined is the singular value given to LLSD objects that are not
+ initialized with any data. It is also used as the return value for
+ operations that return an LLSD.
+
+ The scalar data types are:
+ - Boolean - true or false
+ - Integer - a 32 bit signed integer
+ - Real - a 64 IEEE 754 floating point value
+ - UUID - a 128 unique value
+ - String - a sequence of zero or more Unicode chracters
+ - Date - an absolute point in time, UTC,
+ with resolution to the second
+ - URI - a String that is a URI
+ - Binary - a sequence of zero or more octets (unsigned bytes)
+
+ A map is a dictionary mapping String keys to LLSD values. The keys are
+ unique within a map, and have only one value (though that value could be
+ an LLSD array).
+
+ An array is a sequence of zero or more LLSD values.
+
+ Thread Safety
+
+ In general, these LLSD classes offer *less* safety than STL container
+ classes. Implementations prior to this one were unsafe even when
+ completely unrelated LLSD trees were in two threads due to reference
+ sharing of special 'undefined' values that participated in the reference
+ counting mechanism.
+
+ The dereference-before-refcount and aggressive tree sharing also make
+ it impractical to share an LLSD across threads. A strategy of passing
+ ownership or a copy to another thread is still difficult due to a lack
+ of a cloning interface but it can be done with some care.
+
+ One way of transferring ownership is as follows:
+
+ void method(const LLSD input) {
+ ...
+ LLSD * xfer_tree = new LLSD();
+ {
+ // Top-level values
+ (* xfer_tree)['label'] = "Some text";
+ (* xfer_tree)['mode'] = APP_MODE_CONSTANT;
+
+ // There will be a second-level
+ LLSD subtree(LLSD::emptyMap());
+ (* xfer_tree)['subtree'] = subtree;
+
+ // Do *not* copy from LLSD objects via LLSD
+ // intermediaries. Only use plain-old-data
+ // types as intermediaries to prevent reference
+ // sharing.
+ subtree['value1'] = input['value1'].asInteger();
+ subtree['value2'] = input['value2'].asString();
+
+ // Close scope and drop 'subtree's reference.
+ // Only xfer_tree has a reference to the second
+ // level data.
+ }
+ ...
+ // Transfer the LLSD pointer to another thread. Ownership
+ // transfers, this thread no longer has a reference to any
+ // part of the xfer_tree and there's nothing to free or
+ // release here. Receiving thread does need to delete the
+ // pointer when it is done with the LLSD. Transfer
+ // mechanism must perform correct data ordering operations
+ // as dictated by architecture.
+ other_thread.sendMessageAndPointer("Take This", xfer_tree);
+ xfer_tree = NULL;
+
+
+ Avoid this pattern which provides half of a race condition:
+
+ void method(const LLSD input) {
+ ...
+ LLSD xfer_tree(LLSD::emptyMap());
+ xfer_tree['label'] = "Some text";
+ xfer_tree['mode'] = APP_MODE_CONSTANT;
+ ...
+ other_thread.sendMessageAndPointer("Take This", xfer_tree);
+
+
+ @nosubgrouping
*/
// Normally undefined, used for diagnostics
-//#define LLSD_DEBUG_INFO 1
+//#define LLSD_DEBUG_INFO 1
class LL_COMMON_API LLSD
{
public:
- LLSD(); ///< initially Undefined
- ~LLSD(); ///< this class may NOT be subclassed
-
- /** @name Copyable and Assignable */
- //@{
- LLSD(const LLSD&);
- void assign(const LLSD& other);
- LLSD& operator=(const LLSD& other) { assign(other); return *this; }
-
- //@}
-
- void clear(); ///< resets to Undefined
-
-
- /** @name Scalar Types
- The scalar types, and how they map onto C++
- */
- //@{
- typedef bool Boolean;
- typedef S32 Integer;
- typedef F64 Real;
- typedef std::string String;
- typedef LLUUID UUID;
- typedef LLDate Date;
- typedef LLURI URI;
- typedef std::vector<U8> Binary;
- //@}
-
- /** @name Scalar Constructors */
- //@{
- LLSD(Boolean);
- LLSD(Integer);
- LLSD(Real);
- LLSD(const String&);
- LLSD(const UUID&);
- LLSD(const Date&);
- LLSD(const URI&);
- LLSD(const Binary&);
- //@}
-
- /** @name Convenience Constructors */
- //@{
- // support construction from size_t et al.
- template <typename VALUE,
- typename std::enable_if<std::is_integral<VALUE>::value &&
- ! std::is_same<VALUE, Boolean>::value,
- bool>::type = true>
- LLSD(VALUE v): LLSD(Integer(narrow<VALUE>(v))) {}
- // support construction from F32 et al.
- template <typename VALUE,
- typename std::enable_if<std::is_floating_point<VALUE>::value,
- bool>::type = true>
- LLSD(VALUE v): LLSD(Real(narrow<VALUE>(v))) {}
- //@}
-
- /** @name Scalar Assignment */
- //@{
- void assign(Boolean);
- void assign(Integer);
- void assign(Real);
- void assign(const String&);
- void assign(const UUID&);
- void assign(const Date&);
- void assign(const URI&);
- void assign(const Binary&);
-
- LLSD& operator=(Boolean v) { assign(v); return *this; }
- LLSD& operator=(Integer v) { assign(v); return *this; }
- LLSD& operator=(Real v) { assign(v); return *this; }
- LLSD& operator=(const String& v) { assign(v); return *this; }
- LLSD& operator=(const UUID& v) { assign(v); return *this; }
- LLSD& operator=(const Date& v) { assign(v); return *this; }
- LLSD& operator=(const URI& v) { assign(v); return *this; }
- LLSD& operator=(const Binary& v) { assign(v); return *this; }
- //@}
-
- /**
- @name Scalar Accessors
- @brief Fetch a scalar value, converting if needed and possible
-
- Conversion among the basic types, Boolean, Integer, Real and String, is
- fully defined. Each type can be converted to another with a reasonable
- interpretation. These conversions can be used as a convenience even
- when you know the data is in one format, but you want it in another. Of
- course, many of these conversions lose information.
-
- Note: These conversions are not the same as Perl's. In particular, when
- converting a String to a Boolean, only the empty string converts to
- false. Converting the String "0" to Boolean results in true.
-
- Conversion to and from UUID, Date, and URI is only defined to and from
- String. Conversion is defined to be information preserving for valid
- values of those types. These conversions can be used when one needs to
- convert data to or from another system that cannot handle these types
- natively, but can handle strings.
-
- Conversion to and from Binary isn't defined.
-
- Conversion of the Undefined value to any scalar type results in a
- reasonable null or zero value for the type.
- */
- //@{
- Boolean asBoolean() const;
- Integer asInteger() const;
- Real asReal() const;
- String asString() const;
- UUID asUUID() const;
- Date asDate() const;
- URI asURI() const;
- const Binary& asBinary() const;
-
- // asStringRef on any non-string type will return a ref to an empty string.
- const String& asStringRef() const;
-
- operator Boolean() const { return asBoolean(); }
- operator Integer() const { return asInteger(); }
- operator Real() const { return asReal(); }
- operator String() const { return asString(); }
- operator UUID() const { return asUUID(); }
- operator Date() const { return asDate(); }
- operator URI() const { return asURI(); }
- operator Binary() const { return asBinary(); }
-
- // This is needed because most platforms do not automatically
- // convert the boolean negation as a bool in an if statement.
- bool operator!() const {return !asBoolean();}
- //@}
-
- /** @name Character Pointer Helpers
- These are helper routines to make working with char* as easy as
- working with strings.
- */
- //@{
- LLSD(const char*);
- void assign(const char*);
- LLSD& operator=(const char* v) { assign(v); return *this; }
- //@}
-
- /** @name Map Values */
- //@{
- static LLSD emptyMap();
-
- bool has(const String&) const;
- LLSD get(const String&) const;
- LLSD getKeys() const; // Return an LLSD array with keys as strings
- void insert(const String&, const LLSD&);
- void erase(const String&);
- LLSD& with(const String&, const LLSD&);
-
- LLSD& operator[](const String&);
- LLSD& operator[](const char* c)
+ LLSD(); ///< initially Undefined
+ ~LLSD(); ///< this class may NOT be subclassed
+
+ /** @name Copyable and Assignable */
+ //@{
+ LLSD(const LLSD&);
+ void assign(const LLSD& other);
+ LLSD& operator=(const LLSD& other) { assign(other); return *this; }
+
+ //@}
+
+ void clear(); ///< resets to Undefined
+
+
+ /** @name Scalar Types
+ The scalar types, and how they map onto C++
+ */
+ //@{
+ typedef bool Boolean;
+ typedef S32 Integer;
+ typedef F64 Real;
+ typedef std::string String;
+ typedef LLUUID UUID;
+ typedef LLDate Date;
+ typedef LLURI URI;
+ typedef std::vector<U8> Binary;
+ //@}
+
+ /** @name Scalar Constructors */
+ //@{
+ LLSD(Boolean);
+ LLSD(Integer);
+ LLSD(Real);
+ LLSD(const String&);
+ LLSD(const UUID&);
+ LLSD(const Date&);
+ LLSD(const URI&);
+ LLSD(const Binary&);
+ //@}
+
+ /** @name Convenience Constructors */
+ //@{
+ // support construction from size_t et al.
+ template <typename VALUE,
+ typename std::enable_if<std::is_integral<VALUE>::value &&
+ ! std::is_same<VALUE, Boolean>::value,
+ bool>::type = true>
+ LLSD(VALUE v): LLSD(Integer(narrow<VALUE>(v))) {}
+ // support construction from F32 et al.
+ template <typename VALUE,
+ typename std::enable_if<std::is_floating_point<VALUE>::value,
+ bool>::type = true>
+ LLSD(VALUE v): LLSD(Real(narrow<VALUE>(v))) {}
+ //@}
+
+ /** @name Scalar Assignment */
+ //@{
+ void assign(Boolean);
+ void assign(Integer);
+ void assign(Real);
+ void assign(const String&);
+ void assign(const UUID&);
+ void assign(const Date&);
+ void assign(const URI&);
+ void assign(const Binary&);
+
+ LLSD& operator=(Boolean v) { assign(v); return *this; }
+ LLSD& operator=(Integer v) { assign(v); return *this; }
+ LLSD& operator=(Real v) { assign(v); return *this; }
+ LLSD& operator=(const String& v) { assign(v); return *this; }
+ LLSD& operator=(const UUID& v) { assign(v); return *this; }
+ LLSD& operator=(const Date& v) { assign(v); return *this; }
+ LLSD& operator=(const URI& v) { assign(v); return *this; }
+ LLSD& operator=(const Binary& v) { assign(v); return *this; }
+ //@}
+
+ /**
+ @name Scalar Accessors
+ @brief Fetch a scalar value, converting if needed and possible
+
+ Conversion among the basic types, Boolean, Integer, Real and String, is
+ fully defined. Each type can be converted to another with a reasonable
+ interpretation. These conversions can be used as a convenience even
+ when you know the data is in one format, but you want it in another. Of
+ course, many of these conversions lose information.
+
+ Note: These conversions are not the same as Perl's. In particular, when
+ converting a String to a Boolean, only the empty string converts to
+ false. Converting the String "0" to Boolean results in true.
+
+ Conversion to and from UUID, Date, and URI is only defined to and from
+ String. Conversion is defined to be information preserving for valid
+ values of those types. These conversions can be used when one needs to
+ convert data to or from another system that cannot handle these types
+ natively, but can handle strings.
+
+ Conversion to and from Binary isn't defined.
+
+ Conversion of the Undefined value to any scalar type results in a
+ reasonable null or zero value for the type.
+ */
+ //@{
+ Boolean asBoolean() const;
+ Integer asInteger() const;
+ Real asReal() const;
+ String asString() const;
+ UUID asUUID() const;
+ Date asDate() const;
+ URI asURI() const;
+ const Binary& asBinary() const;
+
+ // asStringRef on any non-string type will return a ref to an empty string.
+ const String& asStringRef() const;
+
+ operator Boolean() const { return asBoolean(); }
+ operator Integer() const { return asInteger(); }
+ operator Real() const { return asReal(); }
+ operator String() const { return asString(); }
+ operator UUID() const { return asUUID(); }
+ operator Date() const { return asDate(); }
+ operator URI() const { return asURI(); }
+ operator Binary() const { return asBinary(); }
+
+ // This is needed because most platforms do not automatically
+ // convert the boolean negation as a bool in an if statement.
+ bool operator!() const {return !asBoolean();}
+ //@}
+
+ /** @name Character Pointer Helpers
+ These are helper routines to make working with char* as easy as
+ working with strings.
+ */
+ //@{
+ LLSD(const char*);
+ void assign(const char*);
+ LLSD& operator=(const char* v) { assign(v); return *this; }
+ //@}
+
+ /** @name Map Values */
+ //@{
+ static LLSD emptyMap();
+
+ bool has(const String&) const;
+ LLSD get(const String&) const;
+ LLSD getKeys() const; // Return an LLSD array with keys as strings
+ void insert(const String&, const LLSD&);
+ void erase(const String&);
+ LLSD& with(const String&, const LLSD&);
+
+ LLSD& operator[](const String&);
+ LLSD& operator[](const char* c)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
return (*this)[String(c)];
}
- const LLSD& operator[](const String&) const;
- const LLSD& operator[](const char* c) const
+ const LLSD& operator[](const String&) const;
+ const LLSD& operator[](const char* c) const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
return (*this)[String(c)];
}
- //@}
-
- /** @name Array Values */
- //@{
- static LLSD emptyArray();
-
- LLSD get(Integer) const;
- void set(Integer, const LLSD&);
- void insert(Integer, const LLSD&);
- LLSD& append(const LLSD&);
- void erase(Integer);
- LLSD& with(Integer, const LLSD&);
-
- // accept size_t so we can index relative to size()
- const LLSD& operator[](size_t) const;
- LLSD& operator[](size_t);
- // template overloads to support int literals, U32 et al.
- template <typename IDX,
- typename std::enable_if<std::is_convertible<IDX, size_t>::value,
- bool>::type = true>
- const LLSD& operator[](IDX i) const { return (*this)[size_t(i)]; }
- template <typename IDX,
- typename std::enable_if<std::is_convertible<IDX, size_t>::value,
- bool>::type = true>
- LLSD& operator[](IDX i) { return (*this)[size_t(i)]; }
- //@}
-
- /** @name Iterators */
- //@{
- size_t size() const;
-
- typedef std::map<String, LLSD>::iterator map_iterator;
- typedef std::map<String, LLSD>::const_iterator map_const_iterator;
-
- map_iterator beginMap();
- map_iterator endMap();
- map_const_iterator beginMap() const;
- map_const_iterator endMap() const;
-
- typedef std::vector<LLSD>::iterator array_iterator;
- typedef std::vector<LLSD>::const_iterator array_const_iterator;
- typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator;
-
- array_iterator beginArray();
- array_iterator endArray();
- array_const_iterator beginArray() const;
- array_const_iterator endArray() const;
-
- reverse_array_iterator rbeginArray();
- reverse_array_iterator rendArray();
- //@}
-
- /** @name Type Testing */
- //@{
- enum Type {
- TypeUndefined = 0,
- TypeBoolean,
- TypeInteger,
- TypeReal,
- TypeString,
- TypeUUID,
- TypeDate,
- TypeURI,
- TypeBinary,
- TypeMap,
- TypeArray,
- TypeLLSDTypeEnd,
- TypeLLSDTypeBegin = TypeUndefined,
- TypeLLSDNumTypes = (TypeLLSDTypeEnd - TypeLLSDTypeBegin)
- };
-
- Type type() const;
-
- bool isUndefined() const { return type() == TypeUndefined; }
- bool isDefined() const { return type() != TypeUndefined; }
- bool isBoolean() const { return type() == TypeBoolean; }
- bool isInteger() const { return type() == TypeInteger; }
- bool isReal() const { return type() == TypeReal; }
- bool isString() const { return type() == TypeString; }
- bool isUUID() const { return type() == TypeUUID; }
- bool isDate() const { return type() == TypeDate; }
- bool isURI() const { return type() == TypeURI; }
- bool isBinary() const { return type() == TypeBinary; }
- bool isMap() const { return type() == TypeMap; }
- bool isArray() const { return type() == TypeArray; }
- //@}
-
- /** @name Automatic Cast Protection
- These are not implemented on purpose. Without them, C++ can perform
- some conversions that are clearly not what the programmer intended.
-
- If you get a linker error about these being missing, you have made
- mistake in your code. DO NOT IMPLEMENT THESE FUNCTIONS as a fix.
-
- All of these problems stem from trying to support char* in LLSD or in
- std::string. There are too many automatic casts that will lead to
- using an arbitrary pointer or scalar type to std::string.
- */
- //@{
- LLSD(const void*); ///< construct from aribrary pointers
- void assign(const void*); ///< assign from arbitrary pointers
- LLSD& operator=(const void*); ///< assign from arbitrary pointers
-
- bool has(Integer) const; ///< has() only works for Maps
- //@}
-
- /** @name Implementation */
- //@{
+ //@}
+
+ /** @name Array Values */
+ //@{
+ static LLSD emptyArray();
+
+ LLSD get(Integer) const;
+ void set(Integer, const LLSD&);
+ void insert(Integer, const LLSD&);
+ LLSD& append(const LLSD&);
+ void erase(Integer);
+ LLSD& with(Integer, const LLSD&);
+
+ // accept size_t so we can index relative to size()
+ const LLSD& operator[](size_t) const;
+ LLSD& operator[](size_t);
+ // template overloads to support int literals, U32 et al.
+ template <typename IDX,
+ typename std::enable_if<std::is_convertible<IDX, size_t>::value,
+ bool>::type = true>
+ const LLSD& operator[](IDX i) const { return (*this)[size_t(i)]; }
+ template <typename IDX,
+ typename std::enable_if<std::is_convertible<IDX, size_t>::value,
+ bool>::type = true>
+ LLSD& operator[](IDX i) { return (*this)[size_t(i)]; }
+ //@}
+
+ /** @name Iterators */
+ //@{
+ size_t size() const;
+
+ typedef std::map<String, LLSD>::iterator map_iterator;
+ typedef std::map<String, LLSD>::const_iterator map_const_iterator;
+
+ map_iterator beginMap();
+ map_iterator endMap();
+ map_const_iterator beginMap() const;
+ map_const_iterator endMap() const;
+
+ typedef std::vector<LLSD>::iterator array_iterator;
+ typedef std::vector<LLSD>::const_iterator array_const_iterator;
+ typedef std::vector<LLSD>::reverse_iterator reverse_array_iterator;
+
+ array_iterator beginArray();
+ array_iterator endArray();
+ array_const_iterator beginArray() const;
+ array_const_iterator endArray() const;
+
+ reverse_array_iterator rbeginArray();
+ reverse_array_iterator rendArray();
+ //@}
+
+ /** @name Type Testing */
+ //@{
+ enum Type {
+ TypeUndefined = 0,
+ TypeBoolean,
+ TypeInteger,
+ TypeReal,
+ TypeString,
+ TypeUUID,
+ TypeDate,
+ TypeURI,
+ TypeBinary,
+ TypeMap,
+ TypeArray,
+ TypeLLSDTypeEnd,
+ TypeLLSDTypeBegin = TypeUndefined,
+ TypeLLSDNumTypes = (TypeLLSDTypeEnd - TypeLLSDTypeBegin)
+ };
+
+ Type type() const;
+
+ bool isUndefined() const { return type() == TypeUndefined; }
+ bool isDefined() const { return type() != TypeUndefined; }
+ bool isBoolean() const { return type() == TypeBoolean; }
+ bool isInteger() const { return type() == TypeInteger; }
+ bool isReal() const { return type() == TypeReal; }
+ bool isString() const { return type() == TypeString; }
+ bool isUUID() const { return type() == TypeUUID; }
+ bool isDate() const { return type() == TypeDate; }
+ bool isURI() const { return type() == TypeURI; }
+ bool isBinary() const { return type() == TypeBinary; }
+ bool isMap() const { return type() == TypeMap; }
+ bool isArray() const { return type() == TypeArray; }
+ //@}
+
+ /** @name Automatic Cast Protection
+ These are not implemented on purpose. Without them, C++ can perform
+ some conversions that are clearly not what the programmer intended.
+
+ If you get a linker error about these being missing, you have made
+ mistake in your code. DO NOT IMPLEMENT THESE FUNCTIONS as a fix.
+
+ All of these problems stem from trying to support char* in LLSD or in
+ std::string. There are too many automatic casts that will lead to
+ using an arbitrary pointer or scalar type to std::string.
+ */
+ //@{
+ LLSD(const void*); ///< construct from aribrary pointers
+ void assign(const void*); ///< assign from arbitrary pointers
+ LLSD& operator=(const void*); ///< assign from arbitrary pointers
+
+ bool has(Integer) const; ///< has() only works for Maps
+ //@}
+
+ /** @name Implementation */
+ //@{
public:
- class Impl;
+ class Impl;
private:
- Impl* impl;
- friend class LLSD::Impl;
- //@}
+ Impl* impl;
+ friend class LLSD::Impl;
+ //@}
private:
- /** @name Debugging Interface */
- //@{
- /// Returns XML version of llsd -- only to be called from debugger
- static const char *dumpXML(const LLSD &llsd);
+ /** @name Debugging Interface */
+ //@{
+ /// Returns XML version of llsd -- only to be called from debugger
+ static const char *dumpXML(const LLSD &llsd);
- /// Returns Notation version of llsd -- only to be called from debugger
- static const char *dump(const LLSD &llsd);
- //@}
+ /// Returns Notation version of llsd -- only to be called from debugger
+ static const char *dump(const LLSD &llsd);
+ //@}
public:
- static std::string typeString(Type type); // Return human-readable type as a string
+ static std::string typeString(Type type); // Return human-readable type as a string
};
struct llsd_select_bool
{
- LLSD::Boolean operator()(const LLSD& sd) const
- {
- return sd.asBoolean();
- }
+ LLSD::Boolean operator()(const LLSD& sd) const
+ {
+ return sd.asBoolean();
+ }
};
struct llsd_select_integer
{
- LLSD::Integer operator()(const LLSD& sd) const
- {
- return sd.asInteger();
- }
+ LLSD::Integer operator()(const LLSD& sd) const
+ {
+ return sd.asInteger();
+ }
};
struct llsd_select_real
{
- LLSD::Real operator()(const LLSD& sd) const
- {
- return sd.asReal();
- }
+ LLSD::Real operator()(const LLSD& sd) const
+ {
+ return sd.asReal();
+ }
};
struct llsd_select_float
{
- F32 operator()(const LLSD& sd) const
- {
- return (F32)sd.asReal();
- }
+ F32 operator()(const LLSD& sd) const
+ {
+ return (F32)sd.asReal();
+ }
};
struct llsd_select_uuid
{
- LLSD::UUID operator()(const LLSD& sd) const
- {
- return sd.asUUID();
- }
+ LLSD::UUID operator()(const LLSD& sd) const
+ {
+ return sd.asUUID();
+ }
};
struct llsd_select_string
{
- LLSD::String operator()(const LLSD& sd) const
- {
- return sd.asString();
- }
+ LLSD::String operator()(const LLSD& sd) const
+ {
+ return sd.asString();
+ }
};
LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
@@ -492,30 +492,30 @@ namespace llsd
#ifdef LLSD_DEBUG_INFO
/** @name Unit Testing Interface */
//@{
- LL_COMMON_API void dumpStats(const LLSD&); ///< Output information on object and usage
-
- /// @warn THE FOLLOWING COUNTS WILL NOT BE ACCURATE IN A MULTI-THREADED
- /// ENVIRONMENT.
- ///
- /// These counts track LLSD::Impl (hidden) objects.
- LL_COMMON_API U32 allocationCount(); ///< how many Impls have been made
- LL_COMMON_API U32 outstandingCount(); ///< how many Impls are still alive
-
- /// These counts track LLSD (public) objects.
- LL_COMMON_API extern S32 sLLSDAllocationCount; ///< Number of LLSD objects ever created
- LL_COMMON_API extern S32 sLLSDNetObjects; ///< Number of LLSD objects that exist
+ LL_COMMON_API void dumpStats(const LLSD&); ///< Output information on object and usage
+
+ /// @warn THE FOLLOWING COUNTS WILL NOT BE ACCURATE IN A MULTI-THREADED
+ /// ENVIRONMENT.
+ ///
+ /// These counts track LLSD::Impl (hidden) objects.
+ LL_COMMON_API U32 allocationCount(); ///< how many Impls have been made
+ LL_COMMON_API U32 outstandingCount(); ///< how many Impls are still alive
+
+ /// These counts track LLSD (public) objects.
+ LL_COMMON_API extern S32 sLLSDAllocationCount; ///< Number of LLSD objects ever created
+ LL_COMMON_API extern S32 sLLSDNetObjects; ///< Number of LLSD objects that exist
#endif
//@}
} // namespace llsd
/** QUESTIONS & TO DOS
- - Would Binary be more convenient as unsigned char* buffer semantics?
- - Should Binary be convertible to/from String, and if so how?
- - as UTF8 encoded strings (making not like UUID<->String)
- - as Base64 or Base96 encoded (making like UUID<->String)
- - Conversions to std::string and LLUUID do not result in easy assignment
- to std::string, std::string or LLUUID due to non-unique conversion paths
+ - Would Binary be more convenient as unsigned char* buffer semantics?
+ - Should Binary be convertible to/from String, and if so how?
+ - as UTF8 encoded strings (making not like UUID<->String)
+ - as Base64 or Base96 encoded (making like UUID<->String)
+ - Conversions to std::string and LLUUID do not result in easy assignment
+ to std::string, std::string or LLUUID due to non-unique conversion paths
*/
#endif // LL_LLSD_NEW_H
diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp
index 8caaaee534..bb2b8681f7 100644
--- a/indra/llcommon/llsdjson.cpp
+++ b/indra/llcommon/llsdjson.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsdjson.cpp
* @brief LLSD flexible data system
*
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2015, 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$
*/
diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h
index e56cf03b45..79bf2c56fa 100644
--- a/indra/llcommon/llsdjson.h
+++ b/indra/llcommon/llsdjson.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsdjson.cpp
* @brief LLSD flexible data system
*
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2015, 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,10 +36,10 @@
#include "llsd.h"
#include "json/value.h"
-/// Convert a parsed JSON structure into LLSD maintaining member names and
+/// Convert a parsed JSON structure into LLSD maintaining member names and
/// array indexes.
/// JSON/JavaScript types are converted as follows:
-///
+///
/// JSON Type | LLSD Type
/// --------------+--------------
/// null | undefined
@@ -50,14 +50,14 @@
/// boolean | LLSD::Boolean
/// array | LLSD::Array
/// object | LLSD::Map
-///
+///
/// For maps and arrays child entries will be converted and added to the structure.
/// Order is preserved for an array but not for objects.
LLSD LlsdFromJson(const Json::Value &val);
-/// Convert an LLSD object into Parsed JSON object maintaining member names and
+/// Convert an LLSD object into Parsed JSON object maintaining member names and
/// array indexs.
-///
+///
/// Types are converted as follows:
/// LLSD Type | JSON Type
/// --------------+----------------
@@ -71,7 +71,7 @@ LLSD LlsdFromJson(const Json::Value &val);
/// TypeUUID | string
/// TypeMap | object
/// TypeArray | array
-/// TypeBinary | unsupported
+/// TypeBinary | unsupported
Json::Value LlsdToJson(const LLSD &val);
#endif // LL_LLSDJSON_H
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 30f49b27ea..b981be4d0a 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -1,26 +1,26 @@
-/**
+/**
* @file llsdparam.cpp
- * @brief parameter block abstraction for creating complex objects and
+ * @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $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$
*/
@@ -32,9 +32,9 @@
#include "llsdutil.h"
#include "boost/bind.hpp"
-static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
-static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
-static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
+static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
+static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
+static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
static const LLSD NO_VALUE_MARKER;
//
@@ -43,95 +43,95 @@ static const LLSD NO_VALUE_MARKER;
LLParamSDParser::LLParamSDParser()
: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
{
- using boost::bind;
-
- if (sReadFuncs.empty())
- {
- registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
- registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
- registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
- registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
- registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
- registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
- registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
- registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
- registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
- registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
- registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
- }
+ using boost::bind;
+
+ if (sReadFuncs.empty())
+ {
+ registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
+ registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
+ registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
+ registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
+ registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
+ registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
+ registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
+ registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
+ registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
+ registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
+ registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
+ }
}
// special case handling of U32 due to ambiguous LLSD::assign overload
bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
- LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
- if (!sdparser.mWriteRootSD) return false;
-
- parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
- LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
- sd_to_write.assign((S32)*((const U32*)val_ptr));
-
- return true;
+ LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+ if (!sdparser.mWriteRootSD) return false;
+
+ parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
+ LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
+ sd_to_write.assign((S32)*((const U32*)val_ptr));
+
+ return true;
}
bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
- LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
- if (!sdparser.mWriteRootSD) return false;
+ LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+ if (!sdparser.mWriteRootSD) return false;
- parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
- LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
+ parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
+ LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
- return true;
+ return true;
}
void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
{
- mCurReadSD = &sd;
- block.submitValue(name_stack, *this);
+ mCurReadSD = &sd;
+ block.submitValue(name_stack, *this);
}
void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
{
- mCurReadSD = NULL;
- mNameStack.clear();
- setParseSilently(silent);
+ mCurReadSD = NULL;
+ mNameStack.clear();
+ setParseSilently(silent);
- LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
- //readSDValues(sd, block);
+ LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
+ //readSDValues(sd, block);
}
void LLParamSDParser::writeSDImpl(LLSD& sd, const LLInitParam::BaseBlock& block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
{
- mNameStack.clear();
- mWriteRootSD = &sd;
+ mNameStack.clear();
+ mWriteRootSD = &sd;
- name_stack_t name_stack;
- block.serializeBlock(*this, name_stack, rules, diff_block);
+ name_stack_t name_stack;
+ block.serializeBlock(*this, name_stack, rules, diff_block);
}
/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
{
- std::string full_name = "sd";
- for (name_stack_t::value_type& stack_pair : mNameStack)
- {
- full_name += llformat("[%s]", stack_pair.first.c_str());
- }
+ std::string full_name = "sd";
+ for (name_stack_t::value_type& stack_pair : mNameStack)
+ {
+ full_name += llformat("[%s]", stack_pair.first.c_str());
+ }
- return full_name;
+ return full_name;
}
bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
- return self.mCurReadSD == &NO_VALUE_MARKER;
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ return self.mCurReadSD == &NO_VALUE_MARKER;
}
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((S32*)val_ptr) = self.mCurReadSD->asInteger();
return true;
@@ -139,7 +139,7 @@ bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((U32*)val_ptr) = self.mCurReadSD->asInteger();
return true;
@@ -147,7 +147,7 @@ bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((F32*)val_ptr) = self.mCurReadSD->asReal();
return true;
@@ -155,7 +155,7 @@ bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((F64*)val_ptr) = self.mCurReadSD->asReal();
return true;
@@ -163,7 +163,7 @@ bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((bool*)val_ptr) = self.mCurReadSD->asBoolean();
return true;
@@ -171,170 +171,170 @@ bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
- *((std::string*)val_ptr) = self.mCurReadSD->asString();
+ *((std::string*)val_ptr) = self.mCurReadSD->asString();
return true;
}
bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
- *((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
+ *((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
return true;
}
bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
- *((LLDate*)val_ptr) = self.mCurReadSD->asDate();
+ *((LLDate*)val_ptr) = self.mCurReadSD->asDate();
return true;
}
bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
- *((LLURI*)val_ptr) = self.mCurReadSD->asURI();
+ *((LLURI*)val_ptr) = self.mCurReadSD->asURI();
return true;
}
bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
{
- LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
- *((LLSD*)val_ptr) = *self.mCurReadSD;
+ *((LLSD*)val_ptr) = *self.mCurReadSD;
return true;
}
// static
LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
{
- LLSD* sd_to_write = &input;
-
- for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
- it != name_stack_range.second;
- ++it)
- {
- bool new_traversal = it->second;
-
- LLSD* child_sd;
- if (it->first.empty())
- {
- child_sd = sd_to_write;
- if (child_sd->isUndefined())
- {
- *child_sd = LLSD::emptyArray();
- }
- if (new_traversal)
- {
- // write to new element at end
- sd_to_write = &(*child_sd)[child_sd->size()];
- }
- else
- {
- // write to last of existing elements, or first element if empty
- sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
- }
- }
- else
- {
- sd_to_write = &(*sd_to_write)[it->first];
- }
- it->second = false;
- }
-
- return *sd_to_write;
+ LLSD* sd_to_write = &input;
+
+ for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
+ it != name_stack_range.second;
+ ++it)
+ {
+ bool new_traversal = it->second;
+
+ LLSD* child_sd;
+ if (it->first.empty())
+ {
+ child_sd = sd_to_write;
+ if (child_sd->isUndefined())
+ {
+ *child_sd = LLSD::emptyArray();
+ }
+ if (new_traversal)
+ {
+ // write to new element at end
+ sd_to_write = &(*child_sd)[child_sd->size()];
+ }
+ else
+ {
+ // write to last of existing elements, or first element if empty
+ sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
+ }
+ }
+ else
+ {
+ sd_to_write = &(*sd_to_write)[it->first];
+ }
+ it->second = false;
+ }
+
+ return *sd_to_write;
}
//static
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
{
- if (sd.isMap())
- {
- for (LLSD::map_const_iterator it = sd.beginMap();
- it != sd.endMap();
- ++it)
- {
- stack.push_back(make_pair(it->first, true));
- readSDValues(cb, it->second, stack);
- stack.pop_back();
- }
- }
- else if (sd.isArray())
- {
- for (LLSD::array_const_iterator it = sd.beginArray();
- it != sd.endArray();
- ++it)
- {
- stack.push_back(make_pair(std::string(), true));
- readSDValues(cb, *it, stack);
- stack.pop_back();
- }
- }
- else if (sd.isUndefined())
- {
- if (!cb.empty())
- {
- cb(NO_VALUE_MARKER, stack);
- }
- }
- else
- {
- if (!cb.empty())
- {
- cb(sd, stack);
- }
- }
+ if (sd.isMap())
+ {
+ for (LLSD::map_const_iterator it = sd.beginMap();
+ it != sd.endMap();
+ ++it)
+ {
+ stack.push_back(make_pair(it->first, true));
+ readSDValues(cb, it->second, stack);
+ stack.pop_back();
+ }
+ }
+ else if (sd.isArray())
+ {
+ for (LLSD::array_const_iterator it = sd.beginArray();
+ it != sd.endArray();
+ ++it)
+ {
+ stack.push_back(make_pair(std::string(), true));
+ readSDValues(cb, *it, stack);
+ stack.pop_back();
+ }
+ }
+ else if (sd.isUndefined())
+ {
+ if (!cb.empty())
+ {
+ cb(NO_VALUE_MARKER, stack);
+ }
+ }
+ else
+ {
+ if (!cb.empty())
+ {
+ cb(sd, stack);
+ }
+ }
}
//static
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
{
- LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
- readSDValues(cb, sd, stack);
+ LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
+ readSDValues(cb, sd, stack);
}
namespace LLInitParam
{
- // LLSD specialization
- // block param interface
- bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name)
- {
- if (name_stack.first == name_stack.second
- && p.readValue<LLSD>(mValue))
- {
- return true;
- }
-
- LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
-
- LLSD::String string;
-
- if (p.readValue<LLSD::String>(string))
- {
- sd = string;
- return true;
- }
- return false;
- }
-
- //static
- void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
- {
- p.writeValue<LLSD::String>(sd.asString(), name_stack);
- }
-
- bool ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack_range, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const
- {
- // attempt to write LLSD out directly
- if (!p.writeValue<LLSD>(mValue, name_stack_range))
- {
- // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
- LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack_range);
- }
- return true;
- }
+ // LLSD specialization
+ // block param interface
+ bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name)
+ {
+ if (name_stack.first == name_stack.second
+ && p.readValue<LLSD>(mValue))
+ {
+ return true;
+ }
+
+ LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
+
+ LLSD::String string;
+
+ if (p.readValue<LLSD::String>(string))
+ {
+ sd = string;
+ return true;
+ }
+ return false;
+ }
+
+ //static
+ void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
+ {
+ p.writeValue<LLSD::String>(sd.asString(), name_stack);
+ }
+
+ bool ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack_range, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const
+ {
+ // attempt to write LLSD out directly
+ if (!p.writeValue<LLSD>(mValue, name_stack_range))
+ {
+ // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
+ LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack_range);
+ }
+ return true;
+ }
}
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 82a623a8a0..21ebb9a258 100644
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -1,26 +1,26 @@
-/**
+/**
* @file llsdparam.h
- * @brief parameter block abstraction for creating complex objects and
+ * @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $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$
*/
@@ -34,79 +34,79 @@
struct LL_COMMON_API LLParamSDParserUtilities
{
- static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
+ static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
- typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
- static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
- static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
+ typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
+ static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
+ static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
};
-class LL_COMMON_API LLParamSDParser
-: public LLInitParam::Parser
+class LL_COMMON_API LLParamSDParser
+: public LLInitParam::Parser
{
LOG_CLASS(LLParamSDParser);
typedef LLInitParam::Parser parser_t;
public:
- LLParamSDParser();
- void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
- template<typename BLOCK>
- void writeSD(LLSD& sd,
- const BLOCK& block,
- const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
- const LLInitParam::BaseBlock* diff_block = NULL)
- {
- if (!diff_block
- && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
- {
- diff_block = &LLInitParam::defaultValue<BLOCK>();
- }
- writeSDImpl(sd, block, rules, diff_block);
- }
-
- /*virtual*/ std::string getCurrentElementName();
- /*virtual*/ std::string getCurrentFileName(){ return LLStringUtil::null; }
+ LLParamSDParser();
+ void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
+ template<typename BLOCK>
+ void writeSD(LLSD& sd,
+ const BLOCK& block,
+ const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
+ const LLInitParam::BaseBlock* diff_block = NULL)
+ {
+ if (!diff_block
+ && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
+ {
+ diff_block = &LLInitParam::defaultValue<BLOCK>();
+ }
+ writeSDImpl(sd, block, rules, diff_block);
+ }
+
+ /*virtual*/ std::string getCurrentElementName();
+ /*virtual*/ std::string getCurrentFileName(){ return LLStringUtil::null; }
private:
- void writeSDImpl(LLSD& sd,
- const LLInitParam::BaseBlock& block,
- const LLInitParam::predicate_rule_t,
- const LLInitParam::BaseBlock* diff_block);
-
- void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
-
- template<typename T>
- static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
- {
- LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
- if (!sdparser.mWriteRootSD) return false;
-
- LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
- LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
-
- sd_to_write.assign(*((const T*)val_ptr));
- return true;
- }
-
- static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
- static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
-
- static bool readFlag(Parser& parser, void* val_ptr);
- static bool readS32(Parser& parser, void* val_ptr);
- static bool readU32(Parser& parser, void* val_ptr);
- static bool readF32(Parser& parser, void* val_ptr);
- static bool readF64(Parser& parser, void* val_ptr);
- static bool readBool(Parser& parser, void* val_ptr);
- static bool readString(Parser& parser, void* val_ptr);
- static bool readUUID(Parser& parser, void* val_ptr);
- static bool readDate(Parser& parser, void* val_ptr);
- static bool readURI(Parser& parser, void* val_ptr);
- static bool readSD(Parser& parser, void* val_ptr);
-
- Parser::name_stack_t mNameStack;
- const LLSD* mCurReadSD;
- LLSD* mWriteRootSD;
+ void writeSDImpl(LLSD& sd,
+ const LLInitParam::BaseBlock& block,
+ const LLInitParam::predicate_rule_t,
+ const LLInitParam::BaseBlock* diff_block);
+
+ void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
+
+ template<typename T>
+ static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
+ {
+ LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
+ if (!sdparser.mWriteRootSD) return false;
+
+ LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
+ LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
+
+ sd_to_write.assign(*((const T*)val_ptr));
+ return true;
+ }
+
+ static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
+ static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
+
+ static bool readFlag(Parser& parser, void* val_ptr);
+ static bool readS32(Parser& parser, void* val_ptr);
+ static bool readU32(Parser& parser, void* val_ptr);
+ static bool readF32(Parser& parser, void* val_ptr);
+ static bool readF64(Parser& parser, void* val_ptr);
+ static bool readBool(Parser& parser, void* val_ptr);
+ static bool readString(Parser& parser, void* val_ptr);
+ static bool readUUID(Parser& parser, void* val_ptr);
+ static bool readDate(Parser& parser, void* val_ptr);
+ static bool readURI(Parser& parser, void* val_ptr);
+ static bool readSD(Parser& parser, void* val_ptr);
+
+ Parser::name_stack_t mNameStack;
+ const LLSD* mCurReadSD;
+ LLSD* mWriteRootSD;
};
@@ -114,29 +114,29 @@ template<typename T>
class LLSDParamAdapter : public T
{
public:
- LLSDParamAdapter() {}
- LLSDParamAdapter(const LLSD& sd)
- {
+ LLSDParamAdapter() {}
+ LLSDParamAdapter(const LLSD& sd)
+ {
LL_PROFILE_ZONE_SCOPED;
- LLParamSDParser parser;
- // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
- bool parse_silently = true;
- parser.readSD(sd, *this, parse_silently);
- }
-
- operator LLSD() const
- {
- LLParamSDParser parser;
- LLSD sd;
- parser.writeSD(sd, *this);
- return sd;
- }
-
- LLSDParamAdapter(const T& val)
- : T(val)
- {
- T::operator=(val);
- }
+ LLParamSDParser parser;
+ // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
+ bool parse_silently = true;
+ parser.readSD(sd, *this, parse_silently);
+ }
+
+ operator LLSD() const
+ {
+ LLParamSDParser parser;
+ LLSD sd;
+ parser.writeSD(sd, *this);
+ return sd;
+ }
+
+ LLSDParamAdapter(const T& val)
+ : T(val)
+ {
+ T::operator=(val);
+ }
};
#endif // LL_LLSDPARAM_H
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 76171f2dfd..d5af31a28e 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdserialize.cpp
* @author Phoenix
* @date 2006-03-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$
*/
@@ -88,42 +88,42 @@ S32 parse_using(std::istream& istr, LLSD& data, size_t max_bytes, S32 max_depth=
// static
void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type,
- LLSDFormatter::EFormatterOptions options)
+ LLSDFormatter::EFormatterOptions options)
{
- LLPointer<LLSDFormatter> f = NULL;
-
- switch (type)
- {
- case LLSD_BINARY:
- str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
- f = new LLSDBinaryFormatter;
- break;
-
- case LLSD_XML:
- str << "<? " << LLSD_XML_HEADER << " ?>\n";
- f = new LLSDXMLFormatter;
- break;
-
- case LLSD_NOTATION:
- str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
- f = new LLSDNotationFormatter;
- break;
-
- default:
- LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
- }
-
- if (f.notNull())
- {
- f->format(sd, str, options);
- }
+ LLPointer<LLSDFormatter> f = NULL;
+
+ switch (type)
+ {
+ case LLSD_BINARY:
+ str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
+ f = new LLSDBinaryFormatter;
+ break;
+
+ case LLSD_XML:
+ str << "<? " << LLSD_XML_HEADER << " ?>\n";
+ f = new LLSDXMLFormatter;
+ break;
+
+ case LLSD_NOTATION:
+ str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
+ f = new LLSDNotationFormatter;
+ break;
+
+ default:
+ LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
+ }
+
+ if (f.notNull())
+ {
+ f->format(sd, str, options);
+ }
}
// static
bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
{
- char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
- bool fail_if_not_legacy = false;
+ char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
+ bool fail_if_not_legacy = false;
/*
* Get the first line before anything. Don't read more than max_bytes:
@@ -132,125 +132,125 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
* sizeof(hdr_buf), get() will read no more than sizeof(hdr_buf)-2.
*/
llssize max_hdr_read = MAX_HDR_LEN;
- if (max_bytes != LLSDSerialize::SIZE_UNLIMITED)
- {
+ if (max_bytes != LLSDSerialize::SIZE_UNLIMITED)
+ {
max_hdr_read = llmin(max_bytes + 1, max_hdr_read);
- }
+ }
str.get(hdr_buf, max_hdr_read, '\n');
- auto inbuf = str.gcount();
-
- // https://en.cppreference.com/w/cpp/io/basic_istream/get
- // When the get() above sees the specified delimiter '\n', it stops there
- // without pulling it from the stream. If it turns out that the stream
- // does NOT contain a header, and the content includes meaningful '\n',
- // it's important to pull that into hdr_buf too.
- if (inbuf < max_bytes && str.get(hdr_buf[inbuf]))
- {
- // got the delimiting '\n'
- ++inbuf;
- // None of the following requires that hdr_buf contain a final '\0'
- // byte. We could store one if needed, since even the incremented
- // inbuf won't exceed sizeof(hdr_buf)-1, but there's no need.
- }
- std::string header{ hdr_buf, static_cast<std::string::size_type>(inbuf) };
- if (str.fail())
- {
- str.clear();
- fail_if_not_legacy = true;
- }
-
- if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
- { // Create a LLSD XML parser, and parse the first chunk read above.
- LLSDXMLParser x;
- x.parsePart(hdr_buf, inbuf); // Parse the first part that was already read
- auto parsed = x.parse(str, sd, max_bytes - inbuf); // Parse the rest of it
- // Formally we should probably check (parsed != PARSE_FAILURE &&
- // parsed > 0), but since PARSE_FAILURE is -1, this suffices.
- return (parsed > 0);
- }
-
- if (fail_if_not_legacy)
- {
- LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
- return false;
- }
-
- /*
- * Remove the newline chars
- */
- std::string::size_type lastchar = header.find_last_not_of("\r\n");
- if (lastchar != std::string::npos)
- {
- // It's important that find_last_not_of() returns size_type, which is
- // why lastchar explicitly declares the type above. erase(size_type)
- // erases from that offset to the end of the string, whereas
- // erase(iterator) erases only a single character.
- header.erase(lastchar+1);
- }
-
- // trim off the <? ... ?> header syntax
- auto start = header.find_first_not_of("<? ");
- if (start != std::string::npos)
- {
- auto end = header.find_first_of(" ?", start);
- if (end != std::string::npos)
- {
- header = header.substr(start, end - start);
- ws(str);
- }
- }
- /*
- * Create the parser as appropriate
- */
- if (0 == LLStringUtil::compareInsensitive(header, LLSD_BINARY_HEADER))
- {
- return (parse_using<LLSDBinaryParser>(str, sd, max_bytes-inbuf) > 0);
- }
- else if (0 == LLStringUtil::compareInsensitive(header, LLSD_XML_HEADER))
- {
- return (parse_using<LLSDXMLParser>(str, sd, max_bytes-inbuf) > 0);
- }
- else if (0 == LLStringUtil::compareInsensitive(header, LLSD_NOTATION_HEADER))
- {
- return (parse_using<LLSDNotationParser>(str, sd, max_bytes-inbuf) > 0);
- }
- else // no header we recognize
- {
- LLPointer<LLSDParser> p;
- if (inbuf && hdr_buf[0] == '<')
- {
- // looks like XML
- LL_DEBUGS() << "deserialize request with no header, assuming XML" << LL_ENDL;
- p = new LLSDXMLParser;
- }
- else
- {
- // assume notation
- LL_DEBUGS() << "deserialize request with no header, assuming notation" << LL_ENDL;
- p = new LLSDNotationParser;
- }
- // Since we've already read 'inbuf' bytes into 'hdr_buf', prepend that
- // data to whatever remains in 'str'.
- LLMemoryStreamBuf already(reinterpret_cast<const U8*>(hdr_buf), inbuf);
- cat_streambuf prebuff(&already, str.rdbuf());
- std::istream prepend(&prebuff);
+ auto inbuf = str.gcount();
+
+ // https://en.cppreference.com/w/cpp/io/basic_istream/get
+ // When the get() above sees the specified delimiter '\n', it stops there
+ // without pulling it from the stream. If it turns out that the stream
+ // does NOT contain a header, and the content includes meaningful '\n',
+ // it's important to pull that into hdr_buf too.
+ if (inbuf < max_bytes && str.get(hdr_buf[inbuf]))
+ {
+ // got the delimiting '\n'
+ ++inbuf;
+ // None of the following requires that hdr_buf contain a final '\0'
+ // byte. We could store one if needed, since even the incremented
+ // inbuf won't exceed sizeof(hdr_buf)-1, but there's no need.
+ }
+ std::string header{ hdr_buf, static_cast<std::string::size_type>(inbuf) };
+ if (str.fail())
+ {
+ str.clear();
+ fail_if_not_legacy = true;
+ }
+
+ if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
+ { // Create a LLSD XML parser, and parse the first chunk read above.
+ LLSDXMLParser x;
+ x.parsePart(hdr_buf, inbuf); // Parse the first part that was already read
+ auto parsed = x.parse(str, sd, max_bytes - inbuf); // Parse the rest of it
+ // Formally we should probably check (parsed != PARSE_FAILURE &&
+ // parsed > 0), but since PARSE_FAILURE is -1, this suffices.
+ return (parsed > 0);
+ }
+
+ if (fail_if_not_legacy)
+ {
+ LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
+ return false;
+ }
+
+ /*
+ * Remove the newline chars
+ */
+ std::string::size_type lastchar = header.find_last_not_of("\r\n");
+ if (lastchar != std::string::npos)
+ {
+ // It's important that find_last_not_of() returns size_type, which is
+ // why lastchar explicitly declares the type above. erase(size_type)
+ // erases from that offset to the end of the string, whereas
+ // erase(iterator) erases only a single character.
+ header.erase(lastchar+1);
+ }
+
+ // trim off the <? ... ?> header syntax
+ auto start = header.find_first_not_of("<? ");
+ if (start != std::string::npos)
+ {
+ auto end = header.find_first_of(" ?", start);
+ if (end != std::string::npos)
+ {
+ header = header.substr(start, end - start);
+ ws(str);
+ }
+ }
+ /*
+ * Create the parser as appropriate
+ */
+ if (0 == LLStringUtil::compareInsensitive(header, LLSD_BINARY_HEADER))
+ {
+ return (parse_using<LLSDBinaryParser>(str, sd, max_bytes-inbuf) > 0);
+ }
+ else if (0 == LLStringUtil::compareInsensitive(header, LLSD_XML_HEADER))
+ {
+ return (parse_using<LLSDXMLParser>(str, sd, max_bytes-inbuf) > 0);
+ }
+ else if (0 == LLStringUtil::compareInsensitive(header, LLSD_NOTATION_HEADER))
+ {
+ return (parse_using<LLSDNotationParser>(str, sd, max_bytes-inbuf) > 0);
+ }
+ else // no header we recognize
+ {
+ LLPointer<LLSDParser> p;
+ if (inbuf && hdr_buf[0] == '<')
+ {
+ // looks like XML
+ LL_DEBUGS() << "deserialize request with no header, assuming XML" << LL_ENDL;
+ p = new LLSDXMLParser;
+ }
+ else
+ {
+ // assume notation
+ LL_DEBUGS() << "deserialize request with no header, assuming notation" << LL_ENDL;
+ p = new LLSDNotationParser;
+ }
+ // Since we've already read 'inbuf' bytes into 'hdr_buf', prepend that
+ // data to whatever remains in 'str'.
+ LLMemoryStreamBuf already(reinterpret_cast<const U8*>(hdr_buf), inbuf);
+ cat_streambuf prebuff(&already, str.rdbuf());
+ std::istream prepend(&prebuff);
#if 1
- return (p->parse(prepend, sd, max_bytes) > 0);
+ return (p->parse(prepend, sd, max_bytes) > 0);
#else
- // debugging the reconstituted 'prepend' stream
- // allocate a buffer that we hope is big enough for the whole thing
- std::vector<char> wholemsg((max_bytes == size_t(SIZE_UNLIMITED))? 1024 : max_bytes);
- prepend.read(wholemsg.data(), std::min(max_bytes, wholemsg.size()));
- LLMemoryStream replay(reinterpret_cast<const U8*>(wholemsg.data()), prepend.gcount());
- auto success{ p->parse(replay, sd, prepend.gcount()) > 0 };
- {
- LL_DEBUGS() << (success? "parsed: $$" : "failed: '")
- << std::string(wholemsg.data(), llmin(prepend.gcount(), 100)) << "$$"
- << LL_ENDL;
- }
- return success;
+ // debugging the reconstituted 'prepend' stream
+ // allocate a buffer that we hope is big enough for the whole thing
+ std::vector<char> wholemsg((max_bytes == size_t(SIZE_UNLIMITED))? 1024 : max_bytes);
+ prepend.read(wholemsg.data(), std::min(max_bytes, wholemsg.size()));
+ LLMemoryStream replay(reinterpret_cast<const U8*>(wholemsg.data()), prepend.gcount());
+ auto success{ p->parse(replay, sd, prepend.gcount()) > 0 };
+ {
+ LL_DEBUGS() << (success? "parsed: $$" : "failed: '")
+ << std::string(wholemsg.data(), llmin(prepend.gcount(), 100)) << "$$"
+ << LL_ENDL;
+ }
+ return success;
#endif
- }
+ }
}
/**
@@ -268,32 +268,32 @@ F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
// operation.
U64 ll_htonll(U64 hostlonglong)
{
- return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
- ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
+ return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
+ ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
}
U64 ll_ntohll(U64 netlonglong)
{
- return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
- ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
+ return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
+ ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
}
union LLEndianSwapper
{
- F64 d;
- U64 i;
+ F64 d;
+ U64 i;
};
F64 ll_htond(F64 hostdouble)
{
- LLEndianSwapper tmp;
- tmp.d = hostdouble;
- tmp.i = ll_htonll(tmp.i);
- return tmp.d;
+ LLEndianSwapper tmp;
+ tmp.d = hostdouble;
+ tmp.i = ll_htonll(tmp.i);
+ return tmp.d;
}
F64 ll_ntohd(F64 netdouble)
{
- LLEndianSwapper tmp;
- tmp.d = netdouble;
- tmp.i = ll_ntohll(tmp.i);
- return tmp.d;
+ LLEndianSwapper tmp;
+ tmp.d = netdouble;
+ tmp.i = ll_ntohll(tmp.i);
+ return tmp.d;
}
#endif
@@ -313,7 +313,7 @@ F64 ll_ntohd(F64 netdouble)
llssize deserialize_string(std::istream& istr, std::string& value, llssize max_bytes);
/**
- * @brief Parse a delimited string.
+ * @brief Parse a delimited string.
*
* @param istr The stream to read from, with the delimiter already popped.
* @param value [out] The string which was found.
@@ -336,9 +336,9 @@ llssize deserialize_string_delim(std::istream& istr, std::string& value, char d)
* PARSE_FAILURE (-1) on failure.
*/
llssize deserialize_string_raw(
- std::istream& istr,
- std::string& value,
- llssize max_bytes);
+ std::istream& istr,
+ std::string& value,
+ llssize max_bytes);
/**
* @brief helper method for dealing with the different notation boolean format.
@@ -351,10 +351,10 @@ llssize deserialize_string_raw(
* PARSE_FAILURE (-1) on failure.
*/
llssize deserialize_boolean(
- std::istream& istr,
- LLSD& data,
- const std::string& compare,
- bool value);
+ std::istream& istr,
+ LLSD& data,
+ const std::string& compare,
+ bool value);
/**
* @brief Do notation escaping of a string to an ostream.
@@ -379,7 +379,7 @@ static const char BINARY_FALSE_SERIAL = '0';
* LLSDParser
*/
LLSDParser::LLSDParser()
- : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false)
+ : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false)
{
}
@@ -389,75 +389,75 @@ LLSDParser::~LLSDParser()
S32 LLSDParser::parse(std::istream& istr, LLSD& data, llssize max_bytes, S32 max_depth)
{
- mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
- mMaxBytesLeft = max_bytes;
- return doParse(istr, data, max_depth);
+ mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
+ mMaxBytesLeft = max_bytes;
+ return doParse(istr, data, max_depth);
}
// Parse using routine to get() lines, faster than parse()
S32 LLSDParser::parseLines(std::istream& istr, LLSD& data)
{
- mCheckLimits = false;
- mParseLines = true;
- return doParse(istr, data);
+ mCheckLimits = false;
+ mParseLines = true;
+ return doParse(istr, data);
}
int LLSDParser::get(std::istream& istr) const
{
- if(mCheckLimits) --mMaxBytesLeft;
- return istr.get();
+ if(mCheckLimits) --mMaxBytesLeft;
+ return istr.get();
}
std::istream& LLSDParser::get(
- std::istream& istr,
- char* s,
- std::streamsize n,
- char delim) const
+ std::istream& istr,
+ char* s,
+ std::streamsize n,
+ char delim) const
{
- istr.get(s, n, delim);
- if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
- return istr;
+ istr.get(s, n, delim);
+ if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
+ return istr;
}
std::istream& LLSDParser::get(
- std::istream& istr,
- std::streambuf& sb,
- char delim) const
+ std::istream& istr,
+ std::streambuf& sb,
+ char delim) const
{
- istr.get(sb, delim);
- if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
- return istr;
+ istr.get(sb, delim);
+ if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
+ return istr;
}
std::istream& LLSDParser::ignore(std::istream& istr) const
{
- istr.ignore();
- if(mCheckLimits) --mMaxBytesLeft;
- return istr;
+ istr.ignore();
+ if(mCheckLimits) --mMaxBytesLeft;
+ return istr;
}
std::istream& LLSDParser::putback(std::istream& istr, char c) const
{
- istr.putback(c);
- if(mCheckLimits) ++mMaxBytesLeft;
- return istr;
+ istr.putback(c);
+ if(mCheckLimits) ++mMaxBytesLeft;
+ return istr;
}
std::istream& LLSDParser::read(
- std::istream& istr,
- char* s,
- std::streamsize n) const
+ std::istream& istr,
+ char* s,
+ std::streamsize n) const
{
- istr.read(s, n);
- if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
- return istr;
+ istr.read(s, n);
+ if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
+ return istr;
}
void LLSDParser::account(llssize bytes) const
{
- if(mCheckLimits) mMaxBytesLeft -= bytes;
+ if(mCheckLimits) mMaxBytesLeft -= bytes;
}
@@ -466,7 +466,7 @@ void LLSDParser::account(llssize bytes) const
*/
LLSDNotationParser::LLSDNotationParser()
{
-}
+}
// virtual
LLSDNotationParser::~LLSDNotationParser()
@@ -475,463 +475,463 @@ LLSDNotationParser::~LLSDNotationParser()
// virtual
S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
- // map: { string:object, string:object }
- // array: [ object, object, object ]
- // undef: !
- // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
- // integer: i####
- // real: r####
- // uuid: u####
- // string: "g'day" | 'have a "nice" day' | s(size)"raw data"
- // uri: l"escaped"
- // date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
- // binary: b##"ff3120ab1" | b(size)"raw data"
- char c;
- c = istr.peek();
- if (max_depth == 0)
- {
- return PARSE_FAILURE;
- }
- while(isspace(c))
- {
- // pop the whitespace.
- c = get(istr);
- c = istr.peek();
- continue;
- }
- if(!istr.good())
- {
- return 0;
- }
- S32 parse_count = 1;
- switch(c)
- {
- case '{':
- {
- S32 child_count = parseMap(istr, data, max_depth - 1);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '[':
- {
- S32 child_count = parseArray(istr, data, max_depth - 1);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '!':
- c = get(istr);
- data.clear();
- break;
-
- case '0':
- c = get(istr);
- data = false;
- break;
-
- case 'F':
- case 'f':
- ignore(istr);
- c = istr.peek();
- if(isalpha(c))
- {
- auto cnt = deserialize_boolean(
- istr,
- data,
- NOTATION_FALSE_SERIAL,
- false);
- if(PARSE_FAILURE == cnt) parse_count = cnt;
- else account(cnt);
- }
- else
- {
- data = false;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- case '1':
- c = get(istr);
- data = true;
- break;
-
- case 'T':
- case 't':
- ignore(istr);
- c = istr.peek();
- if(isalpha(c))
- {
- auto cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
- if(PARSE_FAILURE == cnt) parse_count = cnt;
- else account(cnt);
- }
- else
- {
- data = true;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- case 'i':
- {
- c = get(istr);
- S32 integer = 0;
- istr >> integer;
- data = integer;
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'r':
- {
- c = get(istr);
- F64 real = 0.0;
- istr >> real;
- data = real;
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'u':
- {
- c = get(istr);
- LLUUID id;
- istr >> id;
- data = id;
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '\"':
- case '\'':
- case 's':
- if(!parseString(istr, data))
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- case 'l':
- {
- c = get(istr); // pop the 'l'
- c = get(istr); // pop the delimiter
- std::string str;
- auto cnt = deserialize_string_delim(istr, str, c);
- if(PARSE_FAILURE == cnt)
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- data = LLURI(str);
- account(cnt);
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'd':
- {
- c = get(istr); // pop the 'd'
- c = get(istr); // pop the delimiter
- std::string str;
- auto cnt = deserialize_string_delim(istr, str, c);
- if(PARSE_FAILURE == cnt)
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- data = LLDate(str);
- account(cnt);
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'b':
- if(!parseBinary(istr, data))
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- default:
- parse_count = PARSE_FAILURE;
- LL_INFOS() << "Unrecognized character while parsing: int(" << int(c)
- << ")" << LL_ENDL;
- break;
- }
- if(PARSE_FAILURE == parse_count)
- {
- data.clear();
- }
- return parse_count;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ // map: { string:object, string:object }
+ // array: [ object, object, object ]
+ // undef: !
+ // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
+ // integer: i####
+ // real: r####
+ // uuid: u####
+ // string: "g'day" | 'have a "nice" day' | s(size)"raw data"
+ // uri: l"escaped"
+ // date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
+ // binary: b##"ff3120ab1" | b(size)"raw data"
+ char c;
+ c = istr.peek();
+ if (max_depth == 0)
+ {
+ return PARSE_FAILURE;
+ }
+ while(isspace(c))
+ {
+ // pop the whitespace.
+ c = get(istr);
+ c = istr.peek();
+ continue;
+ }
+ if(!istr.good())
+ {
+ return 0;
+ }
+ S32 parse_count = 1;
+ switch(c)
+ {
+ case '{':
+ {
+ S32 child_count = parseMap(istr, data, max_depth - 1);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '[':
+ {
+ S32 child_count = parseArray(istr, data, max_depth - 1);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '!':
+ c = get(istr);
+ data.clear();
+ break;
+
+ case '0':
+ c = get(istr);
+ data = false;
+ break;
+
+ case 'F':
+ case 'f':
+ ignore(istr);
+ c = istr.peek();
+ if(isalpha(c))
+ {
+ auto cnt = deserialize_boolean(
+ istr,
+ data,
+ NOTATION_FALSE_SERIAL,
+ false);
+ if(PARSE_FAILURE == cnt) parse_count = cnt;
+ else account(cnt);
+ }
+ else
+ {
+ data = false;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ case '1':
+ c = get(istr);
+ data = true;
+ break;
+
+ case 'T':
+ case 't':
+ ignore(istr);
+ c = istr.peek();
+ if(isalpha(c))
+ {
+ auto cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
+ if(PARSE_FAILURE == cnt) parse_count = cnt;
+ else account(cnt);
+ }
+ else
+ {
+ data = true;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ case 'i':
+ {
+ c = get(istr);
+ S32 integer = 0;
+ istr >> integer;
+ data = integer;
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'r':
+ {
+ c = get(istr);
+ F64 real = 0.0;
+ istr >> real;
+ data = real;
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'u':
+ {
+ c = get(istr);
+ LLUUID id;
+ istr >> id;
+ data = id;
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '\"':
+ case '\'':
+ case 's':
+ if(!parseString(istr, data))
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ case 'l':
+ {
+ c = get(istr); // pop the 'l'
+ c = get(istr); // pop the delimiter
+ std::string str;
+ auto cnt = deserialize_string_delim(istr, str, c);
+ if(PARSE_FAILURE == cnt)
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ data = LLURI(str);
+ account(cnt);
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'd':
+ {
+ c = get(istr); // pop the 'd'
+ c = get(istr); // pop the delimiter
+ std::string str;
+ auto cnt = deserialize_string_delim(istr, str, c);
+ if(PARSE_FAILURE == cnt)
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ data = LLDate(str);
+ account(cnt);
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'b':
+ if(!parseBinary(istr, data))
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ default:
+ parse_count = PARSE_FAILURE;
+ LL_INFOS() << "Unrecognized character while parsing: int(" << int(c)
+ << ")" << LL_ENDL;
+ break;
+ }
+ if(PARSE_FAILURE == parse_count)
+ {
+ data.clear();
+ }
+ return parse_count;
}
S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
- // map: { string:object, string:object }
- map = LLSD::emptyMap();
- S32 parse_count = 0;
- char c = get(istr);
- if(c == '{')
- {
- // eat commas, white
- bool found_name = false;
- std::string name;
- c = get(istr);
- while(c != '}' && istr.good())
- {
- if(!found_name)
- {
- if((c == '\"') || (c == '\'') || (c == 's'))
- {
- putback(istr, c);
- found_name = true;
- auto count = deserialize_string(istr, name, mMaxBytesLeft);
- if(PARSE_FAILURE == count) return PARSE_FAILURE;
- account(count);
- }
- c = get(istr);
- }
- else
- {
- if(isspace(c) || (c == ':'))
- {
- c = get(istr);
- continue;
- }
- putback(istr, c);
- LLSD child;
- S32 count = doParse(istr, child, max_depth);
- if(count > 0)
- {
- // There must be a value for every key, thus
- // child_count must be greater than 0.
- parse_count += count;
- map.insert(name, child);
- }
- else
- {
- return PARSE_FAILURE;
- }
- found_name = false;
- c = get(istr);
- }
- }
- if(c != '}')
- {
- map.clear();
- return PARSE_FAILURE;
- }
- }
- return parse_count;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ // map: { string:object, string:object }
+ map = LLSD::emptyMap();
+ S32 parse_count = 0;
+ char c = get(istr);
+ if(c == '{')
+ {
+ // eat commas, white
+ bool found_name = false;
+ std::string name;
+ c = get(istr);
+ while(c != '}' && istr.good())
+ {
+ if(!found_name)
+ {
+ if((c == '\"') || (c == '\'') || (c == 's'))
+ {
+ putback(istr, c);
+ found_name = true;
+ auto count = deserialize_string(istr, name, mMaxBytesLeft);
+ if(PARSE_FAILURE == count) return PARSE_FAILURE;
+ account(count);
+ }
+ c = get(istr);
+ }
+ else
+ {
+ if(isspace(c) || (c == ':'))
+ {
+ c = get(istr);
+ continue;
+ }
+ putback(istr, c);
+ LLSD child;
+ S32 count = doParse(istr, child, max_depth);
+ if(count > 0)
+ {
+ // There must be a value for every key, thus
+ // child_count must be greater than 0.
+ parse_count += count;
+ map.insert(name, child);
+ }
+ else
+ {
+ return PARSE_FAILURE;
+ }
+ found_name = false;
+ c = get(istr);
+ }
+ }
+ if(c != '}')
+ {
+ map.clear();
+ return PARSE_FAILURE;
+ }
+ }
+ return parse_count;
}
S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
- // array: [ object, object, object ]
- array = LLSD::emptyArray();
- S32 parse_count = 0;
- char c = get(istr);
- if(c == '[')
- {
- // eat commas, white
- c = get(istr);
- while((c != ']') && istr.good())
- {
- LLSD child;
- if(isspace(c) || (c == ','))
- {
- c = get(istr);
- continue;
- }
- putback(istr, c);
- S32 count = doParse(istr, child, max_depth);
- if(PARSE_FAILURE == count)
- {
- return PARSE_FAILURE;
- }
- else
- {
- parse_count += count;
- array.append(child);
- }
- c = get(istr);
- }
- if(c != ']')
- {
- return PARSE_FAILURE;
- }
- }
- return parse_count;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ // array: [ object, object, object ]
+ array = LLSD::emptyArray();
+ S32 parse_count = 0;
+ char c = get(istr);
+ if(c == '[')
+ {
+ // eat commas, white
+ c = get(istr);
+ while((c != ']') && istr.good())
+ {
+ LLSD child;
+ if(isspace(c) || (c == ','))
+ {
+ c = get(istr);
+ continue;
+ }
+ putback(istr, c);
+ S32 count = doParse(istr, child, max_depth);
+ if(PARSE_FAILURE == count)
+ {
+ return PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += count;
+ array.append(child);
+ }
+ c = get(istr);
+ }
+ if(c != ']')
+ {
+ return PARSE_FAILURE;
+ }
+ }
+ return parse_count;
}
bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
- std::string value;
- auto count = deserialize_string(istr, value, mMaxBytesLeft);
- if(PARSE_FAILURE == count) return false;
- account(count);
- data = value;
- return true;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ std::string value;
+ auto count = deserialize_string(istr, value, mMaxBytesLeft);
+ if(PARSE_FAILURE == count) return false;
+ account(count);
+ data = value;
+ return true;
}
bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
- // binary: b##"ff3120ab1"
- // or: b(len)"..."
-
- // I want to manually control those values here to make sure the
- // parser doesn't break when someone changes a constant somewhere
- // else.
- const U32 BINARY_BUFFER_SIZE = 256;
- const U32 STREAM_GET_COUNT = 255;
-
- // need to read the base out.
- char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */
- get(istr, buf, STREAM_GET_COUNT, '"');
- char c = get(istr);
- if(c != '"') return false;
- if(0 == strncmp("b(", buf, 2))
- {
- // We probably have a valid raw binary stream. determine
- // the size, and read it.
- auto len = strtol(buf + 2, NULL, 0);
- if(mCheckLimits && (len > mMaxBytesLeft)) return false;
- std::vector<U8> value;
- if(len)
- {
- value.resize(len);
- account(fullread(istr, (char *)&value[0], len));
- }
- c = get(istr); // strip off the trailing double-quote
- data = value;
- }
- else if(0 == strncmp("b64", buf, 3))
- {
- // *FIX: A bit inefficient, but works for now. To make the
- // format better, I would need to add a hint into the
- // serialization format that indicated how long it was.
- std::stringstream coded_stream;
- get(istr, *(coded_stream.rdbuf()), '\"');
- c = get(istr);
- std::string encoded(coded_stream.str());
- S32 len = apr_base64_decode_len(encoded.c_str());
- std::vector<U8> value;
- if(len)
- {
- value.resize(len);
- len = apr_base64_decode_binary(&value[0], encoded.c_str());
- value.resize(len);
- }
- data = value;
- }
- else if(0 == strncmp("b16", buf, 3))
- {
- // yay, base 16. We pop the next character which is either a
- // double quote or base 16 data. If it's a double quote, we're
- // done parsing. If it's not, put the data back, and read the
- // stream until the next double quote.
- char* read; /*Flawfinder: ignore*/
- U8 byte;
- U8 byte_buffer[BINARY_BUFFER_SIZE];
- U8* write;
- std::vector<U8> value;
- c = get(istr);
- while(c != '"')
- {
- putback(istr, c);
- read = buf;
- write = byte_buffer;
- get(istr, buf, STREAM_GET_COUNT, '"');
- c = get(istr);
- while(*read != '\0') /*Flawfinder: ignore*/
- {
- byte = hex_as_nybble(*read++);
- byte = byte << 4;
- byte |= hex_as_nybble(*read++);
- *write++ = byte;
- }
- // copy the data out of the byte buffer
- value.insert(value.end(), byte_buffer, write);
- }
- data = value;
- }
- else
- {
- return false;
- }
- return true;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ // binary: b##"ff3120ab1"
+ // or: b(len)"..."
+
+ // I want to manually control those values here to make sure the
+ // parser doesn't break when someone changes a constant somewhere
+ // else.
+ const U32 BINARY_BUFFER_SIZE = 256;
+ const U32 STREAM_GET_COUNT = 255;
+
+ // need to read the base out.
+ char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */
+ get(istr, buf, STREAM_GET_COUNT, '"');
+ char c = get(istr);
+ if(c != '"') return false;
+ if(0 == strncmp("b(", buf, 2))
+ {
+ // We probably have a valid raw binary stream. determine
+ // the size, and read it.
+ auto len = strtol(buf + 2, NULL, 0);
+ if(mCheckLimits && (len > mMaxBytesLeft)) return false;
+ std::vector<U8> value;
+ if(len)
+ {
+ value.resize(len);
+ account(fullread(istr, (char *)&value[0], len));
+ }
+ c = get(istr); // strip off the trailing double-quote
+ data = value;
+ }
+ else if(0 == strncmp("b64", buf, 3))
+ {
+ // *FIX: A bit inefficient, but works for now. To make the
+ // format better, I would need to add a hint into the
+ // serialization format that indicated how long it was.
+ std::stringstream coded_stream;
+ get(istr, *(coded_stream.rdbuf()), '\"');
+ c = get(istr);
+ std::string encoded(coded_stream.str());
+ S32 len = apr_base64_decode_len(encoded.c_str());
+ std::vector<U8> value;
+ if(len)
+ {
+ value.resize(len);
+ len = apr_base64_decode_binary(&value[0], encoded.c_str());
+ value.resize(len);
+ }
+ data = value;
+ }
+ else if(0 == strncmp("b16", buf, 3))
+ {
+ // yay, base 16. We pop the next character which is either a
+ // double quote or base 16 data. If it's a double quote, we're
+ // done parsing. If it's not, put the data back, and read the
+ // stream until the next double quote.
+ char* read; /*Flawfinder: ignore*/
+ U8 byte;
+ U8 byte_buffer[BINARY_BUFFER_SIZE];
+ U8* write;
+ std::vector<U8> value;
+ c = get(istr);
+ while(c != '"')
+ {
+ putback(istr, c);
+ read = buf;
+ write = byte_buffer;
+ get(istr, buf, STREAM_GET_COUNT, '"');
+ c = get(istr);
+ while(*read != '\0') /*Flawfinder: ignore*/
+ {
+ byte = hex_as_nybble(*read++);
+ byte = byte << 4;
+ byte |= hex_as_nybble(*read++);
+ *write++ = byte;
+ }
+ // copy the data out of the byte buffer
+ value.insert(value.end(), byte_buffer, write);
+ }
+ data = value;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
}
@@ -950,7 +950,7 @@ LLSDBinaryParser::~LLSDBinaryParser()
// virtual
S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
/**
* Undefined: '!'<br>
* Boolean: '1' for true '0' for false<br>
@@ -967,332 +967,332 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con
* map keys are serialized as s + 4 byte integer size + string or in the
* notation format.
*/
- char c;
- c = get(istr);
- if(!istr.good())
- {
- return 0;
- }
- if (max_depth == 0)
- {
- return PARSE_FAILURE;
- }
- S32 parse_count = 1;
- switch(c)
- {
- case '{':
- {
- S32 child_count = parseMap(istr, data, max_depth - 1);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '[':
- {
- S32 child_count = parseArray(istr, data, max_depth - 1);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '!':
- data.clear();
- break;
-
- case '0':
- data = false;
- break;
-
- case '1':
- data = true;
- break;
-
- case 'i':
- {
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- data = (S32)ntohl(value_nbo);
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL;
- }
- break;
- }
-
- case 'r':
- {
- F64 real_nbo = 0.0;
- read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/
- data = ll_ntohd(real_nbo);
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL;
- }
- break;
- }
-
- case 'u':
- {
- LLUUID id;
- read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/
- data = id;
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL;
- }
- break;
- }
-
- case '\'':
- case '"':
- {
- std::string value;
- auto cnt = deserialize_string_delim(istr, value, c);
- if(PARSE_FAILURE == cnt)
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- data = value;
- account(cnt);
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string."
- << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 's':
- {
- std::string value;
- if(parseString(istr, value))
- {
- data = value;
- }
- else
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'l':
- {
- std::string value;
- if(parseString(istr, value))
- {
- data = LLURI(value);
- }
- else
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'd':
- {
- F64 real = 0.0;
- read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/
- data = LLDate(real);
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'b':
- {
- // We probably have a valid raw binary stream. determine
- // the size, and read it.
- U32 size_nbo = 0;
- read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(size_nbo);
- if(mCheckLimits && (size > mMaxBytesLeft))
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- std::vector<U8> value;
- if(size > 0)
- {
- value.resize(size);
- account(fullread(istr, (char*)&value[0], size));
- }
- data = value;
- }
- if(istr.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- default:
- parse_count = PARSE_FAILURE;
- LL_INFOS() << "Unrecognized character while parsing: int(" << int(c)
- << ")" << LL_ENDL;
- break;
- }
- if(PARSE_FAILURE == parse_count)
- {
- data.clear();
- }
- return parse_count;
+ char c;
+ c = get(istr);
+ if(!istr.good())
+ {
+ return 0;
+ }
+ if (max_depth == 0)
+ {
+ return PARSE_FAILURE;
+ }
+ S32 parse_count = 1;
+ switch(c)
+ {
+ case '{':
+ {
+ S32 child_count = parseMap(istr, data, max_depth - 1);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '[':
+ {
+ S32 child_count = parseArray(istr, data, max_depth - 1);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '!':
+ data.clear();
+ break;
+
+ case '0':
+ data = false;
+ break;
+
+ case '1':
+ data = true;
+ break;
+
+ case 'i':
+ {
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ data = (S32)ntohl(value_nbo);
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL;
+ }
+ break;
+ }
+
+ case 'r':
+ {
+ F64 real_nbo = 0.0;
+ read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/
+ data = ll_ntohd(real_nbo);
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL;
+ }
+ break;
+ }
+
+ case 'u':
+ {
+ LLUUID id;
+ read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/
+ data = id;
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL;
+ }
+ break;
+ }
+
+ case '\'':
+ case '"':
+ {
+ std::string value;
+ auto cnt = deserialize_string_delim(istr, value, c);
+ if(PARSE_FAILURE == cnt)
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ data = value;
+ account(cnt);
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string."
+ << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 's':
+ {
+ std::string value;
+ if(parseString(istr, value))
+ {
+ data = value;
+ }
+ else
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'l':
+ {
+ std::string value;
+ if(parseString(istr, value))
+ {
+ data = LLURI(value);
+ }
+ else
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'd':
+ {
+ F64 real = 0.0;
+ read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/
+ data = LLDate(real);
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'b':
+ {
+ // We probably have a valid raw binary stream. determine
+ // the size, and read it.
+ U32 size_nbo = 0;
+ read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(size_nbo);
+ if(mCheckLimits && (size > mMaxBytesLeft))
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ std::vector<U8> value;
+ if(size > 0)
+ {
+ value.resize(size);
+ account(fullread(istr, (char*)&value[0], size));
+ }
+ data = value;
+ }
+ if(istr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ default:
+ parse_count = PARSE_FAILURE;
+ LL_INFOS() << "Unrecognized character while parsing: int(" << int(c)
+ << ")" << LL_ENDL;
+ break;
+ }
+ if(PARSE_FAILURE == parse_count)
+ {
+ data.clear();
+ }
+ return parse_count;
}
S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const
{
- map = LLSD::emptyMap();
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(value_nbo);
- S32 parse_count = 0;
- S32 count = 0;
- char c = get(istr);
- while(c != '}' && (count < size) && istr.good())
- {
- std::string name;
- switch(c)
- {
- case 'k':
- if(!parseString(istr, name))
- {
- return PARSE_FAILURE;
- }
- break;
- case '\'':
- case '"':
- {
- auto cnt = deserialize_string_delim(istr, name, c);
- if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
- account(cnt);
- break;
- }
- }
- LLSD child;
- S32 child_count = doParse(istr, child, max_depth);
- if(child_count > 0)
- {
- // There must be a value for every key, thus child_count
- // must be greater than 0.
- parse_count += child_count;
- map.insert(name, child);
- }
- else
- {
- return PARSE_FAILURE;
- }
- ++count;
- c = get(istr);
- }
- if((c != '}') || (count < size))
- {
- // Make sure it is correctly terminated and we parsed as many
- // as were said to be there.
- return PARSE_FAILURE;
- }
- return parse_count;
+ map = LLSD::emptyMap();
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(value_nbo);
+ S32 parse_count = 0;
+ S32 count = 0;
+ char c = get(istr);
+ while(c != '}' && (count < size) && istr.good())
+ {
+ std::string name;
+ switch(c)
+ {
+ case 'k':
+ if(!parseString(istr, name))
+ {
+ return PARSE_FAILURE;
+ }
+ break;
+ case '\'':
+ case '"':
+ {
+ auto cnt = deserialize_string_delim(istr, name, c);
+ if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
+ account(cnt);
+ break;
+ }
+ }
+ LLSD child;
+ S32 child_count = doParse(istr, child, max_depth);
+ if(child_count > 0)
+ {
+ // There must be a value for every key, thus child_count
+ // must be greater than 0.
+ parse_count += child_count;
+ map.insert(name, child);
+ }
+ else
+ {
+ return PARSE_FAILURE;
+ }
+ ++count;
+ c = get(istr);
+ }
+ if((c != '}') || (count < size))
+ {
+ // Make sure it is correctly terminated and we parsed as many
+ // as were said to be there.
+ return PARSE_FAILURE;
+ }
+ return parse_count;
}
S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const
{
- array = LLSD::emptyArray();
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(value_nbo);
-
- // *FIX: This would be a good place to reserve some space in the
- // array...
-
- S32 parse_count = 0;
- S32 count = 0;
- char c = istr.peek();
- while((c != ']') && (count < size) && istr.good())
- {
- LLSD child;
- S32 child_count = doParse(istr, child, max_depth);
- if(PARSE_FAILURE == child_count)
- {
- return PARSE_FAILURE;
- }
- if(child_count)
- {
- parse_count += child_count;
- array.append(child);
- }
- ++count;
- c = istr.peek();
- }
- c = get(istr);
- if((c != ']') || (count < size))
- {
- // Make sure it is correctly terminated and we parsed as many
- // as were said to be there.
- return PARSE_FAILURE;
- }
- return parse_count;
+ array = LLSD::emptyArray();
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(value_nbo);
+
+ // *FIX: This would be a good place to reserve some space in the
+ // array...
+
+ S32 parse_count = 0;
+ S32 count = 0;
+ char c = istr.peek();
+ while((c != ']') && (count < size) && istr.good())
+ {
+ LLSD child;
+ S32 child_count = doParse(istr, child, max_depth);
+ if(PARSE_FAILURE == child_count)
+ {
+ return PARSE_FAILURE;
+ }
+ if(child_count)
+ {
+ parse_count += child_count;
+ array.append(child);
+ }
+ ++count;
+ c = istr.peek();
+ }
+ c = get(istr);
+ if((c != ']') || (count < size))
+ {
+ // Make sure it is correctly terminated and we parsed as many
+ // as were said to be there.
+ return PARSE_FAILURE;
+ }
+ return parse_count;
}
bool LLSDBinaryParser::parseString(
- std::istream& istr,
- std::string& value) const
+ std::istream& istr,
+ std::string& value) const
{
- // *FIX: This is memory inefficient.
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(value_nbo);
- if(mCheckLimits && (size > mMaxBytesLeft)) return false;
- if(size < 0) return false;
- std::vector<char> buf;
- if(size)
- {
- buf.resize(size);
- account(fullread(istr, &buf[0], size));
- value.assign(buf.begin(), buf.end());
- }
- return true;
+ // *FIX: This is memory inefficient.
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(value_nbo);
+ if(mCheckLimits && (size > mMaxBytesLeft)) return false;
+ if(size < 0) return false;
+ std::vector<char> buf;
+ if(size)
+ {
+ buf.resize(size);
+ account(fullread(istr, &buf[0], size));
+ value.assign(buf.begin(), buf.end());
+ }
+ return true;
}
@@ -1312,12 +1312,12 @@ LLSDFormatter::~LLSDFormatter()
void LLSDFormatter::boolalpha(bool alpha)
{
- mBoolAlpha = alpha;
+ mBoolAlpha = alpha;
}
void LLSDFormatter::realFormat(const std::string& format)
{
- mRealFormat = format;
+ mRealFormat = format;
}
S32 LLSDFormatter::format(const LLSD& data, std::ostream& ostr) const
@@ -1333,8 +1333,8 @@ S32 LLSDFormatter::format(const LLSD& data, std::ostream& ostr, EFormatterOption
void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
{
- std::string buffer = llformat(mRealFormat.c_str(), real);
- ostr << buffer;
+ std::string buffer = llformat(mRealFormat.c_str(), real);
+ ostr << buffer;
}
/**
@@ -1353,174 +1353,174 @@ LLSDNotationFormatter::~LLSDNotationFormatter()
// static
std::string LLSDNotationFormatter::escapeString(const std::string& in)
{
- std::ostringstream ostr;
- serialize_string(in, ostr);
- return ostr.str();
+ std::ostringstream ostr;
+ serialize_string(in, ostr);
+ return ostr.str();
}
S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr,
- EFormatterOptions options, U32 level) const
+ EFormatterOptions options, U32 level) const
{
- S32 format_count = 1;
- std::string pre;
- std::string post;
-
- if (options & LLSDFormatter::OPTIONS_PRETTY)
- {
- for (U32 i = 0; i < level; i++)
- {
- pre += " ";
- }
- post = "\n";
- }
-
- switch(data.type())
- {
- case LLSD::TypeMap:
- {
- if (0 != level) ostr << post << pre;
- ostr << "{";
- std::string inner_pre;
- if (options & LLSDFormatter::OPTIONS_PRETTY)
- {
- inner_pre = pre + " ";
- }
-
- bool need_comma = false;
- LLSD::map_const_iterator iter = data.beginMap();
- LLSD::map_const_iterator end = data.endMap();
- for(; iter != end; ++iter)
- {
- if(need_comma) ostr << ",";
- need_comma = true;
- ostr << post << inner_pre << '\'';
- serialize_string((*iter).first, ostr);
- ostr << "':";
- format_count += format_impl((*iter).second, ostr, options, level + 2);
- }
- ostr << post << pre << "}";
- break;
- }
-
- case LLSD::TypeArray:
- {
- ostr << post << pre << "[";
- bool need_comma = false;
- LLSD::array_const_iterator iter = data.beginArray();
- LLSD::array_const_iterator end = data.endArray();
- for(; iter != end; ++iter)
- {
- if(need_comma) ostr << ",";
- need_comma = true;
- format_count += format_impl(*iter, ostr, options, level + 1);
- }
- ostr << "]";
- break;
- }
-
- case LLSD::TypeUndefined:
- ostr << "!";
- break;
-
- case LLSD::TypeBoolean:
- if(mBoolAlpha ||
+ S32 format_count = 1;
+ std::string pre;
+ std::string post;
+
+ if (options & LLSDFormatter::OPTIONS_PRETTY)
+ {
+ for (U32 i = 0; i < level; i++)
+ {
+ pre += " ";
+ }
+ post = "\n";
+ }
+
+ switch(data.type())
+ {
+ case LLSD::TypeMap:
+ {
+ if (0 != level) ostr << post << pre;
+ ostr << "{";
+ std::string inner_pre;
+ if (options & LLSDFormatter::OPTIONS_PRETTY)
+ {
+ inner_pre = pre + " ";
+ }
+
+ bool need_comma = false;
+ LLSD::map_const_iterator iter = data.beginMap();
+ LLSD::map_const_iterator end = data.endMap();
+ for(; iter != end; ++iter)
+ {
+ if(need_comma) ostr << ",";
+ need_comma = true;
+ ostr << post << inner_pre << '\'';
+ serialize_string((*iter).first, ostr);
+ ostr << "':";
+ format_count += format_impl((*iter).second, ostr, options, level + 2);
+ }
+ ostr << post << pre << "}";
+ break;
+ }
+
+ case LLSD::TypeArray:
+ {
+ ostr << post << pre << "[";
+ bool need_comma = false;
+ LLSD::array_const_iterator iter = data.beginArray();
+ LLSD::array_const_iterator end = data.endArray();
+ for(; iter != end; ++iter)
+ {
+ if(need_comma) ostr << ",";
+ need_comma = true;
+ format_count += format_impl(*iter, ostr, options, level + 1);
+ }
+ ostr << "]";
+ break;
+ }
+
+ case LLSD::TypeUndefined:
+ ostr << "!";
+ break;
+
+ case LLSD::TypeBoolean:
+ if(mBoolAlpha ||
#if( LL_WINDOWS || __GNUC__ > 2)
- (ostr.flags() & std::ios::boolalpha)
+ (ostr.flags() & std::ios::boolalpha)
#else
- (ostr.flags() & 0x0100)
+ (ostr.flags() & 0x0100)
#endif
- )
- {
- ostr << (data.asBoolean()
- ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
- }
- else
- {
- ostr << (data.asBoolean() ? 1 : 0);
- }
- break;
-
- case LLSD::TypeInteger:
- ostr << "i" << data.asInteger();
- break;
-
- case LLSD::TypeReal:
- ostr << "r";
- if(mRealFormat.empty())
- {
- ostr << data.asReal();
- }
- else
- {
- formatReal(data.asReal(), ostr);
- }
- break;
-
- case LLSD::TypeUUID:
- ostr << "u" << data.asUUID();
- break;
-
- case LLSD::TypeString:
- ostr << '\'';
- serialize_string(data.asStringRef(), ostr);
- ostr << '\'';
- break;
-
- case LLSD::TypeDate:
- ostr << "d\"" << data.asDate() << "\"";
- break;
-
- case LLSD::TypeURI:
- ostr << "l\"";
- serialize_string(data.asString(), ostr);
- ostr << "\"";
- break;
-
- case LLSD::TypeBinary:
- {
- // *FIX: memory inefficient.
- const std::vector<U8>& buffer = data.asBinary();
- if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY)
- {
- ostr << "b16\"";
- if (! buffer.empty())
- {
- std::ios_base::fmtflags old_flags = ostr.flags();
- ostr.setf( std::ios::hex, std::ios::basefield );
- // It shouldn't strictly matter whether the emitted hex digits
- // are uppercase; LLSDNotationParser handles either; but as of
- // 2020-05-13, Python's llbase.llsd requires uppercase hex.
- ostr << std::uppercase;
- auto oldfill(ostr.fill('0'));
- auto oldwidth(ostr.width());
- for (size_t i = 0; i < buffer.size(); i++)
- {
- // have to restate setw() before every conversion
- ostr << std::setw(2) << (int) buffer[i];
- }
- ostr.width(oldwidth);
- ostr.fill(oldfill);
- ostr.flags(old_flags);
- }
- }
- else // ! OPTIONS_PRETTY_BINARY
- {
- ostr << "b(" << buffer.size() << ")\"";
- if (! buffer.empty())
- {
- ostr.write((const char*)&buffer[0], buffer.size());
- }
- }
- ostr << "\"";
- break;
- }
-
- default:
- // *NOTE: This should never happen.
- ostr << "!";
- break;
- }
- return format_count;
+ )
+ {
+ ostr << (data.asBoolean()
+ ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
+ }
+ else
+ {
+ ostr << (data.asBoolean() ? 1 : 0);
+ }
+ break;
+
+ case LLSD::TypeInteger:
+ ostr << "i" << data.asInteger();
+ break;
+
+ case LLSD::TypeReal:
+ ostr << "r";
+ if(mRealFormat.empty())
+ {
+ ostr << data.asReal();
+ }
+ else
+ {
+ formatReal(data.asReal(), ostr);
+ }
+ break;
+
+ case LLSD::TypeUUID:
+ ostr << "u" << data.asUUID();
+ break;
+
+ case LLSD::TypeString:
+ ostr << '\'';
+ serialize_string(data.asStringRef(), ostr);
+ ostr << '\'';
+ break;
+
+ case LLSD::TypeDate:
+ ostr << "d\"" << data.asDate() << "\"";
+ break;
+
+ case LLSD::TypeURI:
+ ostr << "l\"";
+ serialize_string(data.asString(), ostr);
+ ostr << "\"";
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ // *FIX: memory inefficient.
+ const std::vector<U8>& buffer = data.asBinary();
+ if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY)
+ {
+ ostr << "b16\"";
+ if (! buffer.empty())
+ {
+ std::ios_base::fmtflags old_flags = ostr.flags();
+ ostr.setf( std::ios::hex, std::ios::basefield );
+ // It shouldn't strictly matter whether the emitted hex digits
+ // are uppercase; LLSDNotationParser handles either; but as of
+ // 2020-05-13, Python's llbase.llsd requires uppercase hex.
+ ostr << std::uppercase;
+ auto oldfill(ostr.fill('0'));
+ auto oldwidth(ostr.width());
+ for (size_t i = 0; i < buffer.size(); i++)
+ {
+ // have to restate setw() before every conversion
+ ostr << std::setw(2) << (int) buffer[i];
+ }
+ ostr.width(oldwidth);
+ ostr.fill(oldfill);
+ ostr.flags(old_flags);
+ }
+ }
+ else // ! OPTIONS_PRETTY_BINARY
+ {
+ ostr << "b(" << buffer.size() << ")\"";
+ if (! buffer.empty())
+ {
+ ostr.write((const char*)&buffer[0], buffer.size());
+ }
+ }
+ ostr << "\"";
+ break;
+ }
+
+ default:
+ // *NOTE: This should never happen.
+ ostr << "!";
+ break;
+ }
+ return format_count;
}
/**
@@ -1538,119 +1538,119 @@ LLSDBinaryFormatter::~LLSDBinaryFormatter()
// virtual
S32 LLSDBinaryFormatter::format_impl(const LLSD& data, std::ostream& ostr,
- EFormatterOptions options, U32 level) const
+ EFormatterOptions options, U32 level) const
{
- S32 format_count = 1;
- switch(data.type())
- {
- case LLSD::TypeMap:
- {
- ostr.put('{');
- U32 size_nbo = htonl(data.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- LLSD::map_const_iterator iter = data.beginMap();
- LLSD::map_const_iterator end = data.endMap();
- for(; iter != end; ++iter)
- {
- ostr.put('k');
- formatString((*iter).first, ostr);
- format_count += format_impl((*iter).second, ostr, options, level+1);
- }
- ostr.put('}');
- break;
- }
-
- case LLSD::TypeArray:
- {
- ostr.put('[');
- U32 size_nbo = htonl(data.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- LLSD::array_const_iterator iter = data.beginArray();
- LLSD::array_const_iterator end = data.endArray();
- for(; iter != end; ++iter)
- {
- format_count += format_impl(*iter, ostr, options, level+1);
- }
- ostr.put(']');
- break;
- }
-
- case LLSD::TypeUndefined:
- ostr.put('!');
- break;
-
- case LLSD::TypeBoolean:
- if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
- else ostr.put(BINARY_FALSE_SERIAL);
- break;
-
- case LLSD::TypeInteger:
- {
- ostr.put('i');
- U32 value_nbo = htonl(data.asInteger());
- ostr.write((const char*)(&value_nbo), sizeof(U32));
- break;
- }
-
- case LLSD::TypeReal:
- {
- ostr.put('r');
- F64 value_nbo = ll_htond(data.asReal());
- ostr.write((const char*)(&value_nbo), sizeof(F64));
- break;
- }
-
- case LLSD::TypeUUID:
- {
- ostr.put('u');
- LLUUID temp = data.asUUID();
- ostr.write((const char*)(&(temp.mData)), UUID_BYTES);
- break;
- }
-
- case LLSD::TypeString:
- ostr.put('s');
- formatString(data.asStringRef(), ostr);
- break;
-
- case LLSD::TypeDate:
- {
- ostr.put('d');
- F64 value = data.asReal();
- ostr.write((const char*)(&value), sizeof(F64));
- break;
- }
-
- case LLSD::TypeURI:
- ostr.put('l');
- formatString(data.asString(), ostr);
- break;
-
- case LLSD::TypeBinary:
- {
- ostr.put('b');
- const std::vector<U8>& buffer = data.asBinary();
- U32 size_nbo = htonl(buffer.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
- break;
- }
-
- default:
- // *NOTE: This should never happen.
- ostr.put('!');
- break;
- }
- return format_count;
+ S32 format_count = 1;
+ switch(data.type())
+ {
+ case LLSD::TypeMap:
+ {
+ ostr.put('{');
+ U32 size_nbo = htonl(data.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ LLSD::map_const_iterator iter = data.beginMap();
+ LLSD::map_const_iterator end = data.endMap();
+ for(; iter != end; ++iter)
+ {
+ ostr.put('k');
+ formatString((*iter).first, ostr);
+ format_count += format_impl((*iter).second, ostr, options, level+1);
+ }
+ ostr.put('}');
+ break;
+ }
+
+ case LLSD::TypeArray:
+ {
+ ostr.put('[');
+ U32 size_nbo = htonl(data.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ LLSD::array_const_iterator iter = data.beginArray();
+ LLSD::array_const_iterator end = data.endArray();
+ for(; iter != end; ++iter)
+ {
+ format_count += format_impl(*iter, ostr, options, level+1);
+ }
+ ostr.put(']');
+ break;
+ }
+
+ case LLSD::TypeUndefined:
+ ostr.put('!');
+ break;
+
+ case LLSD::TypeBoolean:
+ if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
+ else ostr.put(BINARY_FALSE_SERIAL);
+ break;
+
+ case LLSD::TypeInteger:
+ {
+ ostr.put('i');
+ U32 value_nbo = htonl(data.asInteger());
+ ostr.write((const char*)(&value_nbo), sizeof(U32));
+ break;
+ }
+
+ case LLSD::TypeReal:
+ {
+ ostr.put('r');
+ F64 value_nbo = ll_htond(data.asReal());
+ ostr.write((const char*)(&value_nbo), sizeof(F64));
+ break;
+ }
+
+ case LLSD::TypeUUID:
+ {
+ ostr.put('u');
+ LLUUID temp = data.asUUID();
+ ostr.write((const char*)(&(temp.mData)), UUID_BYTES);
+ break;
+ }
+
+ case LLSD::TypeString:
+ ostr.put('s');
+ formatString(data.asStringRef(), ostr);
+ break;
+
+ case LLSD::TypeDate:
+ {
+ ostr.put('d');
+ F64 value = data.asReal();
+ ostr.write((const char*)(&value), sizeof(F64));
+ break;
+ }
+
+ case LLSD::TypeURI:
+ ostr.put('l');
+ formatString(data.asString(), ostr);
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ ostr.put('b');
+ const std::vector<U8>& buffer = data.asBinary();
+ U32 size_nbo = htonl(buffer.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
+ break;
+ }
+
+ default:
+ // *NOTE: This should never happen.
+ ostr.put('!');
+ break;
+ }
+ return format_count;
}
void LLSDBinaryFormatter::formatString(
- const std::string& string,
- std::ostream& ostr) const
+ const std::string& string,
+ std::ostream& ostr) const
{
- U32 size_nbo = htonl(string.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- ostr.write(string.c_str(), string.size());
+ U32 size_nbo = htonl(string.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ ostr.write(string.c_str(), string.size());
}
/**
@@ -1658,491 +1658,491 @@ void LLSDBinaryFormatter::formatString(
*/
llssize deserialize_string(std::istream& istr, std::string& value, llssize max_bytes)
{
- int c = istr.get();
- if(istr.fail())
- {
- // No data in stream, bail out but mention the character we
- // grabbed.
- return LLSDParser::PARSE_FAILURE;
- }
-
- llssize rv = LLSDParser::PARSE_FAILURE;
- switch(c)
- {
- case '\'':
- case '"':
- rv = deserialize_string_delim(istr, value, c);
- break;
- case 's':
- // technically, less than max_bytes, but this is just meant to
- // catch egregious protocol errors. parse errors will be
- // caught in the case of incorrect counts.
- rv = deserialize_string_raw(istr, value, max_bytes);
- break;
- default:
- break;
- }
- if(LLSDParser::PARSE_FAILURE == rv) return rv;
- return rv + 1; // account for the character grabbed at the top.
+ int c = istr.get();
+ if(istr.fail())
+ {
+ // No data in stream, bail out but mention the character we
+ // grabbed.
+ return LLSDParser::PARSE_FAILURE;
+ }
+
+ llssize rv = LLSDParser::PARSE_FAILURE;
+ switch(c)
+ {
+ case '\'':
+ case '"':
+ rv = deserialize_string_delim(istr, value, c);
+ break;
+ case 's':
+ // technically, less than max_bytes, but this is just meant to
+ // catch egregious protocol errors. parse errors will be
+ // caught in the case of incorrect counts.
+ rv = deserialize_string_raw(istr, value, max_bytes);
+ break;
+ default:
+ break;
+ }
+ if(LLSDParser::PARSE_FAILURE == rv) return rv;
+ return rv + 1; // account for the character grabbed at the top.
}
llssize deserialize_string_delim(
- std::istream& istr,
- std::string& value,
- char delim)
+ std::istream& istr,
+ std::string& value,
+ char delim)
{
- std::ostringstream write_buffer;
- bool found_escape = false;
- bool found_hex = false;
- bool found_digit = false;
- U8 byte = 0;
- llssize count = 0;
-
- while (true)
- {
- int next_byte = istr.get();
- ++count;
-
- if(istr.fail())
- {
- // If our stream is empty, break out
- value = write_buffer.str();
- return LLSDParser::PARSE_FAILURE;
- }
-
- char next_char = (char)next_byte; // Now that we know it's not EOF
-
- if(found_escape)
- {
- // next character(s) is a special sequence.
- if(found_hex)
- {
- if(found_digit)
- {
- found_digit = false;
- found_hex = false;
- found_escape = false;
- byte = byte << 4;
- byte |= hex_as_nybble(next_char);
- write_buffer << byte;
- byte = 0;
- }
- else
- {
- // next character is the first nybble of
- //
- found_digit = true;
- byte = hex_as_nybble(next_char);
- }
- }
- else if(next_char == 'x')
- {
- found_hex = true;
- }
- else
- {
- switch(next_char)
- {
- case 'a':
- write_buffer << '\a';
- break;
- case 'b':
- write_buffer << '\b';
- break;
- case 'f':
- write_buffer << '\f';
- break;
- case 'n':
- write_buffer << '\n';
- break;
- case 'r':
- write_buffer << '\r';
- break;
- case 't':
- write_buffer << '\t';
- break;
- case 'v':
- write_buffer << '\v';
- break;
- default:
- write_buffer << next_char;
- break;
- }
- found_escape = false;
- }
- }
- else if(next_char == '\\')
- {
- found_escape = true;
- }
- else if(next_char == delim)
- {
- break;
- }
- else
- {
- write_buffer << next_char;
- }
- }
-
- value = write_buffer.str();
- return count;
+ std::ostringstream write_buffer;
+ bool found_escape = false;
+ bool found_hex = false;
+ bool found_digit = false;
+ U8 byte = 0;
+ llssize count = 0;
+
+ while (true)
+ {
+ int next_byte = istr.get();
+ ++count;
+
+ if(istr.fail())
+ {
+ // If our stream is empty, break out
+ value = write_buffer.str();
+ return LLSDParser::PARSE_FAILURE;
+ }
+
+ char next_char = (char)next_byte; // Now that we know it's not EOF
+
+ if(found_escape)
+ {
+ // next character(s) is a special sequence.
+ if(found_hex)
+ {
+ if(found_digit)
+ {
+ found_digit = false;
+ found_hex = false;
+ found_escape = false;
+ byte = byte << 4;
+ byte |= hex_as_nybble(next_char);
+ write_buffer << byte;
+ byte = 0;
+ }
+ else
+ {
+ // next character is the first nybble of
+ //
+ found_digit = true;
+ byte = hex_as_nybble(next_char);
+ }
+ }
+ else if(next_char == 'x')
+ {
+ found_hex = true;
+ }
+ else
+ {
+ switch(next_char)
+ {
+ case 'a':
+ write_buffer << '\a';
+ break;
+ case 'b':
+ write_buffer << '\b';
+ break;
+ case 'f':
+ write_buffer << '\f';
+ break;
+ case 'n':
+ write_buffer << '\n';
+ break;
+ case 'r':
+ write_buffer << '\r';
+ break;
+ case 't':
+ write_buffer << '\t';
+ break;
+ case 'v':
+ write_buffer << '\v';
+ break;
+ default:
+ write_buffer << next_char;
+ break;
+ }
+ found_escape = false;
+ }
+ }
+ else if(next_char == '\\')
+ {
+ found_escape = true;
+ }
+ else if(next_char == delim)
+ {
+ break;
+ }
+ else
+ {
+ write_buffer << next_char;
+ }
+ }
+
+ value = write_buffer.str();
+ return count;
}
llssize deserialize_string_raw(
- std::istream& istr,
- std::string& value,
- llssize max_bytes)
+ std::istream& istr,
+ std::string& value,
+ llssize max_bytes)
{
- llssize count = 0;
- const S32 BUF_LEN = 20;
- char buf[BUF_LEN]; /* Flawfinder: ignore */
- istr.get(buf, BUF_LEN - 1, ')');
- count += istr.gcount();
- int c = istr.get();
- c = istr.get();
- count += 2;
- if(((c == '"') || (c == '\'')) && (buf[0] == '('))
- {
- // We probably have a valid raw string. determine
- // the size, and read it.
- // *FIX: This is memory inefficient.
- auto len = strtol(buf + 1, NULL, 0);
- if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
- std::vector<char> buf;
- if(len)
- {
- buf.resize(len);
- count += fullread(istr, (char *)&buf[0], len);
- value.assign(buf.begin(), buf.end());
- }
- c = istr.get();
- ++count;
- if(!((c == '"') || (c == '\'')))
- {
- return LLSDParser::PARSE_FAILURE;
- }
- }
- else
- {
- return LLSDParser::PARSE_FAILURE;
- }
- return count;
+ llssize count = 0;
+ const S32 BUF_LEN = 20;
+ char buf[BUF_LEN]; /* Flawfinder: ignore */
+ istr.get(buf, BUF_LEN - 1, ')');
+ count += istr.gcount();
+ int c = istr.get();
+ c = istr.get();
+ count += 2;
+ if(((c == '"') || (c == '\'')) && (buf[0] == '('))
+ {
+ // We probably have a valid raw string. determine
+ // the size, and read it.
+ // *FIX: This is memory inefficient.
+ auto len = strtol(buf + 1, NULL, 0);
+ if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
+ std::vector<char> buf;
+ if(len)
+ {
+ buf.resize(len);
+ count += fullread(istr, (char *)&buf[0], len);
+ value.assign(buf.begin(), buf.end());
+ }
+ c = istr.get();
+ ++count;
+ if(!((c == '"') || (c == '\'')))
+ {
+ return LLSDParser::PARSE_FAILURE;
+ }
+ }
+ else
+ {
+ return LLSDParser::PARSE_FAILURE;
+ }
+ return count;
}
static const char* NOTATION_STRING_CHARACTERS[256] =
{
- "\\x00", // 0
- "\\x01", // 1
- "\\x02", // 2
- "\\x03", // 3
- "\\x04", // 4
- "\\x05", // 5
- "\\x06", // 6
- "\\a", // 7
- "\\b", // 8
- "\\t", // 9
- "\\n", // 10
- "\\v", // 11
- "\\f", // 12
- "\\r", // 13
- "\\x0e", // 14
- "\\x0f", // 15
- "\\x10", // 16
- "\\x11", // 17
- "\\x12", // 18
- "\\x13", // 19
- "\\x14", // 20
- "\\x15", // 21
- "\\x16", // 22
- "\\x17", // 23
- "\\x18", // 24
- "\\x19", // 25
- "\\x1a", // 26
- "\\x1b", // 27
- "\\x1c", // 28
- "\\x1d", // 29
- "\\x1e", // 30
- "\\x1f", // 31
- " ", // 32
- "!", // 33
- "\"", // 34
- "#", // 35
- "$", // 36
- "%", // 37
- "&", // 38
- "\\'", // 39
- "(", // 40
- ")", // 41
- "*", // 42
- "+", // 43
- ",", // 44
- "-", // 45
- ".", // 46
- "/", // 47
- "0", // 48
- "1", // 49
- "2", // 50
- "3", // 51
- "4", // 52
- "5", // 53
- "6", // 54
- "7", // 55
- "8", // 56
- "9", // 57
- ":", // 58
- ";", // 59
- "<", // 60
- "=", // 61
- ">", // 62
- "?", // 63
- "@", // 64
- "A", // 65
- "B", // 66
- "C", // 67
- "D", // 68
- "E", // 69
- "F", // 70
- "G", // 71
- "H", // 72
- "I", // 73
- "J", // 74
- "K", // 75
- "L", // 76
- "M", // 77
- "N", // 78
- "O", // 79
- "P", // 80
- "Q", // 81
- "R", // 82
- "S", // 83
- "T", // 84
- "U", // 85
- "V", // 86
- "W", // 87
- "X", // 88
- "Y", // 89
- "Z", // 90
- "[", // 91
- "\\\\", // 92
- "]", // 93
- "^", // 94
- "_", // 95
- "`", // 96
- "a", // 97
- "b", // 98
- "c", // 99
- "d", // 100
- "e", // 101
- "f", // 102
- "g", // 103
- "h", // 104
- "i", // 105
- "j", // 106
- "k", // 107
- "l", // 108
- "m", // 109
- "n", // 110
- "o", // 111
- "p", // 112
- "q", // 113
- "r", // 114
- "s", // 115
- "t", // 116
- "u", // 117
- "v", // 118
- "w", // 119
- "x", // 120
- "y", // 121
- "z", // 122
- "{", // 123
- "|", // 124
- "}", // 125
- "~", // 126
- "\\x7f", // 127
- "\\x80", // 128
- "\\x81", // 129
- "\\x82", // 130
- "\\x83", // 131
- "\\x84", // 132
- "\\x85", // 133
- "\\x86", // 134
- "\\x87", // 135
- "\\x88", // 136
- "\\x89", // 137
- "\\x8a", // 138
- "\\x8b", // 139
- "\\x8c", // 140
- "\\x8d", // 141
- "\\x8e", // 142
- "\\x8f", // 143
- "\\x90", // 144
- "\\x91", // 145
- "\\x92", // 146
- "\\x93", // 147
- "\\x94", // 148
- "\\x95", // 149
- "\\x96", // 150
- "\\x97", // 151
- "\\x98", // 152
- "\\x99", // 153
- "\\x9a", // 154
- "\\x9b", // 155
- "\\x9c", // 156
- "\\x9d", // 157
- "\\x9e", // 158
- "\\x9f", // 159
- "\\xa0", // 160
- "\\xa1", // 161
- "\\xa2", // 162
- "\\xa3", // 163
- "\\xa4", // 164
- "\\xa5", // 165
- "\\xa6", // 166
- "\\xa7", // 167
- "\\xa8", // 168
- "\\xa9", // 169
- "\\xaa", // 170
- "\\xab", // 171
- "\\xac", // 172
- "\\xad", // 173
- "\\xae", // 174
- "\\xaf", // 175
- "\\xb0", // 176
- "\\xb1", // 177
- "\\xb2", // 178
- "\\xb3", // 179
- "\\xb4", // 180
- "\\xb5", // 181
- "\\xb6", // 182
- "\\xb7", // 183
- "\\xb8", // 184
- "\\xb9", // 185
- "\\xba", // 186
- "\\xbb", // 187
- "\\xbc", // 188
- "\\xbd", // 189
- "\\xbe", // 190
- "\\xbf", // 191
- "\\xc0", // 192
- "\\xc1", // 193
- "\\xc2", // 194
- "\\xc3", // 195
- "\\xc4", // 196
- "\\xc5", // 197
- "\\xc6", // 198
- "\\xc7", // 199
- "\\xc8", // 200
- "\\xc9", // 201
- "\\xca", // 202
- "\\xcb", // 203
- "\\xcc", // 204
- "\\xcd", // 205
- "\\xce", // 206
- "\\xcf", // 207
- "\\xd0", // 208
- "\\xd1", // 209
- "\\xd2", // 210
- "\\xd3", // 211
- "\\xd4", // 212
- "\\xd5", // 213
- "\\xd6", // 214
- "\\xd7", // 215
- "\\xd8", // 216
- "\\xd9", // 217
- "\\xda", // 218
- "\\xdb", // 219
- "\\xdc", // 220
- "\\xdd", // 221
- "\\xde", // 222
- "\\xdf", // 223
- "\\xe0", // 224
- "\\xe1", // 225
- "\\xe2", // 226
- "\\xe3", // 227
- "\\xe4", // 228
- "\\xe5", // 229
- "\\xe6", // 230
- "\\xe7", // 231
- "\\xe8", // 232
- "\\xe9", // 233
- "\\xea", // 234
- "\\xeb", // 235
- "\\xec", // 236
- "\\xed", // 237
- "\\xee", // 238
- "\\xef", // 239
- "\\xf0", // 240
- "\\xf1", // 241
- "\\xf2", // 242
- "\\xf3", // 243
- "\\xf4", // 244
- "\\xf5", // 245
- "\\xf6", // 246
- "\\xf7", // 247
- "\\xf8", // 248
- "\\xf9", // 249
- "\\xfa", // 250
- "\\xfb", // 251
- "\\xfc", // 252
- "\\xfd", // 253
- "\\xfe", // 254
- "\\xff" // 255
+ "\\x00", // 0
+ "\\x01", // 1
+ "\\x02", // 2
+ "\\x03", // 3
+ "\\x04", // 4
+ "\\x05", // 5
+ "\\x06", // 6
+ "\\a", // 7
+ "\\b", // 8
+ "\\t", // 9
+ "\\n", // 10
+ "\\v", // 11
+ "\\f", // 12
+ "\\r", // 13
+ "\\x0e", // 14
+ "\\x0f", // 15
+ "\\x10", // 16
+ "\\x11", // 17
+ "\\x12", // 18
+ "\\x13", // 19
+ "\\x14", // 20
+ "\\x15", // 21
+ "\\x16", // 22
+ "\\x17", // 23
+ "\\x18", // 24
+ "\\x19", // 25
+ "\\x1a", // 26
+ "\\x1b", // 27
+ "\\x1c", // 28
+ "\\x1d", // 29
+ "\\x1e", // 30
+ "\\x1f", // 31
+ " ", // 32
+ "!", // 33
+ "\"", // 34
+ "#", // 35
+ "$", // 36
+ "%", // 37
+ "&", // 38
+ "\\'", // 39
+ "(", // 40
+ ")", // 41
+ "*", // 42
+ "+", // 43
+ ",", // 44
+ "-", // 45
+ ".", // 46
+ "/", // 47
+ "0", // 48
+ "1", // 49
+ "2", // 50
+ "3", // 51
+ "4", // 52
+ "5", // 53
+ "6", // 54
+ "7", // 55
+ "8", // 56
+ "9", // 57
+ ":", // 58
+ ";", // 59
+ "<", // 60
+ "=", // 61
+ ">", // 62
+ "?", // 63
+ "@", // 64
+ "A", // 65
+ "B", // 66
+ "C", // 67
+ "D", // 68
+ "E", // 69
+ "F", // 70
+ "G", // 71
+ "H", // 72
+ "I", // 73
+ "J", // 74
+ "K", // 75
+ "L", // 76
+ "M", // 77
+ "N", // 78
+ "O", // 79
+ "P", // 80
+ "Q", // 81
+ "R", // 82
+ "S", // 83
+ "T", // 84
+ "U", // 85
+ "V", // 86
+ "W", // 87
+ "X", // 88
+ "Y", // 89
+ "Z", // 90
+ "[", // 91
+ "\\\\", // 92
+ "]", // 93
+ "^", // 94
+ "_", // 95
+ "`", // 96
+ "a", // 97
+ "b", // 98
+ "c", // 99
+ "d", // 100
+ "e", // 101
+ "f", // 102
+ "g", // 103
+ "h", // 104
+ "i", // 105
+ "j", // 106
+ "k", // 107
+ "l", // 108
+ "m", // 109
+ "n", // 110
+ "o", // 111
+ "p", // 112
+ "q", // 113
+ "r", // 114
+ "s", // 115
+ "t", // 116
+ "u", // 117
+ "v", // 118
+ "w", // 119
+ "x", // 120
+ "y", // 121
+ "z", // 122
+ "{", // 123
+ "|", // 124
+ "}", // 125
+ "~", // 126
+ "\\x7f", // 127
+ "\\x80", // 128
+ "\\x81", // 129
+ "\\x82", // 130
+ "\\x83", // 131
+ "\\x84", // 132
+ "\\x85", // 133
+ "\\x86", // 134
+ "\\x87", // 135
+ "\\x88", // 136
+ "\\x89", // 137
+ "\\x8a", // 138
+ "\\x8b", // 139
+ "\\x8c", // 140
+ "\\x8d", // 141
+ "\\x8e", // 142
+ "\\x8f", // 143
+ "\\x90", // 144
+ "\\x91", // 145
+ "\\x92", // 146
+ "\\x93", // 147
+ "\\x94", // 148
+ "\\x95", // 149
+ "\\x96", // 150
+ "\\x97", // 151
+ "\\x98", // 152
+ "\\x99", // 153
+ "\\x9a", // 154
+ "\\x9b", // 155
+ "\\x9c", // 156
+ "\\x9d", // 157
+ "\\x9e", // 158
+ "\\x9f", // 159
+ "\\xa0", // 160
+ "\\xa1", // 161
+ "\\xa2", // 162
+ "\\xa3", // 163
+ "\\xa4", // 164
+ "\\xa5", // 165
+ "\\xa6", // 166
+ "\\xa7", // 167
+ "\\xa8", // 168
+ "\\xa9", // 169
+ "\\xaa", // 170
+ "\\xab", // 171
+ "\\xac", // 172
+ "\\xad", // 173
+ "\\xae", // 174
+ "\\xaf", // 175
+ "\\xb0", // 176
+ "\\xb1", // 177
+ "\\xb2", // 178
+ "\\xb3", // 179
+ "\\xb4", // 180
+ "\\xb5", // 181
+ "\\xb6", // 182
+ "\\xb7", // 183
+ "\\xb8", // 184
+ "\\xb9", // 185
+ "\\xba", // 186
+ "\\xbb", // 187
+ "\\xbc", // 188
+ "\\xbd", // 189
+ "\\xbe", // 190
+ "\\xbf", // 191
+ "\\xc0", // 192
+ "\\xc1", // 193
+ "\\xc2", // 194
+ "\\xc3", // 195
+ "\\xc4", // 196
+ "\\xc5", // 197
+ "\\xc6", // 198
+ "\\xc7", // 199
+ "\\xc8", // 200
+ "\\xc9", // 201
+ "\\xca", // 202
+ "\\xcb", // 203
+ "\\xcc", // 204
+ "\\xcd", // 205
+ "\\xce", // 206
+ "\\xcf", // 207
+ "\\xd0", // 208
+ "\\xd1", // 209
+ "\\xd2", // 210
+ "\\xd3", // 211
+ "\\xd4", // 212
+ "\\xd5", // 213
+ "\\xd6", // 214
+ "\\xd7", // 215
+ "\\xd8", // 216
+ "\\xd9", // 217
+ "\\xda", // 218
+ "\\xdb", // 219
+ "\\xdc", // 220
+ "\\xdd", // 221
+ "\\xde", // 222
+ "\\xdf", // 223
+ "\\xe0", // 224
+ "\\xe1", // 225
+ "\\xe2", // 226
+ "\\xe3", // 227
+ "\\xe4", // 228
+ "\\xe5", // 229
+ "\\xe6", // 230
+ "\\xe7", // 231
+ "\\xe8", // 232
+ "\\xe9", // 233
+ "\\xea", // 234
+ "\\xeb", // 235
+ "\\xec", // 236
+ "\\xed", // 237
+ "\\xee", // 238
+ "\\xef", // 239
+ "\\xf0", // 240
+ "\\xf1", // 241
+ "\\xf2", // 242
+ "\\xf3", // 243
+ "\\xf4", // 244
+ "\\xf5", // 245
+ "\\xf6", // 246
+ "\\xf7", // 247
+ "\\xf8", // 248
+ "\\xf9", // 249
+ "\\xfa", // 250
+ "\\xfb", // 251
+ "\\xfc", // 252
+ "\\xfd", // 253
+ "\\xfe", // 254
+ "\\xff" // 255
};
void serialize_string(const std::string& value, std::ostream& str)
{
- std::string::const_iterator it = value.begin();
- std::string::const_iterator end = value.end();
- U8 c;
- for(; it != end; ++it)
- {
- c = (U8)(*it);
- str << NOTATION_STRING_CHARACTERS[c];
- }
+ std::string::const_iterator it = value.begin();
+ std::string::const_iterator end = value.end();
+ U8 c;
+ for(; it != end; ++it)
+ {
+ c = (U8)(*it);
+ str << NOTATION_STRING_CHARACTERS[c];
+ }
}
llssize deserialize_boolean(
- std::istream& istr,
- LLSD& data,
- const std::string& compare,
- bool value)
+ std::istream& istr,
+ LLSD& data,
+ const std::string& compare,
+ bool value)
{
- //
- // this method is a little goofy, because it gets the stream at
- // the point where the t or f has already been
- // consumed. Basically, parse for a patch to the string passed in
- // starting at index 1. If it's a match:
- // * assign data to value
- // * return the number of bytes read
- // otherwise:
- // * set data to LLSD::null
- // * return LLSDParser::PARSE_FAILURE (-1)
- //
- llssize bytes_read = 0;
- std::string::size_type ii = 0;
- char c = istr.peek();
- while((++ii < compare.size())
- && (tolower(c) == (int)compare[ii])
- && istr.good())
- {
- istr.ignore();
- ++bytes_read;
- c = istr.peek();
- }
- if(compare.size() != ii)
- {
- data.clear();
- return LLSDParser::PARSE_FAILURE;
- }
- data = value;
- return bytes_read;
+ //
+ // this method is a little goofy, because it gets the stream at
+ // the point where the t or f has already been
+ // consumed. Basically, parse for a patch to the string passed in
+ // starting at index 1. If it's a match:
+ // * assign data to value
+ // * return the number of bytes read
+ // otherwise:
+ // * set data to LLSD::null
+ // * return LLSDParser::PARSE_FAILURE (-1)
+ //
+ llssize bytes_read = 0;
+ std::string::size_type ii = 0;
+ char c = istr.peek();
+ while((++ii < compare.size())
+ && (tolower(c) == (int)compare[ii])
+ && istr.good())
+ {
+ istr.ignore();
+ ++bytes_read;
+ c = istr.peek();
+ }
+ if(compare.size() != ii)
+ {
+ data.clear();
+ return LLSDParser::PARSE_FAILURE;
+ }
+ data = value;
+ return bytes_read;
}
std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
{
- s << LLSDNotationStreamer(llsd);
- return s;
+ s << LLSDNotationStreamer(llsd);
+ return s;
}
@@ -2151,89 +2151,89 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
//return a string containing gzipped bytes of binary serialized LLSD
// VERY inefficient -- creates several copies of LLSD block in memory
std::string zip_llsd(LLSD& data)
-{
- std::stringstream llsd_strm;
-
- LLSDSerialize::toBinary(data, llsd_strm);
-
- const U32 CHUNK = 65536;
-
- z_stream strm;
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
-
- S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
- if (ret != Z_OK)
- {
- LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
- return std::string();
- }
-
- std::string source = llsd_strm.str();
-
- U8 out[CHUNK];
-
- strm.avail_in = narrow<size_t>(source.size());
- strm.next_in = (U8*) source.data();
- U8* output = NULL;
-
- U32 cur_size = 0;
-
- U32 have = 0;
-
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out;
-
- ret = deflate(&strm, Z_FINISH);
- if (ret == Z_OK || ret == Z_STREAM_END)
- { //copy result into output
- if (strm.avail_out >= CHUNK)
- {
- deflateEnd(&strm);
- if(output)
- free(output);
- LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
- return std::string();
- }
-
- have = CHUNK-strm.avail_out;
- U8* new_output = (U8*) realloc(output, cur_size+have);
- if (new_output == NULL)
- {
- LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
- deflateEnd(&strm);
- if (output)
- {
- free(output);
- }
- return std::string();
- }
- output = new_output;
- memcpy(output+cur_size, out, have);
- cur_size += have;
- }
- else
- {
- deflateEnd(&strm);
- if(output)
- free(output);
- LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
- return std::string();
- }
- }
- while (ret == Z_OK);
-
- std::string::size_type size = cur_size;
-
- std::string result((char*) output, size);
- deflateEnd(&strm);
- if(output)
- free(output);
-
- return result;
+{
+ std::stringstream llsd_strm;
+
+ LLSDSerialize::toBinary(data, llsd_strm);
+
+ const U32 CHUNK = 65536;
+
+ z_stream strm;
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
+ if (ret != Z_OK)
+ {
+ LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
+ return std::string();
+ }
+
+ std::string source = llsd_strm.str();
+
+ U8 out[CHUNK];
+
+ strm.avail_in = narrow<size_t>(source.size());
+ strm.next_in = (U8*) source.data();
+ U8* output = NULL;
+
+ U32 cur_size = 0;
+
+ U32 have = 0;
+
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+
+ ret = deflate(&strm, Z_FINISH);
+ if (ret == Z_OK || ret == Z_STREAM_END)
+ { //copy result into output
+ if (strm.avail_out >= CHUNK)
+ {
+ deflateEnd(&strm);
+ if(output)
+ free(output);
+ LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
+ return std::string();
+ }
+
+ have = CHUNK-strm.avail_out;
+ U8* new_output = (U8*) realloc(output, cur_size+have);
+ if (new_output == NULL)
+ {
+ LL_WARNS() << "Failed to compress LLSD block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have << " bytes." << LL_ENDL;
+ deflateEnd(&strm);
+ if (output)
+ {
+ free(output);
+ }
+ return std::string();
+ }
+ output = new_output;
+ memcpy(output+cur_size, out, have);
+ cur_size += have;
+ }
+ else
+ {
+ deflateEnd(&strm);
+ if(output)
+ free(output);
+ LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
+ return std::string();
+ }
+ }
+ while (ret == Z_OK);
+
+ std::string::size_type size = cur_size;
+
+ std::string result((char*) output, size);
+ deflateEnd(&strm);
+ if(output)
+ free(output);
+
+ return result;
}
//decompress a block of LLSD from provided istream
@@ -2241,230 +2241,230 @@ std::string zip_llsd(LLSD& data)
// and deserializes from that copy using LLSDSerialize
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size)
{
- std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]);
- if (!in)
- {
- return ZR_MEM_ERROR;
- }
- is.read((char*) in.get(), size);
-
- return unzip_llsd(data, in.get(), size);
+ std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]);
+ if (!in)
+ {
+ return ZR_MEM_ERROR;
+ }
+ is.read((char*) in.get(), size);
+
+ return unzip_llsd(data, in.get(), size);
}
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size)
{
- U8* result = NULL;
- llssize cur_size = 0;
- z_stream strm;
-
- constexpr U32 CHUNK = 1024 * 512;
-
- static thread_local std::unique_ptr<U8[]> out;
- if (!out)
- {
- out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);
- }
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = size;
- strm.next_in = const_cast<U8*>(in);
-
- S32 ret = inflateInit(&strm);
-
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out.get();
- ret = inflate(&strm, Z_NO_FLUSH);
- switch (ret)
- {
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- {
- inflateEnd(&strm);
- free(result);
- return ZR_DATA_ERROR;
- }
- case Z_STREAM_ERROR:
- case Z_BUF_ERROR:
- {
- inflateEnd(&strm);
- free(result);
- return ZR_BUFFER_ERROR;
- }
-
- case Z_MEM_ERROR:
- {
- inflateEnd(&strm);
- free(result);
- return ZR_MEM_ERROR;
- }
- }
-
- U32 have = CHUNK-strm.avail_out;
-
- U8* new_result = (U8*)realloc(result, cur_size + have);
- if (new_result == NULL)
- {
- inflateEnd(&strm);
- if (result)
- {
- free(result);
- }
- return ZR_MEM_ERROR;
- }
- result = new_result;
- memcpy(result+cur_size, out.get(), have);
- cur_size += have;
-
- } while (ret == Z_OK && ret != Z_STREAM_END);
-
- inflateEnd(&strm);
-
- if (ret != Z_STREAM_END)
- {
- free(result);
- return ZR_DATA_ERROR;
- }
-
- //result now points to the decompressed LLSD block
- {
- char* result_ptr = strip_deprecated_header((char*)result, cur_size);
-
- boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size);
-
- if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))
- {
- free(result);
- return ZR_PARSE_ERROR;
- }
- }
-
- free(result);
- return ZR_OK;
+ U8* result = NULL;
+ llssize cur_size = 0;
+ z_stream strm;
+
+ constexpr U32 CHUNK = 1024 * 512;
+
+ static thread_local std::unique_ptr<U8[]> out;
+ if (!out)
+ {
+ out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);
+ }
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = size;
+ strm.next_in = const_cast<U8*>(in);
+
+ S32 ret = inflateInit(&strm);
+
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out.get();
+ ret = inflate(&strm, Z_NO_FLUSH);
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ case Z_DATA_ERROR:
+ {
+ inflateEnd(&strm);
+ free(result);
+ return ZR_DATA_ERROR;
+ }
+ case Z_STREAM_ERROR:
+ case Z_BUF_ERROR:
+ {
+ inflateEnd(&strm);
+ free(result);
+ return ZR_BUFFER_ERROR;
+ }
+
+ case Z_MEM_ERROR:
+ {
+ inflateEnd(&strm);
+ free(result);
+ return ZR_MEM_ERROR;
+ }
+ }
+
+ U32 have = CHUNK-strm.avail_out;
+
+ U8* new_result = (U8*)realloc(result, cur_size + have);
+ if (new_result == NULL)
+ {
+ inflateEnd(&strm);
+ if (result)
+ {
+ free(result);
+ }
+ return ZR_MEM_ERROR;
+ }
+ result = new_result;
+ memcpy(result+cur_size, out.get(), have);
+ cur_size += have;
+
+ } while (ret == Z_OK && ret != Z_STREAM_END);
+
+ inflateEnd(&strm);
+
+ if (ret != Z_STREAM_END)
+ {
+ free(result);
+ return ZR_DATA_ERROR;
+ }
+
+ //result now points to the decompressed LLSD block
+ {
+ char* result_ptr = strip_deprecated_header((char*)result, cur_size);
+
+ boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size);
+
+ if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))
+ {
+ free(result);
+ return ZR_PARSE_ERROR;
+ }
+ }
+
+ free(result);
+ return ZR_OK;
}
//This unzip function will only work with a gzip header and trailer - while the contents
//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
//and trailers are different for the formats.
U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size )
{
- if (size == 0)
- {
- LL_WARNS() << "No data to unzip." << LL_ENDL;
- return NULL;
- }
-
- U8* result = NULL;
- U32 cur_size = 0;
- z_stream strm;
-
- const U32 CHUNK = 0x4000;
-
- U8 *in = new(std::nothrow) U8[size];
- if (in == NULL)
- {
- LL_WARNS() << "Memory allocation failure." << LL_ENDL;
- return NULL;
- }
- is.read((char*) in, size);
-
- U8 out[CHUNK];
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = size;
- strm.next_in = in;
-
-
- S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out;
- ret = inflate(&strm, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR)
- {
- inflateEnd(&strm);
- free(result);
- delete [] in;
- valid = false;
- }
-
- switch (ret)
- {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- inflateEnd(&strm);
- free(result);
- delete [] in;
- valid = false;
- break;
- }
-
- U32 have = CHUNK-strm.avail_out;
-
- U8* new_result = (U8*) realloc(result, cur_size + have);
- if (new_result == NULL)
- {
- LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
- << " bytes; requested " << cur_size + have
- << " bytes; total syze: ." << size << " bytes."
- << LL_ENDL;
- inflateEnd(&strm);
- if (result)
- {
- free(result);
- }
- delete[] in;
- valid = false;
- return NULL;
- }
- result = new_result;
- memcpy(result+cur_size, out, have);
- cur_size += have;
-
- } while (ret == Z_OK);
-
- inflateEnd(&strm);
- delete [] in;
-
- if (ret != Z_STREAM_END)
- {
- free(result);
- valid = false;
- return NULL;
- }
-
- //result now points to the decompressed LLSD block
- {
- outsize= cur_size;
- valid = true;
- }
-
- return result;
+ if (size == 0)
+ {
+ LL_WARNS() << "No data to unzip." << LL_ENDL;
+ return NULL;
+ }
+
+ U8* result = NULL;
+ U32 cur_size = 0;
+ z_stream strm;
+
+ const U32 CHUNK = 0x4000;
+
+ U8 *in = new(std::nothrow) U8[size];
+ if (in == NULL)
+ {
+ LL_WARNS() << "Memory allocation failure." << LL_ENDL;
+ return NULL;
+ }
+ is.read((char*) in, size);
+
+ U8 out[CHUNK];
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = size;
+ strm.next_in = in;
+
+
+ S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR)
+ {
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ valid = false;
+ }
+
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ valid = false;
+ break;
+ }
+
+ U32 have = CHUNK-strm.avail_out;
+
+ U8* new_result = (U8*) realloc(result, cur_size + have);
+ if (new_result == NULL)
+ {
+ LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
+ << " bytes; requested " << cur_size + have
+ << " bytes; total syze: ." << size << " bytes."
+ << LL_ENDL;
+ inflateEnd(&strm);
+ if (result)
+ {
+ free(result);
+ }
+ delete[] in;
+ valid = false;
+ return NULL;
+ }
+ result = new_result;
+ memcpy(result+cur_size, out, have);
+ cur_size += have;
+
+ } while (ret == Z_OK);
+
+ inflateEnd(&strm);
+ delete [] in;
+
+ if (ret != Z_STREAM_END)
+ {
+ free(result);
+ valid = false;
+ return NULL;
+ }
+
+ //result now points to the decompressed LLSD block
+ {
+ outsize= cur_size;
+ valid = true;
+ }
+
+ return result;
}
char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size)
{
- const char* deprecated_header = "<? LLSD/Binary ?>";
- constexpr size_t deprecated_header_size = 17;
-
- if (cur_size > deprecated_header_size
- && memcmp(in, deprecated_header, deprecated_header_size) == 0)
- {
- in = in + deprecated_header_size;
- cur_size = cur_size - deprecated_header_size;
- if (header_size)
- {
- *header_size = deprecated_header_size + 1;
- }
- }
-
- return in;
+ const char* deprecated_header = "<? LLSD/Binary ?>";
+ constexpr size_t deprecated_header_size = 17;
+
+ if (cur_size > deprecated_header_size
+ && memcmp(in, deprecated_header, deprecated_header_size) == 0)
+ {
+ in = in + deprecated_header_size;
+ cur_size = cur_size - deprecated_header_size;
+ if (header_size)
+ {
+ *header_size = deprecated_header_size + 1;
+ }
+ }
+
+ return in;
}
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 676b7bfd6a..12dd3c96ec 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdserialize.h
* @author Phoenix
* @date 2006-02-26
@@ -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$
*/
@@ -34,574 +34,574 @@
#include "llrefcount.h"
#include "llsd.h"
-/**
+/**
* @class LLSDParser
* @brief Abstract base class for LLSD parsers.
*/
class LL_COMMON_API LLSDParser : public LLRefCount
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDParser();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDParser();
public:
- /**
- * @brief Anonymous enum to indicate parsing failure.
- */
- enum
- {
- PARSE_FAILURE = -1
- };
-
- /**
- * @brief Constructor
- */
- LLSDParser();
-
- /**
- * @brief Call this method to parse a stream for LLSD.
- *
- * This method parses the istream for a structured data. This
- * method assumes that the istream is a complete llsd object --
- * for example an opened and closed map with an arbitrary nesting
- * of elements. This method will return after reading one data
- * object, allowing continued reading from the stream by the
- * caller.
- * @param istr The input stream.
- * @param data[out] The newly parse structured data.
- * @param max_bytes The maximum number of bytes that will be in
- * the stream. Pass in LLSDSerialize::SIZE_UNLIMITED (-1) to set no
- * byte limit.
- * @return Returns the number of LLSD objects parsed into
- * data. Returns PARSE_FAILURE (-1) on parse failure.
- */
- S32 parse(std::istream& istr, LLSD& data, llssize max_bytes, S32 max_depth = -1);
-
- /** Like parse(), but uses a different call (istream.getline()) to read by lines
- * This API is better suited for XML, where the parse cannot tell
- * where the document actually ends.
- */
- S32 parseLines(std::istream& istr, LLSD& data);
-
- /**
- * @brief Resets the parser so parse() or parseLines() can be called again for another <llsd> chunk.
- */
- void reset() { doReset(); };
+ /**
+ * @brief Anonymous enum to indicate parsing failure.
+ */
+ enum
+ {
+ PARSE_FAILURE = -1
+ };
+
+ /**
+ * @brief Constructor
+ */
+ LLSDParser();
+
+ /**
+ * @brief Call this method to parse a stream for LLSD.
+ *
+ * This method parses the istream for a structured data. This
+ * method assumes that the istream is a complete llsd object --
+ * for example an opened and closed map with an arbitrary nesting
+ * of elements. This method will return after reading one data
+ * object, allowing continued reading from the stream by the
+ * caller.
+ * @param istr The input stream.
+ * @param data[out] The newly parse structured data.
+ * @param max_bytes The maximum number of bytes that will be in
+ * the stream. Pass in LLSDSerialize::SIZE_UNLIMITED (-1) to set no
+ * byte limit.
+ * @return Returns the number of LLSD objects parsed into
+ * data. Returns PARSE_FAILURE (-1) on parse failure.
+ */
+ S32 parse(std::istream& istr, LLSD& data, llssize max_bytes, S32 max_depth = -1);
+
+ /** Like parse(), but uses a different call (istream.getline()) to read by lines
+ * This API is better suited for XML, where the parse cannot tell
+ * where the document actually ends.
+ */
+ S32 parseLines(std::istream& istr, LLSD& data);
+
+ /**
+ * @brief Resets the parser so parse() or parseLines() can be called again for another <llsd> chunk.
+ */
+ void reset() { doReset(); };
protected:
- /**
- * @brief Pure virtual base for doing the parse.
- *
- * This method parses the istream for a structured data. This
- * method assumes that the istream is a complete llsd object --
- * for example an opened and closed map with an arbitrary nesting
- * of elements. This method will return after reading one data
- * object, allowing continued reading from the stream by the
- * caller.
- * @param istr The input stream.
- * @param data[out] The newly parse structured data.
- * @param max_depth Max depth parser will check before exiting
- * with parse error, -1 - unlimited.
- * @return Returns the number of LLSD objects parsed into
- * data. Returns PARSE_FAILURE (-1) on parse failure.
- */
- virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const = 0;
-
- /**
- * @brief Virtual default function for resetting the parser
- */
- virtual void doReset() {};
-
- /* @name Simple istream helper methods
- *
- * These helper methods exist to help correctly use the
- * mMaxBytesLeft without really thinking about it for most simple
- * operations. Use of the streamtools in llstreamtools.h will
- * require custom wrapping.
- */
- //@{
- /**
- * @brief get a byte off the stream
- *
- * @param istr The istream to work with.
- * @return returns the next character.
- */
- int get(std::istream& istr) const;
-
- /**
- * @brief get several bytes off the stream into a buffer.
- *
- * @param istr The istream to work with.
- * @param s The buffer to get into
- * @param n Extract maximum of n-1 bytes and null temrinate.
- * @param delim Delimiter to get until found.
- * @return Returns istr.
- */
- std::istream& get(
- std::istream& istr,
- char* s,
- std::streamsize n,
- char delim) const;
-
- /**
- * @brief get several bytes off the stream into a streambuf
- *
- * @param istr The istream to work with.
- * @param sb The streambuf to read into
- * @param delim Delimiter to get until found.
- * @return Returns istr.
- */
- std::istream& get(
- std::istream& istr,
- std::streambuf& sb,
- char delim) const;
-
- /**
- * @brief ignore the next byte on the istream
- *
- * @param istr The istream to work with.
- * @return Returns istr.
- */
- std::istream& ignore(std::istream& istr) const;
-
- /**
- * @brief put the last character retrieved back on the stream
- *
- * @param istr The istream to work with.
- * @param c The character to put back
- * @return Returns istr.
- */
- std::istream& putback(std::istream& istr, char c) const;
-
- /**
- * @brief read a block of n characters into a buffer
- *
- * @param istr The istream to work with.
- * @param s The buffer to read into
- * @param n The number of bytes to read.
- * @return Returns istr.
- */
- std::istream& read(std::istream& istr, char* s, std::streamsize n) const;
- //@}
+ /**
+ * @brief Pure virtual base for doing the parse.
+ *
+ * This method parses the istream for a structured data. This
+ * method assumes that the istream is a complete llsd object --
+ * for example an opened and closed map with an arbitrary nesting
+ * of elements. This method will return after reading one data
+ * object, allowing continued reading from the stream by the
+ * caller.
+ * @param istr The input stream.
+ * @param data[out] The newly parse structured data.
+ * @param max_depth Max depth parser will check before exiting
+ * with parse error, -1 - unlimited.
+ * @return Returns the number of LLSD objects parsed into
+ * data. Returns PARSE_FAILURE (-1) on parse failure.
+ */
+ virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const = 0;
+
+ /**
+ * @brief Virtual default function for resetting the parser
+ */
+ virtual void doReset() {};
+
+ /* @name Simple istream helper methods
+ *
+ * These helper methods exist to help correctly use the
+ * mMaxBytesLeft without really thinking about it for most simple
+ * operations. Use of the streamtools in llstreamtools.h will
+ * require custom wrapping.
+ */
+ //@{
+ /**
+ * @brief get a byte off the stream
+ *
+ * @param istr The istream to work with.
+ * @return returns the next character.
+ */
+ int get(std::istream& istr) const;
+
+ /**
+ * @brief get several bytes off the stream into a buffer.
+ *
+ * @param istr The istream to work with.
+ * @param s The buffer to get into
+ * @param n Extract maximum of n-1 bytes and null temrinate.
+ * @param delim Delimiter to get until found.
+ * @return Returns istr.
+ */
+ std::istream& get(
+ std::istream& istr,
+ char* s,
+ std::streamsize n,
+ char delim) const;
+
+ /**
+ * @brief get several bytes off the stream into a streambuf
+ *
+ * @param istr The istream to work with.
+ * @param sb The streambuf to read into
+ * @param delim Delimiter to get until found.
+ * @return Returns istr.
+ */
+ std::istream& get(
+ std::istream& istr,
+ std::streambuf& sb,
+ char delim) const;
+
+ /**
+ * @brief ignore the next byte on the istream
+ *
+ * @param istr The istream to work with.
+ * @return Returns istr.
+ */
+ std::istream& ignore(std::istream& istr) const;
+
+ /**
+ * @brief put the last character retrieved back on the stream
+ *
+ * @param istr The istream to work with.
+ * @param c The character to put back
+ * @return Returns istr.
+ */
+ std::istream& putback(std::istream& istr, char c) const;
+
+ /**
+ * @brief read a block of n characters into a buffer
+ *
+ * @param istr The istream to work with.
+ * @param s The buffer to read into
+ * @param n The number of bytes to read.
+ * @return Returns istr.
+ */
+ std::istream& read(std::istream& istr, char* s, std::streamsize n) const;
+ //@}
protected:
- /**
- * @brief Accunt for bytes read outside of the istream helpers.
- *
- * Conceptually const since it only modifies mutable members.
- * @param bytes The number of bytes read.
- */
- void account(llssize bytes) const;
+ /**
+ * @brief Accunt for bytes read outside of the istream helpers.
+ *
+ * Conceptually const since it only modifies mutable members.
+ * @param bytes The number of bytes read.
+ */
+ void account(llssize bytes) const;
protected:
- /**
- * @brief boolean to set if byte counts should be checked during parsing.
- */
- bool mCheckLimits;
-
- /**
- * @brief The maximum number of bytes left to be parsed.
- */
- mutable llssize mMaxBytesLeft;
-
- /**
- * @brief Use line-based reading to get text
- */
- bool mParseLines;
+ /**
+ * @brief boolean to set if byte counts should be checked during parsing.
+ */
+ bool mCheckLimits;
+
+ /**
+ * @brief The maximum number of bytes left to be parsed.
+ */
+ mutable llssize mMaxBytesLeft;
+
+ /**
+ * @brief Use line-based reading to get text
+ */
+ bool mParseLines;
};
-/**
+/**
* @class LLSDNotationParser
* @brief Parser which handles the original notation format for LLSD.
*/
class LL_COMMON_API LLSDNotationParser : public LLSDParser
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDNotationParser();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDNotationParser();
public:
- /**
- * @brief Constructor
- */
- LLSDNotationParser();
+ /**
+ * @brief Constructor
+ */
+ LLSDNotationParser();
protected:
- /**
- * @brief Call this method to parse a stream for LLSD.
- *
- * This method parses the istream for a structured data. This
- * method assumes that the istream is a complete llsd object --
- * for example an opened and closed map with an arbitrary nesting
- * of elements. This method will return after reading one data
- * object, allowing continued reading from the stream by the
- * caller.
- * @param istr The input stream.
- * @param data[out] The newly parse structured data. Undefined on failure.
- * @param max_depth Max depth parser will check before exiting
- * with parse error, -1 - unlimited.
- * @return Returns the number of LLSD objects parsed into
- * data. Returns PARSE_FAILURE (-1) on parse failure.
- */
- virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
+ /**
+ * @brief Call this method to parse a stream for LLSD.
+ *
+ * This method parses the istream for a structured data. This
+ * method assumes that the istream is a complete llsd object --
+ * for example an opened and closed map with an arbitrary nesting
+ * of elements. This method will return after reading one data
+ * object, allowing continued reading from the stream by the
+ * caller.
+ * @param istr The input stream.
+ * @param data[out] The newly parse structured data. Undefined on failure.
+ * @param max_depth Max depth parser will check before exiting
+ * with parse error, -1 - unlimited.
+ * @return Returns the number of LLSD objects parsed into
+ * data. Returns PARSE_FAILURE (-1) on parse failure.
+ */
+ virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
private:
- /**
- * @brief Parse a map from the istream
- *
- * @param istr The input stream.
- * @param map The map to add the parsed data.
- * @param max_depth Allowed parsing depth.
- * @return Returns The number of LLSD objects parsed into data.
- */
- S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const;
-
- /**
- * @brief Parse an array from the istream.
- *
- * @param istr The input stream.
- * @param array The array to append the parsed data.
- * @param max_depth Allowed parsing depth.
- * @return Returns The number of LLSD objects parsed into data.
- */
- S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const;
-
- /**
- * @brief Parse a string from the istream and assign it to data.
- *
- * @param istr The input stream.
- * @param data[out] The data to assign.
- * @return Retuns true if a complete string was parsed.
- */
- bool parseString(std::istream& istr, LLSD& data) const;
-
- /**
- * @brief Parse binary data from the stream.
- *
- * @param istr The input stream.
- * @param data[out] The data to assign.
- * @return Retuns true if a complete blob was parsed.
- */
- bool parseBinary(std::istream& istr, LLSD& data) const;
+ /**
+ * @brief Parse a map from the istream
+ *
+ * @param istr The input stream.
+ * @param map The map to add the parsed data.
+ * @param max_depth Allowed parsing depth.
+ * @return Returns The number of LLSD objects parsed into data.
+ */
+ S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const;
+
+ /**
+ * @brief Parse an array from the istream.
+ *
+ * @param istr The input stream.
+ * @param array The array to append the parsed data.
+ * @param max_depth Allowed parsing depth.
+ * @return Returns The number of LLSD objects parsed into data.
+ */
+ S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const;
+
+ /**
+ * @brief Parse a string from the istream and assign it to data.
+ *
+ * @param istr The input stream.
+ * @param data[out] The data to assign.
+ * @return Retuns true if a complete string was parsed.
+ */
+ bool parseString(std::istream& istr, LLSD& data) const;
+
+ /**
+ * @brief Parse binary data from the stream.
+ *
+ * @param istr The input stream.
+ * @param data[out] The data to assign.
+ * @return Retuns true if a complete blob was parsed.
+ */
+ bool parseBinary(std::istream& istr, LLSD& data) const;
};
-/**
+/**
* @class LLSDXMLParser
* @brief Parser which handles XML format LLSD.
*/
class LL_COMMON_API LLSDXMLParser : public LLSDParser
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDXMLParser();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDXMLParser();
public:
- /**
- * @brief Constructor
- */
- LLSDXMLParser(bool emit_errors=true);
+ /**
+ * @brief Constructor
+ */
+ LLSDXMLParser(bool emit_errors=true);
protected:
- /**
- * @brief Call this method to parse a stream for LLSD.
- *
- * This method parses the istream for a structured data. This
- * method assumes that the istream is a complete llsd object --
- * for example an opened and closed map with an arbitrary nesting
- * of elements. This method will return after reading one data
- * object, allowing continued reading from the stream by the
- * caller.
- * @param istr The input stream.
- * @param data[out] The newly parse structured data.
- * @param max_depth Max depth parser will check before exiting
- * with parse error, -1 - unlimited.
- * @return Returns the number of LLSD objects parsed into
- * data. Returns PARSE_FAILURE (-1) on parse failure.
- */
- virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
-
- /**
- * @brief Virtual default function for resetting the parser
- */
- virtual void doReset();
+ /**
+ * @brief Call this method to parse a stream for LLSD.
+ *
+ * This method parses the istream for a structured data. This
+ * method assumes that the istream is a complete llsd object --
+ * for example an opened and closed map with an arbitrary nesting
+ * of elements. This method will return after reading one data
+ * object, allowing continued reading from the stream by the
+ * caller.
+ * @param istr The input stream.
+ * @param data[out] The newly parse structured data.
+ * @param max_depth Max depth parser will check before exiting
+ * with parse error, -1 - unlimited.
+ * @return Returns the number of LLSD objects parsed into
+ * data. Returns PARSE_FAILURE (-1) on parse failure.
+ */
+ virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
+
+ /**
+ * @brief Virtual default function for resetting the parser
+ */
+ virtual void doReset();
private:
- class Impl;
- Impl& impl;
+ class Impl;
+ Impl& impl;
- void parsePart(const char* buf, llssize len);
- friend class LLSDSerialize;
+ void parsePart(const char* buf, llssize len);
+ friend class LLSDSerialize;
};
-/**
+/**
* @class LLSDBinaryParser
* @brief Parser which handles binary formatted LLSD.
*/
class LL_COMMON_API LLSDBinaryParser : public LLSDParser
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDBinaryParser();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDBinaryParser();
public:
- /**
- * @brief Constructor
- */
- LLSDBinaryParser();
+ /**
+ * @brief Constructor
+ */
+ LLSDBinaryParser();
protected:
- /**
- * @brief Call this method to parse a stream for LLSD.
- *
- * This method parses the istream for a structured data. This
- * method assumes that the istream is a complete llsd object --
- * for example an opened and closed map with an arbitrary nesting
- * of elements. This method will return after reading one data
- * object, allowing continued reading from the stream by the
- * caller.
- * @param istr The input stream.
- * @param data[out] The newly parse structured data.
- * @param max_depth Max depth parser will check before exiting
- * with parse error, -1 - unlimited.
- * @return Returns the number of LLSD objects parsed into
- * data. Returns -1 on parse failure.
- */
- virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
+ /**
+ * @brief Call this method to parse a stream for LLSD.
+ *
+ * This method parses the istream for a structured data. This
+ * method assumes that the istream is a complete llsd object --
+ * for example an opened and closed map with an arbitrary nesting
+ * of elements. This method will return after reading one data
+ * object, allowing continued reading from the stream by the
+ * caller.
+ * @param istr The input stream.
+ * @param data[out] The newly parse structured data.
+ * @param max_depth Max depth parser will check before exiting
+ * with parse error, -1 - unlimited.
+ * @return Returns the number of LLSD objects parsed into
+ * data. Returns -1 on parse failure.
+ */
+ virtual S32 doParse(std::istream& istr, LLSD& data, S32 max_depth = -1) const;
private:
- /**
- * @brief Parse a map from the istream
- *
- * @param istr The input stream.
- * @param map The map to add the parsed data.
- * @param max_depth Allowed parsing depth.
- * @return Returns The number of LLSD objects parsed into data.
- */
- S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const;
-
- /**
- * @brief Parse an array from the istream.
- *
- * @param istr The input stream.
- * @param array The array to append the parsed data.
- * @param max_depth Allowed parsing depth.
- * @return Returns The number of LLSD objects parsed into data.
- */
- S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const;
-
- /**
- * @brief Parse a string from the istream and assign it to data.
- *
- * @param istr The input stream.
- * @param value[out] The string to assign.
- * @return Retuns true if a complete string was parsed.
- */
- bool parseString(std::istream& istr, std::string& value) const;
+ /**
+ * @brief Parse a map from the istream
+ *
+ * @param istr The input stream.
+ * @param map The map to add the parsed data.
+ * @param max_depth Allowed parsing depth.
+ * @return Returns The number of LLSD objects parsed into data.
+ */
+ S32 parseMap(std::istream& istr, LLSD& map, S32 max_depth) const;
+
+ /**
+ * @brief Parse an array from the istream.
+ *
+ * @param istr The input stream.
+ * @param array The array to append the parsed data.
+ * @param max_depth Allowed parsing depth.
+ * @return Returns The number of LLSD objects parsed into data.
+ */
+ S32 parseArray(std::istream& istr, LLSD& array, S32 max_depth) const;
+
+ /**
+ * @brief Parse a string from the istream and assign it to data.
+ *
+ * @param istr The input stream.
+ * @param value[out] The string to assign.
+ * @return Retuns true if a complete string was parsed.
+ */
+ bool parseString(std::istream& istr, std::string& value) const;
};
-/**
+/**
* @class LLSDFormatter
* @brief Abstract base class for formatting LLSD.
*/
class LL_COMMON_API LLSDFormatter : public LLRefCount
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDFormatter();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDFormatter();
public:
- /**
- * Options for output
- */
- typedef enum e_formatter_options_type
- {
- OPTIONS_NONE = 0,
- OPTIONS_PRETTY = 1,
- OPTIONS_PRETTY_BINARY = 2
- } EFormatterOptions;
-
- /**
- * @brief Constructor
- */
- LLSDFormatter(bool boolAlpha=false, const std::string& realFormat="",
- EFormatterOptions options=OPTIONS_PRETTY_BINARY);
-
- /**
- * @brief Set the boolean serialization format.
- *
- * @param alpha Serializes boolean as alpha if true.
- */
- void boolalpha(bool alpha);
-
- /**
- * @brief Set the real format
- *
- * By default, the formatter will use default double serialization
- * which is frequently frustrating for many applications. You can
- * set the precision on the stream independently, but that still
- * might not work depending on the value.
- * EXAMPLES:<br>
- * %.2f<br>
- * @param format A format string which follows the printf format
- * rules. Specify an empty string to return to default formatting.
- */
- void realFormat(const std::string& format);
-
- /**
- * @brief Call this method to format an LLSD to a stream with options as
- * set by the constructor.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @return Returns The number of LLSD objects formatted out
- */
- S32 format(const LLSD& data, std::ostream& ostr) const;
-
- /**
- * @brief Call this method to format an LLSD to a stream, passing options
- * explicitly.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @param options OPTIONS_NONE to emit LLSD::Binary as raw bytes
- * @return Returns The number of LLSD objects formatted out
- */
- virtual S32 format(const LLSD& data, std::ostream& ostr, EFormatterOptions options) const;
+ /**
+ * Options for output
+ */
+ typedef enum e_formatter_options_type
+ {
+ OPTIONS_NONE = 0,
+ OPTIONS_PRETTY = 1,
+ OPTIONS_PRETTY_BINARY = 2
+ } EFormatterOptions;
+
+ /**
+ * @brief Constructor
+ */
+ LLSDFormatter(bool boolAlpha=false, const std::string& realFormat="",
+ EFormatterOptions options=OPTIONS_PRETTY_BINARY);
+
+ /**
+ * @brief Set the boolean serialization format.
+ *
+ * @param alpha Serializes boolean as alpha if true.
+ */
+ void boolalpha(bool alpha);
+
+ /**
+ * @brief Set the real format
+ *
+ * By default, the formatter will use default double serialization
+ * which is frequently frustrating for many applications. You can
+ * set the precision on the stream independently, but that still
+ * might not work depending on the value.
+ * EXAMPLES:<br>
+ * %.2f<br>
+ * @param format A format string which follows the printf format
+ * rules. Specify an empty string to return to default formatting.
+ */
+ void realFormat(const std::string& format);
+
+ /**
+ * @brief Call this method to format an LLSD to a stream with options as
+ * set by the constructor.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects formatted out
+ */
+ S32 format(const LLSD& data, std::ostream& ostr) const;
+
+ /**
+ * @brief Call this method to format an LLSD to a stream, passing options
+ * explicitly.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @param options OPTIONS_NONE to emit LLSD::Binary as raw bytes
+ * @return Returns The number of LLSD objects formatted out
+ */
+ virtual S32 format(const LLSD& data, std::ostream& ostr, EFormatterOptions options) const;
protected:
- /**
- * @brief Implementation to format the data. This is called recursively.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @return Returns The number of LLSD objects formatted out
- */
- virtual S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
- U32 level) const = 0;
-
- /**
- * @brief Helper method which appropriately obeys the real format.
- *
- * @param real The real value to format.
- * @param ostr The destination stream for the data.
- */
- void formatReal(LLSD::Real real, std::ostream& ostr) const;
-
- bool mBoolAlpha;
- std::string mRealFormat;
- EFormatterOptions mOptions;
+ /**
+ * @brief Implementation to format the data. This is called recursively.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects formatted out
+ */
+ virtual S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
+ U32 level) const = 0;
+
+ /**
+ * @brief Helper method which appropriately obeys the real format.
+ *
+ * @param real The real value to format.
+ * @param ostr The destination stream for the data.
+ */
+ void formatReal(LLSD::Real real, std::ostream& ostr) const;
+
+ bool mBoolAlpha;
+ std::string mRealFormat;
+ EFormatterOptions mOptions;
};
-/**
+/**
* @class LLSDNotationFormatter
* @brief Formatter which outputs the original notation format for LLSD.
*/
class LL_COMMON_API LLSDNotationFormatter : public LLSDFormatter
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDNotationFormatter();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDNotationFormatter();
public:
- /**
- * @brief Constructor
- */
- LLSDNotationFormatter(bool boolAlpha=false, const std::string& realFormat="",
- EFormatterOptions options=OPTIONS_PRETTY_BINARY);
-
- /**
- * @brief Helper static method to return a notation escaped string
- *
- * This method will return the notation escaped string, but not
- * the surrounding serialization identifiers such as a double or
- * single quote. It will be up to the caller to embed those as
- * appropriate.
- * @param in The raw, unescaped string.
- * @return Returns an escaped string appropriate for serialization.
- */
- static std::string escapeString(const std::string& in);
+ /**
+ * @brief Constructor
+ */
+ LLSDNotationFormatter(bool boolAlpha=false, const std::string& realFormat="",
+ EFormatterOptions options=OPTIONS_PRETTY_BINARY);
+
+ /**
+ * @brief Helper static method to return a notation escaped string
+ *
+ * This method will return the notation escaped string, but not
+ * the surrounding serialization identifiers such as a double or
+ * single quote. It will be up to the caller to embed those as
+ * appropriate.
+ * @param in The raw, unescaped string.
+ * @return Returns an escaped string appropriate for serialization.
+ */
+ static std::string escapeString(const std::string& in);
protected:
- /**
- * @brief Implementation to format the data. This is called recursively.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @return Returns The number of LLSD objects formatted out
- */
- S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
- U32 level) const override;
+ /**
+ * @brief Implementation to format the data. This is called recursively.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects formatted out
+ */
+ S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
+ U32 level) const override;
};
-/**
+/**
* @class LLSDXMLFormatter
* @brief Formatter which outputs the LLSD as XML.
*/
class LL_COMMON_API LLSDXMLFormatter : public LLSDFormatter
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDXMLFormatter();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDXMLFormatter();
public:
- /**
- * @brief Constructor
- */
- LLSDXMLFormatter(bool boolAlpha=false, const std::string& realFormat="",
- EFormatterOptions options=OPTIONS_PRETTY_BINARY);
-
- /**
- * @brief Helper static method to return an xml escaped string
- *
- * @param in A valid UTF-8 string.
- * @return Returns an escaped string appropriate for serialization.
- */
- static std::string escapeString(const std::string& in);
-
- /**
- * @brief Call this method to format an LLSD to a stream.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @return Returns The number of LLSD objects formatted out
- */
- S32 format(const LLSD& data, std::ostream& ostr, EFormatterOptions options) const override;
-
- // also pull down base-class format() method that isn't overridden
- using LLSDFormatter::format;
+ /**
+ * @brief Constructor
+ */
+ LLSDXMLFormatter(bool boolAlpha=false, const std::string& realFormat="",
+ EFormatterOptions options=OPTIONS_PRETTY_BINARY);
+
+ /**
+ * @brief Helper static method to return an xml escaped string
+ *
+ * @param in A valid UTF-8 string.
+ * @return Returns an escaped string appropriate for serialization.
+ */
+ static std::string escapeString(const std::string& in);
+
+ /**
+ * @brief Call this method to format an LLSD to a stream.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects formatted out
+ */
+ S32 format(const LLSD& data, std::ostream& ostr, EFormatterOptions options) const override;
+
+ // also pull down base-class format() method that isn't overridden
+ using LLSDFormatter::format;
protected:
- /**
- * @brief Implementation to format the data. This is called recursively.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @return Returns The number of LLSD objects formatted out
- */
- S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
- U32 level) const override;
+ /**
+ * @brief Implementation to format the data. This is called recursively.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects formatted out
+ */
+ S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
+ U32 level) const override;
};
-/**
+/**
* @class LLSDBinaryFormatter
* @brief Formatter which outputs the LLSD as a binary notation format.
*
@@ -628,42 +628,42 @@ protected:
class LL_COMMON_API LLSDBinaryFormatter : public LLSDFormatter
{
protected:
- /**
- * @brief Destructor
- */
- virtual ~LLSDBinaryFormatter();
+ /**
+ * @brief Destructor
+ */
+ virtual ~LLSDBinaryFormatter();
public:
- /**
- * @brief Constructor
- */
- LLSDBinaryFormatter(bool boolAlpha=false, const std::string& realFormat="",
- EFormatterOptions options=OPTIONS_PRETTY_BINARY);
+ /**
+ * @brief Constructor
+ */
+ LLSDBinaryFormatter(bool boolAlpha=false, const std::string& realFormat="",
+ EFormatterOptions options=OPTIONS_PRETTY_BINARY);
protected:
- /**
- * @brief Implementation to format the data. This is called recursively.
- *
- * @param data The data to write.
- * @param ostr The destination stream for the data.
- * @return Returns The number of LLSD objects formatted out
- */
- S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
- U32 level) const override;
-
- /**
- * @brief Helper method to serialize strings
- *
- * This method serializes a network byte order size and the raw
- * string contents.
- * @param string The string to write.
- * @param ostr The destination stream for the data.
- */
- void formatString(const std::string& string, std::ostream& ostr) const;
+ /**
+ * @brief Implementation to format the data. This is called recursively.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects formatted out
+ */
+ S32 format_impl(const LLSD& data, std::ostream& ostr, EFormatterOptions options,
+ U32 level) const override;
+
+ /**
+ * @brief Helper method to serialize strings
+ *
+ * This method serializes a network byte order size and the raw
+ * string contents.
+ * @param string The string to write.
+ * @param ostr The destination stream for the data.
+ */
+ void formatString(const std::string& string, std::ostream& ostr) const;
};
-/**
+/**
* @class LLSDNotationStreamFormatter
* @brief Formatter which is specialized for use on streams which
* outputs the original notation format for LLSD.
@@ -674,7 +674,7 @@ protected:
* LLSD sd;<br>
* sd["foo"] = "bar";<br>
* std::stringstream params;<br>
- * params << "[{'version':i1}," << LLSDOStreamer<LLSDNotationFormatter>(sd)
+ * params << "[{'version':i1}," << LLSDOStreamer<LLSDNotationFormatter>(sd)
* << "]";
* </code>
*
@@ -687,165 +687,165 @@ template <class Formatter>
class LLSDOStreamer
{
public:
- /**
- * @brief Constructor
- */
- LLSDOStreamer(const LLSD& data,
- LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY) :
- mSD(data), mOptions(options) {}
-
- /**
- * @brief Stream operator.
- *
- * Use this inline during construction during a stream operation.
- * @param str The destination stream for serialized output.
- * @param The formatter which will output it's LLSD.
- * @return Returns the stream passed in after streaming mSD.
- */
- friend std::ostream& operator<<(
- std::ostream& out,
- const LLSDOStreamer<Formatter>& streamer)
- {
- LLPointer<Formatter> f = new Formatter;
- f->format(streamer.mSD, out, streamer.mOptions);
- return out;
- }
+ /**
+ * @brief Constructor
+ */
+ LLSDOStreamer(const LLSD& data,
+ LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY) :
+ mSD(data), mOptions(options) {}
+
+ /**
+ * @brief Stream operator.
+ *
+ * Use this inline during construction during a stream operation.
+ * @param str The destination stream for serialized output.
+ * @param The formatter which will output it's LLSD.
+ * @return Returns the stream passed in after streaming mSD.
+ */
+ friend std::ostream& operator<<(
+ std::ostream& out,
+ const LLSDOStreamer<Formatter>& streamer)
+ {
+ LLPointer<Formatter> f = new Formatter;
+ f->format(streamer.mSD, out, streamer.mOptions);
+ return out;
+ }
protected:
- LLSD mSD;
- LLSDFormatter::EFormatterOptions mOptions;
+ LLSD mSD;
+ LLSDFormatter::EFormatterOptions mOptions;
};
-typedef LLSDOStreamer<LLSDNotationFormatter> LLSDNotationStreamer;
-typedef LLSDOStreamer<LLSDXMLFormatter> LLSDXMLStreamer;
+typedef LLSDOStreamer<LLSDNotationFormatter> LLSDNotationStreamer;
+typedef LLSDOStreamer<LLSDXMLFormatter> LLSDXMLStreamer;
-/**
+/**
* @class LLSDSerialize
* @brief Serializer / deserializer for the various LLSD formats
*/
class LL_COMMON_API LLSDSerialize
{
public:
- enum ELLSD_Serialize
- {
+ enum ELLSD_Serialize
+ {
LLSD_BINARY, LLSD_XML, LLSD_NOTATION
- };
-
- /**
- * @brief anonymouse enumeration for useful max_bytes constants.
- */
- enum
- {
- // Setting an unlimited size is discouraged and should only be
- // used when reading cin or another stream source which does
- // not provide access to size.
- SIZE_UNLIMITED = -1,
- };
-
- /*
- * Generic in/outs
- */
- static void serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize,
- LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY);
-
- /**
- * @brief Examine a stream, and parse 1 sd object out based on contents.
- *
- * @param sd [out] The data found on the stream
- * @param str The incoming stream
- * @param max_bytes the maximum number of bytes to parse
- * @return Returns true if the stream appears to contain valid data
- */
- static bool deserialize(LLSD& sd, std::istream& str, llssize max_bytes);
-
- /*
- * Notation Methods
- */
- static S32 toNotation(const LLSD& sd, std::ostream& str)
- {
- LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
- return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
- }
- static S32 toPrettyNotation(const LLSD& sd, std::ostream& str)
- {
- LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
- return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
- }
- static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str)
- {
- LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
- return f->format(sd, str,
- LLSDFormatter::EFormatterOptions(LLSDFormatter::OPTIONS_PRETTY |
- LLSDFormatter::OPTIONS_PRETTY_BINARY));
- }
- static S32 fromNotation(LLSD& sd, std::istream& str, llssize max_bytes)
- {
- LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
- return p->parse(str, sd, max_bytes);
- }
- static LLSD fromNotation(std::istream& str, llssize max_bytes)
- {
- LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
- LLSD sd;
- (void)p->parse(str, sd, max_bytes);
- return sd;
- }
-
- /*
- * XML Methods
- */
- static S32 toXML(const LLSD& sd, std::ostream& str)
- {
- LLPointer<LLSDXMLFormatter> f = new LLSDXMLFormatter;
- return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
- }
- static S32 toPrettyXML(const LLSD& sd, std::ostream& str)
- {
- LLPointer<LLSDXMLFormatter> f = new LLSDXMLFormatter;
- return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
- }
-
- static S32 fromXMLEmbedded(LLSD& sd, std::istream& str, bool emit_errors=true)
- {
- // no need for max_bytes since xml formatting is not
- // subvertable by bad sizes.
- LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors);
- return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED);
- }
- // Line oriented parser, 30% faster than fromXML(), but can
- // only be used when you know you have the complete XML
- // document available in the stream.
- static S32 fromXMLDocument(LLSD& sd, std::istream& str, bool emit_errors=true)
- {
- LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors);
- return p->parseLines(str, sd);
- }
- static S32 fromXML(LLSD& sd, std::istream& str, bool emit_errors=true)
- {
- return fromXMLEmbedded(sd, str, emit_errors);
-// return fromXMLDocument(sd, str, emit_errors);
- }
-
- /*
- * Binary Methods
- */
- static S32 toBinary(const LLSD& sd, std::ostream& str)
- {
- LLPointer<LLSDBinaryFormatter> f = new LLSDBinaryFormatter;
- return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
- }
- static S32 fromBinary(LLSD& sd, std::istream& str, llssize max_bytes, S32 max_depth = -1)
- {
- LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
- return p->parse(str, sd, max_bytes, max_depth);
- }
- static LLSD fromBinary(std::istream& str, llssize max_bytes, S32 max_depth = -1)
- {
- LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
- LLSD sd;
- (void)p->parse(str, sd, max_bytes, max_depth);
- return sd;
- }
+ };
+
+ /**
+ * @brief anonymouse enumeration for useful max_bytes constants.
+ */
+ enum
+ {
+ // Setting an unlimited size is discouraged and should only be
+ // used when reading cin or another stream source which does
+ // not provide access to size.
+ SIZE_UNLIMITED = -1,
+ };
+
+ /*
+ * Generic in/outs
+ */
+ static void serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize,
+ LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY);
+
+ /**
+ * @brief Examine a stream, and parse 1 sd object out based on contents.
+ *
+ * @param sd [out] The data found on the stream
+ * @param str The incoming stream
+ * @param max_bytes the maximum number of bytes to parse
+ * @return Returns true if the stream appears to contain valid data
+ */
+ static bool deserialize(LLSD& sd, std::istream& str, llssize max_bytes);
+
+ /*
+ * Notation Methods
+ */
+ static S32 toNotation(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+ return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
+ }
+ static S32 toPrettyNotation(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+ return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
+ }
+ static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+ return f->format(sd, str,
+ LLSDFormatter::EFormatterOptions(LLSDFormatter::OPTIONS_PRETTY |
+ LLSDFormatter::OPTIONS_PRETTY_BINARY));
+ }
+ static S32 fromNotation(LLSD& sd, std::istream& str, llssize max_bytes)
+ {
+ LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
+ return p->parse(str, sd, max_bytes);
+ }
+ static LLSD fromNotation(std::istream& str, llssize max_bytes)
+ {
+ LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
+ LLSD sd;
+ (void)p->parse(str, sd, max_bytes);
+ return sd;
+ }
+
+ /*
+ * XML Methods
+ */
+ static S32 toXML(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDXMLFormatter> f = new LLSDXMLFormatter;
+ return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
+ }
+ static S32 toPrettyXML(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDXMLFormatter> f = new LLSDXMLFormatter;
+ return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
+ }
+
+ static S32 fromXMLEmbedded(LLSD& sd, std::istream& str, bool emit_errors=true)
+ {
+ // no need for max_bytes since xml formatting is not
+ // subvertable by bad sizes.
+ LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors);
+ return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED);
+ }
+ // Line oriented parser, 30% faster than fromXML(), but can
+ // only be used when you know you have the complete XML
+ // document available in the stream.
+ static S32 fromXMLDocument(LLSD& sd, std::istream& str, bool emit_errors=true)
+ {
+ LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors);
+ return p->parseLines(str, sd);
+ }
+ static S32 fromXML(LLSD& sd, std::istream& str, bool emit_errors=true)
+ {
+ return fromXMLEmbedded(sd, str, emit_errors);
+// return fromXMLDocument(sd, str, emit_errors);
+ }
+
+ /*
+ * Binary Methods
+ */
+ static S32 toBinary(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDBinaryFormatter> f = new LLSDBinaryFormatter;
+ return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
+ }
+ static S32 fromBinary(LLSD& sd, std::istream& str, llssize max_bytes, S32 max_depth = -1)
+ {
+ LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
+ return p->parse(str, sd, max_bytes, max_depth);
+ }
+ static LLSD fromBinary(std::istream& str, llssize max_bytes, S32 max_depth = -1)
+ {
+ LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
+ LLSD sd;
+ (void)p->parse(str, sd, max_bytes, max_depth);
+ return sd;
+ }
};
class LL_COMMON_API LLUZipHelper : public LLRefCount
@@ -858,12 +858,12 @@ public:
ZR_SIZE_ERROR,
ZR_DATA_ERROR,
ZR_PARSE_ERROR,
- ZR_BUFFER_ERROR,
- ZR_VERSION_ERROR
+ ZR_BUFFER_ERROR,
+ ZR_VERSION_ERROR
} EZipRresult;
// return OK or reason for failure
static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size);
- static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);
+ static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);
};
//dirty little zip functions -- yell at davep
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index db61f4ae41..88cbb3b984 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsdserialize_xml.cpp
* @brief XML parsers and formatters for LLSD
*
* $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$
*/
@@ -58,195 +58,195 @@ LLSDXMLFormatter::~LLSDXMLFormatter()
// virtual
S32 LLSDXMLFormatter::format(const LLSD& data, std::ostream& ostr,
- EFormatterOptions options) const
+ EFormatterOptions options) const
{
- std::streamsize old_precision = ostr.precision(25);
-
- std::string post;
- if (options & LLSDFormatter::OPTIONS_PRETTY)
- {
- post = "\n";
- }
- ostr << "<llsd>" << post;
- S32 rv = format_impl(data, ostr, options, 1);
- ostr << "</llsd>\n";
-
- ostr.precision(old_precision);
- return rv;
+ std::streamsize old_precision = ostr.precision(25);
+
+ std::string post;
+ if (options & LLSDFormatter::OPTIONS_PRETTY)
+ {
+ post = "\n";
+ }
+ ostr << "<llsd>" << post;
+ S32 rv = format_impl(data, ostr, options, 1);
+ ostr << "</llsd>\n";
+
+ ostr.precision(old_precision);
+ return rv;
}
S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr,
- EFormatterOptions options, U32 level) const
+ EFormatterOptions options, U32 level) const
{
- S32 format_count = 1;
- std::string pre;
- std::string post;
-
- if (options & LLSDFormatter::OPTIONS_PRETTY)
- {
- for (U32 i = 0; i < level; i++)
- {
- pre += " ";
- }
- post = "\n";
- }
-
- switch(data.type())
- {
- case LLSD::TypeMap:
- if(0 == data.size())
- {
- ostr << pre << "<map />" << post;
- }
- else
- {
- ostr << pre << "<map>" << post;
- LLSD::map_const_iterator iter = data.beginMap();
- LLSD::map_const_iterator end = data.endMap();
- for(; iter != end; ++iter)
- {
- ostr << pre << "<key>" << escapeString((*iter).first) << "</key>" << post;
- format_count += format_impl((*iter).second, ostr, options, level + 1);
- }
- ostr << pre << "</map>" << post;
- }
- break;
-
- case LLSD::TypeArray:
- if(0 == data.size())
- {
- ostr << pre << "<array />" << post;
- }
- else
- {
- ostr << pre << "<array>" << post;
- LLSD::array_const_iterator iter = data.beginArray();
- LLSD::array_const_iterator end = data.endArray();
- for(; iter != end; ++iter)
- {
- format_count += format_impl(*iter, ostr, options, level + 1);
- }
- ostr << pre << "</array>" << post;
- }
- break;
-
- case LLSD::TypeUndefined:
- ostr << pre << "<undef />" << post;
- break;
-
- case LLSD::TypeBoolean:
- ostr << pre << "<boolean>";
- if(mBoolAlpha ||
- (ostr.flags() & std::ios::boolalpha)
- )
- {
- ostr << (data.asBoolean() ? "true" : "false");
- }
- else
- {
- ostr << (data.asBoolean() ? 1 : 0);
- }
- ostr << "</boolean>" << post;
- break;
-
- case LLSD::TypeInteger:
- ostr << pre << "<integer>" << data.asInteger() << "</integer>" << post;
- break;
-
- case LLSD::TypeReal:
- ostr << pre << "<real>";
- if(mRealFormat.empty())
- {
- ostr << data.asReal();
- }
- else
- {
- formatReal(data.asReal(), ostr);
- }
- ostr << "</real>" << post;
- break;
-
- case LLSD::TypeUUID:
- if(data.asUUID().isNull()) ostr << pre << "<uuid />" << post;
- else ostr << pre << "<uuid>" << data.asUUID() << "</uuid>" << post;
- break;
-
- case LLSD::TypeString:
- if(data.asStringRef().empty()) ostr << pre << "<string />" << post;
- else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post;
- break;
-
- case LLSD::TypeDate:
- ostr << pre << "<date>" << data.asDate() << "</date>" << post;
- break;
-
- case LLSD::TypeURI:
- ostr << pre << "<uri>" << escapeString(data.asString()) << "</uri>" << post;
- break;
-
- case LLSD::TypeBinary:
- {
- const LLSD::Binary& buffer = data.asBinary();
- if(buffer.empty())
- {
- ostr << pre << "<binary />" << post;
- }
- else
- {
- // *FIX: memory inefficient.
- // *TODO: convert to use LLBase64
- ostr << pre << "<binary encoding=\"base64\">";
- int b64_buffer_length = apr_base64_encode_len(narrow<size_t>(buffer.size()));
- char* b64_buffer = new char[b64_buffer_length];
- b64_buffer_length = apr_base64_encode_binary(
- b64_buffer,
- &buffer[0],
- narrow<size_t>(buffer.size()));
- ostr.write(b64_buffer, b64_buffer_length - 1);
- delete[] b64_buffer;
- ostr << "</binary>" << post;
- }
- break;
- }
- default:
- // *NOTE: This should never happen.
- ostr << pre << "<undef />" << post;
- break;
- }
- return format_count;
+ S32 format_count = 1;
+ std::string pre;
+ std::string post;
+
+ if (options & LLSDFormatter::OPTIONS_PRETTY)
+ {
+ for (U32 i = 0; i < level; i++)
+ {
+ pre += " ";
+ }
+ post = "\n";
+ }
+
+ switch(data.type())
+ {
+ case LLSD::TypeMap:
+ if(0 == data.size())
+ {
+ ostr << pre << "<map />" << post;
+ }
+ else
+ {
+ ostr << pre << "<map>" << post;
+ LLSD::map_const_iterator iter = data.beginMap();
+ LLSD::map_const_iterator end = data.endMap();
+ for(; iter != end; ++iter)
+ {
+ ostr << pre << "<key>" << escapeString((*iter).first) << "</key>" << post;
+ format_count += format_impl((*iter).second, ostr, options, level + 1);
+ }
+ ostr << pre << "</map>" << post;
+ }
+ break;
+
+ case LLSD::TypeArray:
+ if(0 == data.size())
+ {
+ ostr << pre << "<array />" << post;
+ }
+ else
+ {
+ ostr << pre << "<array>" << post;
+ LLSD::array_const_iterator iter = data.beginArray();
+ LLSD::array_const_iterator end = data.endArray();
+ for(; iter != end; ++iter)
+ {
+ format_count += format_impl(*iter, ostr, options, level + 1);
+ }
+ ostr << pre << "</array>" << post;
+ }
+ break;
+
+ case LLSD::TypeUndefined:
+ ostr << pre << "<undef />" << post;
+ break;
+
+ case LLSD::TypeBoolean:
+ ostr << pre << "<boolean>";
+ if(mBoolAlpha ||
+ (ostr.flags() & std::ios::boolalpha)
+ )
+ {
+ ostr << (data.asBoolean() ? "true" : "false");
+ }
+ else
+ {
+ ostr << (data.asBoolean() ? 1 : 0);
+ }
+ ostr << "</boolean>" << post;
+ break;
+
+ case LLSD::TypeInteger:
+ ostr << pre << "<integer>" << data.asInteger() << "</integer>" << post;
+ break;
+
+ case LLSD::TypeReal:
+ ostr << pre << "<real>";
+ if(mRealFormat.empty())
+ {
+ ostr << data.asReal();
+ }
+ else
+ {
+ formatReal(data.asReal(), ostr);
+ }
+ ostr << "</real>" << post;
+ break;
+
+ case LLSD::TypeUUID:
+ if(data.asUUID().isNull()) ostr << pre << "<uuid />" << post;
+ else ostr << pre << "<uuid>" << data.asUUID() << "</uuid>" << post;
+ break;
+
+ case LLSD::TypeString:
+ if(data.asStringRef().empty()) ostr << pre << "<string />" << post;
+ else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post;
+ break;
+
+ case LLSD::TypeDate:
+ ostr << pre << "<date>" << data.asDate() << "</date>" << post;
+ break;
+
+ case LLSD::TypeURI:
+ ostr << pre << "<uri>" << escapeString(data.asString()) << "</uri>" << post;
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ const LLSD::Binary& buffer = data.asBinary();
+ if(buffer.empty())
+ {
+ ostr << pre << "<binary />" << post;
+ }
+ else
+ {
+ // *FIX: memory inefficient.
+ // *TODO: convert to use LLBase64
+ ostr << pre << "<binary encoding=\"base64\">";
+ int b64_buffer_length = apr_base64_encode_len(narrow<size_t>(buffer.size()));
+ char* b64_buffer = new char[b64_buffer_length];
+ b64_buffer_length = apr_base64_encode_binary(
+ b64_buffer,
+ &buffer[0],
+ narrow<size_t>(buffer.size()));
+ ostr.write(b64_buffer, b64_buffer_length - 1);
+ delete[] b64_buffer;
+ ostr << "</binary>" << post;
+ }
+ break;
+ }
+ default:
+ // *NOTE: This should never happen.
+ ostr << pre << "<undef />" << post;
+ break;
+ }
+ return format_count;
}
// static
std::string LLSDXMLFormatter::escapeString(const std::string& in)
{
- std::ostringstream out;
- std::string::const_iterator it = in.begin();
- std::string::const_iterator end = in.end();
- for(; it != end; ++it)
- {
- switch((*it))
- {
- case '<':
- out << "&lt;";
- break;
- case '>':
- out << "&gt;";
- break;
- case '&':
- out << "&amp;";
- break;
- case '\'':
- out << "&apos;";
- break;
- case '"':
- out << "&quot;";
- break;
- default:
- out << (*it);
- break;
- }
- }
- return out.str();
+ std::ostringstream out;
+ std::string::const_iterator it = in.begin();
+ std::string::const_iterator end = in.end();
+ for(; it != end; ++it)
+ {
+ switch((*it))
+ {
+ case '<':
+ out << "&lt;";
+ break;
+ case '>':
+ out << "&gt;";
+ break;
+ case '&':
+ out << "&amp;";
+ break;
+ case '\'':
+ out << "&apos;";
+ break;
+ case '"':
+ out << "&quot;";
+ break;
+ default:
+ out << (*it);
+ break;
+ }
+ }
+ return out.str();
}
@@ -254,161 +254,161 @@ std::string LLSDXMLFormatter::escapeString(const std::string& in)
class LLSDXMLParser::Impl
{
public:
- Impl(bool emit_errors);
- ~Impl();
-
- S32 parse(std::istream& input, LLSD& data);
- S32 parseLines(std::istream& input, LLSD& data);
+ Impl(bool emit_errors);
+ ~Impl();
+
+ S32 parse(std::istream& input, LLSD& data);
+ S32 parseLines(std::istream& input, LLSD& data);
- void parsePart(const char *buf, llssize len);
-
- void reset();
+ void parsePart(const char *buf, llssize len);
+
+ void reset();
private:
- void startElementHandler(const XML_Char* name, const XML_Char** attributes);
- void endElementHandler(const XML_Char* name);
- void characterDataHandler(const XML_Char* data, int length);
-
- static void sStartElementHandler(
- void* userData, const XML_Char* name, const XML_Char** attributes);
- static void sEndElementHandler(
- void* userData, const XML_Char* name);
- static void sCharacterDataHandler(
- void* userData, const XML_Char* data, int length);
-
- void startSkipping();
-
- enum Element {
- ELEMENT_LLSD,
- ELEMENT_UNDEF,
- ELEMENT_BOOL,
- ELEMENT_INTEGER,
- ELEMENT_REAL,
- ELEMENT_STRING,
- ELEMENT_UUID,
- ELEMENT_DATE,
- ELEMENT_URI,
- ELEMENT_BINARY,
- ELEMENT_MAP,
- ELEMENT_ARRAY,
- ELEMENT_KEY,
- ELEMENT_UNKNOWN
- };
- static Element readElement(const XML_Char* name);
-
- static const XML_Char* findAttribute(const XML_Char* name, const XML_Char** pairs);
-
- bool mEmitErrors;
-
- XML_Parser mParser;
-
- LLSD mResult;
- S32 mParseCount;
-
- bool mInLLSDElement; // true if we're on LLSD
- bool mGracefullStop; // true if we found the </llsd
-
- typedef std::deque<LLSD*> LLSDRefStack;
- LLSDRefStack mStack;
-
- int mDepth;
- bool mSkipping;
- int mSkipThrough;
-
- std::string mCurrentKey; // Current XML <tag>
- std::string mCurrentContent; // String data between <tag> and </tag>
+ void startElementHandler(const XML_Char* name, const XML_Char** attributes);
+ void endElementHandler(const XML_Char* name);
+ void characterDataHandler(const XML_Char* data, int length);
+
+ static void sStartElementHandler(
+ void* userData, const XML_Char* name, const XML_Char** attributes);
+ static void sEndElementHandler(
+ void* userData, const XML_Char* name);
+ static void sCharacterDataHandler(
+ void* userData, const XML_Char* data, int length);
+
+ void startSkipping();
+
+ enum Element {
+ ELEMENT_LLSD,
+ ELEMENT_UNDEF,
+ ELEMENT_BOOL,
+ ELEMENT_INTEGER,
+ ELEMENT_REAL,
+ ELEMENT_STRING,
+ ELEMENT_UUID,
+ ELEMENT_DATE,
+ ELEMENT_URI,
+ ELEMENT_BINARY,
+ ELEMENT_MAP,
+ ELEMENT_ARRAY,
+ ELEMENT_KEY,
+ ELEMENT_UNKNOWN
+ };
+ static Element readElement(const XML_Char* name);
+
+ static const XML_Char* findAttribute(const XML_Char* name, const XML_Char** pairs);
+
+ bool mEmitErrors;
+
+ XML_Parser mParser;
+
+ LLSD mResult;
+ S32 mParseCount;
+
+ bool mInLLSDElement; // true if we're on LLSD
+ bool mGracefullStop; // true if we found the </llsd
+
+ typedef std::deque<LLSD*> LLSDRefStack;
+ LLSDRefStack mStack;
+
+ int mDepth;
+ bool mSkipping;
+ int mSkipThrough;
+
+ std::string mCurrentKey; // Current XML <tag>
+ std::string mCurrentContent; // String data between <tag> and </tag>
};
LLSDXMLParser::Impl::Impl(bool emit_errors)
- : mEmitErrors(emit_errors)
+ : mEmitErrors(emit_errors)
{
- mParser = XML_ParserCreate(NULL);
- reset();
+ mParser = XML_ParserCreate(NULL);
+ reset();
}
LLSDXMLParser::Impl::~Impl()
{
- XML_ParserFree(mParser);
+ XML_ParserFree(mParser);
}
inline bool is_eol(char c)
{
- return (c == '\n' || c == '\r');
+ return (c == '\n' || c == '\r');
}
void clear_eol(std::istream& input)
{
- char c = input.peek();
- while (input.good() && is_eol(c))
- {
- input.get(c);
- c = input.peek();
- }
+ char c = input.peek();
+ while (input.good() && is_eol(c))
+ {
+ input.get(c);
+ c = input.peek();
+ }
}
static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
{
- unsigned count = 0;
- while (count < bufsize && input.good())
- {
- char c = input.get();
- buf[count++] = c;
- if (is_eol(c))
- break;
- }
- return count;
+ unsigned count = 0;
+ while (count < bufsize && input.good())
+ {
+ char c = input.get();
+ buf[count++] = c;
+ if (is_eol(c))
+ break;
+ }
+ return count;
}
S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
- XML_Status status;
-
- static const int BUFFER_SIZE = 1024;
- void* buffer = NULL;
- int count = 0;
- while (input.good() && !input.eof())
- {
- buffer = XML_GetBuffer(mParser, BUFFER_SIZE);
-
- /*
- * If we happened to end our last buffer right at the end of the llsd, but the
- * stream is still going we will get a null buffer here. Check for mGracefullStop.
- */
- if (!buffer)
- {
- break;
- }
- count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
- if (!count)
- {
- break;
- }
- status = XML_ParseBuffer(mParser, count, false);
-
- if (status == XML_STATUS_ERROR)
- {
- break;
- }
- }
-
- // *FIX.: This code is buggy - if the stream was empty or not
- // good, there is not buffer to parse, both the call to
- // XML_ParseBuffer and the buffer manipulations are illegal
- // futhermore, it isn't clear that the expat buffer semantics are
- // preserved
-
- status = XML_ParseBuffer(mParser, 0, true);
- if (status == XML_STATUS_ERROR && !mGracefullStop)
- {
- if (buffer)
- {
- ((char*) buffer)[count ? count - 1 : 0] = '\0';
+ XML_Status status;
+
+ static const int BUFFER_SIZE = 1024;
+ void* buffer = NULL;
+ int count = 0;
+ while (input.good() && !input.eof())
+ {
+ buffer = XML_GetBuffer(mParser, BUFFER_SIZE);
+
+ /*
+ * If we happened to end our last buffer right at the end of the llsd, but the
+ * stream is still going we will get a null buffer here. Check for mGracefullStop.
+ */
+ if (!buffer)
+ {
+ break;
+ }
+ count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
+ if (!count)
+ {
+ break;
+ }
+ status = XML_ParseBuffer(mParser, count, false);
+
+ if (status == XML_STATUS_ERROR)
+ {
+ break;
+ }
+ }
+
+ // *FIX.: This code is buggy - if the stream was empty or not
+ // good, there is not buffer to parse, both the call to
+ // XML_ParseBuffer and the buffer manipulations are illegal
+ // futhermore, it isn't clear that the expat buffer semantics are
+ // preserved
+
+ status = XML_ParseBuffer(mParser, 0, true);
+ if (status == XML_STATUS_ERROR && !mGracefullStop)
+ {
+ if (buffer)
+ {
+ ((char*) buffer)[count ? count - 1 : 0] = '\0';
if (mEmitErrors)
{
LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*)buffer << LL_ENDL;
}
- }
+ }
else
{
if (mEmitErrors)
@@ -416,159 +416,159 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR, null buffer" << LL_ENDL;
}
}
- data = LLSD();
- return LLSDParser::PARSE_FAILURE;
- }
+ data = LLSD();
+ return LLSDParser::PARSE_FAILURE;
+ }
- clear_eol(input);
- data = mResult;
- return mParseCount;
+ clear_eol(input);
+ data = mResult;
+ return mParseCount;
}
S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)
{
- XML_Status status = XML_STATUS_OK;
-
- data = LLSD();
-
- static const int BUFFER_SIZE = 1024;
-
- //static char last_buffer[ BUFFER_SIZE ];
- //std::streamsize last_num_read;
-
- // Must get rid of any leading \n, otherwise the stream gets into an error/eof state
- clear_eol(input);
-
- while( !mGracefullStop
- && input.good()
- && !input.eof())
- {
- void* buffer = XML_GetBuffer(mParser, BUFFER_SIZE);
- /*
- * If we happened to end our last buffer right at the end of the llsd, but the
- * stream is still going we will get a null buffer here. Check for mGracefullStop.
- * -- I don't think this is actually true - zero 2008-05-09
- */
- if (!buffer)
- {
- break;
- }
-
- // Get one line
- input.getline((char*)buffer, BUFFER_SIZE);
- std::streamsize num_read = input.gcount();
-
- //memcpy( last_buffer, buffer, num_read );
- //last_num_read = num_read;
-
- if ( num_read > 0 )
- {
- if (!input.good() )
- { // Clear state that's set when we run out of buffer
- input.clear();
- }
-
- // Re-insert with the \n that was absorbed by getline()
- char * text = (char *) buffer;
- if ( text[num_read - 1] == 0)
- {
- text[num_read - 1] = '\n';
- }
- }
-
- status = XML_ParseBuffer(mParser, (int)num_read, false);
- if (status == XML_STATUS_ERROR)
- {
- break;
- }
- }
-
- if (status != XML_STATUS_ERROR
- && !mGracefullStop)
- { // Parse last bit
- status = XML_ParseBuffer(mParser, 0, true);
- }
-
- if (status == XML_STATUS_ERROR
- && !mGracefullStop)
- {
- if (mEmitErrors)
- {
- LL_INFOS() << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << LL_ENDL;
- }
- return LLSDParser::PARSE_FAILURE;
- }
-
- clear_eol(input);
- data = mResult;
- return mParseCount;
+ XML_Status status = XML_STATUS_OK;
+
+ data = LLSD();
+
+ static const int BUFFER_SIZE = 1024;
+
+ //static char last_buffer[ BUFFER_SIZE ];
+ //std::streamsize last_num_read;
+
+ // Must get rid of any leading \n, otherwise the stream gets into an error/eof state
+ clear_eol(input);
+
+ while( !mGracefullStop
+ && input.good()
+ && !input.eof())
+ {
+ void* buffer = XML_GetBuffer(mParser, BUFFER_SIZE);
+ /*
+ * If we happened to end our last buffer right at the end of the llsd, but the
+ * stream is still going we will get a null buffer here. Check for mGracefullStop.
+ * -- I don't think this is actually true - zero 2008-05-09
+ */
+ if (!buffer)
+ {
+ break;
+ }
+
+ // Get one line
+ input.getline((char*)buffer, BUFFER_SIZE);
+ std::streamsize num_read = input.gcount();
+
+ //memcpy( last_buffer, buffer, num_read );
+ //last_num_read = num_read;
+
+ if ( num_read > 0 )
+ {
+ if (!input.good() )
+ { // Clear state that's set when we run out of buffer
+ input.clear();
+ }
+
+ // Re-insert with the \n that was absorbed by getline()
+ char * text = (char *) buffer;
+ if ( text[num_read - 1] == 0)
+ {
+ text[num_read - 1] = '\n';
+ }
+ }
+
+ status = XML_ParseBuffer(mParser, (int)num_read, false);
+ if (status == XML_STATUS_ERROR)
+ {
+ break;
+ }
+ }
+
+ if (status != XML_STATUS_ERROR
+ && !mGracefullStop)
+ { // Parse last bit
+ status = XML_ParseBuffer(mParser, 0, true);
+ }
+
+ if (status == XML_STATUS_ERROR
+ && !mGracefullStop)
+ {
+ if (mEmitErrors)
+ {
+ LL_INFOS() << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << LL_ENDL;
+ }
+ return LLSDParser::PARSE_FAILURE;
+ }
+
+ clear_eol(input);
+ data = mResult;
+ return mParseCount;
}
void LLSDXMLParser::Impl::reset()
{
- mResult.clear();
- mParseCount = 0;
-
- mInLLSDElement = false;
- mDepth = 0;
-
- mGracefullStop = false;
-
- mStack.clear();
-
- mSkipping = false;
-
- mCurrentKey.clear();
-
- XML_ParserReset(mParser, "utf-8");
- XML_SetUserData(mParser, this);
- XML_SetElementHandler(mParser, sStartElementHandler, sEndElementHandler);
- XML_SetCharacterDataHandler(mParser, sCharacterDataHandler);
+ mResult.clear();
+ mParseCount = 0;
+
+ mInLLSDElement = false;
+ mDepth = 0;
+
+ mGracefullStop = false;
+
+ mStack.clear();
+
+ mSkipping = false;
+
+ mCurrentKey.clear();
+
+ XML_ParserReset(mParser, "utf-8");
+ XML_SetUserData(mParser, this);
+ XML_SetElementHandler(mParser, sStartElementHandler, sEndElementHandler);
+ XML_SetCharacterDataHandler(mParser, sCharacterDataHandler);
}
void LLSDXMLParser::Impl::startSkipping()
{
- mSkipping = true;
- mSkipThrough = mDepth;
+ mSkipping = true;
+ mSkipThrough = mDepth;
}
const XML_Char*
LLSDXMLParser::Impl::findAttribute(const XML_Char* name, const XML_Char** pairs)
{
- while (NULL != pairs && NULL != *pairs)
- {
- if(0 == strcmp(name, *pairs))
- {
- return *(pairs + 1);
- }
- pairs += 2;
- }
- return NULL;
+ while (NULL != pairs && NULL != *pairs)
+ {
+ if(0 == strcmp(name, *pairs))
+ {
+ return *(pairs + 1);
+ }
+ pairs += 2;
+ }
+ return NULL;
}
void LLSDXMLParser::Impl::parsePart(const char* buf, llssize len)
{
- if ( buf != NULL
- && len > 0 )
- {
- XML_Status status = XML_Parse(mParser, buf, len, false);
- if (status == XML_STATUS_ERROR)
- {
- LL_INFOS() << "Unexpected XML parsing error at start" << LL_ENDL;
- }
- }
+ if ( buf != NULL
+ && len > 0 )
+ {
+ XML_Status status = XML_Parse(mParser, buf, len, false);
+ if (status == XML_STATUS_ERROR)
+ {
+ LL_INFOS() << "Unexpected XML parsing error at start" << LL_ENDL;
+ }
+ }
}
// Performance testing code
-//#define XML_PARSER_PERFORMANCE_TESTS
+//#define XML_PARSER_PERFORMANCE_TESTS
#ifdef XML_PARSER_PERFORMANCE_TESTS
extern U64 totalTime();
-U64 readElementTime = 0;
+U64 readElementTime = 0;
U64 startElementTime = 0;
U64 endElementTime = 0;
U64 charDataTime = 0;
@@ -577,333 +577,333 @@ U64 parseTime = 0;
class XML_Timer
{
public:
- XML_Timer( U64 * sum ) : mSum( sum )
- {
- mStart = totalTime();
- }
- ~XML_Timer()
- {
- *mSum += (totalTime() - mStart);
- }
-
- U64 * mSum;
- U64 mStart;
+ XML_Timer( U64 * sum ) : mSum( sum )
+ {
+ mStart = totalTime();
+ }
+ ~XML_Timer()
+ {
+ *mSum += (totalTime() - mStart);
+ }
+
+ U64 * mSum;
+ U64 mStart;
};
#endif // XML_PARSER_PERFORMANCE_TESTS
void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Char** attributes)
{
- #ifdef XML_PARSER_PERFORMANCE_TESTS
- XML_Timer timer( &startElementTime );
- #endif // XML_PARSER_PERFORMANCE_TESTS
-
- ++mDepth;
- if (mSkipping)
- {
- return;
- }
-
- Element element = readElement(name);
-
- mCurrentContent.clear();
-
- switch (element)
- {
- case ELEMENT_LLSD:
- if (mInLLSDElement) { return startSkipping(); }
- mInLLSDElement = true;
- return;
-
- case ELEMENT_KEY:
- if (mStack.empty() || !(mStack.back()->isMap()))
- {
- return startSkipping();
- }
- return;
-
- case ELEMENT_BINARY:
- {
- const XML_Char* encoding = findAttribute("encoding", attributes);
- if(encoding && strcmp("base64", encoding) != 0) { return startSkipping(); }
- break;
- }
-
- default:
- // all rest are values, fall through
- ;
- }
-
-
- if (!mInLLSDElement) { return startSkipping(); }
-
- if (mStack.empty())
- {
- mStack.push_back(&mResult);
- }
- else if (mStack.back()->isMap())
- {
- if (mCurrentKey.empty()) { return startSkipping(); }
-
- LLSD& map = *mStack.back();
- LLSD& newElement = map[mCurrentKey];
- mStack.push_back(&newElement);
-
- mCurrentKey.clear();
- }
- else if (mStack.back()->isArray())
- {
- LLSD& array = *mStack.back();
- array.append(LLSD());
- LLSD& newElement = array[array.size()-1];
- mStack.push_back(&newElement);
- }
- else {
- // improperly nested value in a non-structure
- return startSkipping();
- }
-
- ++mParseCount;
- switch (element)
- {
- case ELEMENT_MAP:
- *mStack.back() = LLSD::emptyMap();
- break;
-
- case ELEMENT_ARRAY:
- *mStack.back() = LLSD::emptyArray();
- break;
-
- default:
- // all the other values will be set in the end element handler
- ;
- }
+ #ifdef XML_PARSER_PERFORMANCE_TESTS
+ XML_Timer timer( &startElementTime );
+ #endif // XML_PARSER_PERFORMANCE_TESTS
+
+ ++mDepth;
+ if (mSkipping)
+ {
+ return;
+ }
+
+ Element element = readElement(name);
+
+ mCurrentContent.clear();
+
+ switch (element)
+ {
+ case ELEMENT_LLSD:
+ if (mInLLSDElement) { return startSkipping(); }
+ mInLLSDElement = true;
+ return;
+
+ case ELEMENT_KEY:
+ if (mStack.empty() || !(mStack.back()->isMap()))
+ {
+ return startSkipping();
+ }
+ return;
+
+ case ELEMENT_BINARY:
+ {
+ const XML_Char* encoding = findAttribute("encoding", attributes);
+ if(encoding && strcmp("base64", encoding) != 0) { return startSkipping(); }
+ break;
+ }
+
+ default:
+ // all rest are values, fall through
+ ;
+ }
+
+
+ if (!mInLLSDElement) { return startSkipping(); }
+
+ if (mStack.empty())
+ {
+ mStack.push_back(&mResult);
+ }
+ else if (mStack.back()->isMap())
+ {
+ if (mCurrentKey.empty()) { return startSkipping(); }
+
+ LLSD& map = *mStack.back();
+ LLSD& newElement = map[mCurrentKey];
+ mStack.push_back(&newElement);
+
+ mCurrentKey.clear();
+ }
+ else if (mStack.back()->isArray())
+ {
+ LLSD& array = *mStack.back();
+ array.append(LLSD());
+ LLSD& newElement = array[array.size()-1];
+ mStack.push_back(&newElement);
+ }
+ else {
+ // improperly nested value in a non-structure
+ return startSkipping();
+ }
+
+ ++mParseCount;
+ switch (element)
+ {
+ case ELEMENT_MAP:
+ *mStack.back() = LLSD::emptyMap();
+ break;
+
+ case ELEMENT_ARRAY:
+ *mStack.back() = LLSD::emptyArray();
+ break;
+
+ default:
+ // all the other values will be set in the end element handler
+ ;
+ }
}
void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
{
- #ifdef XML_PARSER_PERFORMANCE_TESTS
- XML_Timer timer( &endElementTime );
- #endif // XML_PARSER_PERFORMANCE_TESTS
-
- --mDepth;
- if (mSkipping)
- {
- if (mDepth < mSkipThrough)
- {
- mSkipping = false;
- }
- return;
- }
-
- Element element = readElement(name);
-
- switch (element)
- {
- case ELEMENT_LLSD:
- if (mInLLSDElement)
- {
- mInLLSDElement = false;
- mGracefullStop = true;
- XML_StopParser(mParser, false);
- }
- return;
-
- case ELEMENT_KEY:
- mCurrentKey = mCurrentContent;
- return;
-
- default:
- // all rest are values, fall through
- ;
- }
-
- if (!mInLLSDElement) { return; }
-
- LLSD& value = *mStack.back();
- mStack.pop_back();
-
- switch (element)
- {
- case ELEMENT_UNDEF:
- value.clear();
- break;
-
- case ELEMENT_BOOL:
- value = (mCurrentContent == "true" || mCurrentContent == "1");
- break;
-
- case ELEMENT_INTEGER:
- {
- S32 i;
- // sscanf okay here with different locales - ints don't change for different locale settings like floats do.
- if ( sscanf(mCurrentContent.c_str(), "%d", &i ) == 1 )
- { // See if sscanf works - it's faster
- value = i;
- }
- else
- {
- value = LLSD(mCurrentContent).asInteger();
- }
- }
- break;
-
- case ELEMENT_REAL:
- {
- value = LLSD(mCurrentContent).asReal();
- // removed since this breaks when locale has decimal separator that isn't '.'
- // investigated changing local to something compatible each time but deemed higher
- // risk that just using LLSD.asReal() each time.
- //F64 r;
- //if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 )
- //{ // See if sscanf works - it's faster
- // value = r;
- //}
- //else
- //{
- // value = LLSD(mCurrentContent).asReal();
- //}
- }
- break;
-
- case ELEMENT_STRING:
- value = mCurrentContent;
- break;
-
- case ELEMENT_UUID:
- value = LLSD(mCurrentContent).asUUID();
- break;
-
- case ELEMENT_DATE:
- value = LLSD(mCurrentContent).asDate();
- break;
-
- case ELEMENT_URI:
- value = LLSD(mCurrentContent).asURI();
- break;
-
- case ELEMENT_BINARY:
- {
- // Regex is expensive, but only fix for whitespace in base64,
- // created by python and other non-linden systems - DEV-39358
- // Fortunately we have very little binary passing now,
- // so performance impact shold be negligible. + poppy 2009-09-04
- boost::regex r;
- r.assign("\\s");
- std::string stripped = boost::regex_replace(mCurrentContent, r, "");
- S32 len = apr_base64_decode_len(stripped.c_str());
- std::vector<U8> data;
- data.resize(len);
- len = apr_base64_decode_binary(&data[0], stripped.c_str());
- data.resize(len);
- value = data;
- break;
- }
-
- case ELEMENT_UNKNOWN:
- value.clear();
- break;
-
- default:
- // other values, map and array, have already been set
- break;
- }
-
- mCurrentContent.clear();
+ #ifdef XML_PARSER_PERFORMANCE_TESTS
+ XML_Timer timer( &endElementTime );
+ #endif // XML_PARSER_PERFORMANCE_TESTS
+
+ --mDepth;
+ if (mSkipping)
+ {
+ if (mDepth < mSkipThrough)
+ {
+ mSkipping = false;
+ }
+ return;
+ }
+
+ Element element = readElement(name);
+
+ switch (element)
+ {
+ case ELEMENT_LLSD:
+ if (mInLLSDElement)
+ {
+ mInLLSDElement = false;
+ mGracefullStop = true;
+ XML_StopParser(mParser, false);
+ }
+ return;
+
+ case ELEMENT_KEY:
+ mCurrentKey = mCurrentContent;
+ return;
+
+ default:
+ // all rest are values, fall through
+ ;
+ }
+
+ if (!mInLLSDElement) { return; }
+
+ LLSD& value = *mStack.back();
+ mStack.pop_back();
+
+ switch (element)
+ {
+ case ELEMENT_UNDEF:
+ value.clear();
+ break;
+
+ case ELEMENT_BOOL:
+ value = (mCurrentContent == "true" || mCurrentContent == "1");
+ break;
+
+ case ELEMENT_INTEGER:
+ {
+ S32 i;
+ // sscanf okay here with different locales - ints don't change for different locale settings like floats do.
+ if ( sscanf(mCurrentContent.c_str(), "%d", &i ) == 1 )
+ { // See if sscanf works - it's faster
+ value = i;
+ }
+ else
+ {
+ value = LLSD(mCurrentContent).asInteger();
+ }
+ }
+ break;
+
+ case ELEMENT_REAL:
+ {
+ value = LLSD(mCurrentContent).asReal();
+ // removed since this breaks when locale has decimal separator that isn't '.'
+ // investigated changing local to something compatible each time but deemed higher
+ // risk that just using LLSD.asReal() each time.
+ //F64 r;
+ //if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 )
+ //{ // See if sscanf works - it's faster
+ // value = r;
+ //}
+ //else
+ //{
+ // value = LLSD(mCurrentContent).asReal();
+ //}
+ }
+ break;
+
+ case ELEMENT_STRING:
+ value = mCurrentContent;
+ break;
+
+ case ELEMENT_UUID:
+ value = LLSD(mCurrentContent).asUUID();
+ break;
+
+ case ELEMENT_DATE:
+ value = LLSD(mCurrentContent).asDate();
+ break;
+
+ case ELEMENT_URI:
+ value = LLSD(mCurrentContent).asURI();
+ break;
+
+ case ELEMENT_BINARY:
+ {
+ // Regex is expensive, but only fix for whitespace in base64,
+ // created by python and other non-linden systems - DEV-39358
+ // Fortunately we have very little binary passing now,
+ // so performance impact shold be negligible. + poppy 2009-09-04
+ boost::regex r;
+ r.assign("\\s");
+ std::string stripped = boost::regex_replace(mCurrentContent, r, "");
+ S32 len = apr_base64_decode_len(stripped.c_str());
+ std::vector<U8> data;
+ data.resize(len);
+ len = apr_base64_decode_binary(&data[0], stripped.c_str());
+ data.resize(len);
+ value = data;
+ break;
+ }
+
+ case ELEMENT_UNKNOWN:
+ value.clear();
+ break;
+
+ default:
+ // other values, map and array, have already been set
+ break;
+ }
+
+ mCurrentContent.clear();
}
void LLSDXMLParser::Impl::characterDataHandler(const XML_Char* data, int length)
{
- #ifdef XML_PARSER_PERFORMANCE_TESTS
- XML_Timer timer( &charDataTime );
- #endif // XML_PARSER_PERFORMANCE_TESTS
+ #ifdef XML_PARSER_PERFORMANCE_TESTS
+ XML_Timer timer( &charDataTime );
+ #endif // XML_PARSER_PERFORMANCE_TESTS
- mCurrentContent.append(data, length);
+ mCurrentContent.append(data, length);
}
void LLSDXMLParser::Impl::sStartElementHandler(
- void* userData, const XML_Char* name, const XML_Char** attributes)
+ void* userData, const XML_Char* name, const XML_Char** attributes)
{
- ((LLSDXMLParser::Impl*)userData)->startElementHandler(name, attributes);
+ ((LLSDXMLParser::Impl*)userData)->startElementHandler(name, attributes);
}
void LLSDXMLParser::Impl::sEndElementHandler(
- void* userData, const XML_Char* name)
+ void* userData, const XML_Char* name)
{
- ((LLSDXMLParser::Impl*)userData)->endElementHandler(name);
+ ((LLSDXMLParser::Impl*)userData)->endElementHandler(name);
}
void LLSDXMLParser::Impl::sCharacterDataHandler(
- void* userData, const XML_Char* data, int length)
+ void* userData, const XML_Char* data, int length)
{
- ((LLSDXMLParser::Impl*)userData)->characterDataHandler(data, length);
+ ((LLSDXMLParser::Impl*)userData)->characterDataHandler(data, length);
}
/*
- This code is time critical
-
- This is a sample of tag occurances of text in simstate file with ~8000 objects.
- A tag pair (<key>something</key>) counts is counted as two:
-
- key - 2680178
- real - 1818362
- integer - 906078
- array - 295682
- map - 191818
- uuid - 177903
- binary - 175748
- string - 53482
- undef - 40353
- boolean - 33874
- llsd - 16332
- uri - 38
- date - 1
+ This code is time critical
+
+ This is a sample of tag occurances of text in simstate file with ~8000 objects.
+ A tag pair (<key>something</key>) counts is counted as two:
+
+ key - 2680178
+ real - 1818362
+ integer - 906078
+ array - 295682
+ map - 191818
+ uuid - 177903
+ binary - 175748
+ string - 53482
+ undef - 40353
+ boolean - 33874
+ llsd - 16332
+ uri - 38
+ date - 1
*/
LLSDXMLParser::Impl::Element LLSDXMLParser::Impl::readElement(const XML_Char* name)
{
- #ifdef XML_PARSER_PERFORMANCE_TESTS
- XML_Timer timer( &readElementTime );
- #endif // XML_PARSER_PERFORMANCE_TESTS
-
- XML_Char c = *name;
- switch (c)
- {
- case 'k':
- if (strcmp(name, "key") == 0) { return ELEMENT_KEY; }
- break;
- case 'r':
- if (strcmp(name, "real") == 0) { return ELEMENT_REAL; }
- break;
- case 'i':
- if (strcmp(name, "integer") == 0) { return ELEMENT_INTEGER; }
- break;
- case 'a':
- if (strcmp(name, "array") == 0) { return ELEMENT_ARRAY; }
- break;
- case 'm':
- if (strcmp(name, "map") == 0) { return ELEMENT_MAP; }
- break;
- case 'u':
- if (strcmp(name, "uuid") == 0) { return ELEMENT_UUID; }
- if (strcmp(name, "undef") == 0) { return ELEMENT_UNDEF; }
- if (strcmp(name, "uri") == 0) { return ELEMENT_URI; }
- break;
- case 'b':
- if (strcmp(name, "binary") == 0) { return ELEMENT_BINARY; }
- if (strcmp(name, "boolean") == 0) { return ELEMENT_BOOL; }
- break;
- case 's':
- if (strcmp(name, "string") == 0) { return ELEMENT_STRING; }
- break;
- case 'l':
- if (strcmp(name, "llsd") == 0) { return ELEMENT_LLSD; }
- break;
- case 'd':
- if (strcmp(name, "date") == 0) { return ELEMENT_DATE; }
- break;
- }
- return ELEMENT_UNKNOWN;
+ #ifdef XML_PARSER_PERFORMANCE_TESTS
+ XML_Timer timer( &readElementTime );
+ #endif // XML_PARSER_PERFORMANCE_TESTS
+
+ XML_Char c = *name;
+ switch (c)
+ {
+ case 'k':
+ if (strcmp(name, "key") == 0) { return ELEMENT_KEY; }
+ break;
+ case 'r':
+ if (strcmp(name, "real") == 0) { return ELEMENT_REAL; }
+ break;
+ case 'i':
+ if (strcmp(name, "integer") == 0) { return ELEMENT_INTEGER; }
+ break;
+ case 'a':
+ if (strcmp(name, "array") == 0) { return ELEMENT_ARRAY; }
+ break;
+ case 'm':
+ if (strcmp(name, "map") == 0) { return ELEMENT_MAP; }
+ break;
+ case 'u':
+ if (strcmp(name, "uuid") == 0) { return ELEMENT_UUID; }
+ if (strcmp(name, "undef") == 0) { return ELEMENT_UNDEF; }
+ if (strcmp(name, "uri") == 0) { return ELEMENT_URI; }
+ break;
+ case 'b':
+ if (strcmp(name, "binary") == 0) { return ELEMENT_BINARY; }
+ if (strcmp(name, "boolean") == 0) { return ELEMENT_BOOL; }
+ break;
+ case 's':
+ if (strcmp(name, "string") == 0) { return ELEMENT_STRING; }
+ break;
+ case 'l':
+ if (strcmp(name, "llsd") == 0) { return ELEMENT_LLSD; }
+ break;
+ case 'd':
+ if (strcmp(name, "date") == 0) { return ELEMENT_DATE; }
+ break;
+ }
+ return ELEMENT_UNKNOWN;
}
@@ -919,34 +919,34 @@ LLSDXMLParser::LLSDXMLParser(bool emit_errors /* = true */) : impl(* new Impl(em
LLSDXMLParser::~LLSDXMLParser()
{
- delete &impl;
+ delete &impl;
}
void LLSDXMLParser::parsePart(const char *buf, llssize len)
{
- impl.parsePart(buf, len);
+ impl.parsePart(buf, len);
}
// virtual
S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data, S32 max_depth) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD
- #ifdef XML_PARSER_PERFORMANCE_TESTS
- XML_Timer timer( &parseTime );
- #endif // XML_PARSER_PERFORMANCE_TESTS
+ #ifdef XML_PARSER_PERFORMANCE_TESTS
+ XML_Timer timer( &parseTime );
+ #endif // XML_PARSER_PERFORMANCE_TESTS
- if (mParseLines)
- {
- // Use line-based reading (faster code)
- return impl.parseLines(input, data);
- }
+ if (mParseLines)
+ {
+ // Use line-based reading (faster code)
+ return impl.parseLines(input, data);
+ }
- return impl.parse(input, data);
+ return impl.parse(input, data);
}
-// virtual
+// virtual
void LLSDXMLParser::doReset()
{
- impl.reset();
+ impl.reset();
}
diff --git a/indra/llcommon/llsdserialize_xml.h b/indra/llcommon/llsdserialize_xml.h
index dcc5f3d3c7..6c1a74c0e3 100644
--- a/indra/llcommon/llsdserialize_xml.h
+++ b/indra/llcommon/llsdserialize_xml.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsdserialize_xml.h
* @brief XML parsers and formatters for LLSD
*
* $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$
*/
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 4d5fb0d818..dff7fdb160 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -32,12 +32,12 @@
#include <sstream>
#if LL_WINDOWS
-# define WIN32_LEAN_AND_MEAN
-# include <winsock2.h> // for htonl
+# define WIN32_LEAN_AND_MEAN
+# include <winsock2.h> // for htonl
#elif LL_LINUX
-# include <netinet/in.h>
+# include <netinet/in.h>
#elif LL_DARWIN
-# include <arpa/inet.h>
+# include <arpa/inet.h>
#endif
#include "llsdserialize.h"
@@ -51,152 +51,152 @@
// U32
LLSD ll_sd_from_U32(const U32 val)
{
- std::vector<U8> v;
- U32 net_order = htonl(val);
+ std::vector<U8> v;
+ U32 net_order = htonl(val);
- v.resize(4);
- memcpy(&(v[0]), &net_order, 4); /* Flawfinder: ignore */
+ v.resize(4);
+ memcpy(&(v[0]), &net_order, 4); /* Flawfinder: ignore */
- return LLSD(v);
+ return LLSD(v);
}
U32 ll_U32_from_sd(const LLSD& sd)
{
- U32 ret;
- std::vector<U8> v = sd.asBinary();
- if (v.size() < 4)
- {
- return 0;
- }
- memcpy(&ret, &(v[0]), 4); /* Flawfinder: ignore */
- ret = ntohl(ret);
- return ret;
+ U32 ret;
+ std::vector<U8> v = sd.asBinary();
+ if (v.size() < 4)
+ {
+ return 0;
+ }
+ memcpy(&ret, &(v[0]), 4); /* Flawfinder: ignore */
+ ret = ntohl(ret);
+ return ret;
}
//U64
LLSD ll_sd_from_U64(const U64 val)
{
- std::vector<U8> v;
- U32 high, low;
+ std::vector<U8> v;
+ U32 high, low;
- high = (U32)(val >> 32);
- low = (U32)val;
- high = htonl(high);
- low = htonl(low);
+ high = (U32)(val >> 32);
+ low = (U32)val;
+ high = htonl(high);
+ low = htonl(low);
- v.resize(8);
- memcpy(&(v[0]), &high, 4); /* Flawfinder: ignore */
- memcpy(&(v[4]), &low, 4); /* Flawfinder: ignore */
+ v.resize(8);
+ memcpy(&(v[0]), &high, 4); /* Flawfinder: ignore */
+ memcpy(&(v[4]), &low, 4); /* Flawfinder: ignore */
- return LLSD(v);
+ return LLSD(v);
}
U64 ll_U64_from_sd(const LLSD& sd)
{
- U32 high, low;
- std::vector<U8> v = sd.asBinary();
+ U32 high, low;
+ std::vector<U8> v = sd.asBinary();
- if (v.size() < 8)
- {
- return 0;
- }
+ if (v.size() < 8)
+ {
+ return 0;
+ }
- memcpy(&high, &(v[0]), 4); /* Flawfinder: ignore */
- memcpy(&low, &(v[4]), 4); /* Flawfinder: ignore */
- high = ntohl(high);
- low = ntohl(low);
+ memcpy(&high, &(v[0]), 4); /* Flawfinder: ignore */
+ memcpy(&low, &(v[4]), 4); /* Flawfinder: ignore */
+ high = ntohl(high);
+ low = ntohl(low);
- return ((U64)high) << 32 | low;
+ return ((U64)high) << 32 | low;
}
// IP Address (stored in net order in a U32, so don't need swizzling)
LLSD ll_sd_from_ipaddr(const U32 val)
{
- std::vector<U8> v;
+ std::vector<U8> v;
- v.resize(4);
- memcpy(&(v[0]), &val, 4); /* Flawfinder: ignore */
+ v.resize(4);
+ memcpy(&(v[0]), &val, 4); /* Flawfinder: ignore */
- return LLSD(v);
+ return LLSD(v);
}
U32 ll_ipaddr_from_sd(const LLSD& sd)
{
- U32 ret;
- std::vector<U8> v = sd.asBinary();
- if (v.size() < 4)
- {
- return 0;
- }
- memcpy(&ret, &(v[0]), 4); /* Flawfinder: ignore */
- return ret;
+ U32 ret;
+ std::vector<U8> v = sd.asBinary();
+ if (v.size() < 4)
+ {
+ return 0;
+ }
+ memcpy(&ret, &(v[0]), 4); /* Flawfinder: ignore */
+ return ret;
}
// Converts an LLSD binary to an LLSD string
LLSD ll_string_from_binary(const LLSD& sd)
{
- std::vector<U8> value = sd.asBinary();
- std::string str;
- str.resize(value.size());
- memcpy(&str[0], &value[0], value.size());
- return str;
+ std::vector<U8> value = sd.asBinary();
+ std::string str;
+ str.resize(value.size());
+ memcpy(&str[0], &value[0], value.size());
+ return str;
}
// Converts an LLSD string to an LLSD binary
LLSD ll_binary_from_string(const LLSD& sd)
{
- std::vector<U8> binary_value;
+ std::vector<U8> binary_value;
- std::string string_value = sd.asString();
- for (const U8 c : string_value)
- {
- binary_value.push_back(c);
- }
+ std::string string_value = sd.asString();
+ for (const U8 c : string_value)
+ {
+ binary_value.push_back(c);
+ }
- binary_value.push_back('\0');
+ binary_value.push_back('\0');
- return binary_value;
+ return binary_value;
}
char* ll_print_sd(const LLSD& sd)
{
- const U32 bufferSize = 10 * 1024;
- static char buffer[bufferSize + 1];
- std::ostringstream stream;
- //stream.rdbuf()->pubsetbuf(buffer, bufferSize);
- stream << LLSDOStreamer<LLSDXMLFormatter>(sd);
- stream << std::ends;
- strncpy(buffer, stream.str().c_str(), bufferSize);
- buffer[bufferSize - 1] = '\0';
- return buffer;
+ const U32 bufferSize = 10 * 1024;
+ static char buffer[bufferSize + 1];
+ std::ostringstream stream;
+ //stream.rdbuf()->pubsetbuf(buffer, bufferSize);
+ stream << LLSDOStreamer<LLSDXMLFormatter>(sd);
+ stream << std::ends;
+ strncpy(buffer, stream.str().c_str(), bufferSize);
+ buffer[bufferSize - 1] = '\0';
+ return buffer;
}
char* ll_pretty_print_sd_ptr(const LLSD* sd)
{
- if (sd)
- {
- return ll_pretty_print_sd(*sd);
- }
- return NULL;
+ if (sd)
+ {
+ return ll_pretty_print_sd(*sd);
+ }
+ return NULL;
}
char* ll_pretty_print_sd(const LLSD& sd)
{
- const U32 bufferSize = 100 * 1024;
- static char buffer[bufferSize + 1];
- std::ostringstream stream;
- //stream.rdbuf()->pubsetbuf(buffer, bufferSize);
- stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY);
- stream << std::ends;
- strncpy(buffer, stream.str().c_str(), bufferSize);
- buffer[bufferSize - 1] = '\0';
- return buffer;
+ const U32 bufferSize = 100 * 1024;
+ static char buffer[bufferSize + 1];
+ std::ostringstream stream;
+ //stream.rdbuf()->pubsetbuf(buffer, bufferSize);
+ stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY);
+ stream << std::ends;
+ strncpy(buffer, stream.str().c_str(), bufferSize);
+ buffer[bufferSize - 1] = '\0';
+ return buffer;
}
std::string ll_stream_notation_sd(const LLSD& sd)
{
- std::ostringstream stream;
- stream << LLSDOStreamer<LLSDNotationFormatter>(sd);
+ std::ostringstream stream;
+ stream << LLSDOStreamer<LLSDNotationFormatter>(sd);
return stream.str();
}
@@ -210,118 +210,118 @@ std::string ll_stream_notation_sd(const LLSD& sd)
//of the same value. Ordering of arrays matters
//Otherwise, returns true
BOOL compare_llsd_with_template(
- const LLSD& llsd_to_test,
- const LLSD& template_llsd,
- LLSD& resultant_llsd)
+ const LLSD& llsd_to_test,
+ const LLSD& template_llsd,
+ LLSD& resultant_llsd)
{
LL_PROFILE_ZONE_SCOPED
- if (
- llsd_to_test.isUndefined() &&
- template_llsd.isDefined() )
- {
- resultant_llsd = template_llsd;
- return TRUE;
- }
- else if ( llsd_to_test.type() != template_llsd.type() )
- {
- resultant_llsd = LLSD();
- return FALSE;
- }
-
- if ( llsd_to_test.isArray() )
- {
- //they are both arrays
- //we loop over all the items in the template
- //verifying that the to_test has a subset (in the same order)
- //any shortcoming in the testing_llsd are just taken
- //to be the rest of the template
- LLSD data;
- LLSD::array_const_iterator test_iter;
- LLSD::array_const_iterator template_iter;
-
- resultant_llsd = LLSD::emptyArray();
- test_iter = llsd_to_test.beginArray();
-
- for (
- template_iter = template_llsd.beginArray();
- (template_iter != template_llsd.endArray() &&
- test_iter != llsd_to_test.endArray());
- ++template_iter)
- {
- if ( !compare_llsd_with_template(
- *test_iter,
- *template_iter,
- data) )
- {
- resultant_llsd = LLSD();
- return FALSE;
- }
- else
- {
- resultant_llsd.append(data);
- }
-
- ++test_iter;
- }
-
- //so either the test or the template ended
- //we do another loop now to the end of the template
- //grabbing the default values
- for (;
- template_iter != template_llsd.endArray();
- ++template_iter)
- {
- resultant_llsd.append(*template_iter);
- }
- }
- else if ( llsd_to_test.isMap() )
- {
- //now we loop over the keys of the two maps
- //any excess is taken from the template
- //excess is ignored in the test
- LLSD value;
- LLSD::map_const_iterator template_iter;
-
- resultant_llsd = LLSD::emptyMap();
- for (
- template_iter = template_llsd.beginMap();
- template_iter != template_llsd.endMap();
- ++template_iter)
- {
- if ( llsd_to_test.has(template_iter->first) )
- {
- //the test LLSD has the same key
- if ( !compare_llsd_with_template(
- llsd_to_test[template_iter->first],
- template_iter->second,
- value) )
- {
- resultant_llsd = LLSD();
- return FALSE;
- }
- else
- {
- resultant_llsd[template_iter->first] = value;
- }
- }
- else
- {
- //test llsd doesn't have it...take the
- //template as default value
- resultant_llsd[template_iter->first] =
- template_iter->second;
- }
- }
- }
- else
- {
- //of same type...take the test llsd's value
- resultant_llsd = llsd_to_test;
- }
-
-
- return TRUE;
+ if (
+ llsd_to_test.isUndefined() &&
+ template_llsd.isDefined() )
+ {
+ resultant_llsd = template_llsd;
+ return TRUE;
+ }
+ else if ( llsd_to_test.type() != template_llsd.type() )
+ {
+ resultant_llsd = LLSD();
+ return FALSE;
+ }
+
+ if ( llsd_to_test.isArray() )
+ {
+ //they are both arrays
+ //we loop over all the items in the template
+ //verifying that the to_test has a subset (in the same order)
+ //any shortcoming in the testing_llsd are just taken
+ //to be the rest of the template
+ LLSD data;
+ LLSD::array_const_iterator test_iter;
+ LLSD::array_const_iterator template_iter;
+
+ resultant_llsd = LLSD::emptyArray();
+ test_iter = llsd_to_test.beginArray();
+
+ for (
+ template_iter = template_llsd.beginArray();
+ (template_iter != template_llsd.endArray() &&
+ test_iter != llsd_to_test.endArray());
+ ++template_iter)
+ {
+ if ( !compare_llsd_with_template(
+ *test_iter,
+ *template_iter,
+ data) )
+ {
+ resultant_llsd = LLSD();
+ return FALSE;
+ }
+ else
+ {
+ resultant_llsd.append(data);
+ }
+
+ ++test_iter;
+ }
+
+ //so either the test or the template ended
+ //we do another loop now to the end of the template
+ //grabbing the default values
+ for (;
+ template_iter != template_llsd.endArray();
+ ++template_iter)
+ {
+ resultant_llsd.append(*template_iter);
+ }
+ }
+ else if ( llsd_to_test.isMap() )
+ {
+ //now we loop over the keys of the two maps
+ //any excess is taken from the template
+ //excess is ignored in the test
+ LLSD value;
+ LLSD::map_const_iterator template_iter;
+
+ resultant_llsd = LLSD::emptyMap();
+ for (
+ template_iter = template_llsd.beginMap();
+ template_iter != template_llsd.endMap();
+ ++template_iter)
+ {
+ if ( llsd_to_test.has(template_iter->first) )
+ {
+ //the test LLSD has the same key
+ if ( !compare_llsd_with_template(
+ llsd_to_test[template_iter->first],
+ template_iter->second,
+ value) )
+ {
+ resultant_llsd = LLSD();
+ return FALSE;
+ }
+ else
+ {
+ resultant_llsd[template_iter->first] = value;
+ }
+ }
+ else
+ {
+ //test llsd doesn't have it...take the
+ //template as default value
+ resultant_llsd[template_iter->first] =
+ template_iter->second;
+ }
+ }
+ }
+ else
+ {
+ //of same type...take the test llsd's value
+ resultant_llsd = llsd_to_test;
+ }
+
+
+ return TRUE;
}
// filter_llsd_with_template() is a direct clone (copy-n-paste) of
@@ -333,171 +333,171 @@ BOOL compare_llsd_with_template(
// for *all* the elements of the test array. If the template array is of
// different size, compare_llsd_with_template() semantics apply.
bool filter_llsd_with_template(
- const LLSD & llsd_to_test,
- const LLSD & template_llsd,
- LLSD & resultant_llsd)
+ const LLSD & llsd_to_test,
+ const LLSD & template_llsd,
+ LLSD & resultant_llsd)
{
LL_PROFILE_ZONE_SCOPED
- if (llsd_to_test.isUndefined() && template_llsd.isDefined())
- {
- resultant_llsd = template_llsd;
- return true;
- }
- else if (llsd_to_test.type() != template_llsd.type())
- {
- resultant_llsd = LLSD();
- return false;
- }
-
- if (llsd_to_test.isArray())
- {
- //they are both arrays
- //we loop over all the items in the template
- //verifying that the to_test has a subset (in the same order)
- //any shortcoming in the testing_llsd are just taken
- //to be the rest of the template
- LLSD data;
- LLSD::array_const_iterator test_iter;
- LLSD::array_const_iterator template_iter;
-
- resultant_llsd = LLSD::emptyArray();
- test_iter = llsd_to_test.beginArray();
-
- if (1 == template_llsd.size())
- {
- // If the template has a single item, treat it as
- // the template for *all* items in the test LLSD.
- template_iter = template_llsd.beginArray();
-
- for (; test_iter != llsd_to_test.endArray(); ++test_iter)
- {
- if (! filter_llsd_with_template(*test_iter, *template_iter, data))
- {
- resultant_llsd = LLSD();
- return false;
- }
- else
- {
- resultant_llsd.append(data);
- }
- }
- }
- else
- {
- // Traditional compare_llsd_with_template matching
-
- for (template_iter = template_llsd.beginArray();
- template_iter != template_llsd.endArray() &&
- test_iter != llsd_to_test.endArray();
- ++template_iter, ++test_iter)
- {
- if (! filter_llsd_with_template(*test_iter, *template_iter, data))
- {
- resultant_llsd = LLSD();
- return false;
- }
- else
- {
- resultant_llsd.append(data);
- }
- }
-
- //so either the test or the template ended
- //we do another loop now to the end of the template
- //grabbing the default values
- for (;
- template_iter != template_llsd.endArray();
- ++template_iter)
- {
- resultant_llsd.append(*template_iter);
- }
- }
- }
- else if (llsd_to_test.isMap())
- {
- resultant_llsd = LLSD::emptyMap();
-
- //now we loop over the keys of the two maps
- //any excess is taken from the template
- //excess is ignored in the test
-
- // Special tag for wildcarded LLSD map key templates
- const LLSD::String wildcard_tag("*");
-
- const bool template_has_wildcard = template_llsd.has(wildcard_tag);
- LLSD wildcard_value;
- LLSD value;
-
- const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
- for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
- template_iter_end != template_iter;
- ++template_iter)
- {
- if (wildcard_tag == template_iter->first)
- {
- wildcard_value = template_iter->second;
- }
- else if (llsd_to_test.has(template_iter->first))
- {
- //the test LLSD has the same key
- if (! filter_llsd_with_template(llsd_to_test[template_iter->first],
- template_iter->second,
- value))
- {
- resultant_llsd = LLSD();
- return false;
- }
- else
- {
- resultant_llsd[template_iter->first] = value;
- }
- }
- else if (! template_has_wildcard)
- {
- // test llsd doesn't have it...take the
- // template as default value
- resultant_llsd[template_iter->first] = template_iter->second;
- }
- }
- if (template_has_wildcard)
- {
- LLSD sub_value;
- LLSD::map_const_iterator test_iter;
-
- for (test_iter = llsd_to_test.beginMap();
- test_iter != llsd_to_test.endMap();
- ++test_iter)
- {
- if (resultant_llsd.has(test_iter->first))
- {
- // Final value has test key, assume more specific
- // template matched and we shouldn't modify it again.
- continue;
- }
- else if (! filter_llsd_with_template(test_iter->second,
- wildcard_value,
- sub_value))
- {
- // Test value doesn't match wildcarded template
- resultant_llsd = LLSD();
- return false;
- }
- else
- {
- // Test value matches template, add the actuals.
- resultant_llsd[test_iter->first] = sub_value;
- }
- }
- }
- }
- else
- {
- //of same type...take the test llsd's value
- resultant_llsd = llsd_to_test;
- }
-
- return true;
+ if (llsd_to_test.isUndefined() && template_llsd.isDefined())
+ {
+ resultant_llsd = template_llsd;
+ return true;
+ }
+ else if (llsd_to_test.type() != template_llsd.type())
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+
+ if (llsd_to_test.isArray())
+ {
+ //they are both arrays
+ //we loop over all the items in the template
+ //verifying that the to_test has a subset (in the same order)
+ //any shortcoming in the testing_llsd are just taken
+ //to be the rest of the template
+ LLSD data;
+ LLSD::array_const_iterator test_iter;
+ LLSD::array_const_iterator template_iter;
+
+ resultant_llsd = LLSD::emptyArray();
+ test_iter = llsd_to_test.beginArray();
+
+ if (1 == template_llsd.size())
+ {
+ // If the template has a single item, treat it as
+ // the template for *all* items in the test LLSD.
+ template_iter = template_llsd.beginArray();
+
+ for (; test_iter != llsd_to_test.endArray(); ++test_iter)
+ {
+ if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ resultant_llsd.append(data);
+ }
+ }
+ }
+ else
+ {
+ // Traditional compare_llsd_with_template matching
+
+ for (template_iter = template_llsd.beginArray();
+ template_iter != template_llsd.endArray() &&
+ test_iter != llsd_to_test.endArray();
+ ++template_iter, ++test_iter)
+ {
+ if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ resultant_llsd.append(data);
+ }
+ }
+
+ //so either the test or the template ended
+ //we do another loop now to the end of the template
+ //grabbing the default values
+ for (;
+ template_iter != template_llsd.endArray();
+ ++template_iter)
+ {
+ resultant_llsd.append(*template_iter);
+ }
+ }
+ }
+ else if (llsd_to_test.isMap())
+ {
+ resultant_llsd = LLSD::emptyMap();
+
+ //now we loop over the keys of the two maps
+ //any excess is taken from the template
+ //excess is ignored in the test
+
+ // Special tag for wildcarded LLSD map key templates
+ const LLSD::String wildcard_tag("*");
+
+ const bool template_has_wildcard = template_llsd.has(wildcard_tag);
+ LLSD wildcard_value;
+ LLSD value;
+
+ const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
+ for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
+ template_iter_end != template_iter;
+ ++template_iter)
+ {
+ if (wildcard_tag == template_iter->first)
+ {
+ wildcard_value = template_iter->second;
+ }
+ else if (llsd_to_test.has(template_iter->first))
+ {
+ //the test LLSD has the same key
+ if (! filter_llsd_with_template(llsd_to_test[template_iter->first],
+ template_iter->second,
+ value))
+ {
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ resultant_llsd[template_iter->first] = value;
+ }
+ }
+ else if (! template_has_wildcard)
+ {
+ // test llsd doesn't have it...take the
+ // template as default value
+ resultant_llsd[template_iter->first] = template_iter->second;
+ }
+ }
+ if (template_has_wildcard)
+ {
+ LLSD sub_value;
+ LLSD::map_const_iterator test_iter;
+
+ for (test_iter = llsd_to_test.beginMap();
+ test_iter != llsd_to_test.endMap();
+ ++test_iter)
+ {
+ if (resultant_llsd.has(test_iter->first))
+ {
+ // Final value has test key, assume more specific
+ // template matched and we shouldn't modify it again.
+ continue;
+ }
+ else if (! filter_llsd_with_template(test_iter->second,
+ wildcard_value,
+ sub_value))
+ {
+ // Test value doesn't match wildcarded template
+ resultant_llsd = LLSD();
+ return false;
+ }
+ else
+ {
+ // Test value matches template, add the actuals.
+ resultant_llsd[test_iter->first] = sub_value;
+ }
+ }
+ }
+ }
+ else
+ {
+ //of same type...take the test llsd's value
+ resultant_llsd = llsd_to_test;
+ }
+
+ return true;
}
/*****************************************************************************
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index fdcc052bd0..aa497c53c7 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdutil.h
* @author Phoenix
* @date 2006-05-24
@@ -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$
*/
@@ -73,11 +73,11 @@ LL_COMMON_API std::string ll_stream_notation_sd(const LLSD& sd);
//Otherwise, returns true
LL_COMMON_API BOOL compare_llsd_with_template(
- const LLSD& llsd_to_test,
- const LLSD& template_llsd,
- LLSD& resultant_llsd);
+ const LLSD& llsd_to_test,
+ const LLSD& template_llsd,
+ LLSD& resultant_llsd);
-// filter_llsd_with_template() is a direct clone (copy-n-paste) of
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of
// compare_llsd_with_template with the following differences:
// (1) bool vs BOOL return types
// (2) A map with the key value "*" is a special value and maps any key in the
@@ -86,9 +86,9 @@ LL_COMMON_API BOOL compare_llsd_with_template(
// for *all* the elements of the test array. If the template array is of
// different size, compare_llsd_with_template() semantics apply.
bool filter_llsd_with_template(
- const LLSD & llsd_to_test,
- const LLSD & template_llsd,
- LLSD & resultant_llsd);
+ const LLSD & llsd_to_test,
+ const LLSD & template_llsd,
+ LLSD & resultant_llsd);
/**
* Recursively determine whether a given LLSD data block "matches" another
@@ -164,12 +164,12 @@ inline bool operator!=(const LLSD& lhs, const LLSD& rhs)
// there is no need for casting.
template<typename Input> LLSD llsd_copy_array(Input iter, Input end)
{
- LLSD dest;
- for (; iter != end; ++iter)
- {
- dest.append(*iter);
- }
- return dest;
+ LLSD dest;
+ for (; iter != end; ++iter)
+ {
+ dest.append(*iter);
+ }
+ return dest;
}
namespace llsd
@@ -526,19 +526,19 @@ private:
} // namespace llsd
-// Creates a deep clone of an LLSD object. Maps, Arrays and binary objects
+// Creates a deep clone of an LLSD object. Maps, Arrays and binary objects
// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply
-// use a shared reference.
-// Optionally a filter may be specified to control what is duplicated. The
+// use a shared reference.
+// Optionally a filter may be specified to control what is duplicated. The
// map takes the form "keyname/boolean".
-// If the value is true the value will be duplicated otherwise it will be skipped
+// If the value is true the value will be duplicated otherwise it will be skipped
// when encountered in a map. A key name of "*" can be specified as a wild card
// and will specify the default behavior. If no wild card is given and the clone
// encounters a name not in the filter, that value will be skipped.
LLSD llsd_clone(LLSD value, LLSD filter = LLSD());
-// Creates a shallow copy of a map or array. If passed any other type of LLSD
-// object it simply returns that value. See llsd_clone for a description of
+// Creates a shallow copy of a map or array. If passed any other type of LLSD
+// object it simply returns that value. See llsd_clone for a description of
// the filter parameter.
LLSD llsd_shallow(LLSD value, LLSD filter = LLSD());
@@ -561,7 +561,7 @@ struct hash<LLSD>
{
typedef LLSD argument_type;
typedef std::size_t result_type;
- result_type operator()(argument_type const& s) const
+ result_type operator()(argument_type const& s) const
{
result_type seed(0);
diff --git a/indra/llcommon/llsimplehash.h b/indra/llcommon/llsimplehash.h
index 727b4568d8..530d566466 100644
--- a/indra/llcommon/llsimplehash.h
+++ b/indra/llcommon/llsimplehash.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llsimplehash.h
*
* $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$
*/
@@ -32,124 +32,124 @@ template <typename HASH_KEY_TYPE>
class LLSimpleHashEntry
{
protected:
- HASH_KEY_TYPE mHashKey;
- LLSimpleHashEntry<HASH_KEY_TYPE>* mNextEntry;
+ HASH_KEY_TYPE mHashKey;
+ LLSimpleHashEntry<HASH_KEY_TYPE>* mNextEntry;
public:
- LLSimpleHashEntry(HASH_KEY_TYPE key) :
- mHashKey(key),
- mNextEntry(0)
- {
- }
- virtual ~LLSimpleHashEntry()
- {
- }
- HASH_KEY_TYPE getHashKey() const
- {
- return mHashKey;
- }
- LLSimpleHashEntry<HASH_KEY_TYPE>* getNextEntry() const
- {
- return mNextEntry;
- }
- void setNextEntry(LLSimpleHashEntry<HASH_KEY_TYPE>* next)
- {
- mNextEntry = next;
- }
+ LLSimpleHashEntry(HASH_KEY_TYPE key) :
+ mHashKey(key),
+ mNextEntry(0)
+ {
+ }
+ virtual ~LLSimpleHashEntry()
+ {
+ }
+ HASH_KEY_TYPE getHashKey() const
+ {
+ return mHashKey;
+ }
+ LLSimpleHashEntry<HASH_KEY_TYPE>* getNextEntry() const
+ {
+ return mNextEntry;
+ }
+ void setNextEntry(LLSimpleHashEntry<HASH_KEY_TYPE>* next)
+ {
+ mNextEntry = next;
+ }
};
template <typename HASH_KEY_TYPE, int TABLE_SIZE>
class LL_COMMON_API LLSimpleHash
{
public:
- LLSimpleHash()
- {
- llassert(TABLE_SIZE);
- llassert((TABLE_SIZE ^ (TABLE_SIZE-1)) == (TABLE_SIZE | (TABLE_SIZE-1))); // power of 2
- memset(mEntryTable, 0, sizeof(mEntryTable));
- }
- virtual ~LLSimpleHash()
- {
- }
+ LLSimpleHash()
+ {
+ llassert(TABLE_SIZE);
+ llassert((TABLE_SIZE ^ (TABLE_SIZE-1)) == (TABLE_SIZE | (TABLE_SIZE-1))); // power of 2
+ memset(mEntryTable, 0, sizeof(mEntryTable));
+ }
+ virtual ~LLSimpleHash()
+ {
+ }
+
+ virtual int getIndex(HASH_KEY_TYPE key)
+ {
+ return key & (TABLE_SIZE-1);
+ }
+
+ bool insert(LLSimpleHashEntry<HASH_KEY_TYPE>* entry)
+ {
+ llassert(entry->getNextEntry() == 0);
+ int index = getIndex(entry->getHashKey());
+ entry->setNextEntry(mEntryTable[index]);
+ mEntryTable[index] = entry;
+ return true;
+ }
+ LLSimpleHashEntry<HASH_KEY_TYPE>* find(HASH_KEY_TYPE key)
+ {
+ int index = getIndex(key);
+ LLSimpleHashEntry<HASH_KEY_TYPE>* res = mEntryTable[index];
+ while(res && (res->getHashKey() != key))
+ {
+ res = res->getNextEntry();
+ }
+ return res;
+ }
+ bool erase(LLSimpleHashEntry<HASH_KEY_TYPE>* entry)
+ {
+ return erase(entry->getHashKey());
+ }
+ bool erase(HASH_KEY_TYPE key)
+ {
+ int index = getIndex(key);
+ LLSimpleHashEntry<HASH_KEY_TYPE>* prev = 0;
+ LLSimpleHashEntry<HASH_KEY_TYPE>* res = mEntryTable[index];
+ while(res && (res->getHashKey() != key))
+ {
+ prev = res;
+ res = res->getNextEntry();
+ }
+ if (res)
+ {
+ LLSimpleHashEntry<HASH_KEY_TYPE>* next = res->getNextEntry();
+ if (prev)
+ {
+ prev->setNextEntry(next);
+ }
+ else
+ {
+ mEntryTable[index] = next;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ // Removes and returns an arbitrary ("first") element from the table
+ // Used for deleting the entire table.
+ LLSimpleHashEntry<HASH_KEY_TYPE>* pop_element()
+ {
+ for (int i=0; i<TABLE_SIZE; i++)
+ {
+ LLSimpleHashEntry<HASH_KEY_TYPE>* entry = mEntryTable[i];
+ if (entry)
+ {
+ mEntryTable[i] = entry->getNextEntry();
+ return entry;
+ }
+ }
+ return 0;
+ }
+ // debugging
+ LLSimpleHashEntry<HASH_KEY_TYPE>* get_element_at_index(S32 index) const
+ {
+ return mEntryTable[index];
+ }
+
- virtual int getIndex(HASH_KEY_TYPE key)
- {
- return key & (TABLE_SIZE-1);
- }
-
- bool insert(LLSimpleHashEntry<HASH_KEY_TYPE>* entry)
- {
- llassert(entry->getNextEntry() == 0);
- int index = getIndex(entry->getHashKey());
- entry->setNextEntry(mEntryTable[index]);
- mEntryTable[index] = entry;
- return true;
- }
- LLSimpleHashEntry<HASH_KEY_TYPE>* find(HASH_KEY_TYPE key)
- {
- int index = getIndex(key);
- LLSimpleHashEntry<HASH_KEY_TYPE>* res = mEntryTable[index];
- while(res && (res->getHashKey() != key))
- {
- res = res->getNextEntry();
- }
- return res;
- }
- bool erase(LLSimpleHashEntry<HASH_KEY_TYPE>* entry)
- {
- return erase(entry->getHashKey());
- }
- bool erase(HASH_KEY_TYPE key)
- {
- int index = getIndex(key);
- LLSimpleHashEntry<HASH_KEY_TYPE>* prev = 0;
- LLSimpleHashEntry<HASH_KEY_TYPE>* res = mEntryTable[index];
- while(res && (res->getHashKey() != key))
- {
- prev = res;
- res = res->getNextEntry();
- }
- if (res)
- {
- LLSimpleHashEntry<HASH_KEY_TYPE>* next = res->getNextEntry();
- if (prev)
- {
- prev->setNextEntry(next);
- }
- else
- {
- mEntryTable[index] = next;
- }
- return true;
- }
- else
- {
- return false;
- }
- }
- // Removes and returns an arbitrary ("first") element from the table
- // Used for deleting the entire table.
- LLSimpleHashEntry<HASH_KEY_TYPE>* pop_element()
- {
- for (int i=0; i<TABLE_SIZE; i++)
- {
- LLSimpleHashEntry<HASH_KEY_TYPE>* entry = mEntryTable[i];
- if (entry)
- {
- mEntryTable[i] = entry->getNextEntry();
- return entry;
- }
- }
- return 0;
- }
- // debugging
- LLSimpleHashEntry<HASH_KEY_TYPE>* get_element_at_index(S32 index) const
- {
- return mEntryTable[index];
- }
-
-
private:
- LLSimpleHashEntry<HASH_KEY_TYPE>* mEntryTable[TABLE_SIZE];
+ LLSimpleHashEntry<HASH_KEY_TYPE>* mEntryTable[TABLE_SIZE];
};
#endif // LL_LLSIMPLEHASH_H
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index 5f1a89670e..d00e703a10 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsingleton.cpp
* @author Brad Kittenbrink
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -363,7 +363,7 @@ LLSingletonBase::vec_t LLSingletonBase::dep_sort()
// should happen basically once: for deleteAll().
typedef LLDependencies<LLSingletonBase*> SingletonDeps;
SingletonDeps sdeps;
- // Lock while traversing the master list
+ // Lock while traversing the master list
MasterList::LockedMaster master;
for (LLSingletonBase* sp : master.get())
{
@@ -455,7 +455,7 @@ std::ostream& operator<<(std::ostream& out, const LLSingletonBase::string_params
return out;
}
-} // anonymous namespace
+} // anonymous namespace
//static
void LLSingletonBase::logwarns(const string_params& args)
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 64027c16c7..91c05bd5ed 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llsingleton.h
*
* $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$
*/
@@ -841,7 +841,7 @@ private: \
// Relatively unsafe singleton implementation that is much faster
// and simpler than LLSingleton, but has no dependency tracking
-// or inherent thread safety and requires manual invocation of
+// or inherent thread safety and requires manual invocation of
// createInstance before first use.
template<class T>
class LLSimpleton
diff --git a/indra/llcommon/llsmoothstep.h b/indra/llcommon/llsmoothstep.h
index 1f97a3ec89..70686c60e2 100644
--- a/indra/llcommon/llsmoothstep.h
+++ b/indra/llcommon/llsmoothstep.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsmoothstep.h
* @brief Smoothstep - transition from 0 to 1 - function, first and second derivatives all continuous (smooth)
*
* $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$
*/
@@ -31,15 +31,15 @@ template <class LLDATATYPE>
inline LLDATATYPE llsmoothstep(const LLDATATYPE& edge0, const LLDATATYPE& edge1, const LLDATATYPE& value)
{
if (value < edge0)
- return (LLDATATYPE)0;
+ return (LLDATATYPE)0;
- if (value >= edge1)
- return (LLDATATYPE)1;
+ if (value >= edge1)
+ return (LLDATATYPE)1;
- // Scale/bias into [0..1] range
- LLDATATYPE scaled_value = (value - edge0) / (edge1 - edge0);
+ // Scale/bias into [0..1] range
+ LLDATATYPE scaled_value = (value - edge0) / (edge1 - edge0);
- return scaled_value * scaled_value * (3 - 2 * scaled_value);
+ return scaled_value * scaled_value * (3 - 2 * scaled_value);
}
#endif // LL_LLSMOOTHSTEP_H
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
index 80057bf0f2..1fe7f0f25f 100644
--- a/indra/llcommon/llstacktrace.cpp
+++ b/indra/llcommon/llstacktrace.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstacktrace.cpp
* @brief stack tracing functionality
*
* $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$
*/
@@ -50,113 +50,113 @@ static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
bool ll_get_stack_trace(std::vector<std::string>& lines)
{
- const S32 MAX_STACK_DEPTH = 32;
- const S32 STRING_NAME_LENGTH = 200;
- const S32 FRAME_SKIP = 2;
- static BOOL symbolsLoaded = false;
- static BOOL firstCall = true;
-
- HANDLE hProc = GetCurrentProcess();
-
- // load the symbols if they're not loaded
- if(!symbolsLoaded && firstCall)
- {
- symbolsLoaded = SymInitialize(hProc, NULL, true);
- firstCall = false;
- }
-
- // if loaded, get the call stack
- if(symbolsLoaded)
- {
- // create the frames to hold the addresses
- void* frames[MAX_STACK_DEPTH];
- memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
- S32 depth = 0;
-
- // get the addresses
- depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
-
- IMAGEHLP_LINE64 line;
- memset(&line, 0, sizeof(IMAGEHLP_LINE64));
- line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-
- // create something to hold address info
- PIMAGEHLP_SYMBOL64 pSym;
- pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
- memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
- pSym->MaxNameLength = STRING_NAME_LENGTH;
- pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
-
- // get address info for each address frame
- // and store
- for(S32 i=0; i < depth; i++)
- {
- std::stringstream stack_line;
- BOOL ret;
-
- DWORD64 addr = (DWORD64)frames[i];
- ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
- if(ret)
- {
- stack_line << pSym->Name << " ";
- }
-
- DWORD dummy;
- ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
- if(ret)
- {
- std::string file_name = line.FileName;
- std::string::size_type index = file_name.rfind("\\");
- stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
- }
-
- lines.push_back(stack_line.str());
- }
-
- free(pSym);
-
- // TODO: figure out a way to cleanup symbol loading
- // Not hugely necessary, however.
- //SymCleanup(hProc);
- return true;
- }
- else
- {
- lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
- }
-
- return false;
+ const S32 MAX_STACK_DEPTH = 32;
+ const S32 STRING_NAME_LENGTH = 200;
+ const S32 FRAME_SKIP = 2;
+ static BOOL symbolsLoaded = false;
+ static BOOL firstCall = true;
+
+ HANDLE hProc = GetCurrentProcess();
+
+ // load the symbols if they're not loaded
+ if(!symbolsLoaded && firstCall)
+ {
+ symbolsLoaded = SymInitialize(hProc, NULL, true);
+ firstCall = false;
+ }
+
+ // if loaded, get the call stack
+ if(symbolsLoaded)
+ {
+ // create the frames to hold the addresses
+ void* frames[MAX_STACK_DEPTH];
+ memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
+ S32 depth = 0;
+
+ // get the addresses
+ depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
+
+ IMAGEHLP_LINE64 line;
+ memset(&line, 0, sizeof(IMAGEHLP_LINE64));
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+ // create something to hold address info
+ PIMAGEHLP_SYMBOL64 pSym;
+ pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+ memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+ pSym->MaxNameLength = STRING_NAME_LENGTH;
+ pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+
+ // get address info for each address frame
+ // and store
+ for(S32 i=0; i < depth; i++)
+ {
+ std::stringstream stack_line;
+ BOOL ret;
+
+ DWORD64 addr = (DWORD64)frames[i];
+ ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
+ if(ret)
+ {
+ stack_line << pSym->Name << " ";
+ }
+
+ DWORD dummy;
+ ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
+ if(ret)
+ {
+ std::string file_name = line.FileName;
+ std::string::size_type index = file_name.rfind("\\");
+ stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
+ }
+
+ lines.push_back(stack_line.str());
+ }
+
+ free(pSym);
+
+ // TODO: figure out a way to cleanup symbol loading
+ // Not hugely necessary, however.
+ //SymCleanup(hProc);
+ return true;
+ }
+ else
+ {
+ lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
+ }
+
+ return false;
}
void ll_get_stack_trace_internal(std::vector<std::string>& lines)
{
- const S32 MAX_STACK_DEPTH = 100;
- const S32 STRING_NAME_LENGTH = 256;
+ const S32 MAX_STACK_DEPTH = 100;
+ const S32 STRING_NAME_LENGTH = 256;
- HANDLE process = GetCurrentProcess();
- SymInitialize( process, NULL, TRUE );
+ HANDLE process = GetCurrentProcess();
+ SymInitialize( process, NULL, TRUE );
- void *stack[MAX_STACK_DEPTH];
+ void *stack[MAX_STACK_DEPTH];
- unsigned short frames = RtlCaptureStackBackTrace_fn( 0, MAX_STACK_DEPTH, stack, NULL );
- SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + STRING_NAME_LENGTH * sizeof(char), 1);
- symbol->MaxNameLen = STRING_NAME_LENGTH-1;
- symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ unsigned short frames = RtlCaptureStackBackTrace_fn( 0, MAX_STACK_DEPTH, stack, NULL );
+ SYMBOL_INFO *symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + STRING_NAME_LENGTH * sizeof(char), 1);
+ symbol->MaxNameLen = STRING_NAME_LENGTH-1;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- for(unsigned int i = 0; i < frames; i++)
- {
- SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
- lines.push_back(symbol->Name);
- }
+ for(unsigned int i = 0; i < frames; i++)
+ {
+ SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
+ lines.push_back(symbol->Name);
+ }
- free( symbol );
+ free( symbol );
}
#else
bool ll_get_stack_trace(std::vector<std::string>& lines)
{
- return false;
+ return false;
}
void ll_get_stack_trace_internal(std::vector<std::string>& lines)
diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h
index 335765386a..693eeced63 100644
--- a/indra/llcommon/llstacktrace.h
+++ b/indra/llcommon/llstacktrace.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstacktrace.h
* @brief stack trace functions
*
* $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$
*/
diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h
index 6515a3e3cb..99f3d3c870 100644
--- a/indra/llcommon/llstatenums.h
+++ b/indra/llcommon/llstatenums.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llstatenums.h
*
* $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$
*/
diff --git a/indra/llcommon/llstaticstringtable.h b/indra/llcommon/llstaticstringtable.h
index d7e0e8a08d..66ba3487c4 100644
--- a/indra/llcommon/llstaticstringtable.h
+++ b/indra/llcommon/llstaticstringtable.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llstringtable.h
* @brief The LLStringTable class provides a _fast_ method for finding
* unique copies of strings.
@@ -6,21 +6,21 @@
* $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$
*/
@@ -36,45 +36,45 @@ class LLStaticHashedString
{
public:
- LLStaticHashedString(const std::string& s)
- {
- string_hash = makehash(s);
- string = s;
- }
+ LLStaticHashedString(const std::string& s)
+ {
+ string_hash = makehash(s);
+ string = s;
+ }
- const std::string& String() const { return string; }
- size_t Hash() const { return string_hash; }
+ const std::string& String() const { return string; }
+ size_t Hash() const { return string_hash; }
- bool operator==(const LLStaticHashedString& b) const { return Hash() == b.Hash(); }
+ bool operator==(const LLStaticHashedString& b) const { return Hash() == b.Hash(); }
protected:
- size_t makehash(const std::string& s)
- {
- size_t len = s.size();
- const char* c = s.c_str();
- size_t hashval = 0;
- for (size_t i=0; i<len; i++)
- {
- hashval = ((hashval<<5) + hashval) + *c++;
- }
- return hashval;
- }
+ size_t makehash(const std::string& s)
+ {
+ size_t len = s.size();
+ const char* c = s.c_str();
+ size_t hashval = 0;
+ for (size_t i=0; i<len; i++)
+ {
+ hashval = ((hashval<<5) + hashval) + *c++;
+ }
+ return hashval;
+ }
- std::string string;
- size_t string_hash;
+ std::string string;
+ size_t string_hash;
};
struct LLStaticStringHasher
{
- enum { bucket_size = 8 };
- size_t operator()(const LLStaticHashedString& key_value) const { return key_value.Hash(); }
- bool operator()(const LLStaticHashedString& left, const LLStaticHashedString& right) const { return left.Hash() < right.Hash(); }
+ enum { bucket_size = 8 };
+ size_t operator()(const LLStaticHashedString& key_value) const { return key_value.Hash(); }
+ bool operator()(const LLStaticHashedString& left, const LLStaticHashedString& right) const { return left.Hash() < right.Hash(); }
};
template< typename MappedObject >
class LL_COMMON_API LLStaticStringTable
- : public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
+ : public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
{
};
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 25131291f9..3a6efd7d34 100644
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstl.h
* @brief helper object & functions for use with the stl.
*
* $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$
*/
@@ -41,39 +41,39 @@
#include <string.h>
#endif
// Use to compare the first element only of a pair
-// e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t;
+// e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t;
template <typename T1, typename T2>
struct compare_pair_first
{
- bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const
- {
- return a.first < b.first;
- }
+ bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const
+ {
+ return a.first < b.first;
+ }
};
template <typename T1, typename T2>
struct compare_pair_greater
{
- bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const
- {
- if (!(a.first < b.first))
- return true;
- else if (!(b.first < a.first))
- return false;
- else
- return !(a.second < b.second);
- }
+ bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const
+ {
+ if (!(a.first < b.first))
+ return true;
+ else if (!(b.first < a.first))
+ return false;
+ else
+ return !(a.second < b.second);
+ }
};
// Use to compare the contents of two pointers (e.g. std::string*)
template <typename T>
struct compare_pointer_contents
{
- typedef const T* Tptr;
- bool operator()(const Tptr& a, const Tptr& b) const
- {
- return *a < *b;
- }
+ typedef const T* Tptr;
+ bool operator()(const Tptr& a, const Tptr& b) const
+ {
+ return *a < *b;
+ }
};
// DeletePointer is a simple helper for deleting all pointers in a container.
@@ -86,40 +86,40 @@ struct compare_pointer_contents
struct DeletePointer
{
- template<typename T> void operator()(T* ptr) const
- {
- delete ptr;
- }
+ template<typename T> void operator()(T* ptr) const
+ {
+ delete ptr;
+ }
};
struct DeletePointerArray
{
- template<typename T> void operator()(T* ptr) const
- {
- delete[] ptr;
- }
+ template<typename T> void operator()(T* ptr) const
+ {
+ delete[] ptr;
+ }
};
// DeletePairedPointer is a simple helper for deleting all pointers in a map.
// The general form is:
//
// std::for_each(somemap.begin(), somemap.end(), DeletePairedPointer());
-// somemap.clear(); // Don't leave dangling pointers around
+// somemap.clear(); // Don't leave dangling pointers around
struct DeletePairedPointer
{
- template<typename T> void operator()(T &ptr) const
- {
- delete ptr.second;
- ptr.second = NULL;
- }
+ template<typename T> void operator()(T &ptr) const
+ {
+ delete ptr.second;
+ ptr.second = NULL;
+ }
};
struct DeletePairedPointerArray
{
- template<typename T> void operator()(T &ptr) const
- {
- delete[] ptr.second;
- ptr.second = NULL;
- }
+ template<typename T> void operator()(T &ptr) const
+ {
+ delete[] ptr.second;
+ ptr.second = NULL;
+ }
};
@@ -144,22 +144,22 @@ struct DeletePairedPointerArray
template<typename T>
struct DeletePointerFunctor
{
- bool operator()(T* ptr) const
- {
- delete ptr;
- return true;
- }
+ bool operator()(T* ptr) const
+ {
+ delete ptr;
+ return true;
+ }
};
// See notes about DeleteArray for why you should consider avoiding this.
template<typename T>
struct DeleteArrayFunctor
{
- bool operator()(T* ptr) const
- {
- delete[] ptr;
- return true;
- }
+ bool operator()(T* ptr) const
+ {
+ delete[] ptr;
+ return true;
+ }
};
// CopyNewPointer is a simple helper which accepts a pointer, and
@@ -169,91 +169,91 @@ struct DeleteArrayFunctor
struct CopyNewPointer
{
- template<typename T> T* operator()(const T* ptr) const
- {
- return new T(*ptr);
- }
+ template<typename T> T* operator()(const T* ptr) const
+ {
+ return new T(*ptr);
+ }
};
template<typename T, typename ALLOC>
void delete_and_clear(std::list<T*, ALLOC>& list)
{
- std::for_each(list.begin(), list.end(), DeletePointer());
- list.clear();
+ std::for_each(list.begin(), list.end(), DeletePointer());
+ list.clear();
}
template<typename T, typename ALLOC>
void delete_and_clear(std::vector<T*, ALLOC>& vector)
{
- std::for_each(vector.begin(), vector.end(), DeletePointer());
- vector.clear();
+ std::for_each(vector.begin(), vector.end(), DeletePointer());
+ vector.clear();
}
template<typename T, typename COMPARE, typename ALLOC>
void delete_and_clear(std::set<T*, COMPARE, ALLOC>& set)
{
- std::for_each(set.begin(), set.end(), DeletePointer());
- set.clear();
+ std::for_each(set.begin(), set.end(), DeletePointer());
+ set.clear();
}
template<typename K, typename V, typename COMPARE, typename ALLOC>
void delete_and_clear(std::map<K, V*, COMPARE, ALLOC>& map)
{
- std::for_each(map.begin(), map.end(), DeletePairedPointer());
- map.clear();
+ std::for_each(map.begin(), map.end(), DeletePairedPointer());
+ map.clear();
}
template<typename T>
void delete_and_clear(T*& ptr)
{
- delete ptr;
- ptr = NULL;
+ delete ptr;
+ ptr = NULL;
}
template<typename T>
void delete_and_clear_array(T*& ptr)
{
- delete[] ptr;
- ptr = NULL;
+ delete[] ptr;
+ ptr = NULL;
}
// Simple function to help with finding pointers in maps.
// For example:
-// typedef map_t;
+// typedef map_t;
// std::map<int, const char*> foo;
-// foo[18] = "there";
-// foo[2] = "hello";
-// const char* bar = get_ptr_in_map(foo, 2); // bar -> "hello"
+// foo[18] = "there";
+// foo[2] = "hello";
+// const char* bar = get_ptr_in_map(foo, 2); // bar -> "hello"
// const char* baz = get_ptr_in_map(foo, 3); // baz == NULL
template <typename K, typename T>
inline T* get_ptr_in_map(const std::map<K,T*>& inmap, const K& key)
{
- // Typedef here avoids warnings because of new c++ naming rules.
- typedef typename std::map<K,T*>::const_iterator map_iter;
- map_iter iter = inmap.find(key);
- if(iter == inmap.end())
- {
- return NULL;
- }
- else
- {
- return iter->second;
- }
+ // Typedef here avoids warnings because of new c++ naming rules.
+ typedef typename std::map<K,T*>::const_iterator map_iter;
+ map_iter iter = inmap.find(key);
+ if(iter == inmap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return iter->second;
+ }
};
// helper function which returns true if key is in inmap.
template <typename K, typename T>
inline bool is_in_map(const std::map<K,T>& inmap, const K& key)
{
- if(inmap.find(key) == inmap.end())
- {
- return false;
- }
- else
- {
- return true;
- }
+ if(inmap.find(key) == inmap.end())
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
// Similar to get_ptr_in_map, but for any type with a valid T(0) constructor.
@@ -263,17 +263,17 @@ inline bool is_in_map(const std::map<K,T>& inmap, const K& key)
template <typename K, typename T>
inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
{
- // Typedef here avoids warnings because of new c++ naming rules.
- typedef typename std::map<K,T>::const_iterator map_iter;
- map_iter iter = inmap.find(key);
- if(iter == inmap.end())
- {
- return default_value;
- }
- else
- {
- return iter->second;
- }
+ // Typedef here avoids warnings because of new c++ naming rules.
+ typedef typename std::map<K,T>::const_iterator map_iter;
+ map_iter iter = inmap.find(key);
+ if(iter == inmap.end())
+ {
+ return default_value;
+ }
+ else
+ {
+ return iter->second;
+ }
};
// Useful for replacing the removeObj() functionality of LLDynamicArray
@@ -288,22 +288,22 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
template <typename T>
inline typename std::vector<T>::iterator vector_replace_with_last(std::vector<T>& invec, typename std::vector<T>::iterator iter)
{
- typename std::vector<T>::iterator last = invec.end(); --last;
- if (iter == invec.end())
- {
- return iter;
- }
- else if (iter == last)
- {
- invec.pop_back();
- return invec.end();
- }
- else
- {
- *iter = *last;
- invec.pop_back();
- return iter;
- }
+ typename std::vector<T>::iterator last = invec.end(); --last;
+ if (iter == invec.end())
+ {
+ return iter;
+ }
+ else if (iter == last)
+ {
+ invec.pop_back();
+ return invec.end();
+ }
+ else
+ {
+ *iter = *last;
+ invec.pop_back();
+ return iter;
+ }
};
// Example:
@@ -311,55 +311,55 @@ inline typename std::vector<T>::iterator vector_replace_with_last(std::vector<T>
template <typename T>
inline bool vector_replace_with_last(std::vector<T>& invec, const T& val)
{
- typename std::vector<T>::iterator iter = std::find(invec.begin(), invec.end(), val);
- if (iter != invec.end())
- {
- typename std::vector<T>::iterator last = invec.end(); --last;
- *iter = *last;
- invec.pop_back();
- return true;
- }
- return false;
+ typename std::vector<T>::iterator iter = std::find(invec.begin(), invec.end(), val);
+ if (iter != invec.end())
+ {
+ typename std::vector<T>::iterator last = invec.end(); --last;
+ *iter = *last;
+ invec.pop_back();
+ return true;
+ }
+ return false;
}
// Append N elements to the vector and return a pointer to the first new element.
template <typename T>
inline T* vector_append(std::vector<T>& invec, S32 N)
{
- U32 sz = invec.size();
- invec.resize(sz+N);
- return &(invec[sz]);
+ U32 sz = invec.size();
+ invec.resize(sz+N);
+ return &(invec[sz]);
}
// call function f to n members starting at first. similar to std::for_each
template <class InputIter, class Size, class Function>
Function ll_for_n(InputIter first, Size n, Function f)
{
- for ( ; n > 0; --n, ++first)
- f(*first);
- return f;
+ for ( ; n > 0; --n, ++first)
+ f(*first);
+ return f;
}
// copy first to result n times, incrementing each as we go
template <class InputIter, class Size, class OutputIter>
OutputIter ll_copy_n(InputIter first, Size n, OutputIter result)
{
- for ( ; n > 0; --n, ++result, ++first)
- *result = *first;
- return result;
+ for ( ; n > 0; --n, ++result, ++first)
+ *result = *first;
+ return result;
}
// set *result = op(*f) for n elements of f
template <class InputIter, class OutputIter, class Size, class UnaryOp>
OutputIter ll_transform_n(
- InputIter first,
- Size n,
- OutputIter result,
- UnaryOp op)
-{
- for ( ; n > 0; --n, ++result, ++first)
- *result = op(*first);
- return result;
+ InputIter first,
+ Size n,
+ OutputIter result,
+ UnaryOp op)
+{
+ for ( ; n > 0; --n, ++result, ++first)
+ *result = op(*first);
+ return result;
}
@@ -448,7 +448,7 @@ protected:
_Operation3 _M_op3;
public:
ll_binary_compose(const _Operation1& __x, const _Operation2& __y,
- const _Operation3& __z)
+ const _Operation3& __z)
: _M_op1(__x), _M_op2(__y), _M_op3(__z) { }
template<typename OP2ARG>
auto
@@ -495,17 +495,17 @@ template <class _Operation, typename _Arg2>
class llbinder2nd
{
protected:
- _Operation op;
- _Arg2 value;
+ _Operation op;
+ _Arg2 value;
public:
- llbinder2nd(const _Operation& __x,
- const _Arg2& __y)
- : op(__x), value(__y) {}
- template <typename _Arg1>
- auto
- operator()(const _Arg1& __x) const {
- return op(__x, value);
- }
+ llbinder2nd(const _Operation& __x,
+ const _Arg2& __y)
+ : op(__x), value(__y) {}
+ template <typename _Arg1>
+ auto
+ operator()(const _Arg1& __x) const {
+ return op(__x, value);
+ }
};
template <class _Operation, class _Tp>
@@ -544,23 +544,23 @@ bool before(const std::type_info* lhs, const std::type_info* rhs)
*/
namespace std
{
- template <>
- struct less<const std::type_info*>
- {
- bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
- {
- return before(lhs, rhs);
- }
- };
-
- template <>
- struct less<std::type_info*>
- {
- bool operator()(std::type_info* lhs, std::type_info* rhs) const
- {
- return before(lhs, rhs);
- }
- };
+ template <>
+ struct less<const std::type_info*>
+ {
+ bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+ {
+ return before(lhs, rhs);
+ }
+ };
+
+ template <>
+ struct less<std::type_info*>
+ {
+ bool operator()(std::type_info* lhs, std::type_info* rhs) const
+ {
+ return before(lhs, rhs);
+ }
+ };
} // std
diff --git a/indra/llcommon/llstreamqueue.cpp b/indra/llcommon/llstreamqueue.cpp
index 1116a2b6a2..981d913749 100644
--- a/indra/llcommon/llstreamqueue.cpp
+++ b/indra/llcommon/llstreamqueue.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-01-05
* @brief Implementation for llstreamqueue.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llstreamqueue.h b/indra/llcommon/llstreamqueue.h
index 0726bad175..a09bf4cb4b 100644
--- a/indra/llcommon/llstreamqueue.h
+++ b/indra/llcommon/llstreamqueue.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-01-04
* @brief Definition of LLStreamQueue
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp
index bc32b6fd9e..1021b08ad1 100644
--- a/indra/llcommon/llstreamtools.cpp
+++ b/indra/llcommon/llstreamtools.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstreamtools.cpp
* @brief some helper functions for parsing legacy simstate and asset files.
*
* $LicenseInfo:firstyear=2005&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,275 +39,275 @@
// skips spaces and tabs
bool skip_whitespace(std::istream& input_stream)
{
- int c = input_stream.peek();
- while (('\t' == c || ' ' == c) && input_stream.good())
- {
- input_stream.get();
- c = input_stream.peek();
- }
- return input_stream.good();
+ int c = input_stream.peek();
+ while (('\t' == c || ' ' == c) && input_stream.good())
+ {
+ input_stream.get();
+ c = input_stream.peek();
+ }
+ return input_stream.good();
}
// skips whitespace, newlines, and carriage returns
bool skip_emptyspace(std::istream& input_stream)
{
- int c = input_stream.peek();
- while ( input_stream.good()
- && ('\t' == c || ' ' == c || '\n' == c || '\r' == c) )
- {
- input_stream.get();
- c = input_stream.peek();
- }
- return input_stream.good();
+ int c = input_stream.peek();
+ while ( input_stream.good()
+ && ('\t' == c || ' ' == c || '\n' == c || '\r' == c) )
+ {
+ input_stream.get();
+ c = input_stream.peek();
+ }
+ return input_stream.good();
}
// skips emptyspace and lines that start with a #
bool skip_comments_and_emptyspace(std::istream& input_stream)
{
- while (skip_emptyspace(input_stream))
- {
- int c = input_stream.peek();
- if ('#' == c )
- {
- while ('\n' != c && input_stream.good())
- {
- c = input_stream.get();
- }
- }
- else
- {
- break;
- }
- }
- return input_stream.good();
+ while (skip_emptyspace(input_stream))
+ {
+ int c = input_stream.peek();
+ if ('#' == c )
+ {
+ while ('\n' != c && input_stream.good())
+ {
+ c = input_stream.get();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ return input_stream.good();
}
bool skip_line(std::istream& input_stream)
{
- int c;
- do
- {
- c = input_stream.get();
- } while ('\n' != c && input_stream.good());
- return input_stream.good();
+ int c;
+ do
+ {
+ c = input_stream.get();
+ } while ('\n' != c && input_stream.good());
+ return input_stream.good();
}
bool skip_to_next_word(std::istream& input_stream)
{
- int c = input_stream.peek();
- while ( input_stream.good()
- && ( (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || '_' == c ) )
- {
- input_stream.get();
- c = input_stream.peek();
- }
- while ( input_stream.good()
- && !( (c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || '_' == c ) )
- {
- input_stream.get();
- c = input_stream.peek();
- }
- return input_stream.good();
+ int c = input_stream.peek();
+ while ( input_stream.good()
+ && ( (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || '_' == c ) )
+ {
+ input_stream.get();
+ c = input_stream.peek();
+ }
+ while ( input_stream.good()
+ && !( (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || '_' == c ) )
+ {
+ input_stream.get();
+ c = input_stream.peek();
+ }
+ return input_stream.good();
}
bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream)
{
- auto key_length = strlen(keyword); /*Flawfinder: ignore*/
- if (0 == key_length)
- {
- return false;
- }
- while (input_stream.good())
- {
- skip_emptyspace(input_stream);
- int c = input_stream.get();
- if (keyword[0] != c)
- {
- skip_line(input_stream);
- }
- else
- {
- int key_index = 1;
- while ( key_index < key_length
- && keyword[key_index - 1] == c
- && input_stream.good())
- {
- key_index++;
- c = input_stream.get();
- }
-
- if (key_index == key_length
- && keyword[key_index-1] == c)
- {
- c = input_stream.peek();
- if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
- {
- return true;
- }
- else
- {
- skip_line(input_stream);
- }
- }
- else
- {
- skip_line(input_stream);
- }
- }
- }
- return false;
+ auto key_length = strlen(keyword); /*Flawfinder: ignore*/
+ if (0 == key_length)
+ {
+ return false;
+ }
+ while (input_stream.good())
+ {
+ skip_emptyspace(input_stream);
+ int c = input_stream.get();
+ if (keyword[0] != c)
+ {
+ skip_line(input_stream);
+ }
+ else
+ {
+ int key_index = 1;
+ while ( key_index < key_length
+ && keyword[key_index - 1] == c
+ && input_stream.good())
+ {
+ key_index++;
+ c = input_stream.get();
+ }
+
+ if (key_index == key_length
+ && keyword[key_index-1] == c)
+ {
+ c = input_stream.peek();
+ if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
+ {
+ return true;
+ }
+ else
+ {
+ skip_line(input_stream);
+ }
+ }
+ else
+ {
+ skip_line(input_stream);
+ }
+ }
+ }
+ return false;
}
/* skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug in windows iostream
bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stream)
{
- int key_length = strlen(keyword);
- if (0 == key_length)
- {
- return false;
- }
- while (input_stream.good())
- {
- skip_emptyspace(input_stream);
- int c = input_stream.get();
- if (keyword[0] != c)
- {
- skip_line(input_stream);
- }
- else
- {
- int key_index = 1;
- while ( key_index < key_length
- && keyword[key_index - 1] == c
- && input_stream.good())
- {
- key_index++;
- c = input_stream.get();
- }
-
- if (key_index == key_length
- && keyword[key_index-1] == c)
- {
- c = input_stream.peek();
- if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
- {
- // put the keyword back onto the stream
- for (int index = key_length - 1; index >= 0; index--)
- {
- input_stream.putback(keyword[index]);
- }
- return true;
- }
- else
- {
- skip_line(input_stream);
- break;
- }
- }
- else
- {
- skip_line(input_stream);
- }
- }
- }
- return false;
+ int key_length = strlen(keyword);
+ if (0 == key_length)
+ {
+ return false;
+ }
+ while (input_stream.good())
+ {
+ skip_emptyspace(input_stream);
+ int c = input_stream.get();
+ if (keyword[0] != c)
+ {
+ skip_line(input_stream);
+ }
+ else
+ {
+ int key_index = 1;
+ while ( key_index < key_length
+ && keyword[key_index - 1] == c
+ && input_stream.good())
+ {
+ key_index++;
+ c = input_stream.get();
+ }
+
+ if (key_index == key_length
+ && keyword[key_index-1] == c)
+ {
+ c = input_stream.peek();
+ if (' ' == c || '\t' == c || '\r' == c || '\n' == c)
+ {
+ // put the keyword back onto the stream
+ for (int index = key_length - 1; index >= 0; index--)
+ {
+ input_stream.putback(keyword[index]);
+ }
+ return true;
+ }
+ else
+ {
+ skip_line(input_stream);
+ break;
+ }
+ }
+ else
+ {
+ skip_line(input_stream);
+ }
+ }
+ }
+ return false;
}
*/
bool get_word(std::string& output_string, std::istream& input_stream)
{
- skip_emptyspace(input_stream);
- int c = input_stream.peek();
- while ( !isspace(c)
- && '\n' != c
- && '\r' != c
- && input_stream.good() )
- {
- output_string += c;
- input_stream.get();
- c = input_stream.peek();
- }
- return input_stream.good();
+ skip_emptyspace(input_stream);
+ int c = input_stream.peek();
+ while ( !isspace(c)
+ && '\n' != c
+ && '\r' != c
+ && input_stream.good() )
+ {
+ output_string += c;
+ input_stream.get();
+ c = input_stream.peek();
+ }
+ return input_stream.good();
}
bool get_word(std::string& output_string, std::istream& input_stream, int n)
{
- skip_emptyspace(input_stream);
- int char_count = 0;
- int c = input_stream.peek();
- while (!isspace(c)
- && '\n' != c
- && '\r' != c
- && input_stream.good()
- && char_count < n)
- {
- char_count++;
- output_string += c;
- input_stream.get();
- c = input_stream.peek();
- }
- return input_stream.good();
+ skip_emptyspace(input_stream);
+ int char_count = 0;
+ int c = input_stream.peek();
+ while (!isspace(c)
+ && '\n' != c
+ && '\r' != c
+ && input_stream.good()
+ && char_count < n)
+ {
+ char_count++;
+ output_string += c;
+ input_stream.get();
+ c = input_stream.peek();
+ }
+ return input_stream.good();
}
// get everything up to and including the next newline
bool get_line(std::string& output_string, std::istream& input_stream)
{
- output_string.clear();
- int c = input_stream.get();
- while (input_stream.good())
- {
- output_string += c;
- if ('\n' == c)
- {
- break;
- }
- c = input_stream.get();
- }
- return input_stream.good();
+ output_string.clear();
+ int c = input_stream.get();
+ while (input_stream.good())
+ {
+ output_string += c;
+ if ('\n' == c)
+ {
+ break;
+ }
+ c = input_stream.get();
+ }
+ return input_stream.good();
}
// get everything up to and including the next newline
-// up to the next n characters.
+// up to the next n characters.
// add a newline on the end if bail before actual line ending
bool get_line(std::string& output_string, std::istream& input_stream, int n)
{
- output_string.clear();
- int char_count = 0;
- int c = input_stream.get();
- while (input_stream.good() && char_count < n)
- {
- char_count++;
- output_string += c;
- if ('\n' == c)
- {
- break;
- }
- if (char_count >= n)
- {
- output_string.append("\n");
- break;
- }
- c = input_stream.get();
- }
- return input_stream.good();
+ output_string.clear();
+ int char_count = 0;
+ int c = input_stream.get();
+ while (input_stream.good() && char_count < n)
+ {
+ char_count++;
+ output_string += c;
+ if ('\n' == c)
+ {
+ break;
+ }
+ if (char_count >= n)
+ {
+ output_string.append("\n");
+ break;
+ }
+ c = input_stream.get();
+ }
+ return input_stream.good();
}
/* disabled -- might tickle bug in windows iostream
// backs up the input_stream by line_size + 1 characters
bool unget_line(const std::string& line, std::istream& input_stream)
{
- input_stream.putback('\n'); // unget the newline
- for (int line_index = line.size()-1; line_index >= 0; line_index--)
- {
- input_stream.putback(line[line_index]);
- }
- return input_stream.good();
+ input_stream.putback('\n'); // unget the newline
+ for (int line_index = line.size()-1; line_index >= 0; line_index--)
+ {
+ input_stream.putback(line[line_index]);
+ }
+ return input_stream.good();
}
*/
@@ -315,14 +315,14 @@ bool unget_line(const std::string& line, std::istream& input_stream)
// returns true if removed last char
bool remove_last_char(char c, std::string& line)
{
- auto line_size = line.size();
- if (line_size > 1
- && c == line[line_size - 1])
- {
- line.replace(line_size - 1, 1, "");
- return true;
- }
- return false;
+ auto line_size = line.size();
+ if (line_size > 1
+ && c == line[line_size - 1])
+ {
+ line.replace(line_size - 1, 1, "");
+ return true;
+ }
+ return false;
}
// replaces escaped characters with the correct characters from left to right
@@ -330,23 +330,23 @@ bool remove_last_char(char c, std::string& line)
// "\\n" ---> '\n' (backslash n becomes carriage return)
void unescape_string(std::string& line)
{
- auto line_size = line.size();
- for (size_t index = 0; line_size >= 1 && index < line_size - 1; ++index)
- {
- if ('\\' == line[index])
- {
- if ('\\' == line[index + 1])
- {
- line.replace(index, 2, "\\");
- line_size--;
- }
- else if ('n' == line[index + 1])
- {
- line.replace(index, 2, "\n");
- line_size--;
- }
- }
- }
+ auto line_size = line.size();
+ for (size_t index = 0; line_size >= 1 && index < line_size - 1; ++index)
+ {
+ if ('\\' == line[index])
+ {
+ if ('\\' == line[index + 1])
+ {
+ line.replace(index, 2, "\\");
+ line_size--;
+ }
+ else if ('n' == line[index + 1])
+ {
+ line.replace(index, 2, "\n");
+ line_size--;
+ }
+ }
+ }
}
// replaces unescaped characters with expanded equivalents from left to right
@@ -354,164 +354,164 @@ void unescape_string(std::string& line)
// '\n' ---> "\\n" (carriage return becomes backslash n)
void escape_string(std::string& line)
{
- auto line_size = line.size();
- for (size_t index = 0; index < line_size; ++index)
- {
- if ('\\' == line[index])
- {
- line.replace(index, 1, "\\\\");
- line_size++;
- index++;
- }
- else if ('\n' == line[index])
- {
- line.replace(index, 1, "\\n");
- line_size++;
- index++;
- }
- }
+ auto line_size = line.size();
+ for (size_t index = 0; index < line_size; ++index)
+ {
+ if ('\\' == line[index])
+ {
+ line.replace(index, 1, "\\\\");
+ line_size++;
+ index++;
+ }
+ else if ('\n' == line[index])
+ {
+ line.replace(index, 1, "\\n");
+ line_size++;
+ index++;
+ }
+ }
}
// removes '\n' characters
void replace_newlines_with_whitespace(std::string& line)
{
- auto line_size = line.size();
- for (size_t index = 0; index < line_size; ++index)
- {
- if ('\n' == line[index])
- {
- line.replace(index, 1, " ");
- }
- }
+ auto line_size = line.size();
+ for (size_t index = 0; index < line_size; ++index)
+ {
+ if ('\n' == line[index])
+ {
+ line.replace(index, 1, " ");
+ }
+ }
}
// erases any double-quote characters in 'line'
void remove_double_quotes(std::string& line)
{
- auto line_size = line.size();
- for (size_t index = 0; index < line_size; )
- {
- if ('"' == line[index])
- {
- int count = 1;
- while (index + count < line_size
- && '"' == line[index + count])
- {
- count++;
- }
- line.replace(index, count, "");
- line_size -= count;
- }
- else
- {
- index++;
- }
- }
+ auto line_size = line.size();
+ for (size_t index = 0; index < line_size; )
+ {
+ if ('"' == line[index])
+ {
+ int count = 1;
+ while (index + count < line_size
+ && '"' == line[index + count])
+ {
+ count++;
+ }
+ line.replace(index, count, "");
+ line_size -= count;
+ }
+ else
+ {
+ index++;
+ }
+ }
}
// the 'keyword' is defined as the first word on a line
// the 'value' is everything after the keyword on the same line
// starting at the first non-whitespace and ending right before the newline
-void get_keyword_and_value(std::string& keyword,
- std::string& value,
- const std::string& line)
+void get_keyword_and_value(std::string& keyword,
+ std::string& value,
+ const std::string& line)
{
- // skip initial whitespace
- auto line_size = line.size();
- size_t line_index = 0;
- char c;
- for ( ; line_index < line_size; ++line_index)
- {
- c = line[line_index];
- if (!LLStringOps::isSpace(c))
- {
- break;
- }
- }
-
- // get the keyword
- keyword.clear();
- for ( ; line_index < line_size; ++line_index)
- {
- c = line[line_index];
- if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c)
- {
- break;
- }
- keyword += c;
- }
-
- // get the value
- value.clear();
- if (keyword.size() > 0
- && '\r' != line[line_index]
- && '\n' != line[line_index])
-
- {
- // discard initial white spaces
- while (line_index < line_size
- && (' ' == line[line_index]
- || '\t' == line[line_index]) )
- {
- line_index++;
- }
-
- for ( ; line_index < line_size; ++line_index)
- {
- c = line[line_index];
- if ('\r' == c || '\n' == c)
- {
- break;
- }
- value += c;
- }
- }
+ // skip initial whitespace
+ auto line_size = line.size();
+ size_t line_index = 0;
+ char c;
+ for ( ; line_index < line_size; ++line_index)
+ {
+ c = line[line_index];
+ if (!LLStringOps::isSpace(c))
+ {
+ break;
+ }
+ }
+
+ // get the keyword
+ keyword.clear();
+ for ( ; line_index < line_size; ++line_index)
+ {
+ c = line[line_index];
+ if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c)
+ {
+ break;
+ }
+ keyword += c;
+ }
+
+ // get the value
+ value.clear();
+ if (keyword.size() > 0
+ && '\r' != line[line_index]
+ && '\n' != line[line_index])
+
+ {
+ // discard initial white spaces
+ while (line_index < line_size
+ && (' ' == line[line_index]
+ || '\t' == line[line_index]) )
+ {
+ line_index++;
+ }
+
+ for ( ; line_index < line_size; ++line_index)
+ {
+ c = line[line_index];
+ if ('\r' == c || '\n' == c)
+ {
+ break;
+ }
+ value += c;
+ }
+ }
}
std::streamsize fullread(
- std::istream& istr,
- char* buf,
- std::streamsize requested)
+ std::istream& istr,
+ char* buf,
+ std::streamsize requested)
{
- std::streamsize got;
- std::streamsize total = 0;
-
- istr.read(buf, requested); /*Flawfinder: ignore*/
- got = istr.gcount();
- total += got;
- while(got && total < requested)
- {
- if(istr.fail())
- {
- // If bad is true, not much we can doo -- it implies loss
- // of stream integrity. Bail in that case, and otherwise
- // clear and attempt to continue.
- if(istr.bad()) return total;
- istr.clear();
- }
- istr.read(buf + total, requested - total); /*Flawfinder: ignore*/
- got = istr.gcount();
- total += got;
- }
- return total;
+ std::streamsize got;
+ std::streamsize total = 0;
+
+ istr.read(buf, requested); /*Flawfinder: ignore*/
+ got = istr.gcount();
+ total += got;
+ while(got && total < requested)
+ {
+ if(istr.fail())
+ {
+ // If bad is true, not much we can doo -- it implies loss
+ // of stream integrity. Bail in that case, and otherwise
+ // clear and attempt to continue.
+ if(istr.bad()) return total;
+ istr.clear();
+ }
+ istr.read(buf + total, requested - total); /*Flawfinder: ignore*/
+ got = istr.gcount();
+ total += got;
+ }
+ return total;
}
std::istream& operator>>(std::istream& str, const char *tocheck)
{
- char c = '\0';
- const char *p;
- p = tocheck;
- while (*p && !str.bad())
- {
- str.get(c);
- if (c != *p)
- {
- str.setstate(std::ios::failbit); /*Flawfinder: ignore*/
- break;
- }
- p++;
- }
- return str;
+ char c = '\0';
+ const char *p;
+ p = tocheck;
+ while (*p && !str.bad())
+ {
+ str.get(c);
+ if (c != *p)
+ {
+ str.setstate(std::ios::failbit); /*Flawfinder: ignore*/
+ break;
+ }
+ p++;
+ }
+ return str;
}
int cat_streambuf::underflow()
diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h
index bb7bc20327..599484361b 100644
--- a/indra/llcommon/llstreamtools.h
+++ b/indra/llcommon/llstreamtools.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstreamtools.h
* @brief some helper functions for parsing legacy simstate and asset files.
*
* $LicenseInfo:firstyear=2005&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$
*/
@@ -49,11 +49,11 @@ LL_COMMON_API bool skip_line(std::istream& input_stream);
// skips to beginning of next non-emptyspace
LL_COMMON_API bool skip_to_next_word(std::istream& input_stream);
-// skips to character after the end of next keyword
+// skips to character after the end of next keyword
// a 'keyword' is defined as the first word on a line
LL_COMMON_API bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);
-// skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug
+// skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug
// in windows iostream
// skips to beginning of next keyword
// a 'keyword' is defined as the first word on a line
@@ -65,7 +65,7 @@ LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stre
LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream);
// characters are pulled out of input_stream (up to a max of 'n')
-// and appended to output_string
+// and appended to output_string
// returns result of input_stream.good() after characters are pulled
LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream, int n);
LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream, int n);
@@ -81,13 +81,13 @@ LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stre
LL_COMMON_API bool remove_last_char(char c, std::string& line);
// replaces escaped characters with the correct characters from left to right
-// "\\" ---> '\\'
-// "\n" ---> '\n'
+// "\\" ---> '\\'
+// "\n" ---> '\n'
LL_COMMON_API void unescape_string(std::string& line);
// replaces unescaped characters with expanded equivalents from left to right
-// '\\' ---> "\\"
-// '\n' ---> "\n"
+// '\\' ---> "\\"
+// '\n' ---> "\n"
LL_COMMON_API void escape_string(std::string& line);
// replaces each '\n' character with ' '
@@ -99,18 +99,18 @@ LL_COMMON_API void remove_double_quotes(std::string& line);
// the 'keyword' is defined as the first word on a line
// the 'value' is everything after the keyword on the same line
// starting at the first non-whitespace and ending right before the newline
-LL_COMMON_API void get_keyword_and_value(std::string& keyword,
- std::string& value,
- const std::string& line);
+LL_COMMON_API void get_keyword_and_value(std::string& keyword,
+ std::string& value,
+ const std::string& line);
// continue to read from the stream until you really can't
// read anymore or until we hit the count. Some istream
// implimentations have a max that they will read.
// Returns the number of bytes read.
LL_COMMON_API std::streamsize fullread(
- std::istream& istr,
- char* buf,
- std::streamsize requested);
+ std::istream& istr,
+ char* buf,
+ std::streamsize requested);
LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);
diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h
index ed9284d2c5..6c76ab8104 100644
--- a/indra/llcommon/llstrider.h
+++ b/indra/llcommon/llstrider.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llstrider.h
*
* $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$
*/
@@ -30,38 +30,38 @@
template <class Object> class LLStrider
{
- union
- {
- Object* mObjectp;
- U8* mBytep;
- };
- U32 mSkip;
+ union
+ {
+ Object* mObjectp;
+ U8* mBytep;
+ };
+ U32 mSkip;
public:
- LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); }
- ~LLStrider() { }
+ LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); }
+ ~LLStrider() { }
- const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}
- void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));}
+ const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}
+ void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));}
- LLStrider<Object> operator+(const S32& index)
- {
- LLStrider<Object> ret;
- ret.mBytep = mBytep + mSkip*index;
- ret.mSkip = mSkip;
+ LLStrider<Object> operator+(const S32& index)
+ {
+ LLStrider<Object> ret;
+ ret.mBytep = mBytep + mSkip*index;
+ ret.mSkip = mSkip;
- return ret;
- }
+ return ret;
+ }
- void skip(const U32 index) { mBytep += mSkip*index;}
- U32 getSkip() const { return mSkip; }
- Object* get() { return mObjectp; }
- Object* operator->() { return mObjectp; }
- Object& operator *() { return *mObjectp; }
- Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; }
- Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; }
+ void skip(const U32 index) { mBytep += mSkip*index;}
+ U32 getSkip() const { return mSkip; }
+ Object* get() { return mObjectp; }
+ Object* operator->() { return mObjectp; }
+ Object& operator *() { return *mObjectp; }
+ Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; }
+ Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; }
- Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); }
+ Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); }
};
#endif // LL_LLSTRIDER_H
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index a746cc11ec..6512bbc392 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstring.cpp
* @brief String utility functions and the 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$
*/
@@ -30,7 +30,6 @@
#include "llerror.h"
#include "llfasttimer.h"
#include "llsd.h"
-#include <unicode/uchar.h>
#include <vector>
#if LL_WINDOWS
@@ -40,85 +39,85 @@
std::string ll_safe_string(const char* in)
{
- if(in) return std::string(in);
- return std::string();
+ if(in) return std::string(in);
+ return std::string();
}
std::string ll_safe_string(const char* in, S32 maxlen)
{
- if(in && maxlen > 0 ) return std::string(in, maxlen);
+ if(in && maxlen > 0 ) return std::string(in, maxlen);
- return std::string();
+ return std::string();
}
bool is_char_hex(char hex)
{
- if((hex >= '0') && (hex <= '9'))
- {
- return true;
- }
- else if((hex >= 'a') && (hex <='f'))
- {
- return true;
- }
- else if((hex >= 'A') && (hex <='F'))
- {
- return true;
- }
- return false; // uh - oh, not hex any more...
+ if((hex >= '0') && (hex <= '9'))
+ {
+ return true;
+ }
+ else if((hex >= 'a') && (hex <='f'))
+ {
+ return true;
+ }
+ else if((hex >= 'A') && (hex <='F'))
+ {
+ return true;
+ }
+ return false; // uh - oh, not hex any more...
}
U8 hex_as_nybble(char hex)
{
- if((hex >= '0') && (hex <= '9'))
- {
- return (U8)(hex - '0');
- }
- else if((hex >= 'a') && (hex <='f'))
- {
- return (U8)(10 + hex - 'a');
- }
- else if((hex >= 'A') && (hex <='F'))
- {
- return (U8)(10 + hex - 'A');
- }
- return 0; // uh - oh, not hex any more...
+ if((hex >= '0') && (hex <= '9'))
+ {
+ return (U8)(hex - '0');
+ }
+ else if((hex >= 'a') && (hex <='f'))
+ {
+ return (U8)(10 + hex - 'a');
+ }
+ else if((hex >= 'A') && (hex <='F'))
+ {
+ return (U8)(10 + hex - 'A');
+ }
+ return 0; // uh - oh, not hex any more...
}
bool iswindividual(llwchar elem)
-{
- U32 cur_char = (U32)elem;
- bool result = false;
- if (0x2E80<= cur_char && cur_char <= 0x9FFF)
- {
- result = true;
- }
- else if (0xAC00<= cur_char && cur_char <= 0xD7A0 )
- {
- result = true;
- }
- else if (0xF900<= cur_char && cur_char <= 0xFA60 )
- {
- result = true;
- }
- return result;
+{
+ U32 cur_char = (U32)elem;
+ bool result = false;
+ if (0x2E80<= cur_char && cur_char <= 0x9FFF)
+ {
+ result = true;
+ }
+ else if (0xAC00<= cur_char && cur_char <= 0xD7A0 )
+ {
+ result = true;
+ }
+ else if (0xF900<= cur_char && cur_char <= 0xFA60 )
+ {
+ result = true;
+ }
+ return result;
}
bool _read_file_into_string(std::string& str, const std::string& filename)
{
- llifstream ifs(filename.c_str(), llifstream::binary);
- if (!ifs.is_open())
- {
- LL_INFOS() << "Unable to open file " << filename << LL_ENDL;
- return false;
- }
+ llifstream ifs(filename.c_str(), llifstream::binary);
+ if (!ifs.is_open())
+ {
+ LL_INFOS() << "Unable to open file " << filename << LL_ENDL;
+ return false;
+ }
- std::ostringstream oss;
+ std::ostringstream oss;
- oss << ifs.rdbuf();
- str = oss.str();
- ifs.close();
- return true;
+ oss << ifs.rdbuf();
+ str = oss.str();
+ ifs.close();
+ return true;
}
@@ -131,179 +130,179 @@ bool _read_file_into_string(std::string& str, const std::string& filename)
std::ostream& operator<<(std::ostream &s, const LLWString &wstr)
{
- std::string utf8_str = wstring_to_utf8str(wstr);
- s << utf8_str;
- return s;
+ std::string utf8_str = wstring_to_utf8str(wstr);
+ s << utf8_str;
+ return s;
}
std::string rawstr_to_utf8(const std::string& raw)
{
- LLWString wstr(utf8str_to_wstring(raw));
- return wstring_to_utf8str(wstr);
+ LLWString wstr(utf8str_to_wstring(raw));
+ return wstring_to_utf8str(wstr);
}
std::ptrdiff_t wchar_to_utf8chars(llwchar in_char, char* outchars)
{
- U32 cur_char = (U32)in_char;
- char* base = outchars;
- if (cur_char < 0x80)
- {
- *outchars++ = (U8)cur_char;
- }
- else if (cur_char < 0x800)
- {
- *outchars++ = 0xC0 | (cur_char >> 6);
- *outchars++ = 0x80 | (cur_char & 0x3F);
- }
- else if (cur_char < 0x10000)
- {
- *outchars++ = 0xE0 | (cur_char >> 12);
- *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | (cur_char & 0x3F);
- }
- else if (cur_char < 0x200000)
- {
- *outchars++ = 0xF0 | (cur_char >> 18);
- *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
- *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | (cur_char & 0x3F);
- }
- else if (cur_char < 0x4000000)
- {
- *outchars++ = 0xF8 | (cur_char >> 24);
- *outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
- *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
- *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | (cur_char & 0x3F);
- }
- else if (cur_char < 0x80000000)
- {
- *outchars++ = 0xFC | (cur_char >> 30);
- *outchars++ = 0x80 | ((cur_char >> 24) & 0x3F);
- *outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
- *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
- *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | (cur_char & 0x3F);
- }
- else
- {
- LL_WARNS() << "Invalid Unicode character " << cur_char << "!" << LL_ENDL;
- *outchars++ = LL_UNKNOWN_CHAR;
- }
- return outchars - base;
-}
+ U32 cur_char = (U32)in_char;
+ char* base = outchars;
+ if (cur_char < 0x80)
+ {
+ *outchars++ = (U8)cur_char;
+ }
+ else if (cur_char < 0x800)
+ {
+ *outchars++ = 0xC0 | (cur_char >> 6);
+ *outchars++ = 0x80 | (cur_char & 0x3F);
+ }
+ else if (cur_char < 0x10000)
+ {
+ *outchars++ = 0xE0 | (cur_char >> 12);
+ *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
+ *outchars++ = 0x80 | (cur_char & 0x3F);
+ }
+ else if (cur_char < 0x200000)
+ {
+ *outchars++ = 0xF0 | (cur_char >> 18);
+ *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
+ *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
+ *outchars++ = 0x80 | (cur_char & 0x3F);
+ }
+ else if (cur_char < 0x4000000)
+ {
+ *outchars++ = 0xF8 | (cur_char >> 24);
+ *outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
+ *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
+ *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
+ *outchars++ = 0x80 | (cur_char & 0x3F);
+ }
+ else if (cur_char < 0x80000000)
+ {
+ *outchars++ = 0xFC | (cur_char >> 30);
+ *outchars++ = 0x80 | ((cur_char >> 24) & 0x3F);
+ *outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
+ *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
+ *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
+ *outchars++ = 0x80 | (cur_char & 0x3F);
+ }
+ else
+ {
+ LL_WARNS() << "Invalid Unicode character " << cur_char << "!" << LL_ENDL;
+ *outchars++ = LL_UNKNOWN_CHAR;
+ }
+ return outchars - base;
+}
auto utf16chars_to_wchar(const U16* inchars, llwchar* outchar)
{
- const U16* base = inchars;
- U16 cur_char = *inchars++;
- llwchar char32 = cur_char;
- if ((cur_char >= 0xD800) && (cur_char <= 0xDFFF))
- {
- // Surrogates
- char32 = ((llwchar)(cur_char - 0xD800)) << 10;
- cur_char = *inchars++;
- char32 += (llwchar)(cur_char - 0xDC00) + 0x0010000UL;
- }
- else
- {
- char32 = (llwchar)cur_char;
- }
- *outchar = char32;
- return inchars - base;
+ const U16* base = inchars;
+ U16 cur_char = *inchars++;
+ llwchar char32 = cur_char;
+ if ((cur_char >= 0xD800) && (cur_char <= 0xDFFF))
+ {
+ // Surrogates
+ char32 = ((llwchar)(cur_char - 0xD800)) << 10;
+ cur_char = *inchars++;
+ char32 += (llwchar)(cur_char - 0xDC00) + 0x0010000UL;
+ }
+ else
+ {
+ char32 = (llwchar)cur_char;
+ }
+ *outchar = char32;
+ return inchars - base;
}
llutf16string wstring_to_utf16str(const llwchar* utf32str, size_t len)
{
- llutf16string out;
-
- S32 i = 0;
- while (i < len)
- {
- U32 cur_char = utf32str[i];
- if (cur_char > 0xFFFF)
- {
- out += (0xD7C0 + (cur_char >> 10));
- out += (0xDC00 | (cur_char & 0x3FF));
- }
- else
- {
- out += cur_char;
- }
- i++;
- }
- return out;
+ llutf16string out;
+
+ S32 i = 0;
+ while (i < len)
+ {
+ U32 cur_char = utf32str[i];
+ if (cur_char > 0xFFFF)
+ {
+ out += (0xD7C0 + (cur_char >> 10));
+ out += (0xDC00 | (cur_char & 0x3FF));
+ }
+ else
+ {
+ out += cur_char;
+ }
+ i++;
+ }
+ return out;
}
llutf16string utf8str_to_utf16str( const char* utf8str, size_t len )
{
- LLWString wstr = utf8str_to_wstring ( utf8str, len );
- return wstring_to_utf16str ( wstr );
+ LLWString wstr = utf8str_to_wstring ( utf8str, len );
+ return wstring_to_utf16str ( wstr );
}
LLWString utf16str_to_wstring(const U16* utf16str, size_t len)
{
- LLWString wout;
- if (len == 0) return wout;
+ LLWString wout;
+ if (len == 0) return wout;
- S32 i = 0;
- const U16* chars16 = utf16str;
- while (i < len)
- {
- llwchar cur_char;
- i += utf16chars_to_wchar(chars16+i, &cur_char);
- wout += cur_char;
- }
- return wout;
+ S32 i = 0;
+ const U16* chars16 = utf16str;
+ while (i < len)
+ {
+ llwchar cur_char;
+ i += utf16chars_to_wchar(chars16+i, &cur_char);
+ wout += cur_char;
+ }
+ return wout;
}
// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
S32 utf16str_wstring_length(const llutf16string &utf16str, const S32 utf16_len)
{
- S32 surrogate_pairs = 0;
- // ... craziness to make gcc happy (llutf16string.c_str() is tweaked on linux):
- const U16 *const utf16_chars = &(*(utf16str.begin()));
- S32 i = 0;
- while (i < utf16_len)
- {
- const U16 c = utf16_chars[i++];
- if (c >= 0xD800 && c <= 0xDBFF) // See http://en.wikipedia.org/wiki/UTF-16
- { // Have first byte of a surrogate pair
- if (i >= utf16_len)
- {
- break;
- }
- const U16 d = utf16_chars[i];
- if (d >= 0xDC00 && d <= 0xDFFF)
- { // Have valid second byte of a surrogate pair
- surrogate_pairs++;
- i++;
- }
- }
- }
- return utf16_len - surrogate_pairs;
+ S32 surrogate_pairs = 0;
+ // ... craziness to make gcc happy (llutf16string.c_str() is tweaked on linux):
+ const U16 *const utf16_chars = &(*(utf16str.begin()));
+ S32 i = 0;
+ while (i < utf16_len)
+ {
+ const U16 c = utf16_chars[i++];
+ if (c >= 0xD800 && c <= 0xDBFF) // See http://en.wikipedia.org/wiki/UTF-16
+ { // Have first byte of a surrogate pair
+ if (i >= utf16_len)
+ {
+ break;
+ }
+ const U16 d = utf16_chars[i];
+ if (d >= 0xDC00 && d <= 0xDFFF)
+ { // Have valid second byte of a surrogate pair
+ surrogate_pairs++;
+ i++;
+ }
+ }
+ }
+ return utf16_len - surrogate_pairs;
}
// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
S32 wstring_utf16_length(const LLWString &wstr, const S32 woffset, const S32 wlen)
{
- const S32 end = llmin((S32)wstr.length(), woffset + wlen);
- if (end < woffset)
- {
- return 0;
- }
- else
- {
- S32 length = end - woffset;
- for (S32 i = woffset; i < end; i++)
- {
- if (wstr[i] >= 0x10000)
- {
- length++;
- }
- }
- return length;
- }
+ const S32 end = llmin((S32)wstr.length(), woffset + wlen);
+ if (end < woffset)
+ {
+ return 0;
+ }
+ else
+ {
+ S32 length = end - woffset;
+ for (S32 i = woffset; i < end; i++)
+ {
+ if (wstr[i] >= 0x10000)
+ {
+ length++;
+ }
+ }
+ return length;
+ }
}
// Given a wstring and an offset in it, returns the length as wstring (i.e.,
@@ -311,56 +310,56 @@ S32 wstring_utf16_length(const LLWString &wstr, const S32 woffset, const S32 wle
// and whose equivalent utf-16 string does not exceeds the given utf16_length.
S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, const S32 woffset, const S32 utf16_length, BOOL *unaligned)
{
- const auto end = wstr.length();
- BOOL u = FALSE;
- S32 n = woffset + utf16_length;
- S32 i = woffset;
- while (i < end)
- {
- if (wstr[i] >= 0x10000)
- {
- --n;
- }
- if (i >= n)
- {
- u = (i > n);
- break;
- }
- i++;
- }
- if (unaligned)
- {
- *unaligned = u;
- }
- return i - woffset;
+ const auto end = wstr.length();
+ BOOL u = FALSE;
+ S32 n = woffset + utf16_length;
+ S32 i = woffset;
+ while (i < end)
+ {
+ if (wstr[i] >= 0x10000)
+ {
+ --n;
+ }
+ if (i >= n)
+ {
+ u = (i > n);
+ break;
+ }
+ i++;
+ }
+ if (unaligned)
+ {
+ *unaligned = u;
+ }
+ return i - woffset;
}
S32 wchar_utf8_length(const llwchar wc)
{
- if (wc < 0x80)
- {
- return 1;
- }
- else if (wc < 0x800)
- {
- return 2;
- }
- else if (wc < 0x10000)
- {
- return 3;
- }
- else if (wc < 0x200000)
- {
- return 4;
- }
- else if (wc < 0x4000000)
- {
- return 5;
- }
- else
- {
- return 6;
- }
+ if (wc < 0x80)
+ {
+ return 1;
+ }
+ else if (wc < 0x800)
+ {
+ return 2;
+ }
+ else if (wc < 0x10000)
+ {
+ return 3;
+ }
+ else if (wc < 0x200000)
+ {
+ return 4;
+ }
+ else if (wc < 0x4000000)
+ {
+ return 5;
+ }
+ else
+ {
+ return 6;
+ }
}
std::string wchar_utf8_preview(const llwchar wc)
@@ -390,179 +389,179 @@ std::string wchar_utf8_preview(const llwchar wc)
S32 wstring_utf8_length(const LLWString& wstr)
{
- S32 len = 0;
- for (S32 i = 0; i < (S32)wstr.length(); i++)
- {
- len += wchar_utf8_length(wstr[i]);
- }
- return len;
+ S32 len = 0;
+ for (S32 i = 0; i < (S32)wstr.length(); i++)
+ {
+ len += wchar_utf8_length(wstr[i]);
+ }
+ return len;
}
LLWString utf8str_to_wstring(const char* utf8str, size_t len)
{
- LLWString wout;
-
- S32 i = 0;
- while (i < len)
- {
- llwchar unichar;
- U8 cur_char = utf8str[i];
-
- if (cur_char < 0x80)
- {
- // Ascii character, just add it
- unichar = cur_char;
- }
- else
- {
- S32 cont_bytes = 0;
- if ((cur_char >> 5) == 0x6) // Two byte UTF8 -> 1 UTF32
- {
- unichar = (0x1F&cur_char);
- cont_bytes = 1;
- }
- else if ((cur_char >> 4) == 0xe) // Three byte UTF8 -> 1 UTF32
- {
- unichar = (0x0F&cur_char);
- cont_bytes = 2;
- }
- else if ((cur_char >> 3) == 0x1e) // Four byte UTF8 -> 1 UTF32
- {
- unichar = (0x07&cur_char);
- cont_bytes = 3;
- }
- else if ((cur_char >> 2) == 0x3e) // Five byte UTF8 -> 1 UTF32
- {
- unichar = (0x03&cur_char);
- cont_bytes = 4;
- }
- else if ((cur_char >> 1) == 0x7e) // Six byte UTF8 -> 1 UTF32
- {
- unichar = (0x01&cur_char);
- cont_bytes = 5;
- }
- else
- {
- wout += LL_UNKNOWN_CHAR;
- ++i;
- continue;
- }
-
- // Check that this character doesn't go past the end of the string
- auto end = (len < (i + cont_bytes)) ? len : (i + cont_bytes);
- do
- {
- ++i;
-
- cur_char = utf8str[i];
- if ( (cur_char >> 6) == 0x2 )
- {
- unichar <<= 6;
- unichar += (0x3F&cur_char);
- }
- else
- {
- // Malformed sequence - roll back to look at this as a new char
- unichar = LL_UNKNOWN_CHAR;
- --i;
- break;
- }
- } while(i < end);
-
- // Handle overlong characters and NULL characters
- if ( ((cont_bytes == 1) && (unichar < 0x80))
- || ((cont_bytes == 2) && (unichar < 0x800))
- || ((cont_bytes == 3) && (unichar < 0x10000))
- || ((cont_bytes == 4) && (unichar < 0x200000))
- || ((cont_bytes == 5) && (unichar < 0x4000000)) )
- {
- unichar = LL_UNKNOWN_CHAR;
- }
- }
-
- wout += unichar;
- ++i;
- }
- return wout;
+ LLWString wout;
+
+ S32 i = 0;
+ while (i < len)
+ {
+ llwchar unichar;
+ U8 cur_char = utf8str[i];
+
+ if (cur_char < 0x80)
+ {
+ // Ascii character, just add it
+ unichar = cur_char;
+ }
+ else
+ {
+ S32 cont_bytes = 0;
+ if ((cur_char >> 5) == 0x6) // Two byte UTF8 -> 1 UTF32
+ {
+ unichar = (0x1F&cur_char);
+ cont_bytes = 1;
+ }
+ else if ((cur_char >> 4) == 0xe) // Three byte UTF8 -> 1 UTF32
+ {
+ unichar = (0x0F&cur_char);
+ cont_bytes = 2;
+ }
+ else if ((cur_char >> 3) == 0x1e) // Four byte UTF8 -> 1 UTF32
+ {
+ unichar = (0x07&cur_char);
+ cont_bytes = 3;
+ }
+ else if ((cur_char >> 2) == 0x3e) // Five byte UTF8 -> 1 UTF32
+ {
+ unichar = (0x03&cur_char);
+ cont_bytes = 4;
+ }
+ else if ((cur_char >> 1) == 0x7e) // Six byte UTF8 -> 1 UTF32
+ {
+ unichar = (0x01&cur_char);
+ cont_bytes = 5;
+ }
+ else
+ {
+ wout += LL_UNKNOWN_CHAR;
+ ++i;
+ continue;
+ }
+
+ // Check that this character doesn't go past the end of the string
+ auto end = (len < (i + cont_bytes)) ? len : (i + cont_bytes);
+ do
+ {
+ ++i;
+
+ cur_char = utf8str[i];
+ if ( (cur_char >> 6) == 0x2 )
+ {
+ unichar <<= 6;
+ unichar += (0x3F&cur_char);
+ }
+ else
+ {
+ // Malformed sequence - roll back to look at this as a new char
+ unichar = LL_UNKNOWN_CHAR;
+ --i;
+ break;
+ }
+ } while(i < end);
+
+ // Handle overlong characters and NULL characters
+ if ( ((cont_bytes == 1) && (unichar < 0x80))
+ || ((cont_bytes == 2) && (unichar < 0x800))
+ || ((cont_bytes == 3) && (unichar < 0x10000))
+ || ((cont_bytes == 4) && (unichar < 0x200000))
+ || ((cont_bytes == 5) && (unichar < 0x4000000)) )
+ {
+ unichar = LL_UNKNOWN_CHAR;
+ }
+ }
+
+ wout += unichar;
+ ++i;
+ }
+ return wout;
}
std::string wstring_to_utf8str(const llwchar* utf32str, size_t len)
{
- std::string out;
+ std::string out;
- S32 i = 0;
- while (i < len)
- {
- char tchars[8]; /* Flawfinder: ignore */
- auto n = wchar_to_utf8chars(utf32str[i], tchars);
- tchars[n] = 0;
- out += tchars;
- i++;
- }
- return out;
+ S32 i = 0;
+ while (i < len)
+ {
+ char tchars[8]; /* Flawfinder: ignore */
+ auto n = wchar_to_utf8chars(utf32str[i], tchars);
+ tchars[n] = 0;
+ out += tchars;
+ i++;
+ }
+ return out;
}
std::string utf16str_to_utf8str(const U16* utf16str, size_t len)
{
- return wstring_to_utf8str(utf16str_to_wstring(utf16str, len));
+ return wstring_to_utf8str(utf16str_to_wstring(utf16str, len));
}
std::string utf8str_trim(const std::string& utf8str)
{
- LLWString wstr = utf8str_to_wstring(utf8str);
- LLWStringUtil::trim(wstr);
- return wstring_to_utf8str(wstr);
+ LLWString wstr = utf8str_to_wstring(utf8str);
+ LLWStringUtil::trim(wstr);
+ return wstring_to_utf8str(wstr);
}
std::string utf8str_tolower(const std::string& utf8str)
{
- LLWString out_str = utf8str_to_wstring(utf8str);
- LLWStringUtil::toLower(out_str);
- return wstring_to_utf8str(out_str);
+ LLWString out_str = utf8str_to_wstring(utf8str);
+ LLWStringUtil::toLower(out_str);
+ return wstring_to_utf8str(out_str);
}
S32 utf8str_compare_insensitive(const std::string& lhs, const std::string& rhs)
{
- LLWString wlhs = utf8str_to_wstring(lhs);
- LLWString wrhs = utf8str_to_wstring(rhs);
- return LLWStringUtil::compareInsensitive(wlhs, wrhs);
+ LLWString wlhs = utf8str_to_wstring(lhs);
+ LLWString wrhs = utf8str_to_wstring(rhs);
+ return LLWStringUtil::compareInsensitive(wlhs, wrhs);
}
std::string utf8str_truncate(const std::string& utf8str, const S32 max_len)
{
- if (0 == max_len)
- {
- return std::string();
- }
- if ((S32)utf8str.length() <= max_len)
- {
- return utf8str;
- }
- else
- {
- S32 cur_char = max_len;
-
- // If we're ASCII, we don't need to do anything
- if ((U8)utf8str[cur_char] > 0x7f)
- {
- // If first two bits are (10), it's the tail end of a multibyte char. We need to shift back
- // to the first character
- while (0x80 == (0xc0 & utf8str[cur_char]))
- {
- cur_char--;
- // Keep moving forward until we hit the first char;
- if (cur_char == 0)
- {
- // Make sure we don't trash memory if we've got a bogus string.
- break;
- }
- }
- }
- // The byte index we're on is one we want to get rid of, so we only want to copy up to (cur_char-1) chars
- return utf8str.substr(0, cur_char);
- }
+ if (0 == max_len)
+ {
+ return std::string();
+ }
+ if ((S32)utf8str.length() <= max_len)
+ {
+ return utf8str;
+ }
+ else
+ {
+ S32 cur_char = max_len;
+
+ // If we're ASCII, we don't need to do anything
+ if ((U8)utf8str[cur_char] > 0x7f)
+ {
+ // If first two bits are (10), it's the tail end of a multibyte char. We need to shift back
+ // to the first character
+ while (0x80 == (0xc0 & utf8str[cur_char]))
+ {
+ cur_char--;
+ // Keep moving forward until we hit the first char;
+ if (cur_char == 0)
+ {
+ // Make sure we don't trash memory if we've got a bogus string.
+ break;
+ }
+ }
+ }
+ // The byte index we're on is one we want to get rid of, so we only want to copy up to (cur_char-1) chars
+ return utf8str.substr(0, cur_char);
+ }
}
std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len)
@@ -593,56 +592,56 @@ std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol
}
std::string utf8str_substChar(
- const std::string& utf8str,
- const llwchar target_char,
- const llwchar replace_char)
-{
- LLWString wstr = utf8str_to_wstring(utf8str);
- LLWStringUtil::replaceChar(wstr, target_char, replace_char);
- //wstr = wstring_substChar(wstr, target_char, replace_char);
- return wstring_to_utf8str(wstr);
+ const std::string& utf8str,
+ const llwchar target_char,
+ const llwchar replace_char)
+{
+ LLWString wstr = utf8str_to_wstring(utf8str);
+ LLWStringUtil::replaceChar(wstr, target_char, replace_char);
+ //wstr = wstring_substChar(wstr, target_char, replace_char);
+ return wstring_to_utf8str(wstr);
}
std::string utf8str_makeASCII(const std::string& utf8str)
{
- LLWString wstr = utf8str_to_wstring(utf8str);
- LLWStringUtil::_makeASCII(wstr);
- return wstring_to_utf8str(wstr);
+ LLWString wstr = utf8str_to_wstring(utf8str);
+ LLWStringUtil::_makeASCII(wstr);
+ return wstring_to_utf8str(wstr);
}
std::string mbcsstring_makeASCII(const std::string& wstr)
{
- // Replace non-ASCII chars with replace_char
- std::string out_str = wstr;
- for (S32 i = 0; i < (S32)out_str.length(); i++)
- {
- if ((U8)out_str[i] > 0x7f)
- {
- out_str[i] = LL_UNKNOWN_CHAR;
- }
- }
- return out_str;
+ // Replace non-ASCII chars with replace_char
+ std::string out_str = wstr;
+ for (S32 i = 0; i < (S32)out_str.length(); i++)
+ {
+ if ((U8)out_str[i] > 0x7f)
+ {
+ out_str[i] = LL_UNKNOWN_CHAR;
+ }
+ }
+ return out_str;
}
std::string utf8str_removeCRLF(const std::string& utf8str)
{
- if (0 == utf8str.length())
- {
- return std::string();
- }
- const char CR = 13;
-
- std::string out;
- out.reserve(utf8str.length());
- const S32 len = (S32)utf8str.length();
- for( S32 i = 0; i < len; i++ )
- {
- if( utf8str[i] != CR )
- {
- out.push_back(utf8str[i]);
- }
- }
- return out;
+ if (0 == utf8str.length())
+ {
+ return std::string();
+ }
+ const char CR = 13;
+
+ std::string out;
+ out.reserve(utf8str.length());
+ const S32 len = (S32)utf8str.length();
+ for( S32 i = 0; i < len; i++ )
+ {
+ if( utf8str[i] != CR )
+ {
+ out.push_back(utf8str[i]);
+ }
+ }
+ return out;
}
llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset, size_t length)
@@ -758,6 +757,43 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
return result;
}
+// Search for any emoji symbol, return true if found
+bool wstring_has_emoji(const LLWString& wstr)
+{
+ for (const llwchar& wch : wstr)
+ {
+ if (LLStringOps::isEmoji(wch))
+ return true;
+ }
+
+ return false;
+}
+
+// Cut emoji symbols if exist
+bool wstring_remove_emojis(LLWString& wstr)
+{
+ bool found = false;
+ for (size_t i = 0; i < wstr.size(); ++i)
+ {
+ if (LLStringOps::isEmoji(wstr[i]))
+ {
+ wstr.erase(i--, 1);
+ found = true;
+ }
+ }
+ return found;
+}
+
+// Cut emoji symbols if exist
+bool utf8str_remove_emojis(std::string& utf8str)
+{
+ LLWString wstr = utf8str_to_wstring(utf8str);
+ if (!wstring_remove_emojis(wstr))
+ return false;
+ utf8str = wstring_to_utf8str(wstr);
+ return true;
+}
+
#if LL_WINDOWS
unsigned int ll_wstring_default_code_page()
{
@@ -766,63 +802,63 @@ unsigned int ll_wstring_default_code_page()
std::string ll_convert_wide_to_string(const wchar_t* in, size_t len_in, unsigned int code_page)
{
- std::string out;
- if(in)
- {
- int len_out = WideCharToMultiByte(
- code_page,
- 0,
- in,
- len_in,
- NULL,
- 0,
- 0,
- 0);
- // We will need two more bytes for the double NULL ending
- // created in WideCharToMultiByte().
- char* pout = new char [len_out + 2];
- memset(pout, 0, len_out + 2);
- if(pout)
- {
- WideCharToMultiByte(
- code_page,
- 0,
- in,
- len_in,
- pout,
- len_out,
- 0,
- 0);
- out.assign(pout);
- delete[] pout;
- }
- }
- return out;
+ std::string out;
+ if(in)
+ {
+ int len_out = WideCharToMultiByte(
+ code_page,
+ 0,
+ in,
+ len_in,
+ NULL,
+ 0,
+ 0,
+ 0);
+ // We will need two more bytes for the double NULL ending
+ // created in WideCharToMultiByte().
+ char* pout = new char [len_out + 2];
+ memset(pout, 0, len_out + 2);
+ if(pout)
+ {
+ WideCharToMultiByte(
+ code_page,
+ 0,
+ in,
+ len_in,
+ pout,
+ len_out,
+ 0,
+ 0);
+ out.assign(pout);
+ delete[] pout;
+ }
+ }
+ return out;
}
std::wstring ll_convert_string_to_wide(const char* in, size_t len, unsigned int code_page)
{
- // From review:
- // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input,
- // plus one for a null terminator, and be guaranteed to not overflow.
+ // From review:
+ // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input,
+ // plus one for a null terminator, and be guaranteed to not overflow.
- // Normally, I'd call that sort of thing premature optimization,
- // but we *are* seeing string operations taking a bunch of time, especially when constructing widgets.
-// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0);
+ // Normally, I'd call that sort of thing premature optimization,
+ // but we *are* seeing string operations taking a bunch of time, especially when constructing widgets.
+// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0);
- // reserve an output buffer that will be destroyed on exit, with a place
- // to put NULL terminator
- std::vector<wchar_t> w_out(len + 1);
+ // reserve an output buffer that will be destroyed on exit, with a place
+ // to put NULL terminator
+ std::vector<wchar_t> w_out(len + 1);
- memset(&w_out[0], 0, w_out.size());
- int real_output_str_len = MultiByteToWideChar(code_page, 0, in, len,
- &w_out[0], w_out.size() - 1);
+ memset(&w_out[0], 0, w_out.size());
+ int real_output_str_len = MultiByteToWideChar(code_page, 0, in, len,
+ &w_out[0], w_out.size() - 1);
- //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858.
- w_out[real_output_str_len] = 0;
+ //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858.
+ w_out[real_output_str_len] = 0;
- // construct string<wchar_t> from our temporary output buffer
- return {&w_out[0]};
+ // construct string<wchar_t> from our temporary output buffer
+ return {&w_out[0]};
}
LLWString ll_convert_wide_to_wstring(const wchar_t* in, size_t len)
@@ -846,11 +882,11 @@ std::wstring ll_convert_wstring_to_wide(const llwchar* in, size_t len)
std::string ll_convert_string_to_utf8_string(const std::string& in)
{
- // If you pass code_page, you must also pass length, otherwise the code
- // page parameter will be mistaken for length.
- auto w_mesg = ll_convert_string_to_wide(in, in.length(), CP_ACP);
- // CP_UTF8 is default -- see ll_wstring_default_code_page() above.
- return ll_convert_wide_to_string(w_mesg);
+ // If you pass code_page, you must also pass length, otherwise the code
+ // page parameter will be mistaken for length.
+ auto w_mesg = ll_convert_string_to_wide(in, in.length(), CP_ACP);
+ // CP_UTF8 is default -- see ll_wstring_default_code_page() above.
+ return ll_convert_wide_to_string(w_mesg);
}
namespace
@@ -971,246 +1007,224 @@ std::string LLStringOps::sAM;
std::string LLStringOps::sPM;
// static
-bool LLStringOps::isEmoji(llwchar wch)
-{
- int ublock = ublock_getCode(wch);
- switch (ublock)
- {
- case UBLOCK_GENERAL_PUNCTUATION:
- case UBLOCK_LETTERLIKE_SYMBOLS:
- case UBLOCK_ARROWS:
- case UBLOCK_MISCELLANEOUS_TECHNICAL:
- case UBLOCK_ENCLOSED_ALPHANUMERICS:
- case UBLOCK_GEOMETRIC_SHAPES:
- case UBLOCK_MISCELLANEOUS_SYMBOLS:
- case UBLOCK_DINGBATS:
- case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
- case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
- case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS:
- case UBLOCK_EMOTICONS:
- case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS:
-#if U_ICU_VERSION_MAJOR_NUM > 56
- // Boost uses ICU so we can't update it independently
- case UBLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS:
-#endif // U_ICU_VERSION_MAJOR_NUM > 56
- return true;
- default:
-#if U_ICU_VERSION_MAJOR_NUM > 56
- return false;
+bool LLStringOps::isEmoji(llwchar a)
+{
+#if 0 // Do not consider special characters that might have a corresponding
+ // glyph in the monochorme fallback fonts as a "genuine" emoji. HB
+ return a == 0xa9 || a == 0xae || (a >= 0x2000 && a < 0x3300) ||
+ (a >= 0x1f000 && a < 0x20000);
#else
- // See https://en.wikipedia.org/wiki/Supplemental_Symbols_and_Pictographs
- return wch >= 0x1F900 && wch <= 0x1F9FF;
-#endif // U_ICU_VERSION_MAJOR_NUM > 56
- }
+ // These are indeed "genuine" emojis, we *do want* rendered as such. HB
+ return a >= 0x1f000 && a < 0x20000;
+#endif
}
-
-S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
-{
- #if LL_WINDOWS
- // in Windows, wide string functions operator on 16-bit strings,
- // not the proper 32 bit wide string
- return strcmp(wstring_to_utf8str(LLWString(a)).c_str(), wstring_to_utf8str(LLWString(b)).c_str());
- #else
- return wcscoll(a, b);
- #endif
+S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
+{
+ #if LL_WINDOWS
+ // in Windows, wide string functions operator on 16-bit strings,
+ // not the proper 32 bit wide string
+ return strcmp(wstring_to_utf8str(LLWString(a)).c_str(), wstring_to_utf8str(LLWString(b)).c_str());
+ #else
+ return wcscoll(a, b);
+ #endif
}
void LLStringOps::setupDatetimeInfo (bool daylight)
{
- time_t nowT, localT, gmtT;
- struct tm * tmpT;
-
- nowT = time (NULL);
-
- tmpT = gmtime (&nowT);
- gmtT = mktime (tmpT);
-
- tmpT = localtime (&nowT);
- localT = mktime (tmpT);
-
- sLocalTimeOffset = (long) (gmtT - localT);
- if (tmpT->tm_isdst)
- {
- sLocalTimeOffset -= 60 * 60; // 1 hour
- }
-
- sPacificDaylightTime = daylight;
- sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
-
- datetimeToCodes["wkday"] = "%a"; // Thu
- datetimeToCodes["weekday"] = "%A"; // Thursday
- datetimeToCodes["year4"] = "%Y"; // 2009
- datetimeToCodes["year"] = "%Y"; // 2009
- datetimeToCodes["year2"] = "%y"; // 09
- datetimeToCodes["mth"] = "%b"; // Aug
- datetimeToCodes["month"] = "%B"; // August
- datetimeToCodes["mthnum"] = "%m"; // 08
- datetimeToCodes["day"] = "%d"; // 31
- datetimeToCodes["sday"] = "%-d"; // 9
- datetimeToCodes["hour24"] = "%H"; // 14
- datetimeToCodes["hour"] = "%H"; // 14
- datetimeToCodes["hour12"] = "%I"; // 02
- datetimeToCodes["min"] = "%M"; // 59
- datetimeToCodes["ampm"] = "%p"; // AM
- datetimeToCodes["second"] = "%S"; // 59
- datetimeToCodes["timezone"] = "%Z"; // PST
+ time_t nowT, localT, gmtT;
+ struct tm * tmpT;
+
+ nowT = time (NULL);
+
+ tmpT = gmtime (&nowT);
+ gmtT = mktime (tmpT);
+
+ tmpT = localtime (&nowT);
+ localT = mktime (tmpT);
+
+ sLocalTimeOffset = (long) (gmtT - localT);
+ if (tmpT->tm_isdst)
+ {
+ sLocalTimeOffset -= 60 * 60; // 1 hour
+ }
+
+ sPacificDaylightTime = daylight;
+ sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
+
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["sday"] = "%-d"; // 9
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
}
void tokenizeStringToArray(const std::string& data, std::vector<std::string>& output)
{
- output.clear();
- size_t length = data.size();
-
- // tokenize it and put it in the array
- std::string cur_word;
- for(size_t i = 0; i < length; ++i)
- {
- if(data[i] == ':')
- {
- output.push_back(cur_word);
- cur_word.clear();
- }
- else
- {
- cur_word.append(1, data[i]);
- }
- }
- output.push_back(cur_word);
+ output.clear();
+ size_t length = data.size();
+
+ // tokenize it and put it in the array
+ std::string cur_word;
+ for(size_t i = 0; i < length; ++i)
+ {
+ if(data[i] == ':')
+ {
+ output.push_back(cur_word);
+ cur_word.clear();
+ }
+ else
+ {
+ cur_word.append(1, data[i]);
+ }
+ }
+ output.push_back(cur_word);
}
void LLStringOps::setupWeekDaysNames(const std::string& data)
{
- tokenizeStringToArray(data,sWeekDayList);
+ tokenizeStringToArray(data,sWeekDayList);
}
void LLStringOps::setupWeekDaysShortNames(const std::string& data)
{
- tokenizeStringToArray(data,sWeekDayShortList);
+ tokenizeStringToArray(data,sWeekDayShortList);
}
void LLStringOps::setupMonthNames(const std::string& data)
{
- tokenizeStringToArray(data,sMonthList);
+ tokenizeStringToArray(data,sMonthList);
}
void LLStringOps::setupMonthShortNames(const std::string& data)
{
- tokenizeStringToArray(data,sMonthShortList);
+ tokenizeStringToArray(data,sMonthShortList);
}
void LLStringOps::setupDayFormat(const std::string& data)
{
- sDayFormat = data;
+ sDayFormat = data;
}
std::string LLStringOps::getDatetimeCode (std::string key)
{
- std::map<std::string, std::string>::iterator iter;
+ std::map<std::string, std::string>::iterator iter;
- iter = datetimeToCodes.find (key);
- if (iter != datetimeToCodes.end())
- {
- return iter->second;
- }
- else
- {
- return std::string("");
- }
+ iter = datetimeToCodes.find (key);
+ if (iter != datetimeToCodes.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return std::string("");
+ }
}
std::string LLStringOps::getReadableNumber(F64 num)
{
if (fabs(num)>=1e9)
{
- return llformat("%.2lfB", num / 1e9);
+ return llformat("%.2lfB", num / 1e9);
}
else if (fabs(num)>=1e6)
{
- return llformat("%.2lfM", num / 1e6);
+ return llformat("%.2lfM", num / 1e6);
}
else if (fabs(num)>=1e3)
{
- return llformat("%.2lfK", num / 1e3);
+ return llformat("%.2lfK", num / 1e3);
}
else
{
- return llformat("%.2lf", num);
+ return llformat("%.2lf", num);
}
}
namespace LLStringFn
{
- // NOTE - this restricts output to ascii
- void replace_nonprintable_in_ascii(std::basic_string<char>& string, char replacement)
- {
- const char MIN = 0x20;
- std::basic_string<char>::size_type len = string.size();
- for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
- {
- if(string[ii] < MIN)
- {
- string[ii] = replacement;
- }
- }
- }
-
-
- // NOTE - this restricts output to ascii
- void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
- char replacement)
- {
- const char MIN = 0x20;
- const char PIPE = 0x7c;
- std::basic_string<char>::size_type len = str.size();
- for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
- {
- if( (str[ii] < MIN) || (str[ii] == PIPE) )
- {
- str[ii] = replacement;
- }
- }
- }
-
- // https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on
- // allowable code points for XML. Specifically, they are:
- // 0x09, 0x0a, 0x0d, and 0x20 on up. JC
- std::string strip_invalid_xml(const std::string& instr)
- {
- std::string output;
- output.reserve( instr.size() );
- std::string::const_iterator it = instr.begin();
- while (it != instr.end())
- {
- // Must compare as unsigned for >=
- // Test most likely match first
- const unsigned char c = (unsigned char)*it;
- if ( c >= (unsigned char)0x20 // SPACE
- || c == (unsigned char)0x09 // TAB
- || c == (unsigned char)0x0a // LINE_FEED
- || c == (unsigned char)0x0d ) // CARRIAGE_RETURN
- {
- output.push_back(c);
- }
- ++it;
- }
- return output;
- }
-
- /**
- * @brief Replace all control characters (c < 0x20) with replacement in
- * string.
- */
- void replace_ascii_controlchars(std::basic_string<char>& string, char replacement)
- {
- const unsigned char MIN = 0x20;
- std::basic_string<char>::size_type len = string.size();
- for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
- {
- const unsigned char c = (unsigned char) string[ii];
- if(c < MIN)
- {
- string[ii] = replacement;
- }
- }
- }
+ // NOTE - this restricts output to ascii
+ void replace_nonprintable_in_ascii(std::basic_string<char>& string, char replacement)
+ {
+ const char MIN = 0x20;
+ std::basic_string<char>::size_type len = string.size();
+ for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
+ {
+ if(string[ii] < MIN)
+ {
+ string[ii] = replacement;
+ }
+ }
+ }
+
+
+ // NOTE - this restricts output to ascii
+ void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
+ char replacement)
+ {
+ const char MIN = 0x20;
+ const char PIPE = 0x7c;
+ std::basic_string<char>::size_type len = str.size();
+ for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
+ {
+ if( (str[ii] < MIN) || (str[ii] == PIPE) )
+ {
+ str[ii] = replacement;
+ }
+ }
+ }
+
+ // https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on
+ // allowable code points for XML. Specifically, they are:
+ // 0x09, 0x0a, 0x0d, and 0x20 on up. JC
+ std::string strip_invalid_xml(const std::string& instr)
+ {
+ std::string output;
+ output.reserve( instr.size() );
+ std::string::const_iterator it = instr.begin();
+ while (it != instr.end())
+ {
+ // Must compare as unsigned for >=
+ // Test most likely match first
+ const unsigned char c = (unsigned char)*it;
+ if ( c >= (unsigned char)0x20 // SPACE
+ || c == (unsigned char)0x09 // TAB
+ || c == (unsigned char)0x0a // LINE_FEED
+ || c == (unsigned char)0x0d ) // CARRIAGE_RETURN
+ {
+ output.push_back(c);
+ }
+ ++it;
+ }
+ return output;
+ }
+
+ /**
+ * @brief Replace all control characters (c < 0x20) with replacement in
+ * string.
+ */
+ void replace_ascii_controlchars(std::basic_string<char>& string, char replacement)
+ {
+ const unsigned char MIN = 0x20;
+ std::basic_string<char>::size_type len = string.size();
+ for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
+ {
+ const unsigned char c = (unsigned char) string[ii];
+ if(c < MIN)
+ {
+ string[ii] = replacement;
+ }
+ }
+ }
}
////////////////////////////////////////////////////////////
@@ -1220,268 +1234,268 @@ template<>
S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions);
//static
-template<>
+template<>
void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims)
{
- // Starting at offset 0, scan forward for the next non-delimiter. We're
- // done when the only characters left in 'instr' are delimiters.
- for (std::string::size_type begIdx, endIdx = 0;
- (begIdx = instr.find_first_not_of (delims, endIdx)) != std::string::npos; )
- {
- // Found a non-delimiter. After that, find the next delimiter.
- endIdx = instr.find_first_of (delims, begIdx);
- if (endIdx == std::string::npos)
- {
- // No more delimiters: this token extends to the end of the string.
- endIdx = instr.length();
- }
-
- // extract the token between begIdx and endIdx; substr() needs length
- std::string currToken(instr.substr(begIdx, endIdx - begIdx));
- LLStringUtil::trim (currToken);
- tokens.push_back(currToken);
- // next scan past delimiters starts at endIdx
- }
-}
-
-template<>
+ // Starting at offset 0, scan forward for the next non-delimiter. We're
+ // done when the only characters left in 'instr' are delimiters.
+ for (std::string::size_type begIdx, endIdx = 0;
+ (begIdx = instr.find_first_not_of (delims, endIdx)) != std::string::npos; )
+ {
+ // Found a non-delimiter. After that, find the next delimiter.
+ endIdx = instr.find_first_of (delims, begIdx);
+ if (endIdx == std::string::npos)
+ {
+ // No more delimiters: this token extends to the end of the string.
+ endIdx = instr.length();
+ }
+
+ // extract the token between begIdx and endIdx; substr() needs length
+ std::string currToken(instr.substr(begIdx, endIdx - begIdx));
+ LLStringUtil::trim (currToken);
+ tokens.push_back(currToken);
+ // next scan past delimiters starts at endIdx
+ }
+}
+
+template<>
LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr, size_type& start, std::vector<std::string>& tokens)
{
- const std::string delims (",");
-
- // Find the first [
- size_type pos1 = instr.find('[', start);
- if (pos1 == std::string::npos)
- return std::string::npos;
-
- //Find the first ] after the initial [
- size_type pos2 = instr.find(']', pos1);
- if (pos2 == std::string::npos)
- return std::string::npos;
-
- // Find the last [ before ] in case of nested [[]]
- pos1 = instr.find_last_of('[', pos2-1);
- if (pos1 == std::string::npos || pos1 < start)
- return std::string::npos;
-
- getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims);
- start = pos2+1;
-
- return pos1;
+ const std::string delims (",");
+
+ // Find the first [
+ size_type pos1 = instr.find('[', start);
+ if (pos1 == std::string::npos)
+ return std::string::npos;
+
+ //Find the first ] after the initial [
+ size_type pos2 = instr.find(']', pos1);
+ if (pos2 == std::string::npos)
+ return std::string::npos;
+
+ // Find the last [ before ] in case of nested [[]]
+ pos1 = instr.find_last_of('[', pos2-1);
+ if (pos1 == std::string::npos || pos1 < start)
+ return std::string::npos;
+
+ getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims);
+ start = pos2+1;
+
+ return pos1;
}
// static
-template<>
+template<>
bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const format_map_t& substitutions)
{
- // see if we have a replacement for the bracketed string (without the brackets)
- // test first using has() because if we just look up with operator[] we get back an
- // empty string even if the value is missing. We want to distinguish between
- // missing replacements and deliberately empty replacement strings.
- format_map_t::const_iterator iter = substitutions.find(token);
- if (iter != substitutions.end())
- {
- replacement = iter->second;
- return true;
- }
- // if not, see if there's one WITH brackets
- iter = substitutions.find(std::string("[" + token + "]"));
- if (iter != substitutions.end())
- {
- replacement = iter->second;
- return true;
- }
-
- return false;
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ format_map_t::const_iterator iter = substitutions.find(token);
+ if (iter != substitutions.end())
+ {
+ replacement = iter->second;
+ return true;
+ }
+ // if not, see if there's one WITH brackets
+ iter = substitutions.find(std::string("[" + token + "]"));
+ if (iter != substitutions.end())
+ {
+ replacement = iter->second;
+ return true;
+ }
+
+ return false;
}
// static
-template<>
+template<>
bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const LLSD& substitutions)
{
- // see if we have a replacement for the bracketed string (without the brackets)
- // test first using has() because if we just look up with operator[] we get back an
- // empty string even if the value is missing. We want to distinguish between
- // missing replacements and deliberately empty replacement strings.
- if (substitutions.has(token))
- {
- replacement = substitutions[token].asString();
- return true;
- }
- // if not, see if there's one WITH brackets
- else if (substitutions.has(std::string("[" + token + "]")))
- {
- replacement = substitutions[std::string("[" + token + "]")].asString();
- return true;
- }
-
- return false;
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ if (substitutions.has(token))
+ {
+ replacement = substitutions[token].asString();
+ return true;
+ }
+ // if not, see if there's one WITH brackets
+ else if (substitutions.has(std::string("[" + token + "]")))
+ {
+ replacement = substitutions[std::string("[" + token + "]")].asString();
+ return true;
+ }
+
+ return false;
}
//static
template<>
void LLStringUtil::setLocale(std::string inLocale)
{
- sLocale = inLocale;
+ sLocale = inLocale;
};
//static
template<>
std::string LLStringUtil::getLocale(void)
{
- return sLocale;
+ return sLocale;
};
// static
-template<>
+template<>
void LLStringUtil::formatNumber(std::string& numStr, std::string decimals)
{
- std::stringstream strStream;
- S32 intDecimals = 0;
-
- convertToS32 (decimals, intDecimals);
- if (!sLocale.empty())
- {
- // std::locale() throws if the locale is unknown! (EXT-7926)
- try
- {
- strStream.imbue(std::locale(sLocale.c_str()));
- } catch (const std::exception &)
- {
- LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL;
- }
- }
-
- if (!intDecimals)
- {
- S32 intStr;
-
- if (convertToS32(numStr, intStr))
- {
- strStream << intStr;
- numStr = strStream.str();
- }
- }
- else
- {
- F32 floatStr;
-
- if (convertToF32(numStr, floatStr))
- {
- strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr;
- numStr = strStream.str();
- }
- }
+ std::stringstream strStream;
+ S32 intDecimals = 0;
+
+ convertToS32 (decimals, intDecimals);
+ if (!sLocale.empty())
+ {
+ // std::locale() throws if the locale is unknown! (EXT-7926)
+ try
+ {
+ strStream.imbue(std::locale(sLocale.c_str()));
+ } catch (const std::exception &)
+ {
+ LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL;
+ }
+ }
+
+ if (!intDecimals)
+ {
+ S32 intStr;
+
+ if (convertToS32(numStr, intStr))
+ {
+ strStream << intStr;
+ numStr = strStream.str();
+ }
+ }
+ else
+ {
+ F32 floatStr;
+
+ if (convertToF32(numStr, floatStr))
+ {
+ strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr;
+ numStr = strStream.str();
+ }
+ }
}
// static
-template<>
+template<>
bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
- std::string param, S32 secFromEpoch)
-{
- if (param == "local") // local
- {
- secFromEpoch -= LLStringOps::getLocalTimeOffset();
- }
- else if (param != "utc") // slt
- {
- secFromEpoch -= LLStringOps::getPacificTimeOffset();
- }
-
- // if never fell into those two ifs above, param must be utc
- if (secFromEpoch < 0) secFromEpoch = 0;
-
- LLDate datetime((F64)secFromEpoch);
- std::string code = LLStringOps::getDatetimeCode (token);
-
- // special case to handle timezone
- if (code == "%Z") {
- if (param == "utc")
- {
- replacement = "GMT";
- }
- else if (param == "local")
- {
- replacement = ""; // user knows their own timezone
- }
- else
- {
+ std::string param, S32 secFromEpoch)
+{
+ if (param == "local") // local
+ {
+ secFromEpoch -= LLStringOps::getLocalTimeOffset();
+ }
+ else if (param != "utc") // slt
+ {
+ secFromEpoch -= LLStringOps::getPacificTimeOffset();
+ }
+
+ // if never fell into those two ifs above, param must be utc
+ if (secFromEpoch < 0) secFromEpoch = 0;
+
+ LLDate datetime((F64)secFromEpoch);
+ std::string code = LLStringOps::getDatetimeCode (token);
+
+ // special case to handle timezone
+ if (code == "%Z") {
+ if (param == "utc")
+ {
+ replacement = "GMT";
+ }
+ else if (param == "local")
+ {
+ replacement = ""; // user knows their own timezone
+ }
+ else
+ {
#if 0
- // EXT-1565 : Zai Lynch, James Linden : 15/Oct/09
- // [BSI] Feedback: Viewer clock mentions SLT, but would prefer it to show PST/PDT
- // "slt" = Second Life Time, which is deprecated.
- // If not utc or user local time, fallback to Pacific time
- replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
+ // EXT-1565 : Zai Lynch, James Linden : 15/Oct/09
+ // [BSI] Feedback: Viewer clock mentions SLT, but would prefer it to show PST/PDT
+ // "slt" = Second Life Time, which is deprecated.
+ // If not utc or user local time, fallback to Pacific time
+ replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
#else
- // SL-20370 : Steeltoe Linden : 29/Sep/23
- // Change "PDT" to "SLT" on menu bar
- replacement = "SLT";
+ // SL-20370 : Steeltoe Linden : 29/Sep/23
+ // Change "PDT" to "SLT" on menu bar
+ replacement = "SLT";
#endif
- }
- return true;
- }
-
- //EXT-7013
- //few codes are not suppotred by strtime function (example - weekdays for Japanise)
- //so use predefined ones
-
- //if sWeekDayList is not empty than current locale doesn't support
+ }
+ return true;
+ }
+
+ //EXT-7013
+ //few codes are not suppotred by strtime function (example - weekdays for Japanise)
+ //so use predefined ones
+
+ //if sWeekDayList is not empty than current locale doesn't support
//weekday name.
- time_t loc_seconds = (time_t) secFromEpoch;
- if(LLStringOps::sWeekDayList.size() == 7 && code == "%A")
- {
- struct tm * gmt = gmtime (&loc_seconds);
- replacement = LLStringOps::sWeekDayList[gmt->tm_wday];
- }
- else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a")
- {
- struct tm * gmt = gmtime (&loc_seconds);
- replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday];
- }
- else if(LLStringOps::sMonthList.size() == 12 && code == "%B")
- {
- struct tm * gmt = gmtime (&loc_seconds);
- replacement = LLStringOps::sMonthList[gmt->tm_mon];
- }
- else if( !LLStringOps::sDayFormat.empty() && code == "%d" )
- {
- struct tm * gmt = gmtime (&loc_seconds);
- LLStringUtil::format_map_t args;
- args["[MDAY]"] = llformat ("%d", gmt->tm_mday);
- replacement = LLStringOps::sDayFormat;
- LLStringUtil::format(replacement, args);
- }
- else if (code == "%-d")
- {
- struct tm * gmt = gmtime (&loc_seconds);
- replacement = llformat ("%d", gmt->tm_mday); // day of the month without leading zero
- }
- else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" )
- {
- struct tm * gmt = gmtime (&loc_seconds);
- if(gmt->tm_hour<12)
- {
- replacement = LLStringOps::sAM;
- }
- else
- {
- replacement = LLStringOps::sPM;
- }
- }
- else
- {
- replacement = datetime.toHTTPDateString(code);
- }
-
- // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format
- // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738).
- // We could have used '%l' format instead, but it's not supported by Windows.
- if(code == "%I" && token == "hour12" && replacement.at(0) == '0')
- {
- replacement = replacement.at(1);
- }
-
- return !code.empty();
+ time_t loc_seconds = (time_t) secFromEpoch;
+ if(LLStringOps::sWeekDayList.size() == 7 && code == "%A")
+ {
+ struct tm * gmt = gmtime (&loc_seconds);
+ replacement = LLStringOps::sWeekDayList[gmt->tm_wday];
+ }
+ else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a")
+ {
+ struct tm * gmt = gmtime (&loc_seconds);
+ replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday];
+ }
+ else if(LLStringOps::sMonthList.size() == 12 && code == "%B")
+ {
+ struct tm * gmt = gmtime (&loc_seconds);
+ replacement = LLStringOps::sMonthList[gmt->tm_mon];
+ }
+ else if( !LLStringOps::sDayFormat.empty() && code == "%d" )
+ {
+ struct tm * gmt = gmtime (&loc_seconds);
+ LLStringUtil::format_map_t args;
+ args["[MDAY]"] = llformat ("%d", gmt->tm_mday);
+ replacement = LLStringOps::sDayFormat;
+ LLStringUtil::format(replacement, args);
+ }
+ else if (code == "%-d")
+ {
+ struct tm * gmt = gmtime (&loc_seconds);
+ replacement = llformat ("%d", gmt->tm_mday); // day of the month without leading zero
+ }
+ else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" )
+ {
+ struct tm * gmt = gmtime (&loc_seconds);
+ if(gmt->tm_hour<12)
+ {
+ replacement = LLStringOps::sAM;
+ }
+ else
+ {
+ replacement = LLStringOps::sPM;
+ }
+ }
+ else
+ {
+ replacement = datetime.toHTTPDateString(code);
+ }
+
+ // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format
+ // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738).
+ // We could have used '%l' format instead, but it's not supported by Windows.
+ if(code == "%I" && token == "hour12" && replacement.at(0) == '0')
+ {
+ replacement = replacement.at(1);
+ }
+
+ return !code.empty();
}
// LLStringUtil::format recogizes the following patterns.
@@ -1493,146 +1507,146 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
// static
-template<>
+template<>
S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STRING;
- S32 res = 0;
-
- std::string output;
- std::vector<std::string> tokens;
-
- std::string::size_type start = 0;
- std::string::size_type prev_start = 0;
- std::string::size_type key_start = 0;
- while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
- {
- output += std::string(s, prev_start, key_start-prev_start);
- prev_start = start;
-
- bool found_replacement = false;
- std::string replacement;
-
- if (tokens.size() == 0)
- {
- found_replacement = false;
- }
- else if (tokens.size() == 1)
- {
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- }
- else if (tokens[1] == "number")
- {
- std::string param = "0";
-
- if (tokens.size() > 2) param = tokens[2];
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- if (found_replacement) formatNumber (replacement, param);
- }
- else if (tokens[1] == "datetime")
- {
- std::string param;
- if (tokens.size() > 2) param = tokens[2];
-
- format_map_t::const_iterator iter = substitutions.find("datetime");
- if (iter != substitutions.end())
- {
- S32 secFromEpoch = 0;
- BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
- if (r)
- {
- found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
- }
- }
- }
-
- if (found_replacement)
- {
- output += replacement;
- res++;
- }
- else
- {
- // we had no replacement, use the string as is
- // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
- output += std::string(s, key_start, start-key_start);
- }
- tokens.clear();
- }
- // send the remainder of the string (with no further matches for bracketed names)
- output += std::string(s, start);
- s = output;
- return res;
+ S32 res = 0;
+
+ std::string output;
+ std::vector<std::string> tokens;
+
+ std::string::size_type start = 0;
+ std::string::size_type prev_start = 0;
+ std::string::size_type key_start = 0;
+ while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
+ {
+ output += std::string(s, prev_start, key_start-prev_start);
+ prev_start = start;
+
+ bool found_replacement = false;
+ std::string replacement;
+
+ if (tokens.size() == 0)
+ {
+ found_replacement = false;
+ }
+ else if (tokens.size() == 1)
+ {
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ }
+ else if (tokens[1] == "number")
+ {
+ std::string param = "0";
+
+ if (tokens.size() > 2) param = tokens[2];
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ if (found_replacement) formatNumber (replacement, param);
+ }
+ else if (tokens[1] == "datetime")
+ {
+ std::string param;
+ if (tokens.size() > 2) param = tokens[2];
+
+ format_map_t::const_iterator iter = substitutions.find("datetime");
+ if (iter != substitutions.end())
+ {
+ S32 secFromEpoch = 0;
+ BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
+ if (r)
+ {
+ found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
+ }
+ }
+ }
+
+ if (found_replacement)
+ {
+ output += replacement;
+ res++;
+ }
+ else
+ {
+ // we had no replacement, use the string as is
+ // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
+ output += std::string(s, key_start, start-key_start);
+ }
+ tokens.clear();
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output += std::string(s, start);
+ s = output;
+ return res;
}
//static
-template<>
+template<>
S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STRING;
- S32 res = 0;
-
- if (!substitutions.isMap())
- {
- return res;
- }
-
- std::string output;
- std::vector<std::string> tokens;
-
- std::string::size_type start = 0;
- std::string::size_type prev_start = 0;
- std::string::size_type key_start = 0;
- while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
- {
- output += std::string(s, prev_start, key_start-prev_start);
- prev_start = start;
-
- bool found_replacement = false;
- std::string replacement;
-
- if (tokens.size() == 0)
- {
- found_replacement = false;
- }
- else if (tokens.size() == 1)
- {
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- }
- else if (tokens[1] == "number")
- {
- std::string param = "0";
-
- if (tokens.size() > 2) param = tokens[2];
- found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
- if (found_replacement) formatNumber (replacement, param);
- }
- else if (tokens[1] == "datetime")
- {
- std::string param;
- if (tokens.size() > 2) param = tokens[2];
-
- S32 secFromEpoch = (S32) substitutions["datetime"].asInteger();
- found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch);
- }
-
- if (found_replacement)
- {
- output += replacement;
- res++;
- }
- else
- {
- // we had no replacement, use the string as is
- // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
- output += std::string(s, key_start, start-key_start);
- }
- tokens.clear();
- }
- // send the remainder of the string (with no further matches for bracketed names)
- output += std::string(s, start);
- s = output;
- return res;
+ S32 res = 0;
+
+ if (!substitutions.isMap())
+ {
+ return res;
+ }
+
+ std::string output;
+ std::vector<std::string> tokens;
+
+ std::string::size_type start = 0;
+ std::string::size_type prev_start = 0;
+ std::string::size_type key_start = 0;
+ while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
+ {
+ output += std::string(s, prev_start, key_start-prev_start);
+ prev_start = start;
+
+ bool found_replacement = false;
+ std::string replacement;
+
+ if (tokens.size() == 0)
+ {
+ found_replacement = false;
+ }
+ else if (tokens.size() == 1)
+ {
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ }
+ else if (tokens[1] == "number")
+ {
+ std::string param = "0";
+
+ if (tokens.size() > 2) param = tokens[2];
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ if (found_replacement) formatNumber (replacement, param);
+ }
+ else if (tokens[1] == "datetime")
+ {
+ std::string param;
+ if (tokens.size() > 2) param = tokens[2];
+
+ S32 secFromEpoch = (S32) substitutions["datetime"].asInteger();
+ found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch);
+ }
+
+ if (found_replacement)
+ {
+ output += replacement;
+ res++;
+ }
+ else
+ {
+ // we had no replacement, use the string as is
+ // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
+ output += std::string(s, key_start, start-key_start);
+ }
+ tokens.clear();
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output += std::string(s, start);
+ s = output;
+ return res;
}
////////////////////////////////////////////////////////////
@@ -1640,102 +1654,102 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
#ifdef _DEBUG
-template<class T>
+template<class T>
void LLStringUtilBase<T>::testHarness()
{
- std::string s1;
-
- llassert( s1.c_str() == NULL );
- llassert( s1.size() == 0 );
- llassert( s1.empty() );
-
- std::string s2( "hello");
- llassert( !strcmp( s2.c_str(), "hello" ) );
- llassert( s2.size() == 5 );
- llassert( !s2.empty() );
- std::string s3( s2 );
-
- llassert( "hello" == s2 );
- llassert( s2 == "hello" );
- llassert( s2 > "gello" );
- llassert( "gello" < s2 );
- llassert( "gello" != s2 );
- llassert( s2 != "gello" );
-
- std::string s4 = s2;
- llassert( !s4.empty() );
- s4.empty();
- llassert( s4.empty() );
-
- std::string s5("");
- llassert( s5.empty() );
-
- llassert( isValidIndex(s5, 0) );
- llassert( !isValidIndex(s5, 1) );
-
- s3 = s2;
- s4 = "hello again";
-
- s4 += "!";
- s4 += s4;
- llassert( s4 == "hello again!hello again!" );
-
-
- std::string s6 = s2 + " " + s2;
- std::string s7 = s6;
- llassert( s6 == s7 );
- llassert( !( s6 != s7) );
- llassert( !(s6 < s7) );
- llassert( !(s6 > s7) );
-
- llassert( !(s6 == "hi"));
- llassert( s6 == "hello hello");
- llassert( s6 < "hi");
-
- llassert( s6[1] == 'e' );
- s6[1] = 'f';
- llassert( s6[1] == 'f' );
-
- s2.erase( 4, 1 );
- llassert( s2 == "hell");
- s2.insert( 0, "y" );
- llassert( s2 == "yhell");
- s2.erase( 1, 3 );
- llassert( s2 == "yl");
- s2.insert( 1, "awn, don't yel");
- llassert( s2 == "yawn, don't yell");
-
- std::string s8 = s2.substr( 6, 5 );
- llassert( s8 == "don't" );
-
- std::string s9 = " \t\ntest \t\t\n ";
- trim(s9);
- llassert( s9 == "test" );
-
- s8 = "abc123&*(ABC";
-
- s9 = s8;
- toUpper(s9);
- llassert( s9 == "ABC123&*(ABC" );
-
- s9 = s8;
- toLower(s9);
- llassert( s9 == "abc123&*(abc" );
-
-
- std::string s10( 10, 'x' );
- llassert( s10 == "xxxxxxxxxx" );
-
- std::string s11( "monkey in the middle", 7, 2 );
- llassert( s11 == "in" );
-
- std::string s12; //empty
- s12 += "foo";
- llassert( s12 == "foo" );
-
- std::string s13; //empty
- s13 += 'f';
- llassert( s13 == "f" );
+ std::string s1;
+
+ llassert( s1.c_str() == NULL );
+ llassert( s1.size() == 0 );
+ llassert( s1.empty() );
+
+ std::string s2( "hello");
+ llassert( !strcmp( s2.c_str(), "hello" ) );
+ llassert( s2.size() == 5 );
+ llassert( !s2.empty() );
+ std::string s3( s2 );
+
+ llassert( "hello" == s2 );
+ llassert( s2 == "hello" );
+ llassert( s2 > "gello" );
+ llassert( "gello" < s2 );
+ llassert( "gello" != s2 );
+ llassert( s2 != "gello" );
+
+ std::string s4 = s2;
+ llassert( !s4.empty() );
+ s4.empty();
+ llassert( s4.empty() );
+
+ std::string s5("");
+ llassert( s5.empty() );
+
+ llassert( isValidIndex(s5, 0) );
+ llassert( !isValidIndex(s5, 1) );
+
+ s3 = s2;
+ s4 = "hello again";
+
+ s4 += "!";
+ s4 += s4;
+ llassert( s4 == "hello again!hello again!" );
+
+
+ std::string s6 = s2 + " " + s2;
+ std::string s7 = s6;
+ llassert( s6 == s7 );
+ llassert( !( s6 != s7) );
+ llassert( !(s6 < s7) );
+ llassert( !(s6 > s7) );
+
+ llassert( !(s6 == "hi"));
+ llassert( s6 == "hello hello");
+ llassert( s6 < "hi");
+
+ llassert( s6[1] == 'e' );
+ s6[1] = 'f';
+ llassert( s6[1] == 'f' );
+
+ s2.erase( 4, 1 );
+ llassert( s2 == "hell");
+ s2.insert( 0, "y" );
+ llassert( s2 == "yhell");
+ s2.erase( 1, 3 );
+ llassert( s2 == "yl");
+ s2.insert( 1, "awn, don't yel");
+ llassert( s2 == "yawn, don't yell");
+
+ std::string s8 = s2.substr( 6, 5 );
+ llassert( s8 == "don't" );
+
+ std::string s9 = " \t\ntest \t\t\n ";
+ trim(s9);
+ llassert( s9 == "test" );
+
+ s8 = "abc123&*(ABC";
+
+ s9 = s8;
+ toUpper(s9);
+ llassert( s9 == "ABC123&*(ABC" );
+
+ s9 = s8;
+ toLower(s9);
+ llassert( s9 == "abc123&*(abc" );
+
+
+ std::string s10( 10, 'x' );
+ llassert( s10 == "xxxxxxxxxx" );
+
+ std::string s11( "monkey in the middle", 7, 2 );
+ llassert( s11 == "in" );
+
+ std::string s12; //empty
+ s12 += "foo";
+ llassert( s12 == "foo" );
+
+ std::string s13; //empty
+ s13 += 'f';
+ llassert( s13 == "f" );
}
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index be00aa277b..6503da2e77 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$
*/
@@ -59,85 +59,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; }
};
};
@@ -146,72 +146,73 @@ 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);
+ // Returns true when 'a' corresponds to a "genuine" emoji. HB
+ static bool isEmoji(llwchar a);
- 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);
};
@@ -228,216 +229,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;
@@ -453,18 +454,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);
+ }
};
@@ -481,10 +482,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);
}
/**
@@ -677,10 +678,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);
@@ -697,7 +698,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.
@@ -710,8 +711,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.
@@ -732,14 +733,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);
@@ -747,6 +748,12 @@ LL_COMMON_API llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset
LL_COMMON_API std::string utf8str_showBytesUTF8(const std::string& utf8str);
+LL_COMMON_API bool wstring_has_emoji(const LLWString& wstr);
+
+LL_COMMON_API bool wstring_remove_emojis(LLWString& wstr);
+
+LL_COMMON_API bool utf8str_remove_emojis(std::string& utf8str);
+
#if LL_WINDOWS
/* @name Windows string helpers
*/
@@ -845,52 +852,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);
}
////////////////////////////////////////////////////////////
@@ -905,36 +912,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
@@ -950,62 +957,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
@@ -1013,177 +1020,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
@@ -1191,256 +1198,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 );
+ }
}
@@ -1449,67 +1456,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())
@@ -1538,269 +1545,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
@@ -1835,187 +1842,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/llstringtable.cpp b/indra/llcommon/llstringtable.cpp
index 92a5e777a6..d28e1e2219 100644
--- a/indra/llcommon/llstringtable.cpp
+++ b/indra/llcommon/llstringtable.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llstringtable.cpp
* @brief The LLStringTable class provides a _fast_ method for finding
* unique copies of strings.
@@ -6,21 +6,21 @@
* $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$
*/
@@ -35,101 +35,101 @@ LLStringTable gStringTable(32768);
LLStringTableEntry::LLStringTableEntry(const char *str)
: mString(NULL), mCount(1)
{
- // Copy string
- U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/
- length = llmin(length, MAX_STRINGS_LENGTH);
- mString = new char[length];
- strncpy(mString, str, length); /*Flawfinder: ignore*/
- mString[length - 1] = 0;
+ // Copy string
+ U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/
+ length = llmin(length, MAX_STRINGS_LENGTH);
+ mString = new char[length];
+ strncpy(mString, str, length); /*Flawfinder: ignore*/
+ mString[length - 1] = 0;
}
LLStringTableEntry::~LLStringTableEntry()
{
- delete [] mString;
- mCount = 0;
+ delete [] mString;
+ mCount = 0;
}
LLStringTable::LLStringTable(int tablesize)
: mUniqueEntries(0)
{
- S32 i;
- if (!tablesize)
- tablesize = 4096; // some arbitrary default
- // Make sure tablesize is power of 2
- for (i = 31; i>0; i--)
- {
- if (tablesize & (1<<i))
- {
- if (tablesize >= (3<<(i-1)))
- tablesize = (1<<(i+1));
- else
- tablesize = (1<<i);
- break;
- }
- }
- mMaxEntries = tablesize;
+ S32 i;
+ if (!tablesize)
+ tablesize = 4096; // some arbitrary default
+ // Make sure tablesize is power of 2
+ for (i = 31; i>0; i--)
+ {
+ if (tablesize & (1<<i))
+ {
+ if (tablesize >= (3<<(i-1)))
+ tablesize = (1<<(i+1));
+ else
+ tablesize = (1<<i);
+ break;
+ }
+ }
+ mMaxEntries = tablesize;
#if !STRING_TABLE_HASH_MAP
- // ALlocate strings
- mStringList = new string_list_ptr_t[mMaxEntries];
- // Clear strings
- for (i = 0; i < mMaxEntries; i++)
- {
- mStringList[i] = NULL;
- }
+ // ALlocate strings
+ mStringList = new string_list_ptr_t[mMaxEntries];
+ // Clear strings
+ for (i = 0; i < mMaxEntries; i++)
+ {
+ mStringList[i] = NULL;
+ }
#endif
}
LLStringTable::~LLStringTable()
{
#if !STRING_TABLE_HASH_MAP
- if (mStringList)
- {
- for (S32 i = 0; i < mMaxEntries; i++)
- {
- if (mStringList[i])
- {
- for (LLStringTableEntry* entry : *mStringList[i])
- delete entry;
- }
- delete mStringList[i];
- }
- delete [] mStringList;
- mStringList = NULL;
- }
+ if (mStringList)
+ {
+ for (S32 i = 0; i < mMaxEntries; i++)
+ {
+ if (mStringList[i])
+ {
+ for (LLStringTableEntry* entry : *mStringList[i])
+ delete entry;
+ }
+ delete mStringList[i];
+ }
+ delete [] mStringList;
+ mStringList = NULL;
+ }
#else
- // Need to clean up the string hash
- for_each(mStringHash.begin(), mStringHash.end(), DeletePairedPointer());
- mStringHash.clear();
+ // Need to clean up the string hash
+ for_each(mStringHash.begin(), mStringHash.end(), DeletePairedPointer());
+ mStringHash.clear();
#endif
}
static U32 hash_my_string(const char *str, int max_entries)
{
- U32 retval = 0;
+ U32 retval = 0;
#if 0
- while (*str)
- {
- retval <<= 1;
- retval += *str++;
- }
+ while (*str)
+ {
+ retval <<= 1;
+ retval += *str++;
+ }
#else
- while (*str)
- {
- retval = (retval<<4) + *str;
- U32 x = (retval & 0xf0000000);
- if (x) retval = retval ^ (x>>24);
- retval = retval & (~x);
- str++;
- }
+ while (*str)
+ {
+ retval = (retval<<4) + *str;
+ U32 x = (retval & 0xf0000000);
+ if (x) retval = retval ^ (x>>24);
+ retval = retval & (~x);
+ str++;
+ }
#endif
- return (retval & (max_entries-1)); // max_entries is gauranteed to be power of 2
+ return (retval & (max_entries-1)); // max_entries is gauranteed to be power of 2
}
char* LLStringTable::checkString(const std::string& str)
{
- return checkString(str.c_str());
+ return checkString(str.c_str());
}
char* LLStringTable::checkString(const char *str)
@@ -137,11 +137,11 @@ char* LLStringTable::checkString(const char *str)
LLStringTableEntry* entry = checkStringEntry(str);
if (entry)
{
- return entry->mString;
+ return entry->mString;
}
else
{
- return NULL;
+ return NULL;
}
}
@@ -152,51 +152,51 @@ LLStringTableEntry* LLStringTable::checkStringEntry(const std::string& str)
LLStringTableEntry* LLStringTable::checkStringEntry(const char *str)
{
- if (str)
- {
- char *ret_val;
- U32 hash_value = hash_my_string(str, mMaxEntries);
+ if (str)
+ {
+ char *ret_val;
+ U32 hash_value = hash_my_string(str, mMaxEntries);
#if STRING_TABLE_HASH_MAP
- LLStringTableEntry *entry;
+ LLStringTableEntry *entry;
#if 1 // Microsoft
- string_hash_t::iterator lower = mStringHash.lower_bound(hash_value);
- string_hash_t::iterator upper = mStringHash.upper_bound(hash_value);
+ string_hash_t::iterator lower = mStringHash.lower_bound(hash_value);
+ string_hash_t::iterator upper = mStringHash.upper_bound(hash_value);
#else // stlport
- std::pair<string_hash_t::iterator, string_hash_t::iterator> P = mStringHash.equal_range(hash_value);
- string_hash_t::iterator lower = P.first;
- string_hash_t::iterator upper = P.second;
+ std::pair<string_hash_t::iterator, string_hash_t::iterator> P = mStringHash.equal_range(hash_value);
+ string_hash_t::iterator lower = P.first;
+ string_hash_t::iterator upper = P.second;
#endif
- for (string_hash_t::iterator iter = lower; iter != upper; iter++)
- {
- entry = iter->second;
- ret_val = entry->mString;
- if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
- {
- return entry;
- }
- }
+ for (string_hash_t::iterator iter = lower; iter != upper; iter++)
+ {
+ entry = iter->second;
+ ret_val = entry->mString;
+ if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
+ {
+ return entry;
+ }
+ }
#else
- string_list_t *strlist = mStringList[hash_value];
- if (strlist)
- {
- for (LLStringTableEntry* entry : *strlist)
- {
- ret_val = entry->mString;
- if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
- {
- return entry;
- }
- }
- }
+ string_list_t *strlist = mStringList[hash_value];
+ if (strlist)
+ {
+ for (LLStringTableEntry* entry : *strlist)
+ {
+ ret_val = entry->mString;
+ if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
+ {
+ return entry;
+ }
+ }
+ }
#endif
- }
- return NULL;
+ }
+ return NULL;
}
char* LLStringTable::addString(const std::string& str)
{
- //RN: safe to use temporary c_str since string is copied
- return addString(str.c_str());
+ //RN: safe to use temporary c_str since string is copied
+ return addString(str.c_str());
}
char* LLStringTable::addString(const char *str)
@@ -205,11 +205,11 @@ char* LLStringTable::addString(const char *str)
LLStringTableEntry* entry = addStringEntry(str);
if (entry)
{
- return entry->mString;
+ return entry->mString;
}
else
{
- return NULL;
+ return NULL;
}
}
@@ -220,132 +220,132 @@ LLStringTableEntry* LLStringTable::addStringEntry(const std::string& str)
LLStringTableEntry* LLStringTable::addStringEntry(const char *str)
{
- if (str)
- {
- char *ret_val = NULL;
- U32 hash_value = hash_my_string(str, mMaxEntries);
+ if (str)
+ {
+ char *ret_val = NULL;
+ U32 hash_value = hash_my_string(str, mMaxEntries);
#if STRING_TABLE_HASH_MAP
- LLStringTableEntry *entry;
+ LLStringTableEntry *entry;
#if 1 // Microsoft
- string_hash_t::iterator lower = mStringHash.lower_bound(hash_value);
- string_hash_t::iterator upper = mStringHash.upper_bound(hash_value);
+ string_hash_t::iterator lower = mStringHash.lower_bound(hash_value);
+ string_hash_t::iterator upper = mStringHash.upper_bound(hash_value);
#else // stlport
- std::pair<string_hash_t::iterator, string_hash_t::iterator> P = mStringHash.equal_range(hash_value);
- string_hash_t::iterator lower = P.first;
- string_hash_t::iterator upper = P.second;
+ std::pair<string_hash_t::iterator, string_hash_t::iterator> P = mStringHash.equal_range(hash_value);
+ string_hash_t::iterator lower = P.first;
+ string_hash_t::iterator upper = P.second;
#endif
- for (string_hash_t::iterator iter = lower; iter != upper; iter++)
- {
- entry = iter->second;
- ret_val = entry->mString;
- if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
- {
- entry->incCount();
- return entry;
- }
- }
+ for (string_hash_t::iterator iter = lower; iter != upper; iter++)
+ {
+ entry = iter->second;
+ ret_val = entry->mString;
+ if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
+ {
+ entry->incCount();
+ return entry;
+ }
+ }
- // not found, so add!
- LLStringTableEntry* newentry = new LLStringTableEntry(str);
- ret_val = newentry->mString;
- mStringHash.insert(string_hash_t::value_type(hash_value, newentry));
+ // not found, so add!
+ LLStringTableEntry* newentry = new LLStringTableEntry(str);
+ ret_val = newentry->mString;
+ mStringHash.insert(string_hash_t::value_type(hash_value, newentry));
#else
- string_list_t *strlist = mStringList[hash_value];
+ string_list_t *strlist = mStringList[hash_value];
- if (strlist)
- {
- for (LLStringTableEntry* entry : *strlist)
- {
- ret_val = entry->mString;
- if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
- {
- entry->incCount();
- return entry;
- }
- }
- }
- else
- {
- mStringList[hash_value] = new string_list_t;
- strlist = mStringList[hash_value];
- }
+ if (strlist)
+ {
+ for (LLStringTableEntry* entry : *strlist)
+ {
+ ret_val = entry->mString;
+ if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
+ {
+ entry->incCount();
+ return entry;
+ }
+ }
+ }
+ else
+ {
+ mStringList[hash_value] = new string_list_t;
+ strlist = mStringList[hash_value];
+ }
- // not found, so add!
- LLStringTableEntry *newentry = new LLStringTableEntry(str);
- //ret_val = newentry->mString;
- strlist->push_front(newentry);
+ // not found, so add!
+ LLStringTableEntry *newentry = new LLStringTableEntry(str);
+ //ret_val = newentry->mString;
+ strlist->push_front(newentry);
#endif
- mUniqueEntries++;
- return newentry;
- }
- else
- {
- return NULL;
- }
+ mUniqueEntries++;
+ return newentry;
+ }
+ else
+ {
+ return NULL;
+ }
}
void LLStringTable::removeString(const char *str)
{
- if (str)
- {
- char *ret_val;
- U32 hash_value = hash_my_string(str, mMaxEntries);
+ if (str)
+ {
+ char *ret_val;
+ U32 hash_value = hash_my_string(str, mMaxEntries);
#if STRING_TABLE_HASH_MAP
- {
- LLStringTableEntry *entry;
+ {
+ LLStringTableEntry *entry;
#if 1 // Microsoft
- string_hash_t::iterator lower = mStringHash.lower_bound(hash_value);
- string_hash_t::iterator upper = mStringHash.upper_bound(hash_value);
+ string_hash_t::iterator lower = mStringHash.lower_bound(hash_value);
+ string_hash_t::iterator upper = mStringHash.upper_bound(hash_value);
#else // stlport
- std::pair<string_hash_t::iterator, string_hash_t::iterator> P = mStringHash.equal_range(hash_value);
- string_hash_t::iterator lower = P.first;
- string_hash_t::iterator upper = P.second;
+ std::pair<string_hash_t::iterator, string_hash_t::iterator> P = mStringHash.equal_range(hash_value);
+ string_hash_t::iterator lower = P.first;
+ string_hash_t::iterator upper = P.second;
#endif
- for (string_hash_t::iterator iter = lower; iter != upper; iter++)
- {
- entry = iter->second;
- ret_val = entry->mString;
- if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
- {
- if (!entry->decCount())
- {
- mUniqueEntries--;
- if (mUniqueEntries < 0)
- {
- LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
- }
- delete iter->second;
- mStringHash.erase(iter);
- }
- return;
- }
- }
- }
+ for (string_hash_t::iterator iter = lower; iter != upper; iter++)
+ {
+ entry = iter->second;
+ ret_val = entry->mString;
+ if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
+ {
+ if (!entry->decCount())
+ {
+ mUniqueEntries--;
+ if (mUniqueEntries < 0)
+ {
+ LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
+ }
+ delete iter->second;
+ mStringHash.erase(iter);
+ }
+ return;
+ }
+ }
+ }
#else
- string_list_t *strlist = mStringList[hash_value];
+ string_list_t *strlist = mStringList[hash_value];
- if (strlist)
- {
- for (LLStringTableEntry* entry : *strlist)
- {
- ret_val = entry->mString;
- if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
- {
- if (!entry->decCount())
- {
- mUniqueEntries--;
- if (mUniqueEntries < 0)
- {
- LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
- }
- strlist->remove(entry);
- delete entry;
- }
- return;
- }
- }
- }
+ if (strlist)
+ {
+ for (LLStringTableEntry* entry : *strlist)
+ {
+ ret_val = entry->mString;
+ if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
+ {
+ if (!entry->decCount())
+ {
+ mUniqueEntries--;
+ if (mUniqueEntries < 0)
+ {
+ LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
+ }
+ strlist->remove(entry);
+ delete entry;
+ }
+ return;
+ }
+ }
+ }
#endif
- }
+ }
}
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 0a292c8bac..e41701ce9c 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llstringtable.h
* @brief The LLStringTable class provides a _fast_ method for finding
* unique copies of strings.
@@ -6,21 +6,21 @@
* $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$
*/
@@ -47,48 +47,48 @@ const U32 MAX_STRINGS_LENGTH = 256;
class LL_COMMON_API LLStringTableEntry
{
public:
- LLStringTableEntry(const char *str);
- ~LLStringTableEntry();
+ LLStringTableEntry(const char *str);
+ ~LLStringTableEntry();
- void incCount() { mCount++; }
- BOOL decCount() { return --mCount; }
+ void incCount() { mCount++; }
+ BOOL decCount() { return --mCount; }
- char *mString;
- S32 mCount;
+ char *mString;
+ S32 mCount;
};
class LL_COMMON_API LLStringTable
{
public:
- LLStringTable(int tablesize);
- ~LLStringTable();
-
- char *checkString(const char *str);
- char *checkString(const std::string& str);
- LLStringTableEntry *checkStringEntry(const char *str);
- LLStringTableEntry *checkStringEntry(const std::string& str);
-
- char *addString(const char *str);
- char *addString(const std::string& str);
- LLStringTableEntry *addStringEntry(const char *str);
- LLStringTableEntry *addStringEntry(const std::string& str);
- void removeString(const char *str);
-
- S32 mMaxEntries;
- S32 mUniqueEntries;
-
+ LLStringTable(int tablesize);
+ ~LLStringTable();
+
+ char *checkString(const char *str);
+ char *checkString(const std::string& str);
+ LLStringTableEntry *checkStringEntry(const char *str);
+ LLStringTableEntry *checkStringEntry(const std::string& str);
+
+ char *addString(const char *str);
+ char *addString(const std::string& str);
+ LLStringTableEntry *addStringEntry(const char *str);
+ LLStringTableEntry *addStringEntry(const std::string& str);
+ void removeString(const char *str);
+
+ S32 mMaxEntries;
+ S32 mUniqueEntries;
+
#if STRING_TABLE_HASH_MAP
#if LL_WINDOWS
- typedef std::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
+ typedef std::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
#else
- typedef __gnu_cxx::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
+ typedef __gnu_cxx::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
#endif
- string_hash_t mStringHash;
+ string_hash_t mStringHash;
#else
- typedef std::list<LLStringTableEntry *> string_list_t;
- typedef string_list_t * string_list_ptr_t;
- string_list_ptr_t *mStringList;
-#endif
+ typedef std::list<LLStringTableEntry *> string_list_t;
+ typedef string_list_t * string_list_ptr_t;
+ string_list_ptr_t *mStringList;
+#endif
};
extern LL_COMMON_API LLStringTable gStringTable;
@@ -104,105 +104,105 @@ typedef const std::string* LLStdStringHandle;
class LL_COMMON_API LLStdStringTable
{
public:
- LLStdStringTable(S32 tablesize = 0)
- {
- if (tablesize == 0)
- {
- tablesize = 256; // default
- }
- // Make sure tablesize is power of 2
- for (S32 i = 31; i>0; i--)
- {
- if (tablesize & (1<<i))
- {
- if (tablesize >= (3<<(i-1)))
- tablesize = (1<<(i+1));
- else
- tablesize = (1<<i);
- break;
- }
- }
- mTableSize = tablesize;
- mStringList = new string_set_t[tablesize];
- }
- ~LLStdStringTable()
- {
- cleanup();
- delete[] mStringList;
- }
- void cleanup()
- {
- // remove strings
- for (S32 i = 0; i<mTableSize; i++)
- {
- string_set_t& stringset = mStringList[i];
- for (LLStdStringHandle str : stringset)
- {
- delete str;
- }
- stringset.clear();
- }
- }
-
- LLStdStringHandle lookup(const std::string& s)
- {
- U32 hashval = makehash(s);
- return lookup(hashval, s);
- }
-
- LLStdStringHandle checkString(const std::string& s)
- {
- U32 hashval = makehash(s);
- return lookup(hashval, s);
- }
-
- LLStdStringHandle insert(const std::string& s)
- {
- U32 hashval = makehash(s);
- LLStdStringHandle result = lookup(hashval, s);
- if (result == NULL)
- {
- result = new std::string(s);
- mStringList[hashval].insert(result);
- }
- return result;
- }
- LLStdStringHandle addString(const std::string& s)
- {
- return insert(s);
- }
-
+ LLStdStringTable(S32 tablesize = 0)
+ {
+ if (tablesize == 0)
+ {
+ tablesize = 256; // default
+ }
+ // Make sure tablesize is power of 2
+ for (S32 i = 31; i>0; i--)
+ {
+ if (tablesize & (1<<i))
+ {
+ if (tablesize >= (3<<(i-1)))
+ tablesize = (1<<(i+1));
+ else
+ tablesize = (1<<i);
+ break;
+ }
+ }
+ mTableSize = tablesize;
+ mStringList = new string_set_t[tablesize];
+ }
+ ~LLStdStringTable()
+ {
+ cleanup();
+ delete[] mStringList;
+ }
+ void cleanup()
+ {
+ // remove strings
+ for (S32 i = 0; i<mTableSize; i++)
+ {
+ string_set_t& stringset = mStringList[i];
+ for (LLStdStringHandle str : stringset)
+ {
+ delete str;
+ }
+ stringset.clear();
+ }
+ }
+
+ LLStdStringHandle lookup(const std::string& s)
+ {
+ U32 hashval = makehash(s);
+ return lookup(hashval, s);
+ }
+
+ LLStdStringHandle checkString(const std::string& s)
+ {
+ U32 hashval = makehash(s);
+ return lookup(hashval, s);
+ }
+
+ LLStdStringHandle insert(const std::string& s)
+ {
+ U32 hashval = makehash(s);
+ LLStdStringHandle result = lookup(hashval, s);
+ if (result == NULL)
+ {
+ result = new std::string(s);
+ mStringList[hashval].insert(result);
+ }
+ return result;
+ }
+ LLStdStringHandle addString(const std::string& s)
+ {
+ return insert(s);
+ }
+
private:
- U32 makehash(const std::string& s)
- {
- S32 len = (S32)s.size();
- const char* c = s.c_str();
- U32 hashval = 0;
- for (S32 i=0; i<len; i++)
- {
- hashval = ((hashval<<5) + hashval) + *c++;
- }
- return hashval & (mTableSize-1);
- }
- LLStdStringHandle lookup(U32 hashval, const std::string& s)
- {
- string_set_t& stringset = mStringList[hashval];
- LLStdStringHandle handle = &s;
- string_set_t::iterator iter = stringset.find(handle); // compares actual strings
- if (iter != stringset.end())
- {
- return *iter;
- }
- else
- {
- return NULL;
- }
- }
-
+ U32 makehash(const std::string& s)
+ {
+ S32 len = (S32)s.size();
+ const char* c = s.c_str();
+ U32 hashval = 0;
+ for (S32 i=0; i<len; i++)
+ {
+ hashval = ((hashval<<5) + hashval) + *c++;
+ }
+ return hashval & (mTableSize-1);
+ }
+ LLStdStringHandle lookup(U32 hashval, const std::string& s)
+ {
+ string_set_t& stringset = mStringList[hashval];
+ LLStdStringHandle handle = &s;
+ string_set_t::iterator iter = stringset.find(handle); // compares actual strings
+ if (iter != stringset.end())
+ {
+ return *iter;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
private:
- S32 mTableSize;
- typedef std::set<LLStdStringHandle, compare_pointer_contents<std::string> > string_set_t;
- string_set_t* mStringList; // [mTableSize]
+ S32 mTableSize;
+ typedef std::set<LLStdStringHandle, compare_pointer_contents<std::string> > string_set_t;
+ string_set_t* mStringList; // [mTableSize]
};
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index e53c82ad2b..4f888f1f5a 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -59,26 +59,26 @@
using namespace llsd;
#if LL_WINDOWS
-# include "llwin32headerslean.h"
+# include "llwin32headerslean.h"
# include <psapi.h> // GetPerformanceInfo() et al.
-# include <VersionHelpers.h>
+# include <VersionHelpers.h>
#elif LL_DARWIN
# include "llsys_objc.h"
-# include <errno.h>
-# include <sys/sysctl.h>
-# include <sys/utsname.h>
-# include <stdint.h>
-# include <CoreServices/CoreServices.h>
+# include <errno.h>
+# include <sys/sysctl.h>
+# include <sys/utsname.h>
+# include <stdint.h>
+# include <CoreServices/CoreServices.h>
# include <stdexcept>
-# include <mach/host_info.h>
-# include <mach/mach_host.h>
-# include <mach/task.h>
-# include <mach/task_info.h>
+# include <mach/host_info.h>
+# include <mach/mach_host.h>
+# include <mach/task.h>
+# include <mach/task_info.h>
#elif LL_LINUX
-# include <errno.h>
-# include <sys/utsname.h>
-# include <unistd.h>
-# include <sys/sysinfo.h>
+# include <errno.h>
+# include <sys/utsname.h>
+# include <unistd.h>
+# include <sys/sysinfo.h>
# include <stdexcept>
const char MEMINFO_FILE[] = "/proc/meminfo";
# include <gnu/libc-version.h>
@@ -96,132 +96,132 @@ static const F32 MEM_INFO_THROTTLE = 20;
static const F32 MEM_INFO_WINDOW = 10*60;
LLOSInfo::LLOSInfo() :
- mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
+ mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
{
#if LL_WINDOWS
if (IsWindows10OrGreater())
- {
- mMajorVer = 10;
- mMinorVer = 0;
- mOSStringSimple = "Microsoft Windows 10 ";
- }
- else if (IsWindows8Point1OrGreater())
- {
- mMajorVer = 6;
- mMinorVer = 3;
- if (IsWindowsServer())
- {
- mOSStringSimple = "Windows Server 2012 R2 ";
- }
- else
- {
- mOSStringSimple = "Microsoft Windows 8.1 ";
- }
- }
- else if (IsWindows8OrGreater())
- {
- mMajorVer = 6;
- mMinorVer = 2;
- if (IsWindowsServer())
- {
- mOSStringSimple = "Windows Server 2012 ";
- }
- else
- {
- mOSStringSimple = "Microsoft Windows 8 ";
- }
- }
- else if (IsWindows7SP1OrGreater())
- {
- mMajorVer = 6;
- mMinorVer = 1;
- if (IsWindowsServer())
- {
- mOSStringSimple = "Windows Server 2008 R2 SP1 ";
- }
- else
- {
- mOSStringSimple = "Microsoft Windows 7 SP1 ";
- }
- }
- else if (IsWindows7OrGreater())
- {
- mMajorVer = 6;
- mMinorVer = 1;
- if (IsWindowsServer())
- {
- mOSStringSimple = "Windows Server 2008 R2 ";
- }
- else
- {
- mOSStringSimple = "Microsoft Windows 7 ";
- }
- }
- else if (IsWindowsVistaSP2OrGreater())
- {
- mMajorVer = 6;
- mMinorVer = 0;
- if (IsWindowsServer())
- {
- mOSStringSimple = "Windows Server 2008 SP2 ";
- }
- else
- {
- mOSStringSimple = "Microsoft Windows Vista SP2 ";
- }
- }
- else
- {
- mOSStringSimple = "Unsupported Windows version ";
- }
-
- ///get native system info if available..
- typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
- SYSTEM_INFO si; //System Info object file contains architecture info
- PGNSI pGNSI; //pointer object
- ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
- pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
- if (NULL != pGNSI) //check if it has failed
- pGNSI(&si); //success
- else
- GetSystemInfo(&si); //if it fails get regular system info
- //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
-
- // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
- OSVERSIONINFOEX osvi;
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- if (GetVersionEx((OSVERSIONINFO *)&osvi))
- {
- mBuild = osvi.dwBuildNumber & 0xffff;
- }
- else
- {
- // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx((OSVERSIONINFO *)&osvi))
- {
- mBuild = osvi.dwBuildNumber & 0xffff;
- }
- }
-
- S32 ubr = 0; // Windows 10 Update Build Revision, can be retrieved from a registry
- if (mMajorVer == 10)
- {
- DWORD cbData(sizeof(DWORD));
- DWORD data(0);
- HKEY key;
- BOOL ret_code = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_READ, &key);
- if (ERROR_SUCCESS == ret_code)
- {
- ret_code = RegQueryValueExW(key, L"UBR", 0, NULL, reinterpret_cast<LPBYTE>(&data), &cbData);
- if (ERROR_SUCCESS == ret_code)
- {
- ubr = data;
- }
- }
+ {
+ mMajorVer = 10;
+ mMinorVer = 0;
+ mOSStringSimple = "Microsoft Windows 10 ";
+ }
+ else if (IsWindows8Point1OrGreater())
+ {
+ mMajorVer = 6;
+ mMinorVer = 3;
+ if (IsWindowsServer())
+ {
+ mOSStringSimple = "Windows Server 2012 R2 ";
+ }
+ else
+ {
+ mOSStringSimple = "Microsoft Windows 8.1 ";
+ }
+ }
+ else if (IsWindows8OrGreater())
+ {
+ mMajorVer = 6;
+ mMinorVer = 2;
+ if (IsWindowsServer())
+ {
+ mOSStringSimple = "Windows Server 2012 ";
+ }
+ else
+ {
+ mOSStringSimple = "Microsoft Windows 8 ";
+ }
+ }
+ else if (IsWindows7SP1OrGreater())
+ {
+ mMajorVer = 6;
+ mMinorVer = 1;
+ if (IsWindowsServer())
+ {
+ mOSStringSimple = "Windows Server 2008 R2 SP1 ";
+ }
+ else
+ {
+ mOSStringSimple = "Microsoft Windows 7 SP1 ";
+ }
+ }
+ else if (IsWindows7OrGreater())
+ {
+ mMajorVer = 6;
+ mMinorVer = 1;
+ if (IsWindowsServer())
+ {
+ mOSStringSimple = "Windows Server 2008 R2 ";
+ }
+ else
+ {
+ mOSStringSimple = "Microsoft Windows 7 ";
+ }
+ }
+ else if (IsWindowsVistaSP2OrGreater())
+ {
+ mMajorVer = 6;
+ mMinorVer = 0;
+ if (IsWindowsServer())
+ {
+ mOSStringSimple = "Windows Server 2008 SP2 ";
+ }
+ else
+ {
+ mOSStringSimple = "Microsoft Windows Vista SP2 ";
+ }
+ }
+ else
+ {
+ mOSStringSimple = "Unsupported Windows version ";
+ }
+
+ ///get native system info if available..
+ typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
+ SYSTEM_INFO si; //System Info object file contains architecture info
+ PGNSI pGNSI; //pointer object
+ ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
+ pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
+ if (NULL != pGNSI) //check if it has failed
+ pGNSI(&si); //success
+ else
+ GetSystemInfo(&si); //if it fails get regular system info
+ //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
+
+ // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
+ OSVERSIONINFOEX osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if (GetVersionEx((OSVERSIONINFO *)&osvi))
+ {
+ mBuild = osvi.dwBuildNumber & 0xffff;
+ }
+ else
+ {
+ // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx((OSVERSIONINFO *)&osvi))
+ {
+ mBuild = osvi.dwBuildNumber & 0xffff;
+ }
+ }
+
+ S32 ubr = 0; // Windows 10 Update Build Revision, can be retrieved from a registry
+ if (mMajorVer == 10)
+ {
+ DWORD cbData(sizeof(DWORD));
+ DWORD data(0);
+ HKEY key;
+ BOOL ret_code = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_READ, &key);
+ if (ERROR_SUCCESS == ret_code)
+ {
+ ret_code = RegQueryValueExW(key, L"UBR", 0, NULL, reinterpret_cast<LPBYTE>(&data), &cbData);
+ if (ERROR_SUCCESS == ret_code)
+ {
+ ubr = data;
+ }
+ }
if (mBuild >= 22000)
{
@@ -251,262 +251,262 @@ LLOSInfo::LLOSInfo() :
mOSStringSimple += "32-bit ";
}
- mOSString = mOSStringSimple;
- if (mBuild > 0)
- {
- mOSString += llformat("(Build %d", mBuild);
- if (ubr > 0)
- {
- mOSString += llformat(".%d", ubr);
- }
- mOSString += ")";
- }
+ mOSString = mOSStringSimple;
+ if (mBuild > 0)
+ {
+ mOSString += llformat("(Build %d", mBuild);
+ if (ubr > 0)
+ {
+ mOSString += llformat(".%d", ubr);
+ }
+ mOSString += ")";
+ }
- LLStringUtil::trim(mOSStringSimple);
- LLStringUtil::trim(mOSString);
+ LLStringUtil::trim(mOSStringSimple);
+ LLStringUtil::trim(mOSString);
#elif LL_DARWIN
- // Initialize mOSStringSimple to something like:
- // "Mac OS X 10.6.7"
- {
- const char * DARWIN_PRODUCT_NAME = "Mac OS X";
-
- int64_t major_version, minor_version, bugfix_version = 0;
-
- if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version))
- {
- mMajorVer = major_version;
- mMinorVer = minor_version;
- mBuild = bugfix_version;
-
- std::stringstream os_version_string;
- os_version_string << DARWIN_PRODUCT_NAME << " " << mMajorVer << "." << mMinorVer << "." << mBuild;
-
- // Put it in the OS string we are compiling
- mOSStringSimple.append(os_version_string.str());
- }
- else
- {
- mOSStringSimple.append("Unable to collect OS info");
- }
- }
-
- // Initialize mOSString to something like:
- // "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386"
- struct utsname un;
- if(uname(&un) != -1)
- {
- mOSString = mOSStringSimple;
- mOSString.append(" ");
- mOSString.append(un.sysname);
- mOSString.append(" ");
- mOSString.append(un.release);
- mOSString.append(" ");
- mOSString.append(un.version);
- mOSString.append(" ");
- mOSString.append(un.machine);
- }
- else
- {
- mOSString = mOSStringSimple;
- }
+ // Initialize mOSStringSimple to something like:
+ // "Mac OS X 10.6.7"
+ {
+ const char * DARWIN_PRODUCT_NAME = "Mac OS X";
+
+ int64_t major_version, minor_version, bugfix_version = 0;
+
+ if (LLGetDarwinOSInfo(major_version, minor_version, bugfix_version))
+ {
+ mMajorVer = major_version;
+ mMinorVer = minor_version;
+ mBuild = bugfix_version;
+
+ std::stringstream os_version_string;
+ os_version_string << DARWIN_PRODUCT_NAME << " " << mMajorVer << "." << mMinorVer << "." << mBuild;
+
+ // Put it in the OS string we are compiling
+ mOSStringSimple.append(os_version_string.str());
+ }
+ else
+ {
+ mOSStringSimple.append("Unable to collect OS info");
+ }
+ }
+
+ // Initialize mOSString to something like:
+ // "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386"
+ struct utsname un;
+ if(uname(&un) != -1)
+ {
+ mOSString = mOSStringSimple;
+ mOSString.append(" ");
+ mOSString.append(un.sysname);
+ mOSString.append(" ");
+ mOSString.append(un.release);
+ mOSString.append(" ");
+ mOSString.append(un.version);
+ mOSString.append(" ");
+ mOSString.append(un.machine);
+ }
+ else
+ {
+ mOSString = mOSStringSimple;
+ }
#elif LL_LINUX
- struct utsname un;
- if(uname(&un) != -1)
- {
- mOSStringSimple.append(un.sysname);
- mOSStringSimple.append(" ");
- mOSStringSimple.append(un.release);
-
- mOSString = mOSStringSimple;
- mOSString.append(" ");
- mOSString.append(un.version);
- mOSString.append(" ");
- mOSString.append(un.machine);
-
- // Simplify 'Simple'
- std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
- if (ostype == "Linux")
- {
- // Only care about major and minor Linux versions, truncate at second '.'
- std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
- std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
- std::string simple = mOSStringSimple.substr(0, idx2);
- if (simple.length() > 0)
- mOSStringSimple = simple;
- }
- }
- else
- {
- mOSStringSimple.append("Unable to collect OS info");
- mOSString = mOSStringSimple;
- }
-
- const char OS_VERSION_MATCH_EXPRESSION[] = "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?";
- boost::regex os_version_parse(OS_VERSION_MATCH_EXPRESSION);
- boost::smatch matched;
-
- std::string glibc_version(gnu_get_libc_version());
- if ( ll_regex_match(glibc_version, matched, os_version_parse) )
- {
- LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL;
-
- std::string version_value;
-
- if ( matched[1].matched ) // Major version
- {
- version_value.assign(matched[1].first, matched[1].second);
- if (sscanf(version_value.c_str(), "%d", &mMajorVer) != 1)
- {
- LL_WARNS("AppInit") << "failed to parse major version '" << version_value << "' as a number" << LL_ENDL;
- }
- }
- else
- {
- LL_ERRS("AppInit")
- << "OS version regex '" << OS_VERSION_MATCH_EXPRESSION
- << "' returned true, but major version [1] did not match"
- << LL_ENDL;
- }
-
- if ( matched[2].matched ) // Minor version
- {
- version_value.assign(matched[2].first, matched[2].second);
- if (sscanf(version_value.c_str(), "%d", &mMinorVer) != 1)
- {
- LL_ERRS("AppInit") << "failed to parse minor version '" << version_value << "' as a number" << LL_ENDL;
- }
- }
- else
- {
- LL_ERRS("AppInit")
- << "OS version regex '" << OS_VERSION_MATCH_EXPRESSION
- << "' returned true, but minor version [1] did not match"
- << LL_ENDL;
- }
-
- if ( matched[4].matched ) // Build version (optional) - note that [3] includes the '.'
- {
- version_value.assign(matched[4].first, matched[4].second);
- if (sscanf(version_value.c_str(), "%d", &mBuild) != 1)
- {
- LL_ERRS("AppInit") << "failed to parse build version '" << version_value << "' as a number" << LL_ENDL;
- }
- }
- else
- {
- LL_INFOS("AppInit")
- << "OS build version not provided; using zero"
- << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("AppInit") << "glibc version '" << glibc_version << "' cannot be parsed to three numbers; using all zeros" << LL_ENDL;
- }
+ struct utsname un;
+ if(uname(&un) != -1)
+ {
+ mOSStringSimple.append(un.sysname);
+ mOSStringSimple.append(" ");
+ mOSStringSimple.append(un.release);
+
+ mOSString = mOSStringSimple;
+ mOSString.append(" ");
+ mOSString.append(un.version);
+ mOSString.append(" ");
+ mOSString.append(un.machine);
+
+ // Simplify 'Simple'
+ std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
+ if (ostype == "Linux")
+ {
+ // Only care about major and minor Linux versions, truncate at second '.'
+ std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
+ std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
+ std::string simple = mOSStringSimple.substr(0, idx2);
+ if (simple.length() > 0)
+ mOSStringSimple = simple;
+ }
+ }
+ else
+ {
+ mOSStringSimple.append("Unable to collect OS info");
+ mOSString = mOSStringSimple;
+ }
+
+ const char OS_VERSION_MATCH_EXPRESSION[] = "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?";
+ boost::regex os_version_parse(OS_VERSION_MATCH_EXPRESSION);
+ boost::smatch matched;
+
+ std::string glibc_version(gnu_get_libc_version());
+ if ( ll_regex_match(glibc_version, matched, os_version_parse) )
+ {
+ LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL;
+
+ std::string version_value;
+
+ if ( matched[1].matched ) // Major version
+ {
+ version_value.assign(matched[1].first, matched[1].second);
+ if (sscanf(version_value.c_str(), "%d", &mMajorVer) != 1)
+ {
+ LL_WARNS("AppInit") << "failed to parse major version '" << version_value << "' as a number" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_ERRS("AppInit")
+ << "OS version regex '" << OS_VERSION_MATCH_EXPRESSION
+ << "' returned true, but major version [1] did not match"
+ << LL_ENDL;
+ }
+
+ if ( matched[2].matched ) // Minor version
+ {
+ version_value.assign(matched[2].first, matched[2].second);
+ if (sscanf(version_value.c_str(), "%d", &mMinorVer) != 1)
+ {
+ LL_ERRS("AppInit") << "failed to parse minor version '" << version_value << "' as a number" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_ERRS("AppInit")
+ << "OS version regex '" << OS_VERSION_MATCH_EXPRESSION
+ << "' returned true, but minor version [1] did not match"
+ << LL_ENDL;
+ }
+
+ if ( matched[4].matched ) // Build version (optional) - note that [3] includes the '.'
+ {
+ version_value.assign(matched[4].first, matched[4].second);
+ if (sscanf(version_value.c_str(), "%d", &mBuild) != 1)
+ {
+ LL_ERRS("AppInit") << "failed to parse build version '" << version_value << "' as a number" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_INFOS("AppInit")
+ << "OS build version not provided; using zero"
+ << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "glibc version '" << glibc_version << "' cannot be parsed to three numbers; using all zeros" << LL_ENDL;
+ }
#else
- struct utsname un;
- if(uname(&un) != -1)
- {
- mOSStringSimple.append(un.sysname);
- mOSStringSimple.append(" ");
- mOSStringSimple.append(un.release);
-
- mOSString = mOSStringSimple;
- mOSString.append(" ");
- mOSString.append(un.version);
- mOSString.append(" ");
- mOSString.append(un.machine);
-
- // Simplify 'Simple'
- std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
- if (ostype == "Linux")
- {
- // Only care about major and minor Linux versions, truncate at second '.'
- std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
- std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
- std::string simple = mOSStringSimple.substr(0, idx2);
- if (simple.length() > 0)
- mOSStringSimple = simple;
- }
- }
- else
- {
- mOSStringSimple.append("Unable to collect OS info");
- mOSString = mOSStringSimple;
- }
+ struct utsname un;
+ if(uname(&un) != -1)
+ {
+ mOSStringSimple.append(un.sysname);
+ mOSStringSimple.append(" ");
+ mOSStringSimple.append(un.release);
+
+ mOSString = mOSStringSimple;
+ mOSString.append(" ");
+ mOSString.append(un.version);
+ mOSString.append(" ");
+ mOSString.append(un.machine);
+
+ // Simplify 'Simple'
+ std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
+ if (ostype == "Linux")
+ {
+ // Only care about major and minor Linux versions, truncate at second '.'
+ std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
+ std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
+ std::string simple = mOSStringSimple.substr(0, idx2);
+ if (simple.length() > 0)
+ mOSStringSimple = simple;
+ }
+ }
+ else
+ {
+ mOSStringSimple.append("Unable to collect OS info");
+ mOSString = mOSStringSimple;
+ }
#endif
- std::stringstream dotted_version_string;
- dotted_version_string << mMajorVer << "." << mMinorVer << "." << mBuild;
- mOSVersionString.append(dotted_version_string.str());
+ std::stringstream dotted_version_string;
+ dotted_version_string << mMajorVer << "." << mMinorVer << "." << mBuild;
+ mOSVersionString.append(dotted_version_string.str());
- mOSBitness = is64Bit() ? 64 : 32;
- LL_INFOS("LLOSInfo") << "OS bitness: " << mOSBitness << LL_ENDL;
+ mOSBitness = is64Bit() ? 64 : 32;
+ LL_INFOS("LLOSInfo") << "OS bitness: " << mOSBitness << LL_ENDL;
}
#ifndef LL_WINDOWS
// static
long LLOSInfo::getMaxOpenFiles()
{
- const long OPEN_MAX_GUESS = 256;
+ const long OPEN_MAX_GUESS = 256;
-#ifdef OPEN_MAX
- static long open_max = OPEN_MAX;
+#ifdef OPEN_MAX
+ static long open_max = OPEN_MAX;
#else
- static long open_max = 0;
+ static long open_max = 0;
#endif
- if (0 == open_max)
- {
- // First time through.
- errno = 0;
- if ( (open_max = sysconf(_SC_OPEN_MAX)) < 0)
- {
- if (0 == errno)
- {
- // Indeterminate.
- open_max = OPEN_MAX_GUESS;
- }
- else
- {
- LL_ERRS() << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << LL_ENDL;
- }
- }
- }
- return open_max;
+ if (0 == open_max)
+ {
+ // First time through.
+ errno = 0;
+ if ( (open_max = sysconf(_SC_OPEN_MAX)) < 0)
+ {
+ if (0 == errno)
+ {
+ // Indeterminate.
+ open_max = OPEN_MAX_GUESS;
+ }
+ else
+ {
+ LL_ERRS() << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << LL_ENDL;
+ }
+ }
+ }
+ return open_max;
}
#endif
void LLOSInfo::stream(std::ostream& s) const
{
- s << mOSString;
+ s << mOSString;
}
const std::string& LLOSInfo::getOSString() const
{
- return mOSString;
+ return mOSString;
}
const std::string& LLOSInfo::getOSStringSimple() const
{
- return mOSStringSimple;
+ return mOSStringSimple;
}
const std::string& LLOSInfo::getOSVersionString() const
{
- return mOSVersionString;
+ return mOSVersionString;
}
const S32 LLOSInfo::getOSBitness() const
{
- return mOSBitness;
+ return mOSBitness;
}
namespace {
@@ -520,7 +520,7 @@ namespace {
LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
if (status_filep)
{
- char buff[STATUS_SIZE]; /* Flawfinder: ignore */
+ char buff[STATUS_SIZE]; /* Flawfinder: ignore */
size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
buff[nbytes] = '\0';
@@ -572,28 +572,28 @@ bool LLOSInfo::is64Bit()
LLCPUInfo::LLCPUInfo()
{
- std::ostringstream out;
- LLProcessorInfo proc;
- // proc.WriteInfoTextFile("procInfo.txt");
- mHasSSE = proc.hasSSE();
- mHasSSE2 = proc.hasSSE2();
+ std::ostringstream out;
+ LLProcessorInfo proc;
+ // proc.WriteInfoTextFile("procInfo.txt");
+ mHasSSE = proc.hasSSE();
+ mHasSSE2 = proc.hasSSE2();
mHasSSE3 = proc.hasSSE3();
mHasSSE3S = proc.hasSSE3S();
mHasSSE41 = proc.hasSSE41();
mHasSSE42 = proc.hasSSE42();
mHasSSE4a = proc.hasSSE4a();
- mHasAltivec = proc.hasAltivec();
- mCPUMHz = (F64)proc.getCPUFrequency();
- mFamily = proc.getCPUFamilyName();
- mCPUString = "Unknown";
-
- out << proc.getCPUBrandName();
- if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
- {
- out << " (" << mCPUMHz << " MHz)";
- }
- mCPUString = out.str();
- LLStringUtil::trim(mCPUString);
+ mHasAltivec = proc.hasAltivec();
+ mCPUMHz = (F64)proc.getCPUFrequency();
+ mFamily = proc.getCPUFamilyName();
+ mCPUString = "Unknown";
+
+ out << proc.getCPUBrandName();
+ if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
+ {
+ out << " (" << mCPUMHz << " MHz)";
+ }
+ mCPUString = out.str();
+ LLStringUtil::trim(mCPUString);
if (mHasSSE)
{
@@ -627,17 +627,17 @@ LLCPUInfo::LLCPUInfo()
bool LLCPUInfo::hasAltivec() const
{
- return mHasAltivec;
+ return mHasAltivec;
}
bool LLCPUInfo::hasSSE() const
{
- return mHasSSE;
+ return mHasSSE;
}
bool LLCPUInfo::hasSSE2() const
{
- return mHasSSE2;
+ return mHasSSE2;
}
bool LLCPUInfo::hasSSE3() const
@@ -667,12 +667,12 @@ bool LLCPUInfo::hasSSE4a() const
F64 LLCPUInfo::getMHz() const
{
- return mCPUMHz;
+ return mCPUMHz;
}
std::string LLCPUInfo::getCPUString() const
{
- return mCPUString;
+ return mCPUString;
}
const LLSD& LLCPUInfo::getSSEVersions() const
@@ -682,21 +682,21 @@ const LLSD& LLCPUInfo::getSSEVersions() const
void LLCPUInfo::stream(std::ostream& s) const
{
- // gather machine information.
- s << LLProcessorInfo().getCPUFeatureDescription();
+ // gather machine information.
+ s << LLProcessorInfo().getCPUFeatureDescription();
- // These are interesting as they reflect our internal view of the
- // CPU's attributes regardless of platform
- s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
- s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl;
+ // These are interesting as they reflect our internal view of the
+ // CPU's attributes regardless of platform
+ s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
+ s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl;
s << "->mHasSSE3: " << (U32)mHasSSE3 << std::endl;
s << "->mHasSSE3S: " << (U32)mHasSSE3S << std::endl;
s << "->mHasSSE41: " << (U32)mHasSSE41 << std::endl;
s << "->mHasSSE42: " << (U32)mHasSSE42 << std::endl;
s << "->mHasSSE4a: " << (U32)mHasSSE4a << std::endl;
- s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
- s << "->mCPUMHz: " << mCPUMHz << std::endl;
- s << "->mCPUString: " << mCPUString << std::endl;
+ s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
+ s << "->mCPUMHz: " << mCPUMHz << std::endl;
+ s << "->mCPUString: " << mCPUString << std::endl;
}
// Helper class for LLMemoryInfo: accumulate stats in the form we store for
@@ -704,58 +704,58 @@ void LLCPUInfo::stream(std::ostream& s) const
class Stats
{
public:
- Stats():
- mStats(LLSD::emptyMap())
- {}
-
- // Store every integer type as LLSD::Integer.
- template <class T>
- void add(const LLSD::String& name, const T& value,
- typename boost::enable_if<boost::is_integral<T> >::type* = 0)
- {
- mStats[name] = LLSD::Integer(value);
- }
-
- // Store every floating-point type as LLSD::Real.
- template <class T>
- void add(const LLSD::String& name, const T& value,
- typename boost::enable_if<boost::is_float<T> >::type* = 0)
- {
- mStats[name] = LLSD::Real(value);
- }
-
- // Hope that LLSD::Date values are sufficiently unambiguous.
- void add(const LLSD::String& name, const LLSD::Date& value)
- {
- mStats[name] = value;
- }
-
- LLSD get() const { return mStats; }
+ Stats():
+ mStats(LLSD::emptyMap())
+ {}
+
+ // Store every integer type as LLSD::Integer.
+ template <class T>
+ void add(const LLSD::String& name, const T& value,
+ typename boost::enable_if<boost::is_integral<T> >::type* = 0)
+ {
+ mStats[name] = LLSD::Integer(value);
+ }
+
+ // Store every floating-point type as LLSD::Real.
+ template <class T>
+ void add(const LLSD::String& name, const T& value,
+ typename boost::enable_if<boost::is_float<T> >::type* = 0)
+ {
+ mStats[name] = LLSD::Real(value);
+ }
+
+ // Hope that LLSD::Date values are sufficiently unambiguous.
+ void add(const LLSD::String& name, const LLSD::Date& value)
+ {
+ mStats[name] = value;
+ }
+
+ LLSD get() const { return mStats; }
private:
- LLSD mStats;
+ LLSD mStats;
};
LLMemoryInfo::LLMemoryInfo()
{
- refresh();
+ refresh();
}
#if LL_WINDOWS
static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
{
- // Moved this here from llfloaterabout.cpp
-
- //! \bug
- // For some reason, the reported amount of memory is always wrong.
- // The original adjustment assumes it's always off by one meg, however
- // errors of as much as 2520 KB have been observed in the value
- // returned from the GetMemoryStatusEx function. Here we keep the
- // original adjustment from llfoaterabout.cpp until this can be
- // fixed somehow.
- inKB += U32Megabytes(1);
-
- return inKB;
+ // Moved this here from llfloaterabout.cpp
+
+ //! \bug
+ // For some reason, the reported amount of memory is always wrong.
+ // The original adjustment assumes it's always off by one meg, however
+ // errors of as much as 2520 KB have been observed in the value
+ // returned from the GetMemoryStatusEx function. Here we keep the
+ // original adjustment from llfoaterabout.cpp until this can be
+ // fixed somehow.
+ inKB += U32Megabytes(1);
+
+ return inKB;
}
#endif
@@ -777,18 +777,18 @@ U32Kilobytes LLMemoryInfo::getHardwareMemSize()
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
{
#if LL_WINDOWS
- return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
+ return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
#elif LL_DARWIN
return getHardwareMemSize();
#elif LL_LINUX
- U64 phys = 0;
- phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
- return U64Bytes(phys);
+ U64 phys = 0;
+ phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
+ return U64Bytes(phys);
#else
- return 0;
+ return 0;
#endif
}
@@ -797,373 +797,373 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
{
#if LL_WINDOWS
- // Sigh, this shouldn't be a static method, then we wouldn't have to
- // reload this data separately from refresh()
- LLSD statsMap(loadStatsMap());
+ // Sigh, this shouldn't be a static method, then we wouldn't have to
+ // reload this data separately from refresh()
+ LLSD statsMap(loadStatsMap());
- avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
- avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
+ avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
+ avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
#elif LL_DARWIN
- // mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
- // $ vm_stat
- // Mach Virtual Memory Statistics: (page size of 4096 bytes)
- // Pages free: 462078.
- // Pages active: 142010.
- // Pages inactive: 220007.
- // Pages wired down: 159552.
- // "Translation faults": 220825184.
- // Pages copy-on-write: 2104153.
- // Pages zero filled: 167034876.
- // Pages reactivated: 65153.
- // Pageins: 2097212.
- // Pageouts: 41759.
- // Object cache: 841598 hits of 7629869 lookups (11% hit rate)
- avail_physical_mem_kb = (U32Kilobytes)-1 ;
- avail_virtual_mem_kb = (U32Kilobytes)-1 ;
+ // mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
+ // $ vm_stat
+ // Mach Virtual Memory Statistics: (page size of 4096 bytes)
+ // Pages free: 462078.
+ // Pages active: 142010.
+ // Pages inactive: 220007.
+ // Pages wired down: 159552.
+ // "Translation faults": 220825184.
+ // Pages copy-on-write: 2104153.
+ // Pages zero filled: 167034876.
+ // Pages reactivated: 65153.
+ // Pageins: 2097212.
+ // Pageouts: 41759.
+ // Object cache: 841598 hits of 7629869 lookups (11% hit rate)
+ avail_physical_mem_kb = (U32Kilobytes)-1 ;
+ avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#elif LL_LINUX
- // mStatsMap is derived from MEMINFO_FILE:
- // $ cat /proc/meminfo
- // MemTotal: 4108424 kB
- // MemFree: 1244064 kB
- // Buffers: 85164 kB
- // Cached: 1990264 kB
- // SwapCached: 0 kB
- // Active: 1176648 kB
- // Inactive: 1427532 kB
- // Active(anon): 529152 kB
- // Inactive(anon): 15924 kB
- // Active(file): 647496 kB
- // Inactive(file): 1411608 kB
- // Unevictable: 16 kB
- // Mlocked: 16 kB
- // HighTotal: 3266316 kB
- // HighFree: 721308 kB
- // LowTotal: 842108 kB
- // LowFree: 522756 kB
- // SwapTotal: 6384632 kB
- // SwapFree: 6384632 kB
- // Dirty: 28 kB
- // Writeback: 0 kB
- // AnonPages: 528820 kB
- // Mapped: 89472 kB
- // Shmem: 16324 kB
- // Slab: 159624 kB
- // SReclaimable: 145168 kB
- // SUnreclaim: 14456 kB
- // KernelStack: 2560 kB
- // PageTables: 5560 kB
- // NFS_Unstable: 0 kB
- // Bounce: 0 kB
- // WritebackTmp: 0 kB
- // CommitLimit: 8438844 kB
- // Committed_AS: 1271596 kB
- // VmallocTotal: 122880 kB
- // VmallocUsed: 65252 kB
- // VmallocChunk: 52356 kB
- // HardwareCorrupted: 0 kB
- // HugePages_Total: 0
- // HugePages_Free: 0
- // HugePages_Rsvd: 0
- // HugePages_Surp: 0
- // Hugepagesize: 2048 kB
- // DirectMap4k: 434168 kB
- // DirectMap2M: 477184 kB
- // (could also run 'free', but easier to read a file than run a program)
- avail_physical_mem_kb = (U32Kilobytes)-1 ;
- avail_virtual_mem_kb = (U32Kilobytes)-1 ;
+ // mStatsMap is derived from MEMINFO_FILE:
+ // $ cat /proc/meminfo
+ // MemTotal: 4108424 kB
+ // MemFree: 1244064 kB
+ // Buffers: 85164 kB
+ // Cached: 1990264 kB
+ // SwapCached: 0 kB
+ // Active: 1176648 kB
+ // Inactive: 1427532 kB
+ // Active(anon): 529152 kB
+ // Inactive(anon): 15924 kB
+ // Active(file): 647496 kB
+ // Inactive(file): 1411608 kB
+ // Unevictable: 16 kB
+ // Mlocked: 16 kB
+ // HighTotal: 3266316 kB
+ // HighFree: 721308 kB
+ // LowTotal: 842108 kB
+ // LowFree: 522756 kB
+ // SwapTotal: 6384632 kB
+ // SwapFree: 6384632 kB
+ // Dirty: 28 kB
+ // Writeback: 0 kB
+ // AnonPages: 528820 kB
+ // Mapped: 89472 kB
+ // Shmem: 16324 kB
+ // Slab: 159624 kB
+ // SReclaimable: 145168 kB
+ // SUnreclaim: 14456 kB
+ // KernelStack: 2560 kB
+ // PageTables: 5560 kB
+ // NFS_Unstable: 0 kB
+ // Bounce: 0 kB
+ // WritebackTmp: 0 kB
+ // CommitLimit: 8438844 kB
+ // Committed_AS: 1271596 kB
+ // VmallocTotal: 122880 kB
+ // VmallocUsed: 65252 kB
+ // VmallocChunk: 52356 kB
+ // HardwareCorrupted: 0 kB
+ // HugePages_Total: 0
+ // HugePages_Free: 0
+ // HugePages_Rsvd: 0
+ // HugePages_Surp: 0
+ // Hugepagesize: 2048 kB
+ // DirectMap4k: 434168 kB
+ // DirectMap2M: 477184 kB
+ // (could also run 'free', but easier to read a file than run a program)
+ avail_physical_mem_kb = (U32Kilobytes)-1 ;
+ avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#else
- //do not know how to collect available memory info for other systems.
- //leave it blank here for now.
+ //do not know how to collect available memory info for other systems.
+ //leave it blank here for now.
- avail_physical_mem_kb = (U32Kilobytes)-1 ;
- avail_virtual_mem_kb = (U32Kilobytes)-1 ;
+ avail_physical_mem_kb = (U32Kilobytes)-1 ;
+ avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#endif
}
void LLMemoryInfo::stream(std::ostream& s) const
{
- // We want these memory stats to be easy to grep from the log, along with
- // the timestamp. So preface each line with the timestamp and a
- // distinctive marker. Without that, we'd have to search the log for the
- // introducer line, then read subsequent lines, etc...
- std::string pfx(LLError::utcTime() + " <mem> ");
-
- // Max key length
- size_t key_width(0);
- for (const auto& [key, value] : inMap(mStatsMap))
- {
- size_t len(key.length());
- if (len > key_width)
- {
- key_width = len;
- }
- }
-
- // Now stream stats
- for (const auto& [key, value] : inMap(mStatsMap))
- {
- s << pfx << std::setw(narrow<size_t>(key_width+1)) << (key + ':') << ' ';
- if (value.isInteger())
- s << std::setw(12) << value.asInteger();
- else if (value.isReal())
- s << std::fixed << std::setprecision(1) << value.asReal();
- else if (value.isDate())
- value.asDate().toStream(s);
- else
- s << value; // just use default LLSD formatting
- s << std::endl;
- }
+ // We want these memory stats to be easy to grep from the log, along with
+ // the timestamp. So preface each line with the timestamp and a
+ // distinctive marker. Without that, we'd have to search the log for the
+ // introducer line, then read subsequent lines, etc...
+ std::string pfx(LLError::utcTime() + " <mem> ");
+
+ // Max key length
+ size_t key_width(0);
+ for (const auto& [key, value] : inMap(mStatsMap))
+ {
+ size_t len(key.length());
+ if (len > key_width)
+ {
+ key_width = len;
+ }
+ }
+
+ // Now stream stats
+ for (const auto& [key, value] : inMap(mStatsMap))
+ {
+ s << pfx << std::setw(narrow<size_t>(key_width+1)) << (key + ':') << ' ';
+ if (value.isInteger())
+ s << std::setw(12) << value.asInteger();
+ else if (value.isReal())
+ s << std::fixed << std::setprecision(1) << value.asReal();
+ else if (value.isDate())
+ value.asDate().toStream(s);
+ else
+ s << value; // just use default LLSD formatting
+ s << std::endl;
+ }
}
LLSD LLMemoryInfo::getStatsMap() const
{
- return mStatsMap;
+ return mStatsMap;
}
LLMemoryInfo& LLMemoryInfo::refresh()
{
- LL_PROFILE_ZONE_SCOPED
- mStatsMap = loadStatsMap();
+ LL_PROFILE_ZONE_SCOPED
+ mStatsMap = loadStatsMap();
- LL_DEBUGS("LLMemoryInfo") << "Populated mStatsMap:\n";
- LLSDSerialize::toPrettyXML(mStatsMap, LL_CONT);
- LL_ENDL;
+ LL_DEBUGS("LLMemoryInfo") << "Populated mStatsMap:\n";
+ LLSDSerialize::toPrettyXML(mStatsMap, LL_CONT);
+ LL_ENDL;
- return *this;
+ return *this;
}
LLSD LLMemoryInfo::loadStatsMap()
{
LL_PROFILE_ZONE_SCOPED;
- // This implementation is derived from stream() code (as of 2011-06-29).
- Stats stats;
+ // This implementation is derived from stream() code (as of 2011-06-29).
+ Stats stats;
- // associate timestamp for analysis over time
- stats.add("timestamp", LLDate::now());
+ // associate timestamp for analysis over time
+ stats.add("timestamp", LLDate::now());
#if LL_WINDOWS
- MEMORYSTATUSEX state;
- state.dwLength = sizeof(state);
- GlobalMemoryStatusEx(&state);
-
- DWORDLONG div = 1024;
-
- stats.add("Percent Memory use", state.dwMemoryLoad/div);
- stats.add("Total Physical KB", state.ullTotalPhys/div);
- stats.add("Avail Physical KB", state.ullAvailPhys/div);
- stats.add("Total page KB", state.ullTotalPageFile/div);
- stats.add("Avail page KB", state.ullAvailPageFile/div);
- stats.add("Total Virtual KB", state.ullTotalVirtual/div);
- stats.add("Avail Virtual KB", state.ullAvailVirtual/div);
-
- // SL-12122 - Call to GetPerformanceInfo() was removed here. Took
- // on order of 10 ms, causing unacceptable frame time spike every
- // second, and results were never used. If this is needed in the
- // future, must find a way to avoid frame time impact (e.g. move
- // to another thread, call much less often).
-
- PROCESS_MEMORY_COUNTERS_EX pmem;
- pmem.cb = sizeof(pmem);
- // GetProcessMemoryInfo() is documented to accept either
- // PROCESS_MEMORY_COUNTERS* or PROCESS_MEMORY_COUNTERS_EX*, presumably
- // using the redundant size info to distinguish. But its prototype
- // specifically accepts PROCESS_MEMORY_COUNTERS*, and since this is a
- // classic-C API, PROCESS_MEMORY_COUNTERS_EX isn't a subclass. Cast the
- // pointer.
- GetProcessMemoryInfo(GetCurrentProcess(), PPROCESS_MEMORY_COUNTERS(&pmem), sizeof(pmem));
-
- stats.add("Page Fault Count", pmem.PageFaultCount);
- stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize/div);
- stats.add("WorkingSetSize KB", pmem.WorkingSetSize/div);
- stats.add("QutaPeakPagedPoolUsage KB", pmem.QuotaPeakPagedPoolUsage/div);
- stats.add("QuotaPagedPoolUsage KB", pmem.QuotaPagedPoolUsage/div);
- stats.add("QuotaPeakNonPagedPoolUsage KB", pmem.QuotaPeakNonPagedPoolUsage/div);
- stats.add("QuotaNonPagedPoolUsage KB", pmem.QuotaNonPagedPoolUsage/div);
- stats.add("PagefileUsage KB", pmem.PagefileUsage/div);
- stats.add("PeakPagefileUsage KB", pmem.PeakPagefileUsage/div);
- stats.add("PrivateUsage KB", pmem.PrivateUsage/div);
+ MEMORYSTATUSEX state;
+ state.dwLength = sizeof(state);
+ GlobalMemoryStatusEx(&state);
+
+ DWORDLONG div = 1024;
+
+ stats.add("Percent Memory use", state.dwMemoryLoad/div);
+ stats.add("Total Physical KB", state.ullTotalPhys/div);
+ stats.add("Avail Physical KB", state.ullAvailPhys/div);
+ stats.add("Total page KB", state.ullTotalPageFile/div);
+ stats.add("Avail page KB", state.ullAvailPageFile/div);
+ stats.add("Total Virtual KB", state.ullTotalVirtual/div);
+ stats.add("Avail Virtual KB", state.ullAvailVirtual/div);
+
+ // SL-12122 - Call to GetPerformanceInfo() was removed here. Took
+ // on order of 10 ms, causing unacceptable frame time spike every
+ // second, and results were never used. If this is needed in the
+ // future, must find a way to avoid frame time impact (e.g. move
+ // to another thread, call much less often).
+
+ PROCESS_MEMORY_COUNTERS_EX pmem;
+ pmem.cb = sizeof(pmem);
+ // GetProcessMemoryInfo() is documented to accept either
+ // PROCESS_MEMORY_COUNTERS* or PROCESS_MEMORY_COUNTERS_EX*, presumably
+ // using the redundant size info to distinguish. But its prototype
+ // specifically accepts PROCESS_MEMORY_COUNTERS*, and since this is a
+ // classic-C API, PROCESS_MEMORY_COUNTERS_EX isn't a subclass. Cast the
+ // pointer.
+ GetProcessMemoryInfo(GetCurrentProcess(), PPROCESS_MEMORY_COUNTERS(&pmem), sizeof(pmem));
+
+ stats.add("Page Fault Count", pmem.PageFaultCount);
+ stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize/div);
+ stats.add("WorkingSetSize KB", pmem.WorkingSetSize/div);
+ stats.add("QutaPeakPagedPoolUsage KB", pmem.QuotaPeakPagedPoolUsage/div);
+ stats.add("QuotaPagedPoolUsage KB", pmem.QuotaPagedPoolUsage/div);
+ stats.add("QuotaPeakNonPagedPoolUsage KB", pmem.QuotaPeakNonPagedPoolUsage/div);
+ stats.add("QuotaNonPagedPoolUsage KB", pmem.QuotaNonPagedPoolUsage/div);
+ stats.add("PagefileUsage KB", pmem.PagefileUsage/div);
+ stats.add("PeakPagefileUsage KB", pmem.PeakPagefileUsage/div);
+ stats.add("PrivateUsage KB", pmem.PrivateUsage/div);
#elif LL_DARWIN
- const vm_size_t pagekb(vm_page_size / 1024);
-
- //
- // Collect the vm_stat's
- //
-
- {
- vm_statistics64_data_t vmstat;
- mach_msg_type_number_t vmstatCount = HOST_VM_INFO64_COUNT;
-
- if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
- {
- LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
- }
- else
- {
- stats.add("Pages free KB", pagekb * vmstat.free_count);
- stats.add("Pages active KB", pagekb * vmstat.active_count);
- stats.add("Pages inactive KB", pagekb * vmstat.inactive_count);
- stats.add("Pages wired KB", pagekb * vmstat.wire_count);
-
- stats.add("Pages zero fill", vmstat.zero_fill_count);
- stats.add("Page reactivations", vmstat.reactivations);
- stats.add("Page-ins", vmstat.pageins);
- stats.add("Page-outs", vmstat.pageouts);
-
- stats.add("Faults", vmstat.faults);
- stats.add("Faults copy-on-write", vmstat.cow_faults);
-
- stats.add("Cache lookups", vmstat.lookups);
- stats.add("Cache hits", vmstat.hits);
-
- stats.add("Page purgeable count", vmstat.purgeable_count);
- stats.add("Page purges", vmstat.purges);
-
- stats.add("Page speculative reads", vmstat.speculative_count);
- }
- }
-
- //
- // Collect the misc task info
- //
-
- {
- task_events_info_data_t taskinfo;
- unsigned taskinfoSize = sizeof(taskinfo);
-
- if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
- {
- LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
- }
- else
- {
- stats.add("Task page-ins", taskinfo.pageins);
- stats.add("Task copy-on-write faults", taskinfo.cow_faults);
- stats.add("Task messages sent", taskinfo.messages_sent);
- stats.add("Task messages received", taskinfo.messages_received);
- stats.add("Task mach system call count", taskinfo.syscalls_mach);
- stats.add("Task unix system call count", taskinfo.syscalls_unix);
- stats.add("Task context switch count", taskinfo.csw);
- }
- }
-
- //
- // Collect the basic task info
- //
-
- {
- mach_task_basic_info_data_t taskinfo;
- mach_msg_type_number_t task_count = MACH_TASK_BASIC_INFO_COUNT;
- if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t) &taskinfo, &task_count) != KERN_SUCCESS)
- {
- LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
- }
- else
- {
- stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024);
- stats.add("Basic resident memory KB", taskinfo.resident_size / 1024);
- stats.add("Basic max resident memory KB", taskinfo.resident_size_max / 1024);
- stats.add("Basic new thread policy", taskinfo.policy);
- stats.add("Basic suspend count", taskinfo.suspend_count);
- }
- }
+ const vm_size_t pagekb(vm_page_size / 1024);
+
+ //
+ // Collect the vm_stat's
+ //
+
+ {
+ vm_statistics64_data_t vmstat;
+ mach_msg_type_number_t vmstatCount = HOST_VM_INFO64_COUNT;
+
+ if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
+ {
+ LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
+ }
+ else
+ {
+ stats.add("Pages free KB", pagekb * vmstat.free_count);
+ stats.add("Pages active KB", pagekb * vmstat.active_count);
+ stats.add("Pages inactive KB", pagekb * vmstat.inactive_count);
+ stats.add("Pages wired KB", pagekb * vmstat.wire_count);
+
+ stats.add("Pages zero fill", vmstat.zero_fill_count);
+ stats.add("Page reactivations", vmstat.reactivations);
+ stats.add("Page-ins", vmstat.pageins);
+ stats.add("Page-outs", vmstat.pageouts);
+
+ stats.add("Faults", vmstat.faults);
+ stats.add("Faults copy-on-write", vmstat.cow_faults);
+
+ stats.add("Cache lookups", vmstat.lookups);
+ stats.add("Cache hits", vmstat.hits);
+
+ stats.add("Page purgeable count", vmstat.purgeable_count);
+ stats.add("Page purges", vmstat.purges);
+
+ stats.add("Page speculative reads", vmstat.speculative_count);
+ }
+ }
+
+ //
+ // Collect the misc task info
+ //
+
+ {
+ task_events_info_data_t taskinfo;
+ unsigned taskinfoSize = sizeof(taskinfo);
+
+ if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
+ {
+ LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
+ }
+ else
+ {
+ stats.add("Task page-ins", taskinfo.pageins);
+ stats.add("Task copy-on-write faults", taskinfo.cow_faults);
+ stats.add("Task messages sent", taskinfo.messages_sent);
+ stats.add("Task messages received", taskinfo.messages_received);
+ stats.add("Task mach system call count", taskinfo.syscalls_mach);
+ stats.add("Task unix system call count", taskinfo.syscalls_unix);
+ stats.add("Task context switch count", taskinfo.csw);
+ }
+ }
+
+ //
+ // Collect the basic task info
+ //
+
+ {
+ mach_task_basic_info_data_t taskinfo;
+ mach_msg_type_number_t task_count = MACH_TASK_BASIC_INFO_COUNT;
+ if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t) &taskinfo, &task_count) != KERN_SUCCESS)
+ {
+ LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
+ }
+ else
+ {
+ stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024);
+ stats.add("Basic resident memory KB", taskinfo.resident_size / 1024);
+ stats.add("Basic max resident memory KB", taskinfo.resident_size_max / 1024);
+ stats.add("Basic new thread policy", taskinfo.policy);
+ stats.add("Basic suspend count", taskinfo.suspend_count);
+ }
+ }
#elif LL_LINUX
- std::ifstream meminfo(MEMINFO_FILE);
- if (meminfo.is_open())
- {
- // MemTotal: 4108424 kB
- // MemFree: 1244064 kB
- // Buffers: 85164 kB
- // Cached: 1990264 kB
- // SwapCached: 0 kB
- // Active: 1176648 kB
- // Inactive: 1427532 kB
- // ...
- // VmallocTotal: 122880 kB
- // VmallocUsed: 65252 kB
- // VmallocChunk: 52356 kB
- // HardwareCorrupted: 0 kB
- // HugePages_Total: 0
- // HugePages_Free: 0
- // HugePages_Rsvd: 0
- // HugePages_Surp: 0
- // Hugepagesize: 2048 kB
- // DirectMap4k: 434168 kB
- // DirectMap2M: 477184 kB
-
- // Intentionally don't pass the boost::no_except flag. This
- // boost::regex object is constructed with a string literal, so it
- // should be valid every time. If it becomes invalid, we WANT an
- // exception, hopefully even before the dev checks in.
- boost::regex stat_rx("(.+): +([0-9]+)( kB)?");
- boost::smatch matched;
-
- std::string line;
- while (std::getline(meminfo, line))
- {
- LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL;
- if (ll_regex_match(line, matched, stat_rx))
- {
- // e.g. "MemTotal: 4108424 kB"
- LLSD::String key(matched[1].first, matched[1].second);
- LLSD::String value_str(matched[2].first, matched[2].second);
- LLSD::Integer value(0);
- try
- {
- value = boost::lexical_cast<LLSD::Integer>(value_str);
- }
- catch (const boost::bad_lexical_cast&)
- {
- LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str
- << "' in " << MEMINFO_FILE << " line: "
- << line << LL_ENDL;
- continue;
- }
- // Store this statistic.
- stats.add(key, value);
- }
- else
- {
- LL_WARNS("LLMemoryInfo") << "unrecognized " << MEMINFO_FILE << " line: "
- << line << LL_ENDL;
- }
- }
- }
- else
- {
- LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
- }
+ std::ifstream meminfo(MEMINFO_FILE);
+ if (meminfo.is_open())
+ {
+ // MemTotal: 4108424 kB
+ // MemFree: 1244064 kB
+ // Buffers: 85164 kB
+ // Cached: 1990264 kB
+ // SwapCached: 0 kB
+ // Active: 1176648 kB
+ // Inactive: 1427532 kB
+ // ...
+ // VmallocTotal: 122880 kB
+ // VmallocUsed: 65252 kB
+ // VmallocChunk: 52356 kB
+ // HardwareCorrupted: 0 kB
+ // HugePages_Total: 0
+ // HugePages_Free: 0
+ // HugePages_Rsvd: 0
+ // HugePages_Surp: 0
+ // Hugepagesize: 2048 kB
+ // DirectMap4k: 434168 kB
+ // DirectMap2M: 477184 kB
+
+ // Intentionally don't pass the boost::no_except flag. This
+ // boost::regex object is constructed with a string literal, so it
+ // should be valid every time. If it becomes invalid, we WANT an
+ // exception, hopefully even before the dev checks in.
+ boost::regex stat_rx("(.+): +([0-9]+)( kB)?");
+ boost::smatch matched;
+
+ std::string line;
+ while (std::getline(meminfo, line))
+ {
+ LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL;
+ if (ll_regex_match(line, matched, stat_rx))
+ {
+ // e.g. "MemTotal: 4108424 kB"
+ LLSD::String key(matched[1].first, matched[1].second);
+ LLSD::String value_str(matched[2].first, matched[2].second);
+ LLSD::Integer value(0);
+ try
+ {
+ value = boost::lexical_cast<LLSD::Integer>(value_str);
+ }
+ catch (const boost::bad_lexical_cast&)
+ {
+ LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str
+ << "' in " << MEMINFO_FILE << " line: "
+ << line << LL_ENDL;
+ continue;
+ }
+ // Store this statistic.
+ stats.add(key, value);
+ }
+ else
+ {
+ LL_WARNS("LLMemoryInfo") << "unrecognized " << MEMINFO_FILE << " line: "
+ << line << LL_ENDL;
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
+ }
#else
- LL_WARNS("LLMemoryInfo") << "Unknown system; unable to collect memory information" << LL_ENDL;
+ LL_WARNS("LLMemoryInfo") << "Unknown system; unable to collect memory information" << LL_ENDL;
#endif
- return stats.get();
+ return stats.get();
}
std::ostream& operator<<(std::ostream& s, const LLOSInfo& info)
{
- info.stream(s);
- return s;
+ info.stream(s);
+ return s;
}
std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info)
{
- info.stream(s);
- return s;
+ info.stream(s);
+ return s;
}
std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info)
{
- info.stream(s);
- return s;
+ info.stream(s);
+ return s;
}
class FrameWatcher
@@ -1275,13 +1275,13 @@ public:
<< " seconds ";
}
- auto precision = LL_CONT.precision();
+ auto precision = LL_CONT.precision();
LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
<< LLMemoryInfo();
- LL_CONT.precision(precision);
- LL_CONT << LL_ENDL;
+ LL_CONT.precision(precision);
+ LL_CONT << LL_ENDL;
return false;
}
@@ -1310,53 +1310,57 @@ static FrameWatcher sFrameWatcher;
BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
{
- std::string tmpfile;
- const S32 UNCOMPRESS_BUFFER_SIZE = 32768;
- BOOL retval = FALSE;
- gzFile src = NULL;
- U8 buffer[UNCOMPRESS_BUFFER_SIZE];
- LLFILE *dst = NULL;
- S32 bytes = 0;
- tmpfile = dstfile + ".t";
+ std::string tmpfile;
+ const S32 UNCOMPRESS_BUFFER_SIZE = 32768;
+ BOOL retval = FALSE;
+ gzFile src = NULL;
+ U8 buffer[UNCOMPRESS_BUFFER_SIZE];
+ LLFILE *dst = NULL;
+ S32 bytes = 0;
+ tmpfile = dstfile + ".t";
#ifdef LL_WINDOWS
llutf16string utf16filename = utf8str_to_utf16str(srcfile);
src = gzopen_w(utf16filename.c_str(), "rb");
#else
src = gzopen(srcfile.c_str(), "rb");
#endif
- if (! src) goto err;
- dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
- if (! dst) goto err;
- do
- {
- bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE);
- size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
- if (nwrit < (size_t) bytes)
- {
- LL_WARNS() << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << LL_ENDL;
- goto err;
- }
- } while(gzeof(src) == 0);
- fclose(dst);
- dst = NULL;
- if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
- retval = TRUE;
+ if (! src) goto err;
+ dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
+ if (! dst) goto err;
+ do
+ {
+ bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE);
+ size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
+ if (nwrit < (size_t) bytes)
+ {
+ LL_WARNS() << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << LL_ENDL;
+ goto err;
+ }
+ } while(gzeof(src) == 0);
+ fclose(dst);
+ dst = NULL;
+#if LL_WINDOWS
+ // Rename in windows needs the dstfile to not exist.
+ LLFile::remove(dstfile, ENOENT);
+#endif
+ if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
+ retval = TRUE;
err:
- if (src != NULL) gzclose(src);
- if (dst != NULL) fclose(dst);
- return retval;
+ if (src != NULL) gzclose(src);
+ if (dst != NULL) fclose(dst);
+ return retval;
}
BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
{
- const S32 COMPRESS_BUFFER_SIZE = 32768;
- std::string tmpfile;
- BOOL retval = FALSE;
- U8 buffer[COMPRESS_BUFFER_SIZE];
- gzFile dst = NULL;
- LLFILE *src = NULL;
- S32 bytes = 0;
- tmpfile = dstfile + ".t";
+ const S32 COMPRESS_BUFFER_SIZE = 32768;
+ std::string tmpfile;
+ BOOL retval = FALSE;
+ U8 buffer[COMPRESS_BUFFER_SIZE];
+ gzFile dst = NULL;
+ LLFILE *src = NULL;
+ S32 bytes = 0;
+ tmpfile = dstfile + ".t";
#ifdef LL_WINDOWS
llutf16string utf16filename = utf8str_to_utf16str(tmpfile);
@@ -1365,35 +1369,35 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
dst = gzopen(tmpfile.c_str(), "wb");
#endif
- if (! dst) goto err;
- src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
- if (! src) goto err;
-
- while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0)
- {
- if (gzwrite(dst, buffer, bytes) <= 0)
- {
- LL_WARNS() << "gzwrite failed: " << gzerror(dst, NULL) << LL_ENDL;
- goto err;
- }
- }
-
- if (ferror(src))
- {
- LL_WARNS() << "Error reading " << srcfile << LL_ENDL;
- goto err;
- }
-
- gzclose(dst);
- dst = NULL;
+ if (! dst) goto err;
+ src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
+ if (! src) goto err;
+
+ while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0)
+ {
+ if (gzwrite(dst, buffer, bytes) <= 0)
+ {
+ LL_WARNS() << "gzwrite failed: " << gzerror(dst, NULL) << LL_ENDL;
+ goto err;
+ }
+ }
+
+ if (ferror(src))
+ {
+ LL_WARNS() << "Error reading " << srcfile << LL_ENDL;
+ goto err;
+ }
+
+ gzclose(dst);
+ dst = NULL;
#if LL_WINDOWS
- // Rename in windows needs the dstfile to not exist.
- LLFile::remove(dstfile);
+ // Rename in windows needs the dstfile to not exist.
+ LLFile::remove(dstfile);
#endif
- if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
- retval = TRUE;
+ if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
+ retval = TRUE;
err:
- if (src != NULL) fclose(src);
- if (dst != NULL) gzclose(dst);
- return retval;
+ if (src != NULL) fclose(src);
+ if (dst != NULL) gzclose(dst);
+ return retval;
}
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 08d4abffa2..5c87ce6bf2 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsys.h
* @brief System information debugging classes.
*
* $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$
*/
@@ -43,120 +43,120 @@
class LL_COMMON_API LLOSInfo : public LLSingleton<LLOSInfo>
{
- LLSINGLETON(LLOSInfo);
+ LLSINGLETON(LLOSInfo);
public:
- void stream(std::ostream& s) const;
+ void stream(std::ostream& s) const;
+
+ const std::string& getOSString() const;
+ const std::string& getOSStringSimple() const;
- const std::string& getOSString() const;
- const std::string& getOSStringSimple() const;
+ const std::string& getOSVersionString() const;
- const std::string& getOSVersionString() const;
+ const S32 getOSBitness() const;
- const S32 getOSBitness() const;
-
- S32 mMajorVer;
- S32 mMinorVer;
- S32 mBuild;
+ S32 mMajorVer;
+ S32 mMinorVer;
+ S32 mBuild;
#ifndef LL_WINDOWS
- static long getMaxOpenFiles();
+ static long getMaxOpenFiles();
#endif
- static bool is64Bit();
+ static bool is64Bit();
- static U32 getProcessVirtualSizeKB();
- static U32 getProcessResidentSizeKB();
+ static U32 getProcessVirtualSizeKB();
+ static U32 getProcessResidentSizeKB();
private:
- std::string mOSString;
- std::string mOSStringSimple;
- std::string mOSVersionString;
- S32 mOSBitness;
+ std::string mOSString;
+ std::string mOSStringSimple;
+ std::string mOSVersionString;
+ S32 mOSBitness;
};
class LL_COMMON_API LLCPUInfo
{
public:
- LLCPUInfo();
- void stream(std::ostream& s) const;
+ LLCPUInfo();
+ void stream(std::ostream& s) const;
- std::string getCPUString() const;
- const LLSD& getSSEVersions() const;
+ std::string getCPUString() const;
+ const LLSD& getSSEVersions() const;
- bool hasAltivec() const;
- bool hasSSE() const;
- bool hasSSE2() const;
+ bool hasAltivec() const;
+ bool hasSSE() const;
+ bool hasSSE2() const;
bool hasSSE3() const;
bool hasSSE3S() const;
bool hasSSE41() const;
bool hasSSE42() const;
bool hasSSE4a() const;
- F64 getMHz() const;
+ F64 getMHz() const;
- // Family is "AMD Duron" or "Intel Pentium Pro"
- const std::string& getFamily() const { return mFamily; }
+ // Family is "AMD Duron" or "Intel Pentium Pro"
+ const std::string& getFamily() const { return mFamily; }
private:
- bool mHasSSE;
- bool mHasSSE2;
+ bool mHasSSE;
+ bool mHasSSE2;
bool mHasSSE3;
bool mHasSSE3S;
bool mHasSSE41;
bool mHasSSE42;
bool mHasSSE4a;
- bool mHasAltivec;
- F64 mCPUMHz;
- std::string mFamily;
- std::string mCPUString;
+ bool mHasAltivec;
+ F64 mCPUMHz;
+ std::string mFamily;
+ std::string mCPUString;
LLSD mSSEVersions;
};
//=============================================================================
//
-// CLASS LLMemoryInfo
+// CLASS LLMemoryInfo
class LL_COMMON_API LLMemoryInfo
-/*! @brief Class to query the memory subsystem
+/*! @brief Class to query the memory subsystem
+
+ @details
+ Here's how you use an LLMemoryInfo:
- @details
- Here's how you use an LLMemoryInfo:
-
- LLMemoryInfo info;
-<br> LL_INFOS() << info << LL_ENDL;
+ LLMemoryInfo info;
+<br> LL_INFOS() << info << LL_ENDL;
*/
{
public:
- LLMemoryInfo(); ///< Default constructor
- void stream(std::ostream& s) const; ///< output text info to s
+ LLMemoryInfo(); ///< Default constructor
+ void stream(std::ostream& s) const; ///< output text info to s
- U32Kilobytes getPhysicalMemoryKB() const;
+ U32Kilobytes getPhysicalMemoryKB() const;
#if LL_DARWIN
static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib.
#endif
- //get the available memory infomation in KiloBytes.
- static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
+ //get the available memory infomation in KiloBytes.
+ static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
- // Retrieve a map of memory statistics. The keys of the map are platform-
- // dependent. The values are in kilobytes to try to avoid integer overflow.
- LLSD getStatsMap() const;
+ // Retrieve a map of memory statistics. The keys of the map are platform-
+ // dependent. The values are in kilobytes to try to avoid integer overflow.
+ LLSD getStatsMap() const;
- // Re-fetch memory data (as reported by stream() and getStatsMap()) from the
- // system. Normally this is fetched at construction time. Return (*this)
- // to permit usage of the form:
- // @code
- // LLMemoryInfo info;
- // ...
- // info.refresh().getStatsMap();
- // @endcode
- LLMemoryInfo& refresh();
+ // Re-fetch memory data (as reported by stream() and getStatsMap()) from the
+ // system. Normally this is fetched at construction time. Return (*this)
+ // to permit usage of the form:
+ // @code
+ // LLMemoryInfo info;
+ // ...
+ // info.refresh().getStatsMap();
+ // @endcode
+ LLMemoryInfo& refresh();
private:
- // set mStatsMap
- static LLSD loadStatsMap();
+ // set mStatsMap
+ static LLSD loadStatsMap();
- // Memory stats for getStatsMap().
- LLSD mStatsMap;
+ // Memory stats for getStatsMap().
+ LLSD mStatsMap;
};
diff --git a/indra/llcommon/lltempredirect.cpp b/indra/llcommon/lltempredirect.cpp
index ec194c1d29..ee7923e8ca 100644
--- a/indra/llcommon/lltempredirect.cpp
+++ b/indra/llcommon/lltempredirect.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2019-10-31
* @brief Implementation for lltempredirect.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/lltempredirect.h b/indra/llcommon/lltempredirect.h
index 33e05dc06b..0ab3575d30 100644
--- a/indra/llcommon/lltempredirect.h
+++ b/indra/llcommon/lltempredirect.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2019-10-31
* @brief RAII low-level file-descriptor redirection
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index cd4975d9d3..e6b0c03371 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llthread.cpp
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010-2013, 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$
*/
@@ -91,7 +91,7 @@ void set_thread_name( DWORD dwThreadID, const char* threadName)
// break;
// }
// }
-//
+//
//----------------------------------------------------------------------------
namespace
{
@@ -155,7 +155,7 @@ void LLThread::threadRun()
mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
// Run the user supplied function
- do
+ do
{
try
{
@@ -258,7 +258,7 @@ void LLThread::shutdown()
// This thread just wouldn't stop, even though we gave it time
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
// Put a stake in its heart. (A very hostile method to force a thread to quit)
-#if LL_WINDOWS
+#if LL_WINDOWS
TerminateThread(mNativeHandle, 0);
#else
pthread_cancel(mNativeHandle);
@@ -291,7 +291,7 @@ void LLThread::shutdown()
void LLThread::start()
{
llassert(isStopped());
-
+
// Set thread state to running
mStatus = RUNNING;
@@ -319,7 +319,7 @@ void LLThread::pause()
{
// this will cause the thread to stop execution as soon as checkPause() is called
mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
- }
+ }
}
void LLThread::unpause()
@@ -355,7 +355,7 @@ void LLThread::checkPause()
mDataLock->lock();
// mRunCondition is locked when the thread wakes up
}
-
+
mDataLock->unlock();
}
@@ -441,7 +441,7 @@ void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
delete sMutex;
sMutex = NULL;
}
-
+
//----------------------------------------------------------------------------
@@ -456,10 +456,10 @@ LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
}
LLThreadSafeRefCount::~LLThreadSafeRefCount()
-{
+{
if (mRef != 0)
{
- LL_ERRS() << "deleting referenced object mRef = " << mRef << LL_ENDL;
+ LL_ERRS() << "deleting referenced object mRef = " << mRef << LL_ENDL;
}
}
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 9f1c589fcd..e21e6265ea 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llthread.h
* @brief Base classes for thread, mutex and condition handling.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010-2013, 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$
*/
@@ -55,21 +55,21 @@ public:
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
virtual void shutdown(); // stops the thread
-
+
bool isQuitting() const { return (QUITTING == mStatus); }
bool isStopped() const { return (STOPPED == mStatus) || (CRASHED == mStatus); }
- bool isCrashed() const { return (CRASHED == mStatus); }
-
+ bool isCrashed() const { return (CRASHED == mStatus); }
+
static id_t currentID(); // Return ID of current thread
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
-
+
public:
// PAUSE / RESUME functionality. See source code for important usage notes.
// Called from MAIN THREAD.
void pause();
void unpause();
bool isPaused() { return isStopped() || mPaused == TRUE; }
-
+
// Cause the thread to wake up and check its condition
void wake();
@@ -90,11 +90,11 @@ public:
// internal state used by LLMutex. You must call this once early
// in the running thread to prevent collisions with the main thread.
static void registerThreadID();
-
+
private:
bool mPaused;
std::thread::native_handle_type mNativeHandle; // for termination in case of issues
-
+
// static function passed to APR thread creation routine
void threadRun();
@@ -111,21 +111,21 @@ protected:
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
// otherwise it will cause severe memory leaking!!! --bao
- LLVolatileAPRPool *mLocalAPRFilePoolp ;
+ LLVolatileAPRPool *mLocalAPRFilePoolp ;
void setQuitting();
-
+
// virtual function overridden by subclass -- this will be called when the thread runs
- virtual void run(void) = 0;
-
+ virtual void run(void) = 0;
+
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
virtual bool runCondition(void);
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
void lockData();
void unlockData();
-
- // This is the predicate that decides whether the thread should sleep.
+
+ // This is the predicate that decides whether the thread should sleep.
// It should only be called with mDataLock locked, since the virtual runCondition() function may need to access
// data structures that are thread-unsafe.
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index bdd28ec865..151d8a666b 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llthreadlocalstorage.h
* @author Richard
* @brief Class wrappers for thread local storage
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2004&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$
*/
@@ -34,18 +34,18 @@ template<typename DERIVED_TYPE>
class LLThreadLocalSingletonPointer
{
public:
- LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
- {
- return sInstance;
- }
+ LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
+ {
+ return sInstance;
+ }
- static void setInstance(DERIVED_TYPE* instance)
- {
- sInstance = instance;
- }
+ static void setInstance(DERIVED_TYPE* instance)
+ {
+ sInstance = instance;
+ }
private:
- static thread_local DERIVED_TYPE* sInstance;
+ static thread_local DERIVED_TYPE* sInstance;
};
template<typename DERIVED_TYPE>
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
index bde36999ba..03baca2f0a 100644
--- a/indra/llcommon/llthreadsafequeue.cpp
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llthread.cpp
*
* $LicenseInfo:firstyear=2004&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$
*/
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index f396a71e6f..034e3f7897 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llthreadsafequeue.h
* @brief Queue protected with mutexes for cross-thread use
*
* $LicenseInfo:firstyear=2004&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,14 +44,14 @@
// A general queue exception.
//
class LL_COMMON_API LLThreadSafeQueueError:
- public LLException
+ public LLException
{
public:
- LLThreadSafeQueueError(std::string const & message):
- LLException(message)
- {
- ; // No op.
- }
+ LLThreadSafeQueueError(std::string const & message):
+ LLException(message)
+ {
+ ; // No op.
+ }
};
@@ -59,14 +59,14 @@ public:
// An exception raised when blocking operations are interrupted.
//
class LL_COMMON_API LLThreadSafeQueueInterrupt:
- public LLThreadSafeQueueError
+ public LLThreadSafeQueueError
{
public:
- LLThreadSafeQueueInterrupt(void):
- LLThreadSafeQueueError("queue operation interrupted")
- {
- ; // No op.
- }
+ LLThreadSafeQueueInterrupt(void):
+ LLThreadSafeQueueError("queue operation interrupted")
+ {
+ ; // No op.
+ }
};
/**
@@ -78,138 +78,138 @@ template<typename ElementT, typename QueueT=std::queue<ElementT>>
class LLThreadSafeQueue
{
public:
- typedef ElementT value_type;
-
- // Limiting the number of pending items prevents unbounded growth of the
- // underlying queue.
- LLThreadSafeQueue(size_t capacity = 1024);
- virtual ~LLThreadSafeQueue() {}
-
- // Add an element to the queue (will block if the queue has reached
- // capacity).
- //
- // This call will raise an interrupt error if the queue is closed while
- // the caller is blocked.
- template <typename T>
- void push(T&& element);
- // legacy name
- void pushFront(ElementT const & element) { return push(element); }
-
- // Add an element to the queue (will block if the queue has reached
- // capacity). Return false if the queue is closed before push is possible.
- template <typename T>
- bool pushIfOpen(T&& element);
-
- // Try to add an element to the queue without blocking. Returns
- // true only if the element was actually added.
- template <typename T>
- bool tryPush(T&& element);
- // legacy name
- bool tryPushFront(ElementT const & element) { return tryPush(element); }
-
- // Try to add an element to the queue, blocking if full but with timeout
- // after specified duration. Returns true if the element was added.
- // There are potentially two different timeouts involved: how long to try
- // to lock the mutex, versus how long to wait for the queue to stop being
- // full. Careful settings for each timeout might be orders of magnitude
- // apart. However, this method conflates them.
- template <typename Rep, typename Period, typename T>
- bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout,
- T&& element);
- // legacy name
- template <typename Rep, typename Period>
- bool tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout,
- ElementT const & element) { return tryPushFor(timeout, element); }
-
- // Try to add an element to the queue, blocking if full but with
- // timeout at specified time_point. Returns true if the element was added.
- template <typename Clock, typename Duration, typename T>
- bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until,
- T&& element);
- // no legacy name because this is a newer method
-
- // Pop the element at the head of the queue (will block if the queue is
- // empty).
- //
- // This call will raise an interrupt error if the queue is closed while
- // the caller is blocked.
- ElementT pop(void);
- // legacy name
- ElementT popBack(void) { return pop(); }
-
- // Pop an element from the head of the queue if there is one available.
- // Returns true only if an element was popped.
- bool tryPop(ElementT & element);
- // legacy name
- bool tryPopBack(ElementT & element) { return tryPop(element); }
-
- // Pop the element at the head of the queue, blocking if empty, with
- // timeout after specified duration. Returns true if an element was popped.
- template <typename Rep, typename Period>
- bool tryPopFor(const std::chrono::duration<Rep, Period>& timeout, ElementT& element);
- // no legacy name because this is a newer method
-
- // Pop the element at the head of the queue, blocking if empty, with
- // timeout at specified time_point. Returns true if an element was popped.
- template <typename Clock, typename Duration>
- bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until,
- ElementT& element);
- // no legacy name because this is a newer method
-
- // Returns the size of the queue.
- size_t size();
+ typedef ElementT value_type;
+
+ // Limiting the number of pending items prevents unbounded growth of the
+ // underlying queue.
+ LLThreadSafeQueue(size_t capacity = 1024);
+ virtual ~LLThreadSafeQueue() {}
+
+ // Add an element to the queue (will block if the queue has reached
+ // capacity).
+ //
+ // This call will raise an interrupt error if the queue is closed while
+ // the caller is blocked.
+ template <typename T>
+ void push(T&& element);
+ // legacy name
+ void pushFront(ElementT const & element) { return push(element); }
+
+ // Add an element to the queue (will block if the queue has reached
+ // capacity). Return false if the queue is closed before push is possible.
+ template <typename T>
+ bool pushIfOpen(T&& element);
+
+ // Try to add an element to the queue without blocking. Returns
+ // true only if the element was actually added.
+ template <typename T>
+ bool tryPush(T&& element);
+ // legacy name
+ bool tryPushFront(ElementT const & element) { return tryPush(element); }
+
+ // Try to add an element to the queue, blocking if full but with timeout
+ // after specified duration. Returns true if the element was added.
+ // There are potentially two different timeouts involved: how long to try
+ // to lock the mutex, versus how long to wait for the queue to stop being
+ // full. Careful settings for each timeout might be orders of magnitude
+ // apart. However, this method conflates them.
+ template <typename Rep, typename Period, typename T>
+ bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout,
+ T&& element);
+ // legacy name
+ template <typename Rep, typename Period>
+ bool tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout,
+ ElementT const & element) { return tryPushFor(timeout, element); }
+
+ // Try to add an element to the queue, blocking if full but with
+ // timeout at specified time_point. Returns true if the element was added.
+ template <typename Clock, typename Duration, typename T>
+ bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until,
+ T&& element);
+ // no legacy name because this is a newer method
+
+ // Pop the element at the head of the queue (will block if the queue is
+ // empty).
+ //
+ // This call will raise an interrupt error if the queue is closed while
+ // the caller is blocked.
+ ElementT pop(void);
+ // legacy name
+ ElementT popBack(void) { return pop(); }
+
+ // Pop an element from the head of the queue if there is one available.
+ // Returns true only if an element was popped.
+ bool tryPop(ElementT & element);
+ // legacy name
+ bool tryPopBack(ElementT & element) { return tryPop(element); }
+
+ // Pop the element at the head of the queue, blocking if empty, with
+ // timeout after specified duration. Returns true if an element was popped.
+ template <typename Rep, typename Period>
+ bool tryPopFor(const std::chrono::duration<Rep, Period>& timeout, ElementT& element);
+ // no legacy name because this is a newer method
+
+ // Pop the element at the head of the queue, blocking if empty, with
+ // timeout at specified time_point. Returns true if an element was popped.
+ template <typename Clock, typename Duration>
+ bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until,
+ ElementT& element);
+ // no legacy name because this is a newer method
+
+ // Returns the size of the queue.
+ size_t size();
//Returns the capacity of the queue.
U32 capacity() { return mCapacity; }
- // closes the queue:
- // - every subsequent push() call will throw LLThreadSafeQueueInterrupt
- // - every subsequent tryPush() call will return false
- // - pop() calls will return normally until the queue is drained, then
- // every subsequent pop() will throw LLThreadSafeQueueInterrupt
- // - tryPop() calls will return normally until the queue is drained,
- // then every subsequent tryPop() call will return false
- void close();
+ // closes the queue:
+ // - every subsequent push() call will throw LLThreadSafeQueueInterrupt
+ // - every subsequent tryPush() call will return false
+ // - pop() calls will return normally until the queue is drained, then
+ // every subsequent pop() will throw LLThreadSafeQueueInterrupt
+ // - tryPop() calls will return normally until the queue is drained,
+ // then every subsequent tryPop() call will return false
+ void close();
- // producer end: are we prevented from pushing any additional items?
- bool isClosed();
- // consumer end: are we done, is the queue entirely drained?
- bool done();
+ // producer end: are we prevented from pushing any additional items?
+ bool isClosed();
+ // consumer end: are we done, is the queue entirely drained?
+ bool done();
protected:
- typedef QueueT queue_type;
- QueueT mStorage;
- size_t mCapacity;
- bool mClosed;
-
- boost::fibers::timed_mutex mLock;
- typedef std::unique_lock<decltype(mLock)> lock_t;
- boost::fibers::condition_variable_any mCapacityCond;
- boost::fibers::condition_variable_any mEmptyCond;
-
- enum pop_result { EMPTY, DONE, WAITING, POPPED };
- // implementation logic, suitable for passing to tryLockUntil()
- template <typename Clock, typename Duration>
- pop_result tryPopUntil_(lock_t& lock,
- const std::chrono::time_point<Clock, Duration>& until,
- ElementT& element);
- // if we're able to lock immediately, do so and run the passed callable,
- // which must accept lock_t& and return bool
- template <typename CALLABLE>
- bool tryLock(CALLABLE&& callable);
- // if we're able to lock before the passed time_point, do so and run the
- // passed callable, which must accept lock_t& and return bool
- template <typename Clock, typename Duration, typename CALLABLE>
- bool tryLockUntil(const std::chrono::time_point<Clock, Duration>& until,
- CALLABLE&& callable);
- // while lock is locked, really push the passed element, if we can
- template <typename T>
- bool push_(lock_t& lock, T&& element);
- // while lock is locked, really pop the head element, if we can
- pop_result pop_(lock_t& lock, ElementT& element);
- // Is the current head element ready to pop? We say yes; subclass can
- // override as needed.
- virtual bool canPop(const ElementT& head) const { return true; }
+ typedef QueueT queue_type;
+ QueueT mStorage;
+ size_t mCapacity;
+ bool mClosed;
+
+ boost::fibers::timed_mutex mLock;
+ typedef std::unique_lock<decltype(mLock)> lock_t;
+ boost::fibers::condition_variable_any mCapacityCond;
+ boost::fibers::condition_variable_any mEmptyCond;
+
+ enum pop_result { EMPTY, DONE, WAITING, POPPED };
+ // implementation logic, suitable for passing to tryLockUntil()
+ template <typename Clock, typename Duration>
+ pop_result tryPopUntil_(lock_t& lock,
+ const std::chrono::time_point<Clock, Duration>& until,
+ ElementT& element);
+ // if we're able to lock immediately, do so and run the passed callable,
+ // which must accept lock_t& and return bool
+ template <typename CALLABLE>
+ bool tryLock(CALLABLE&& callable);
+ // if we're able to lock before the passed time_point, do so and run the
+ // passed callable, which must accept lock_t& and return bool
+ template <typename Clock, typename Duration, typename CALLABLE>
+ bool tryLockUntil(const std::chrono::time_point<Clock, Duration>& until,
+ CALLABLE&& callable);
+ // while lock is locked, really push the passed element, if we can
+ template <typename T>
+ bool push_(lock_t& lock, T&& element);
+ // while lock is locked, really pop the head element, if we can
+ pop_result pop_(lock_t& lock, ElementT& element);
+ // Is the current head element ready to pop? We say yes; subclass can
+ // override as needed.
+ virtual bool canPop(const ElementT& head) const { return true; }
};
/*****************************************************************************
@@ -426,7 +426,7 @@ LLThreadSafeQueue<ElementT, QueueT>::pop_(lock_t& lock, ElementT& element)
if (mStorage.empty())
return mClosed? DONE : EMPTY;
- // If there's a head element, pass it to canPop() to see if it's ready to pop.
+ // If there's a head element, pass it to canPop() to see if it's ready to pop.
if (! canPop(mStorage.front()))
return WAITING;
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 1a99ac2886..6f74bf3fc8 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltimer.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$
*/
@@ -34,12 +34,12 @@
#include <thread>
#if LL_WINDOWS
-# include "llwin32headerslean.h"
+# include "llwin32headerslean.h"
#elif LL_LINUX || LL_DARWIN
# include <errno.h>
-# include <sys/time.h>
-#else
-# error "architecture not supported"
+# include <sys/time.h>
+#else
+# error "architecture not supported"
#endif
//
@@ -83,7 +83,7 @@ U32 micro_sleep(U64 us, U32 max_yields)
{
// max_yields is unused; just fiddle with it to avoid warnings.
max_yields = 0;
- ms_sleep((U32)(us / 1000));
+ ms_sleep((U32)(us / 1000));
return 0;
}
@@ -118,43 +118,43 @@ void ms_sleep(U32 ms)
#elif LL_LINUX || LL_DARWIN
static void _sleep_loop(struct timespec& thiswait)
{
- struct timespec nextwait;
- bool sleep_more = false;
-
- do {
- int result = nanosleep(&thiswait, &nextwait);
-
- // check if sleep was interrupted by a signal; unslept
- // remainder was written back into 't' and we just nanosleep
- // again.
- sleep_more = (result == -1 && EINTR == errno);
-
- if (sleep_more)
- {
- if ( nextwait.tv_sec > thiswait.tv_sec ||
- (nextwait.tv_sec == thiswait.tv_sec &&
- nextwait.tv_nsec >= thiswait.tv_nsec) )
- {
- // if the remaining time isn't actually going
- // down then we're being shafted by low clock
- // resolution - manually massage the sleep time
- // downward.
- if (nextwait.tv_nsec > 1000000) {
- // lose 1ms
- nextwait.tv_nsec -= 1000000;
- } else {
- if (nextwait.tv_sec == 0) {
- // already so close to finished
- sleep_more = false;
- } else {
- // lose up to 1ms
- nextwait.tv_nsec = 0;
- }
- }
- }
- thiswait = nextwait;
- }
- } while (sleep_more);
+ struct timespec nextwait;
+ bool sleep_more = false;
+
+ do {
+ int result = nanosleep(&thiswait, &nextwait);
+
+ // check if sleep was interrupted by a signal; unslept
+ // remainder was written back into 't' and we just nanosleep
+ // again.
+ sleep_more = (result == -1 && EINTR == errno);
+
+ if (sleep_more)
+ {
+ if ( nextwait.tv_sec > thiswait.tv_sec ||
+ (nextwait.tv_sec == thiswait.tv_sec &&
+ nextwait.tv_nsec >= thiswait.tv_nsec) )
+ {
+ // if the remaining time isn't actually going
+ // down then we're being shafted by low clock
+ // resolution - manually massage the sleep time
+ // downward.
+ if (nextwait.tv_nsec > 1000000) {
+ // lose 1ms
+ nextwait.tv_nsec -= 1000000;
+ } else {
+ if (nextwait.tv_sec == 0) {
+ // already so close to finished
+ sleep_more = false;
+ } else {
+ // lose up to 1ms
+ nextwait.tv_nsec = 0;
+ }
+ }
+ }
+ thiswait = nextwait;
+ }
+ } while (sleep_more);
}
U32 micro_sleep(U64 us, U32 max_yields)
@@ -193,10 +193,10 @@ U32 micro_sleep(U64 us, U32 max_yields)
void ms_sleep(U32 ms)
{
- long mslong = ms; // tv_nsec is a long
- struct timespec thiswait;
- thiswait.tv_sec = ms / 1000;
- thiswait.tv_nsec = (mslong % 1000) * 1000000l;
+ long mslong = ms; // tv_nsec is a long
+ struct timespec thiswait;
+ thiswait.tv_sec = ms / 1000;
+ thiswait.tv_nsec = (mslong % 1000) * 1000000l;
_sleep_loop(thiswait);
}
#else
@@ -210,25 +210,25 @@ void ms_sleep(U32 ms)
#if LL_WINDOWS
U64 get_clock_count()
{
- static bool firstTime = true;
- static U64 offset;
- // ensures that callers to this function never have to deal with wrap
+ static bool firstTime = true;
+ static U64 offset;
+ // ensures that callers to this function never have to deal with wrap
- // QueryPerformanceCounter implementation
- LARGE_INTEGER clock_count;
- QueryPerformanceCounter(&clock_count);
- if (firstTime) {
- offset = clock_count.QuadPart;
- firstTime = false;
- }
- return clock_count.QuadPart - offset;
+ // QueryPerformanceCounter implementation
+ LARGE_INTEGER clock_count;
+ QueryPerformanceCounter(&clock_count);
+ if (firstTime) {
+ offset = clock_count.QuadPart;
+ firstTime = false;
+ }
+ return clock_count.QuadPart - offset;
}
F64 calc_clock_frequency()
{
- __int64 freq;
- QueryPerformanceFrequency((LARGE_INTEGER *) &freq);
- return (F64)freq;
+ __int64 freq;
+ QueryPerformanceFrequency((LARGE_INTEGER *) &freq);
+ return (F64)freq;
}
#endif // LL_WINDOWS
@@ -237,81 +237,81 @@ F64 calc_clock_frequency()
// Both Linux and Mac use gettimeofday for accurate time
F64 calc_clock_frequency()
{
- return 1000000.0; // microseconds, so 1 MHz.
+ return 1000000.0; // microseconds, so 1 MHz.
}
U64 get_clock_count()
{
- // Linux clocks are in microseconds
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec*SEC_TO_MICROSEC_U64 + tv.tv_usec;
+ // Linux clocks are in microseconds
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec*SEC_TO_MICROSEC_U64 + tv.tv_usec;
}
#endif
TimerInfo::TimerInfo()
-: mClockFrequency(0.0),
- mTotalTimeClockCount(0),
- mLastTotalTimeClockCount(0)
+: mClockFrequency(0.0),
+ mTotalTimeClockCount(0),
+ mLastTotalTimeClockCount(0)
{}
void TimerInfo::update()
{
- mClockFrequency = calc_clock_frequency();
- mClockFrequencyInv = 1.0/mClockFrequency;
- mClocksToMicroseconds = mClockFrequencyInv;
+ mClockFrequency = calc_clock_frequency();
+ mClockFrequencyInv = 1.0/mClockFrequency;
+ mClocksToMicroseconds = mClockFrequencyInv;
}
TimerInfo& get_timer_info()
{
- static TimerInfo sTimerInfo;
- return sTimerInfo;
+ static TimerInfo sTimerInfo;
+ return sTimerInfo;
}
///////////////////////////////////////////////////////////////////////////////
-// returns a U64 number that represents the number of
+// returns a U64 number that represents the number of
// microseconds since the Unix epoch - Jan 1, 1970
U64MicrosecondsImplicit totalTime()
{
- U64 current_clock_count = get_clock_count();
- if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
- {
- get_timer_info().update();
- get_timer_info().mTotalTimeClockCount = current_clock_count;
+ U64 current_clock_count = get_clock_count();
+ if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
+ {
+ get_timer_info().update();
+ get_timer_info().mTotalTimeClockCount = current_clock_count;
#if LL_WINDOWS
- // Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
- // Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
- // make in the future.
+ // Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
+ // Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
+ // make in the future.
- get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
+ get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
#endif
- // Update the last clock count
- get_timer_info().mLastTotalTimeClockCount = current_clock_count;
- }
- else
- {
- if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
- {
- // No wrapping, we're all okay.
- get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
- }
- else
- {
- // We've wrapped. Compensate correctly
- get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
- }
-
- // Update the last clock count
- get_timer_info().mLastTotalTimeClockCount = current_clock_count;
- }
+ // Update the last clock count
+ get_timer_info().mLastTotalTimeClockCount = current_clock_count;
+ }
+ else
+ {
+ if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
+ {
+ // No wrapping, we're all okay.
+ get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
+ }
+ else
+ {
+ // We've wrapped. Compensate correctly
+ get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
+ }
+
+ // Update the last clock count
+ get_timer_info().mLastTotalTimeClockCount = current_clock_count;
+ }
- // Return the total clock tick count in microseconds.
- U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
- return time;
+ // Return the total clock tick count in microseconds.
+ U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
+ return time;
}
@@ -319,13 +319,13 @@ U64MicrosecondsImplicit totalTime()
LLTimer::LLTimer()
{
- if (!get_timer_info().mClockFrequency)
- {
- get_timer_info().update();
- }
+ if (!get_timer_info().mClockFrequency)
+ {
+ get_timer_info().update();
+ }
- mStarted = TRUE;
- reset();
+ mStarted = TRUE;
+ reset();
}
LLTimer::~LLTimer()
@@ -334,47 +334,47 @@ LLTimer::~LLTimer()
// static
void LLTimer::initClass()
{
- if (!sTimer) sTimer = new LLTimer;
+ if (!sTimer) sTimer = new LLTimer;
}
// static
void LLTimer::cleanupClass()
{
- delete sTimer; sTimer = NULL;
+ delete sTimer; sTimer = NULL;
}
// static
U64MicrosecondsImplicit LLTimer::getTotalTime()
{
- // simply call into the implementation function.
- U64MicrosecondsImplicit total_time = totalTime();
- return total_time;
-}
+ // simply call into the implementation function.
+ U64MicrosecondsImplicit total_time = totalTime();
+ return total_time;
+}
// static
F64SecondsImplicit LLTimer::getTotalSeconds()
{
- return F64Microseconds(U64_to_F64(getTotalTime()));
+ return F64Microseconds(U64_to_F64(getTotalTime()));
}
void LLTimer::reset()
{
- mLastClockCount = get_clock_count();
- mExpirationTicks = 0;
+ mLastClockCount = get_clock_count();
+ mExpirationTicks = 0;
}
///////////////////////////////////////////////////////////////////////////////
U64 LLTimer::getCurrentClockCount()
{
- return get_clock_count();
+ return get_clock_count();
}
///////////////////////////////////////////////////////////////////////////////
void LLTimer::setLastClockCount(U64 current_count)
{
- mLastClockCount = current_count;
+ mLastClockCount = current_count;
}
///////////////////////////////////////////////////////////////////////////////
@@ -382,152 +382,152 @@ void LLTimer::setLastClockCount(U64 current_count)
static
U64 getElapsedTimeAndUpdate(U64& lastClockCount)
{
- U64 current_clock_count = get_clock_count();
- U64 result;
+ U64 current_clock_count = get_clock_count();
+ U64 result;
- if (current_clock_count >= lastClockCount)
- {
- result = current_clock_count - lastClockCount;
- }
- else
- {
- // time has gone backward
- result = 0;
- }
+ if (current_clock_count >= lastClockCount)
+ {
+ result = current_clock_count - lastClockCount;
+ }
+ else
+ {
+ // time has gone backward
+ result = 0;
+ }
- lastClockCount = current_clock_count;
+ lastClockCount = current_clock_count;
- return result;
+ return result;
}
F64SecondsImplicit LLTimer::getElapsedTimeF64() const
{
- U64 last = mLastClockCount;
- return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
+ U64 last = mLastClockCount;
+ return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
}
F32SecondsImplicit LLTimer::getElapsedTimeF32() const
{
- return (F32)getElapsedTimeF64();
+ return (F32)getElapsedTimeF64();
}
F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
{
- return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
+ return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
}
F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
{
- return (F32)getElapsedTimeAndResetF64();
+ return (F32)getElapsedTimeAndResetF64();
}
///////////////////////////////////////////////////////////////////////////////
void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
{
- mExpirationTicks = get_clock_count()
- + (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));
+ mExpirationTicks = get_clock_count()
+ + (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));
}
F32SecondsImplicit LLTimer::getRemainingTimeF32() const
{
- U64 cur_ticks = get_clock_count();
- if (cur_ticks > mExpirationTicks)
- {
- return 0.0f;
- }
- return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
+ U64 cur_ticks = get_clock_count();
+ if (cur_ticks > mExpirationTicks)
+ {
+ return 0.0f;
+ }
+ return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
}
BOOL LLTimer::checkExpirationAndReset(F32 expiration)
{
- U64 cur_ticks = get_clock_count();
- if (cur_ticks < mExpirationTicks)
- {
- return FALSE;
- }
+ U64 cur_ticks = get_clock_count();
+ if (cur_ticks < mExpirationTicks)
+ {
+ return FALSE;
+ }
- mExpirationTicks = cur_ticks
- + (U64)((F32)(expiration * get_timer_info().mClockFrequency));
- return TRUE;
+ mExpirationTicks = cur_ticks
+ + (U64)((F32)(expiration * get_timer_info().mClockFrequency));
+ return TRUE;
}
BOOL LLTimer::hasExpired() const
{
- return (get_clock_count() >= mExpirationTicks)
- ? TRUE : FALSE;
+ return (get_clock_count() >= mExpirationTicks)
+ ? TRUE : FALSE;
}
///////////////////////////////////////////////////////////////////////////////
BOOL LLTimer::knownBadTimer()
{
- BOOL failed = FALSE;
+ BOOL failed = FALSE;
#if LL_WINDOWS
- WCHAR bad_pci_list[][10] = {L"1039:0530",
- L"1039:0620",
- L"10B9:0533",
- L"10B9:1533",
- L"1106:0596",
- L"1106:0686",
- L"1166:004F",
- L"1166:0050",
- L"8086:7110",
- L"\0"
- };
-
- HKEY hKey = NULL;
- LONG nResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SYSTEM\\CurrentControlSet\\Enum\\PCI", 0,
- KEY_EXECUTE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey);
-
- WCHAR name[1024];
- DWORD name_len = 1024;
- FILETIME scrap;
-
- S32 key_num = 0;
- WCHAR pci_id[10];
-
- wcscpy(pci_id, L"0000:0000"); /*Flawfinder: ignore*/
-
- while (nResult == ERROR_SUCCESS)
- {
- nResult = ::RegEnumKeyEx(hKey, key_num++, name, &name_len, NULL, NULL, NULL, &scrap);
-
- if (nResult == ERROR_SUCCESS)
- {
- memcpy(&pci_id[0],&name[4],4); /* Flawfinder: ignore */
- memcpy(&pci_id[5],&name[13],4); /* Flawfinder: ignore */
-
- for (S32 check = 0; bad_pci_list[check][0]; check++)
- {
- if (!wcscmp(pci_id, bad_pci_list[check]))
- {
-// LL_WARNS() << "unreliable PCI chipset found!! " << pci_id << endl;
- failed = TRUE;
- break;
- }
- }
-// llinfo << "PCI chipset found: " << pci_id << endl;
- name_len = 1024;
- }
- }
+ WCHAR bad_pci_list[][10] = {L"1039:0530",
+ L"1039:0620",
+ L"10B9:0533",
+ L"10B9:1533",
+ L"1106:0596",
+ L"1106:0686",
+ L"1166:004F",
+ L"1166:0050",
+ L"8086:7110",
+ L"\0"
+ };
+
+ HKEY hKey = NULL;
+ LONG nResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SYSTEM\\CurrentControlSet\\Enum\\PCI", 0,
+ KEY_EXECUTE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey);
+
+ WCHAR name[1024];
+ DWORD name_len = 1024;
+ FILETIME scrap;
+
+ S32 key_num = 0;
+ WCHAR pci_id[10];
+
+ wcscpy(pci_id, L"0000:0000"); /*Flawfinder: ignore*/
+
+ while (nResult == ERROR_SUCCESS)
+ {
+ nResult = ::RegEnumKeyEx(hKey, key_num++, name, &name_len, NULL, NULL, NULL, &scrap);
+
+ if (nResult == ERROR_SUCCESS)
+ {
+ memcpy(&pci_id[0],&name[4],4); /* Flawfinder: ignore */
+ memcpy(&pci_id[5],&name[13],4); /* Flawfinder: ignore */
+
+ for (S32 check = 0; bad_pci_list[check][0]; check++)
+ {
+ if (!wcscmp(pci_id, bad_pci_list[check]))
+ {
+// LL_WARNS() << "unreliable PCI chipset found!! " << pci_id << endl;
+ failed = TRUE;
+ break;
+ }
+ }
+// llinfo << "PCI chipset found: " << pci_id << endl;
+ name_len = 1024;
+ }
+ }
#endif
- return(failed);
+ return(failed);
}
///////////////////////////////////////////////////////////////////////////////
-//
+//
// NON-MEMBER FUNCTIONS
//
///////////////////////////////////////////////////////////////////////////////
time_t time_corrected()
{
- return time(NULL) + gUTCOffset;
+ return time(NULL) + gUTCOffset;
}
@@ -535,75 +535,75 @@ time_t time_corrected()
// observing daylight savings time?
BOOL is_daylight_savings()
{
- time_t now = time(NULL);
+ time_t now = time(NULL);
- // Internal buffer to local server time
- struct tm* internal_time = localtime(&now);
+ // Internal buffer to local server time
+ struct tm* internal_time = localtime(&now);
- // tm_isdst > 0 => daylight savings
- // tm_isdst = 0 => not daylight savings
- // tm_isdst < 0 => can't tell
- return (internal_time->tm_isdst > 0);
+ // tm_isdst > 0 => daylight savings
+ // tm_isdst = 0 => not daylight savings
+ // tm_isdst < 0 => can't tell
+ return (internal_time->tm_isdst > 0);
}
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
{
- S32Hours pacific_offset_hours;
- if (pacific_daylight_time)
- {
- pacific_offset_hours = S32Hours(7);
- }
- else
- {
- pacific_offset_hours = S32Hours(8);
- }
+ S32Hours pacific_offset_hours;
+ if (pacific_daylight_time)
+ {
+ pacific_offset_hours = S32Hours(7);
+ }
+ else
+ {
+ pacific_offset_hours = S32Hours(8);
+ }
+
+ // We subtract off the PST/PDT offset _before_ getting
+ // "UTC" time, because this will handle wrapping around
+ // for 5 AM UTC -> 10 PM PDT of the previous day.
+ utc_time -= S32SecondsImplicit(pacific_offset_hours);
- // We subtract off the PST/PDT offset _before_ getting
- // "UTC" time, because this will handle wrapping around
- // for 5 AM UTC -> 10 PM PDT of the previous day.
- utc_time -= S32SecondsImplicit(pacific_offset_hours);
-
- // Internal buffer to PST/PDT (see above)
- struct tm* internal_time = gmtime(&utc_time);
+ // Internal buffer to PST/PDT (see above)
+ struct tm* internal_time = gmtime(&utc_time);
- /*
- // Don't do this, this won't correctly tell you if daylight savings is active in CA or not.
- if (pacific_daylight_time)
- {
- internal_time->tm_isdst = 1;
- }
- */
+ /*
+ // Don't do this, this won't correctly tell you if daylight savings is active in CA or not.
+ if (pacific_daylight_time)
+ {
+ internal_time->tm_isdst = 1;
+ }
+ */
- return internal_time;
+ return internal_time;
}
void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
{
- U64 hours;
- U64 minutes;
- U64 seconds;
- U64 frames;
- U64 subframes;
+ U64 hours;
+ U64 minutes;
+ U64 seconds;
+ U64 frames;
+ U64 subframes;
- hours = current_time / (U64)3600000000ul;
- minutes = current_time / (U64)60000000;
- minutes %= 60;
- seconds = current_time / (U64)1000000;
- seconds %= 60;
- frames = current_time / (U64)41667;
- frames %= 24;
- subframes = current_time / (U64)42;
- subframes %= 100;
+ hours = current_time / (U64)3600000000ul;
+ minutes = current_time / (U64)60000000;
+ minutes %= 60;
+ seconds = current_time / (U64)1000000;
+ seconds %= 60;
+ frames = current_time / (U64)41667;
+ frames %= 24;
+ subframes = current_time / (U64)42;
+ subframes %= 100;
- tcstring = llformat("%3.3d:%2.2d:%2.2d:%2.2d.%2.2d",(int)hours,(int)minutes,(int)seconds,(int)frames,(int)subframes);
+ tcstring = llformat("%3.3d:%2.2d:%2.2d:%2.2d.%2.2d",(int)hours,(int)minutes,(int)seconds,(int)frames,(int)subframes);
}
void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
{
- microsecondsToTimecodeString(current_time, tcstring);
+ microsecondsToTimecodeString(current_time, tcstring);
}
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 010f290b24..fe4a3afc7a 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -1,30 +1,30 @@
-/**
+/**
* @file lltimer.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$
*/
-#ifndef LL_TIMER_H
+#ifndef LL_TIMER_H
#define LL_TIMER_H
#if LL_LINUX || LL_DARWIN
@@ -39,76 +39,76 @@
// units conversions
#include "llunits.h"
#ifndef USEC_PER_SEC
- const U32 USEC_PER_SEC = 1000000;
+ const U32 USEC_PER_SEC = 1000000;
#endif
-const U32 SEC_PER_MIN = 60;
-const U32 MIN_PER_HOUR = 60;
-const U32 USEC_PER_MIN = USEC_PER_SEC * SEC_PER_MIN;
-const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR;
-const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR;
-const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC;
-
-class LL_COMMON_API LLTimer
+const U32 SEC_PER_MIN = 60;
+const U32 MIN_PER_HOUR = 60;
+const U32 USEC_PER_MIN = USEC_PER_SEC * SEC_PER_MIN;
+const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR;
+const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR;
+const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC;
+
+class LL_COMMON_API LLTimer
{
public:
- static LLTimer *sTimer; // global timer
-
-protected:
- U64 mLastClockCount;
- U64 mExpirationTicks;
- bool mStarted;
+ static LLTimer *sTimer; // global timer
+
+protected:
+ U64 mLastClockCount;
+ U64 mExpirationTicks;
+ bool mStarted;
public:
- LLTimer();
- ~LLTimer();
+ LLTimer();
+ ~LLTimer();
- static void initClass();
- static void cleanupClass();
+ static void initClass();
+ static void cleanupClass();
- // Return a high precision number of seconds since the start of
- // this application instance.
- static F64SecondsImplicit getElapsedSeconds()
- {
- if (sTimer)
- {
- return sTimer->getElapsedTimeF64();
- }
- else
- {
- return 0;
- }
- }
+ // Return a high precision number of seconds since the start of
+ // this application instance.
+ static F64SecondsImplicit getElapsedSeconds()
+ {
+ if (sTimer)
+ {
+ return sTimer->getElapsedTimeF64();
+ }
+ else
+ {
+ return 0;
+ }
+ }
- // Return a high precision usec since epoch
- static U64MicrosecondsImplicit getTotalTime();
+ // Return a high precision usec since epoch
+ static U64MicrosecondsImplicit getTotalTime();
- // Return a high precision seconds since epoch
- static F64SecondsImplicit getTotalSeconds();
+ // Return a high precision seconds since epoch
+ static F64SecondsImplicit getTotalSeconds();
- // MANIPULATORS
- void start() { reset(); mStarted = TRUE; }
- void stop() { mStarted = FALSE; }
- void reset(); // Resets the timer
- void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time
- void setTimerExpirySec(F32SecondsImplicit expiration);
- BOOL checkExpirationAndReset(F32 expiration);
- BOOL hasExpired() const;
- F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
- F64SecondsImplicit getElapsedTimeAndResetF64();
+ // MANIPULATORS
+ void start() { reset(); mStarted = TRUE; }
+ void stop() { mStarted = FALSE; }
+ void reset(); // Resets the timer
+ void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time
+ void setTimerExpirySec(F32SecondsImplicit expiration);
+ BOOL checkExpirationAndReset(F32 expiration);
+ BOOL hasExpired() const;
+ F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
+ F64SecondsImplicit getElapsedTimeAndResetF64();
- F32SecondsImplicit getRemainingTimeF32() const;
+ F32SecondsImplicit getRemainingTimeF32() const;
- static BOOL knownBadTimer();
+ static BOOL knownBadTimer();
- // ACCESSORS
- F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
- F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
+ // ACCESSORS
+ F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
+ F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
- bool getStarted() const { return mStarted; }
+ bool getStarted() const { return mStarted; }
- static U64 getCurrentClockCount(); // Returns the raw clockticks
+ static U64 getCurrentClockCount(); // Returns the raw clockticks
};
//
@@ -116,14 +116,14 @@ public:
//
struct TimerInfo
{
- TimerInfo();
- void update();
-
- F64HertzImplicit mClockFrequency;
- F64SecondsImplicit mClockFrequencyInv;
- F64MicrosecondsImplicit mClocksToMicroseconds;
- U64 mTotalTimeClockCount;
- U64 mLastTotalTimeClockCount;
+ TimerInfo();
+ void update();
+
+ F64HertzImplicit mClockFrequency;
+ F64SecondsImplicit mClockFrequencyInv;
+ F64MicrosecondsImplicit mClocksToMicroseconds;
+ U64 mTotalTimeClockCount;
+ U64 mLastTotalTimeClockCount;
};
TimerInfo& get_timer_info();
@@ -140,30 +140,30 @@ LL_COMMON_API time_t time_corrected();
static inline time_t time_min()
{
- if (sizeof(time_t) == 4)
- {
- return (time_t) INT_MIN;
- } else {
+ if (sizeof(time_t) == 4)
+ {
+ return (time_t) INT_MIN;
+ } else {
#ifdef LLONG_MIN
- return (time_t) LLONG_MIN;
+ return (time_t) LLONG_MIN;
#else
- return (time_t) LONG_MIN;
+ return (time_t) LONG_MIN;
#endif
- }
+ }
}
static inline time_t time_max()
{
- if (sizeof(time_t) == 4)
- {
- return (time_t) INT_MAX;
- } else {
+ if (sizeof(time_t) == 4)
+ {
+ return (time_t) INT_MAX;
+ } else {
#ifdef LLONG_MAX
- return (time_t) LLONG_MAX;
+ return (time_t) LLONG_MAX;
#else
- return (time_t) LONG_MAX;
+ return (time_t) LONG_MAX;
#endif
- }
+ }
}
// Correction factor used by time_corrected() above.
@@ -183,6 +183,6 @@ LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_dayli
LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
-U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds
+U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds
#endif
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 87457ad907..440529b8e8 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file lltrace.cpp
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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$
*/
@@ -33,53 +33,53 @@
namespace LLTrace
{
-StatBase::StatBase( const char* name, const char* description )
-: mName(name),
- mDescription(description ? description : "")
+StatBase::StatBase( const char* name, const char* description )
+: mName(name),
+ mDescription(description ? description : "")
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
- if (LLTrace::get_thread_recorder() != NULL)
- {
- LL_ERRS() << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << LL_ENDL;
- }
+ if (LLTrace::get_thread_recorder() != NULL)
+ {
+ LL_ERRS() << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << LL_ENDL;
+ }
#endif
}
const char* StatBase::getUnitLabel() const
{
- return "";
+ return "";
}
-TimeBlockTreeNode::TimeBlockTreeNode()
-: mBlock(NULL),
- mParent(NULL),
- mNeedsSorting(false),
- mCollapsed(true)
+TimeBlockTreeNode::TimeBlockTreeNode()
+: mBlock(NULL),
+ mParent(NULL),
+ mNeedsSorting(false),
+ mCollapsed(true)
{}
void TimeBlockTreeNode::setParent( BlockTimerStatHandle* parent )
{
LL_PROFILE_ZONE_SCOPED;
- llassert_always(parent != mBlock);
- llassert_always(parent != NULL);
+ llassert_always(parent != mBlock);
+ llassert_always(parent != NULL);
- TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(narrow<size_t>(parent->getIndex()));
- if (!parent_tree_node) return;
+ TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(narrow<size_t>(parent->getIndex()));
+ if (!parent_tree_node) return;
- if (mParent)
- {
- std::vector<BlockTimerStatHandle*>& children = mParent->getChildren();
- std::vector<BlockTimerStatHandle*>::iterator found_it = std::find(children.begin(), children.end(), mBlock);
- if (found_it != children.end())
- {
- children.erase(found_it);
- }
- }
+ if (mParent)
+ {
+ std::vector<BlockTimerStatHandle*>& children = mParent->getChildren();
+ std::vector<BlockTimerStatHandle*>::iterator found_it = std::find(children.begin(), children.end(), mBlock);
+ if (found_it != children.end())
+ {
+ children.erase(found_it);
+ }
+ }
- mParent = parent;
- mBlock->getCurrentAccumulator().mParent = parent;
- parent_tree_node->mChildren.push_back(mBlock);
- parent_tree_node->mNeedsSorting = true;
+ mParent = parent;
+ mBlock->getCurrentAccumulator().mParent = parent;
+ parent_tree_node->mChildren.push_back(mBlock);
+ parent_tree_node->mNeedsSorting = true;
}
}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 21a5803a76..edb010b0a4 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltrace.h
* @brief Runtime statistics accumulation.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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$
*/
@@ -47,90 +47,90 @@ class Recording;
template<typename T>
T storage_value(T val) { return val; }
-template<typename UNIT_TYPE, typename STORAGE_TYPE>
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
-template<typename UNIT_TYPE, typename STORAGE_TYPE>
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
class StatBase
{
public:
- StatBase(const char* name, const char* description);
- virtual ~StatBase() {}
- virtual const char* getUnitLabel() const;
+ StatBase(const char* name, const char* description);
+ virtual ~StatBase() {}
+ virtual const char* getUnitLabel() const;
- const std::string& getName() const { return mName; }
- const std::string& getDescription() const { return mDescription; }
+ const std::string& getName() const { return mName; }
+ const std::string& getDescription() const { return mDescription; }
protected:
- std::string mName;
- std::string mDescription;
+ std::string mName;
+ std::string mDescription;
};
template<typename ACCUMULATOR>
-class StatType
-: public StatBase,
- public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
+class StatType
+: public StatBase,
+ public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
{
public:
- typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string> instance_tracker_t;
- StatType(const char* name, const char* description)
- : instance_tracker_t(name),
- StatBase(name, description),
- mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
- {}
-
- LL_FORCE_INLINE ACCUMULATOR& getCurrentAccumulator() const
- {
- ACCUMULATOR* accumulator_storage = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
- return accumulator_storage ? accumulator_storage[mAccumulatorIndex] : (*AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer())[mAccumulatorIndex];
- }
-
- size_t getIndex() const { return mAccumulatorIndex; }
- static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
+ typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string> instance_tracker_t;
+ StatType(const char* name, const char* description)
+ : instance_tracker_t(name),
+ StatBase(name, description),
+ mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
+ {}
+
+ LL_FORCE_INLINE ACCUMULATOR& getCurrentAccumulator() const
+ {
+ ACCUMULATOR* accumulator_storage = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
+ return accumulator_storage ? accumulator_storage[mAccumulatorIndex] : (*AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer())[mAccumulatorIndex];
+ }
+
+ size_t getIndex() const { return mAccumulatorIndex; }
+ static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
protected:
- const size_t mAccumulatorIndex;
+ const size_t mAccumulatorIndex;
};
template<>
class StatType<TimeBlockAccumulator::CallCountFacet>
-: public StatType<TimeBlockAccumulator>
+: public StatType<TimeBlockAccumulator>
{
public:
- StatType(const char* name, const char* description = "")
- : StatType<TimeBlockAccumulator>(name, description)
- {}
+ StatType(const char* name, const char* description = "")
+ : StatType<TimeBlockAccumulator>(name, description)
+ {}
};
template<>
class StatType<TimeBlockAccumulator::SelfTimeFacet>
- : public StatType<TimeBlockAccumulator>
+ : public StatType<TimeBlockAccumulator>
{
public:
- StatType(const char* name, const char* description = "")
- : StatType<TimeBlockAccumulator>(name, description)
- {}
+ StatType(const char* name, const char* description = "")
+ : StatType<TimeBlockAccumulator>(name, description)
+ {}
};
template <typename T = F64>
class EventStatHandle
-: public StatType<EventAccumulator>
+: public StatType<EventAccumulator>
{
public:
- typedef F64 storage_t;
- typedef StatType<EventAccumulator> stat_t;
- typedef EventStatHandle<T> self_t;
+ typedef F64 storage_t;
+ typedef StatType<EventAccumulator> stat_t;
+ typedef EventStatHandle<T> self_t;
- EventStatHandle(const char* name, const char* description = NULL)
- : stat_t(name, description)
- {}
+ EventStatHandle(const char* name, const char* description = NULL)
+ : stat_t(name, description)
+ {}
- /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
+ /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
};
@@ -138,58 +138,58 @@ template<typename T, typename VALUE_T>
void record(EventStatHandle<T>& measurement, VALUE_T value)
{
#if LL_TRACE_ENABLED
- T converted_value(value);
- measurement.getCurrentAccumulator().record(storage_value(converted_value));
+ T converted_value(value);
+ measurement.getCurrentAccumulator().record(storage_value(converted_value));
#endif
}
template <typename T = F64>
class SampleStatHandle
-: public StatType<SampleAccumulator>
+: public StatType<SampleAccumulator>
{
public:
- typedef F64 storage_t;
- typedef StatType<SampleAccumulator> stat_t;
- typedef SampleStatHandle<T> self_t;
+ typedef F64 storage_t;
+ typedef StatType<SampleAccumulator> stat_t;
+ typedef SampleStatHandle<T> self_t;
- SampleStatHandle(const char* name, const char* description = NULL)
- : stat_t(name, description)
- {}
+ SampleStatHandle(const char* name, const char* description = NULL)
+ : stat_t(name, description)
+ {}
- /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
+ /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
};
template<typename T, typename VALUE_T>
void sample(SampleStatHandle<T>& measurement, VALUE_T value)
{
#if LL_TRACE_ENABLED
- T converted_value(value);
- measurement.getCurrentAccumulator().sample(storage_value(converted_value));
+ T converted_value(value);
+ measurement.getCurrentAccumulator().sample(storage_value(converted_value));
#endif
}
template <typename T = F64>
class CountStatHandle
-: public StatType<CountAccumulator>
+: public StatType<CountAccumulator>
{
public:
- typedef F64 storage_t;
- typedef StatType<CountAccumulator> stat_t;
- typedef CountStatHandle<T> self_t;
+ typedef F64 storage_t;
+ typedef StatType<CountAccumulator> stat_t;
+ typedef CountStatHandle<T> self_t;
- CountStatHandle(const char* name, const char* description = NULL)
- : stat_t(name, description)
- {}
+ CountStatHandle(const char* name, const char* description = NULL)
+ : stat_t(name, description)
+ {}
- /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
+ /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
};
template<typename T, typename VALUE_T>
void add(CountStatHandle<T>& count, VALUE_T value)
{
#if LL_TRACE_ENABLED
- T converted_value(value);
- count.getCurrentAccumulator().add(storage_value(converted_value));
+ T converted_value(value);
+ count.getCurrentAccumulator().add(storage_value(converted_value));
#endif
}
@@ -198,85 +198,85 @@ void add(CountStatHandle<T>& count, VALUE_T value)
template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void>
struct MeasureMem
{
- static size_t measureFootprint(const T& value)
- {
- return sizeof(T);
- }
+ static size_t measureFootprint(const T& value)
+ {
+ return sizeof(T);
+ }
};
template<typename T, typename IS_BYTES>
struct MeasureMem<T, typename T::mem_trackable_tag_t, IS_BYTES>
{
- static size_t measureFootprint(const T& value)
- {
+ static size_t measureFootprint(const T& value)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return sizeof(T) + value.getMemFootprint();
- }
+ return sizeof(T) + value.getMemFootprint();
+ }
};
template<typename T, typename IS_MEM_TRACKABLE>
struct MeasureMem<T, IS_MEM_TRACKABLE, typename T::is_unit_t>
{
- static size_t measureFootprint(const T& value)
- {
+ static size_t measureFootprint(const T& value)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return U32Bytes(value).value();
- }
+ return U32Bytes(value).value();
+ }
};
template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
struct MeasureMem<T*, IS_MEM_TRACKABLE, IS_BYTES>
{
- static size_t measureFootprint(const T* value)
- {
+ static size_t measureFootprint(const T* value)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (!value)
- {
- return 0;
- }
- return MeasureMem<T>::measureFootprint(*value);
- }
+ if (!value)
+ {
+ return 0;
+ }
+ return MeasureMem<T>::measureFootprint(*value);
+ }
};
template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
struct MeasureMem<LLPointer<T>, IS_MEM_TRACKABLE, IS_BYTES>
{
- static size_t measureFootprint(const LLPointer<T> value)
- {
- if (value.isNull())
- {
- return 0;
- }
- return MeasureMem<T>::measureFootprint(*value);
- }
+ static size_t measureFootprint(const LLPointer<T> value)
+ {
+ if (value.isNull())
+ {
+ return 0;
+ }
+ return MeasureMem<T>::measureFootprint(*value);
+ }
};
template<typename IS_MEM_TRACKABLE, typename IS_BYTES>
struct MeasureMem<S32, IS_MEM_TRACKABLE, IS_BYTES>
{
- static size_t measureFootprint(S32 value)
- {
- return value;
- }
+ static size_t measureFootprint(S32 value)
+ {
+ return value;
+ }
};
template<typename IS_MEM_TRACKABLE, typename IS_BYTES>
struct MeasureMem<U32, IS_MEM_TRACKABLE, IS_BYTES>
{
- static size_t measureFootprint(U32 value)
- {
- return value;
- }
+ static size_t measureFootprint(U32 value)
+ {
+ return value;
+ }
};
template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES>
{
- static size_t measureFootprint(const std::basic_string<T>& value)
- {
+ static size_t measureFootprint(const std::basic_string<T>& value)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return value.capacity() * sizeof(T);
- }
+ return value.capacity() * sizeof(T);
+ }
};
}
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index b5b32cba38..8741087f3a 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -38,246 +38,246 @@ namespace LLTrace
AccumulatorBufferGroup::AccumulatorBufferGroup()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
}
AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other)
-: mCounts(other.mCounts),
- mSamples(other.mSamples),
- mEvents(other.mEvents),
- mStackTimers(other.mStackTimers)
+: mCounts(other.mCounts),
+ mSamples(other.mSamples),
+ mEvents(other.mEvents),
+ mStackTimers(other.mStackTimers)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
}
AccumulatorBufferGroup::~AccumulatorBufferGroup()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
}
void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- other.mCounts.reset(&mCounts);
- other.mSamples.reset(&mSamples);
- other.mEvents.reset(&mEvents);
- other.mStackTimers.reset(&mStackTimers);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ other.mCounts.reset(&mCounts);
+ other.mSamples.reset(&mSamples);
+ other.mEvents.reset(&mEvents);
+ other.mStackTimers.reset(&mStackTimers);
}
void AccumulatorBufferGroup::makeCurrent()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mCounts.makeCurrent();
- mSamples.makeCurrent();
- mEvents.makeCurrent();
- mStackTimers.makeCurrent();
-
- ThreadRecorder* thread_recorder = get_thread_recorder();
- AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
- // update stacktimer parent pointers
- for (size_t i = 0, end_i = mStackTimers.size(); i < end_i; i++)
- {
- TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(narrow<size_t>(i));
- if (tree_node)
- {
- timer_accumulator_buffer[i].mParent = tree_node->mParent;
- }
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mCounts.makeCurrent();
+ mSamples.makeCurrent();
+ mEvents.makeCurrent();
+ mStackTimers.makeCurrent();
+
+ ThreadRecorder* thread_recorder = get_thread_recorder();
+ AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
+ // update stacktimer parent pointers
+ for (size_t i = 0, end_i = mStackTimers.size(); i < end_i; i++)
+ {
+ TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(narrow<size_t>(i));
+ if (tree_node)
+ {
+ timer_accumulator_buffer[i].mParent = tree_node->mParent;
+ }
+ }
}
//static
void AccumulatorBufferGroup::clearCurrent()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- AccumulatorBuffer<CountAccumulator>::clearCurrent();
- AccumulatorBuffer<SampleAccumulator>::clearCurrent();
- AccumulatorBuffer<EventAccumulator>::clearCurrent();
- AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ AccumulatorBuffer<CountAccumulator>::clearCurrent();
+ AccumulatorBuffer<SampleAccumulator>::clearCurrent();
+ AccumulatorBuffer<EventAccumulator>::clearCurrent();
+ AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent();
}
bool AccumulatorBufferGroup::isCurrent() const
{
- return mCounts.isCurrent();
+ return mCounts.isCurrent();
}
void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mCounts.addSamples(other.mCounts, SEQUENTIAL);
- mSamples.addSamples(other.mSamples, SEQUENTIAL);
- mEvents.addSamples(other.mEvents, SEQUENTIAL);
- mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mCounts.addSamples(other.mCounts, SEQUENTIAL);
+ mSamples.addSamples(other.mSamples, SEQUENTIAL);
+ mEvents.addSamples(other.mEvents, SEQUENTIAL);
+ mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL);
}
void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mCounts.addSamples(other.mCounts, NON_SEQUENTIAL);
- mSamples.addSamples(other.mSamples, NON_SEQUENTIAL);
- mEvents.addSamples(other.mEvents, NON_SEQUENTIAL);
- // for now, hold out timers from merge, need to be displayed per thread
- //mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mCounts.addSamples(other.mCounts, NON_SEQUENTIAL);
+ mSamples.addSamples(other.mSamples, NON_SEQUENTIAL);
+ mEvents.addSamples(other.mEvents, NON_SEQUENTIAL);
+ // for now, hold out timers from merge, need to be displayed per thread
+ //mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL);
}
void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mCounts.reset(other ? &other->mCounts : NULL);
- mSamples.reset(other ? &other->mSamples : NULL);
- mEvents.reset(other ? &other->mEvents : NULL);
- mStackTimers.reset(other ? &other->mStackTimers : NULL);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mCounts.reset(other ? &other->mCounts : NULL);
+ mSamples.reset(other ? &other->mSamples : NULL);
+ mEvents.reset(other ? &other->mEvents : NULL);
+ mStackTimers.reset(other ? &other->mStackTimers : NULL);
}
void AccumulatorBufferGroup::sync()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (isCurrent())
- {
- F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
- mSamples.sync(time_stamp);
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ if (isCurrent())
+ {
+ F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
+ mSamples.sync(time_stamp);
+ }
}
F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b)
{
- const F64 epsilon = 0.0000001;
-
- if (a.getSamplingTime() > epsilon && b.getSamplingTime() > epsilon)
- {
- // combine variance (and hence standard deviation) of 2 different sized sample groups using
- // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
- F64 n_1 = a.getSamplingTime(),
- n_2 = b.getSamplingTime();
- F64 m_1 = a.getMean(),
- m_2 = b.getMean();
- F64 v_1 = a.getSumOfSquares() / a.getSamplingTime(),
- v_2 = b.getSumOfSquares() / b.getSamplingTime();
- if (n_1 < epsilon)
- {
- return b.getSumOfSquares();
- }
- else
- {
- return a.getSamplingTime()
- * ((((n_1 - epsilon) * v_1)
- + ((n_2 - epsilon) * v_2)
- + (((n_1 * n_2) / (n_1 + n_2))
- * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
- / (n_1 + n_2 - epsilon));
- }
- }
-
- return a.getSumOfSquares();
+ const F64 epsilon = 0.0000001;
+
+ if (a.getSamplingTime() > epsilon && b.getSamplingTime() > epsilon)
+ {
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = a.getSamplingTime(),
+ n_2 = b.getSamplingTime();
+ F64 m_1 = a.getMean(),
+ m_2 = b.getMean();
+ F64 v_1 = a.getSumOfSquares() / a.getSamplingTime(),
+ v_2 = b.getSumOfSquares() / b.getSamplingTime();
+ if (n_1 < epsilon)
+ {
+ return b.getSumOfSquares();
+ }
+ else
+ {
+ return a.getSamplingTime()
+ * ((((n_1 - epsilon) * v_1)
+ + ((n_2 - epsilon) * v_2)
+ + (((n_1 * n_2) / (n_1 + n_2))
+ * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+ / (n_1 + n_2 - epsilon));
+ }
+ }
+
+ return a.getSumOfSquares();
}
void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
{
- if (append_type == NON_SEQUENTIAL)
- {
- return;
- }
-
- if (!mHasValue)
- {
- *this = other;
-
- if (append_type == NON_SEQUENTIAL)
- {
- // restore own last value state
- mLastValue = NaN;
- mHasValue = false;
- }
- }
- else if (other.mHasValue)
- {
- mSum += other.mSum;
-
- if (other.mMin < mMin) { mMin = other.mMin; }
- if (other.mMax > mMax) { mMax = other.mMax; }
-
- mSumOfSquares = mergeSumsOfSquares(*this, other);
-
- if (append_type == SEQUENTIAL)
- {
- mLastValue = other.mLastValue;
- mLastSampleTimeStamp = other.mLastSampleTimeStamp;
- }
- }
+ if (append_type == NON_SEQUENTIAL)
+ {
+ return;
+ }
+
+ if (!mHasValue)
+ {
+ *this = other;
+
+ if (append_type == NON_SEQUENTIAL)
+ {
+ // restore own last value state
+ mLastValue = NaN;
+ mHasValue = false;
+ }
+ }
+ else if (other.mHasValue)
+ {
+ mSum += other.mSum;
+
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ mSumOfSquares = mergeSumsOfSquares(*this, other);
+
+ if (append_type == SEQUENTIAL)
+ {
+ mLastValue = other.mLastValue;
+ mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+ }
+ }
}
void SampleAccumulator::reset( const SampleAccumulator* other )
{
- mLastValue = other ? other->mLastValue : NaN;
- mHasValue = other ? other->mHasValue : false;
- mNumSamples = 0;
- mSum = 0;
- mMin = mLastValue;
- mMax = mLastValue;
- mMean = mLastValue;
- llassert(!mHasValue || mMean < 0 || mMean >= 0);
- mSumOfSquares = 0;
- mLastSampleTimeStamp = LLTimer::getTotalSeconds();
- mTotalSamplingTime = 0;
+ mLastValue = other ? other->mLastValue : NaN;
+ mHasValue = other ? other->mHasValue : false;
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = mLastValue;
+ mMax = mLastValue;
+ mMean = mLastValue;
+ llassert(!mHasValue || mMean < 0 || mMean >= 0);
+ mSumOfSquares = 0;
+ mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+ mTotalSamplingTime = 0;
}
F64 EventAccumulator::mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b)
{
- if (a.mNumSamples && b.mNumSamples)
- {
- // combine variance (and hence standard deviation) of 2 different sized sample groups using
- // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
- F64 n_1 = a.mNumSamples,
- n_2 = b.mNumSamples;
- F64 m_1 = a.mMean,
- m_2 = b.mMean;
- F64 v_1 = a.mSumOfSquares / a.mNumSamples,
- v_2 = b.mSumOfSquares / b.mNumSamples;
- return (F64)a.mNumSamples
- * ((((n_1 - 1.f) * v_1)
- + ((n_2 - 1.f) * v_2)
- + (((n_1 * n_2) / (n_1 + n_2))
- * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
- / (n_1 + n_2 - 1.f));
- }
-
- return a.mSumOfSquares;
+ if (a.mNumSamples && b.mNumSamples)
+ {
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = a.mNumSamples,
+ n_2 = b.mNumSamples;
+ F64 m_1 = a.mMean,
+ m_2 = b.mMean;
+ F64 v_1 = a.mSumOfSquares / a.mNumSamples,
+ v_2 = b.mSumOfSquares / b.mNumSamples;
+ return (F64)a.mNumSamples
+ * ((((n_1 - 1.f) * v_1)
+ + ((n_2 - 1.f) * v_2)
+ + (((n_1 * n_2) / (n_1 + n_2))
+ * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+ / (n_1 + n_2 - 1.f));
+ }
+
+ return a.mSumOfSquares;
}
void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type )
{
- if (other.mNumSamples)
- {
- if (!mNumSamples)
- {
- *this = other;
- }
- else
- {
- mSum += other.mSum;
-
- // NOTE: both conditions will hold first time through
- if (other.mMin < mMin) { mMin = other.mMin; }
- if (other.mMax > mMax) { mMax = other.mMax; }
-
- mSumOfSquares = mergeSumsOfSquares(*this, other);
-
- F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
- mNumSamples += other.mNumSamples;
- mMean = mMean * weight + other.mMean * (1.f - weight);
- if (append_type == SEQUENTIAL) mLastValue = other.mLastValue;
- }
- }
+ if (other.mNumSamples)
+ {
+ if (!mNumSamples)
+ {
+ *this = other;
+ }
+ else
+ {
+ mSum += other.mSum;
+
+ // NOTE: both conditions will hold first time through
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ mSumOfSquares = mergeSumsOfSquares(*this, other);
+
+ F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+ mNumSamples += other.mNumSamples;
+ mMean = mMean * weight + other.mMean * (1.f - weight);
+ if (append_type == SEQUENTIAL) mLastValue = other.mLastValue;
+ }
+ }
}
void EventAccumulator::reset( const EventAccumulator* other )
{
- mNumSamples = 0;
- mSum = 0;
- mMin = F32(NaN);
- mMax = F32(NaN);
- mMean = NaN;
- mSumOfSquares = 0;
- mLastValue = other ? other->mLastValue : NaN;
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = F32(NaN);
+ mMax = F32(NaN);
+ mMean = NaN;
+ mSumOfSquares = 0;
+ mLastValue = other ? other->mLastValue : NaN;
}
}
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index b9d577be9e..692bbe5acf 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -39,515 +39,515 @@
namespace LLTrace
{
- const F64 NaN = std::numeric_limits<double>::quiet_NaN();
-
- enum EBufferAppendType
- {
- SEQUENTIAL,
- NON_SEQUENTIAL
- };
-
- template<typename ACCUMULATOR>
- class AccumulatorBuffer : public LLRefCount
- {
- typedef AccumulatorBuffer<ACCUMULATOR> self_t;
- static const S32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 32;
- private:
- struct StaticAllocationMarker { };
-
- AccumulatorBuffer(StaticAllocationMarker m)
- : mStorageSize(0),
- mStorage(NULL)
- {}
-
- public:
- AccumulatorBuffer()
- : mStorageSize(0),
- mStorage(NULL)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- const AccumulatorBuffer& other = *getDefaultBuffer();
- resize(sNextStorageSlot);
- for (S32 i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i] = other.mStorage[i];
- }
- }
-
- ~AccumulatorBuffer()
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (isCurrent())
- {
- LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
- }
- delete[] mStorage;
- }
-
- LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index)
- {
- return mStorage[index];
- }
-
- LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
- {
- return mStorage[index];
- }
-
-
- AccumulatorBuffer(const AccumulatorBuffer& other)
- : mStorageSize(0),
- mStorage(NULL)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- resize(sNextStorageSlot);
- for (S32 i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i] = other.mStorage[i];
- }
- }
-
- void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i].addSamples(other.mStorage[i], append_type);
- }
- }
-
- void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i] = other.mStorage[i];
- }
- }
-
- void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- llassert(mStorageSize >= sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i].reset(other ? &other->mStorage[i] : NULL);
- }
- }
-
- void sync(F64SecondsImplicit time_stamp)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- llassert(mStorageSize >= sNextStorageSlot);
- for (size_t i = 0; i < sNextStorageSlot; i++)
- {
- mStorage[i].sync(time_stamp);
- }
- }
-
- void makeCurrent()
- {
- LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
- }
-
- bool isCurrent() const
- {
- return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
- }
-
- static void clearCurrent()
- {
- LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
- }
-
- // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
- size_t reserveSlot()
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- size_t next_slot = sNextStorageSlot++;
- if (next_slot >= mStorageSize)
- {
- // don't perform doubling, as this should only happen during startup
- // want to keep a tight bounds as we will have a lot of these buffers
- resize(mStorageSize + mStorageSize / 2);
- }
- llassert(mStorage && next_slot < mStorageSize);
- return next_slot;
- }
-
- void resize(size_t new_size)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (new_size <= mStorageSize) return;
-
- ACCUMULATOR* old_storage = mStorage;
- mStorage = new ACCUMULATOR[new_size];
- if (old_storage)
- {
- for (S32 i = 0; i < mStorageSize; i++)
- {
- mStorage[i] = old_storage[i];
- }
- }
- mStorageSize = new_size;
- delete[] old_storage;
-
- self_t* default_buffer = getDefaultBuffer();
- if (this != default_buffer
- && new_size > default_buffer->size())
- {
- //NB: this is not thread safe, but we assume that all resizing occurs during static initialization
- default_buffer->resize(new_size);
- }
- }
-
- size_t size() const
- {
- return getNumIndices();
- }
-
- size_t capacity() const
- {
- return mStorageSize;
- }
-
- static size_t getNumIndices()
- {
- return sNextStorageSlot;
- }
-
- static self_t* getDefaultBuffer()
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- static bool sInitialized = false;
- if (!sInitialized)
- {
- // this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
- // so as not to trigger an access violation
- sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
- sInitialized = true;
- sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
- }
- return sDefaultBuffer;
- }
-
- private:
- ACCUMULATOR* mStorage;
- size_t mStorageSize;
- static size_t sNextStorageSlot;
- static self_t* sDefaultBuffer;
- };
-
- template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
- template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
-
- class EventAccumulator
- {
- public:
- typedef F64 value_t;
- static F64 getDefaultValue() { return NaN; }
-
- EventAccumulator()
- : mSum(0),
- mMin(F32(NaN)),
- mMax(F32(NaN)),
- mMean(NaN),
- mSumOfSquares(0),
- mNumSamples(0),
- mLastValue(NaN)
- {}
-
- void record(F64 value)
- {
- if (mNumSamples == 0)
- {
- mSum = value;
- mMean = value;
- mMin = value;
- mMax = value;
- }
- else
- {
- mSum += value;
- F64 old_mean = mMean;
- mMean += (value - old_mean) / (F64)mNumSamples;
- mSumOfSquares += (value - old_mean) * (value - mMean);
-
- if (value < mMin) { mMin = value; }
- else if (value > mMax) { mMax = value; }
- }
-
- mNumSamples++;
- mLastValue = value;
- }
-
- void addSamples(const EventAccumulator& other, EBufferAppendType append_type);
- void reset(const EventAccumulator* other);
- void sync(F64SecondsImplicit) {}
-
- F64 getSum() const { return mSum; }
- F32 getMin() const { return mMin; }
- F32 getMax() const { return mMax; }
- F64 getLastValue() const { return mLastValue; }
- F64 getMean() const { return mMean; }
- F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
- F64 getSumOfSquares() const { return mSumOfSquares; }
- S32 getSampleCount() const { return mNumSamples; }
- bool hasValue() const { return mNumSamples > 0; }
-
- // helper utility to calculate combined sumofsquares total
- static F64 mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b);
-
- private:
- F64 mSum,
- mLastValue;
-
- F64 mMean,
- mSumOfSquares;
-
- F32 mMin,
- mMax;
-
- S32 mNumSamples;
- };
-
-
- class SampleAccumulator
- {
- public:
- typedef F64 value_t;
- static F64 getDefaultValue() { return NaN; }
-
- SampleAccumulator()
- : mSum(0),
- mMin(F32(NaN)),
- mMax(F32(NaN)),
- mMean(NaN),
- mSumOfSquares(0),
- mLastSampleTimeStamp(0),
- mTotalSamplingTime(0),
- mNumSamples(0),
- mLastValue(NaN),
- mHasValue(false)
- {}
-
- void sample(F64 value)
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
-
- // store effect of last value
- sync(time_stamp);
-
- if (!mHasValue)
- {
- mHasValue = true;
-
- mMin = value;
- mMax = value;
- mMean = value;
- mLastSampleTimeStamp = time_stamp;
- }
- else
- {
- if (value < mMin) { mMin = value; }
- else if (value > mMax) { mMax = value; }
- }
-
- mLastValue = value;
- mNumSamples++;
- }
-
- void addSamples(const SampleAccumulator& other, EBufferAppendType append_type);
- void reset(const SampleAccumulator* other);
-
- void sync(F64SecondsImplicit time_stamp)
- {
- if (mHasValue && time_stamp != mLastSampleTimeStamp)
- {
- F64SecondsImplicit delta_time = time_stamp - mLastSampleTimeStamp;
- mSum += mLastValue * delta_time;
- mTotalSamplingTime += delta_time;
- F64 old_mean = mMean;
- mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
- mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
- }
- mLastSampleTimeStamp = time_stamp;
- }
-
- F64 getSum() const { return mSum; }
- F32 getMin() const { return mMin; }
- F32 getMax() const { return mMax; }
- F64 getLastValue() const { return mLastValue; }
- F64 getMean() const { return mMean; }
- F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
- F64 getSumOfSquares() const { return mSumOfSquares; }
- F64SecondsImplicit getSamplingTime() const { return mTotalSamplingTime; }
- S32 getSampleCount() const { return mNumSamples; }
- bool hasValue() const { return mHasValue; }
-
- // helper utility to calculate combined sumofsquares total
- static F64 mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b);
-
- private:
- F64 mSum,
- mLastValue;
-
- F64 mMean,
- mSumOfSquares;
-
- F64SecondsImplicit
- mLastSampleTimeStamp,
- mTotalSamplingTime;
-
- F32 mMin,
- mMax;
-
- S32 mNumSamples;
- // distinct from mNumSamples, since we might have inherited a last value from
- // a previous sampling period
- bool mHasValue;
- };
-
- class CountAccumulator
- {
- public:
- typedef F64 value_t;
- static F64 getDefaultValue() { return 0; }
-
- CountAccumulator()
- : mSum(0),
- mNumSamples(0)
- {}
-
- void add(F64 value)
- {
- mNumSamples++;
- mSum += value;
- }
-
- void addSamples(const CountAccumulator& other, EBufferAppendType /*type*/)
- {
- mSum += other.mSum;
- mNumSamples += other.mNumSamples;
- }
-
- void reset(const CountAccumulator* other)
- {
- mNumSamples = 0;
- mSum = 0;
- }
-
- void sync(F64SecondsImplicit) {}
-
- F64 getSum() const { return mSum; }
-
- S32 getSampleCount() const { return mNumSamples; }
-
- bool hasValue() const { return true; }
-
- private:
- F64 mSum;
-
- S32 mNumSamples;
- };
-
- class alignas(32) TimeBlockAccumulator
- {
- public:
- typedef F64Seconds value_t;
- static F64Seconds getDefaultValue() { return F64Seconds(0); }
-
- typedef TimeBlockAccumulator self_t;
-
- // fake classes that allows us to view different facets of underlying statistic
- struct CallCountFacet
- {
- typedef S32 value_t;
- };
-
- struct SelfTimeFacet
- {
- typedef F64Seconds value_t;
- };
-
- // arrays are allocated with 32 byte alignment
- void *operator new [](size_t size)
- {
- return ll_aligned_malloc<32>(size);
- }
-
- void operator delete[](void* ptr, size_t size)
- {
- ll_aligned_free<32>(ptr);
- }
-
- TimeBlockAccumulator();
- void addSamples(const self_t& other, EBufferAppendType append_type);
- void reset(const self_t* other);
- void sync(F64SecondsImplicit) {}
- bool hasValue() const { return true; }
-
- //
- // members
- //
- U64 mTotalTimeCounter,
- mSelfTimeCounter;
- S32 mCalls;
- class BlockTimerStatHandle* mParent; // last acknowledged parent of this time block
- class BlockTimerStatHandle* mLastCaller; // used to bootstrap tree construction
- U16 mActiveCount; // number of timers with this ID active on stack
- bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
-
- };
-
- class BlockTimerStatHandle;
-
- class TimeBlockTreeNode
- {
- public:
- TimeBlockTreeNode();
-
- void setParent(BlockTimerStatHandle* parent);
- BlockTimerStatHandle* getParent() { return mParent; }
-
- BlockTimerStatHandle* mBlock;
- BlockTimerStatHandle* mParent;
- std::vector<BlockTimerStatHandle*> mChildren;
- bool mCollapsed;
- bool mNeedsSorting;
- };
-
- struct BlockTimerStackRecord
- {
- class BlockTimer* mActiveTimer;
- class BlockTimerStatHandle* mTimeBlock;
- U64 mChildTime;
- };
-
- struct AccumulatorBufferGroup : public LLRefCount
- {
- AccumulatorBufferGroup();
- AccumulatorBufferGroup(const AccumulatorBufferGroup&);
- ~AccumulatorBufferGroup();
-
- void handOffTo(AccumulatorBufferGroup& other);
- void makeCurrent();
- bool isCurrent() const;
- static void clearCurrent();
-
- void append(const AccumulatorBufferGroup& other);
- void merge(const AccumulatorBufferGroup& other);
- void reset(AccumulatorBufferGroup* other = NULL);
- void sync();
-
- AccumulatorBuffer<CountAccumulator> mCounts;
- AccumulatorBuffer<SampleAccumulator> mSamples;
- AccumulatorBuffer<EventAccumulator> mEvents;
- AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
- };
+ const F64 NaN = std::numeric_limits<double>::quiet_NaN();
+
+ enum EBufferAppendType
+ {
+ SEQUENTIAL,
+ NON_SEQUENTIAL
+ };
+
+ template<typename ACCUMULATOR>
+ class AccumulatorBuffer : public LLRefCount
+ {
+ typedef AccumulatorBuffer<ACCUMULATOR> self_t;
+ static const S32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 32;
+ private:
+ struct StaticAllocationMarker { };
+
+ AccumulatorBuffer(StaticAllocationMarker m)
+ : mStorageSize(0),
+ mStorage(NULL)
+ {}
+
+ public:
+ AccumulatorBuffer()
+ : mStorageSize(0),
+ mStorage(NULL)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ const AccumulatorBuffer& other = *getDefaultBuffer();
+ resize(sNextStorageSlot);
+ for (S32 i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ ~AccumulatorBuffer()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ if (isCurrent())
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+ }
+ delete[] mStorage;
+ }
+
+ LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index)
+ {
+ return mStorage[index];
+ }
+
+ LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
+ {
+ return mStorage[index];
+ }
+
+
+ AccumulatorBuffer(const AccumulatorBuffer& other)
+ : mStorageSize(0),
+ mStorage(NULL)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ resize(sNextStorageSlot);
+ for (S32 i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].addSamples(other.mStorage[i], append_type);
+ }
+ }
+
+ void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].reset(other ? &other->mStorage[i] : NULL);
+ }
+ }
+
+ void sync(F64SecondsImplicit time_stamp)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].sync(time_stamp);
+ }
+ }
+
+ void makeCurrent()
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
+ }
+
+ bool isCurrent() const
+ {
+ return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
+ }
+
+ static void clearCurrent()
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+ }
+
+ // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
+ size_t reserveSlot()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ size_t next_slot = sNextStorageSlot++;
+ if (next_slot >= mStorageSize)
+ {
+ // don't perform doubling, as this should only happen during startup
+ // want to keep a tight bounds as we will have a lot of these buffers
+ resize(mStorageSize + mStorageSize / 2);
+ }
+ llassert(mStorage && next_slot < mStorageSize);
+ return next_slot;
+ }
+
+ void resize(size_t new_size)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ if (new_size <= mStorageSize) return;
+
+ ACCUMULATOR* old_storage = mStorage;
+ mStorage = new ACCUMULATOR[new_size];
+ if (old_storage)
+ {
+ for (S32 i = 0; i < mStorageSize; i++)
+ {
+ mStorage[i] = old_storage[i];
+ }
+ }
+ mStorageSize = new_size;
+ delete[] old_storage;
+
+ self_t* default_buffer = getDefaultBuffer();
+ if (this != default_buffer
+ && new_size > default_buffer->size())
+ {
+ //NB: this is not thread safe, but we assume that all resizing occurs during static initialization
+ default_buffer->resize(new_size);
+ }
+ }
+
+ size_t size() const
+ {
+ return getNumIndices();
+ }
+
+ size_t capacity() const
+ {
+ return mStorageSize;
+ }
+
+ static size_t getNumIndices()
+ {
+ return sNextStorageSlot;
+ }
+
+ static self_t* getDefaultBuffer()
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ static bool sInitialized = false;
+ if (!sInitialized)
+ {
+ // this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+ // so as not to trigger an access violation
+ sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
+ sInitialized = true;
+ sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+ }
+ return sDefaultBuffer;
+ }
+
+ private:
+ ACCUMULATOR* mStorage;
+ size_t mStorageSize;
+ static size_t sNextStorageSlot;
+ static self_t* sDefaultBuffer;
+ };
+
+ template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
+ template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
+
+ class EventAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ static F64 getDefaultValue() { return NaN; }
+
+ EventAccumulator()
+ : mSum(0),
+ mMin(F32(NaN)),
+ mMax(F32(NaN)),
+ mMean(NaN),
+ mSumOfSquares(0),
+ mNumSamples(0),
+ mLastValue(NaN)
+ {}
+
+ void record(F64 value)
+ {
+ if (mNumSamples == 0)
+ {
+ mSum = value;
+ mMean = value;
+ mMin = value;
+ mMax = value;
+ }
+ else
+ {
+ mSum += value;
+ F64 old_mean = mMean;
+ mMean += (value - old_mean) / (F64)mNumSamples;
+ mSumOfSquares += (value - old_mean) * (value - mMean);
+
+ if (value < mMin) { mMin = value; }
+ else if (value > mMax) { mMax = value; }
+ }
+
+ mNumSamples++;
+ mLastValue = value;
+ }
+
+ void addSamples(const EventAccumulator& other, EBufferAppendType append_type);
+ void reset(const EventAccumulator* other);
+ void sync(F64SecondsImplicit) {}
+
+ F64 getSum() const { return mSum; }
+ F32 getMin() const { return mMin; }
+ F32 getMax() const { return mMax; }
+ F64 getLastValue() const { return mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
+ F64 getSumOfSquares() const { return mSumOfSquares; }
+ S32 getSampleCount() const { return mNumSamples; }
+ bool hasValue() const { return mNumSamples > 0; }
+
+ // helper utility to calculate combined sumofsquares total
+ static F64 mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b);
+
+ private:
+ F64 mSum,
+ mLastValue;
+
+ F64 mMean,
+ mSumOfSquares;
+
+ F32 mMin,
+ mMax;
+
+ S32 mNumSamples;
+ };
+
+
+ class SampleAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ static F64 getDefaultValue() { return NaN; }
+
+ SampleAccumulator()
+ : mSum(0),
+ mMin(F32(NaN)),
+ mMax(F32(NaN)),
+ mMean(NaN),
+ mSumOfSquares(0),
+ mLastSampleTimeStamp(0),
+ mTotalSamplingTime(0),
+ mNumSamples(0),
+ mLastValue(NaN),
+ mHasValue(false)
+ {}
+
+ void sample(F64 value)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
+
+ // store effect of last value
+ sync(time_stamp);
+
+ if (!mHasValue)
+ {
+ mHasValue = true;
+
+ mMin = value;
+ mMax = value;
+ mMean = value;
+ mLastSampleTimeStamp = time_stamp;
+ }
+ else
+ {
+ if (value < mMin) { mMin = value; }
+ else if (value > mMax) { mMax = value; }
+ }
+
+ mLastValue = value;
+ mNumSamples++;
+ }
+
+ void addSamples(const SampleAccumulator& other, EBufferAppendType append_type);
+ void reset(const SampleAccumulator* other);
+
+ void sync(F64SecondsImplicit time_stamp)
+ {
+ if (mHasValue && time_stamp != mLastSampleTimeStamp)
+ {
+ F64SecondsImplicit delta_time = time_stamp - mLastSampleTimeStamp;
+ mSum += mLastValue * delta_time;
+ mTotalSamplingTime += delta_time;
+ F64 old_mean = mMean;
+ mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+ mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
+ }
+ mLastSampleTimeStamp = time_stamp;
+ }
+
+ F64 getSum() const { return mSum; }
+ F32 getMin() const { return mMin; }
+ F32 getMax() const { return mMax; }
+ F64 getLastValue() const { return mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
+ F64 getSumOfSquares() const { return mSumOfSquares; }
+ F64SecondsImplicit getSamplingTime() const { return mTotalSamplingTime; }
+ S32 getSampleCount() const { return mNumSamples; }
+ bool hasValue() const { return mHasValue; }
+
+ // helper utility to calculate combined sumofsquares total
+ static F64 mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b);
+
+ private:
+ F64 mSum,
+ mLastValue;
+
+ F64 mMean,
+ mSumOfSquares;
+
+ F64SecondsImplicit
+ mLastSampleTimeStamp,
+ mTotalSamplingTime;
+
+ F32 mMin,
+ mMax;
+
+ S32 mNumSamples;
+ // distinct from mNumSamples, since we might have inherited a last value from
+ // a previous sampling period
+ bool mHasValue;
+ };
+
+ class CountAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ static F64 getDefaultValue() { return 0; }
+
+ CountAccumulator()
+ : mSum(0),
+ mNumSamples(0)
+ {}
+
+ void add(F64 value)
+ {
+ mNumSamples++;
+ mSum += value;
+ }
+
+ void addSamples(const CountAccumulator& other, EBufferAppendType /*type*/)
+ {
+ mSum += other.mSum;
+ mNumSamples += other.mNumSamples;
+ }
+
+ void reset(const CountAccumulator* other)
+ {
+ mNumSamples = 0;
+ mSum = 0;
+ }
+
+ void sync(F64SecondsImplicit) {}
+
+ F64 getSum() const { return mSum; }
+
+ S32 getSampleCount() const { return mNumSamples; }
+
+ bool hasValue() const { return true; }
+
+ private:
+ F64 mSum;
+
+ S32 mNumSamples;
+ };
+
+ class alignas(32) TimeBlockAccumulator
+ {
+ public:
+ typedef F64Seconds value_t;
+ static F64Seconds getDefaultValue() { return F64Seconds(0); }
+
+ typedef TimeBlockAccumulator self_t;
+
+ // fake classes that allows us to view different facets of underlying statistic
+ struct CallCountFacet
+ {
+ typedef S32 value_t;
+ };
+
+ struct SelfTimeFacet
+ {
+ typedef F64Seconds value_t;
+ };
+
+ // arrays are allocated with 32 byte alignment
+ void *operator new [](size_t size)
+ {
+ return ll_aligned_malloc<32>(size);
+ }
+
+ void operator delete[](void* ptr, size_t size)
+ {
+ ll_aligned_free<32>(ptr);
+ }
+
+ TimeBlockAccumulator();
+ void addSamples(const self_t& other, EBufferAppendType append_type);
+ void reset(const self_t* other);
+ void sync(F64SecondsImplicit) {}
+ bool hasValue() const { return true; }
+
+ //
+ // members
+ //
+ U64 mTotalTimeCounter,
+ mSelfTimeCounter;
+ S32 mCalls;
+ class BlockTimerStatHandle* mParent; // last acknowledged parent of this time block
+ class BlockTimerStatHandle* mLastCaller; // used to bootstrap tree construction
+ U16 mActiveCount; // number of timers with this ID active on stack
+ bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
+
+ };
+
+ class BlockTimerStatHandle;
+
+ class TimeBlockTreeNode
+ {
+ public:
+ TimeBlockTreeNode();
+
+ void setParent(BlockTimerStatHandle* parent);
+ BlockTimerStatHandle* getParent() { return mParent; }
+
+ BlockTimerStatHandle* mBlock;
+ BlockTimerStatHandle* mParent;
+ std::vector<BlockTimerStatHandle*> mChildren;
+ bool mCollapsed;
+ bool mNeedsSorting;
+ };
+
+ struct BlockTimerStackRecord
+ {
+ class BlockTimer* mActiveTimer;
+ class BlockTimerStatHandle* mTimeBlock;
+ U64 mChildTime;
+ };
+
+ struct AccumulatorBufferGroup : public LLRefCount
+ {
+ AccumulatorBufferGroup();
+ AccumulatorBufferGroup(const AccumulatorBufferGroup&);
+ ~AccumulatorBufferGroup();
+
+ void handOffTo(AccumulatorBufferGroup& other);
+ void makeCurrent();
+ bool isCurrent() const;
+ static void clearCurrent();
+
+ void append(const AccumulatorBufferGroup& other);
+ void merge(const AccumulatorBufferGroup& other);
+ void reset(AccumulatorBufferGroup* other = NULL);
+ void sync();
+
+ AccumulatorBuffer<CountAccumulator> mCounts;
+ AccumulatorBuffer<SampleAccumulator> mSamples;
+ AccumulatorBuffer<EventAccumulator> mEvents;
+ AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
+ };
}
#endif // LL_LLTRACEACCUMULATORS_H
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 075e7c1d28..1ec83be7cb 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -34,7 +34,7 @@
inline F64 lerp(F64 a, F64 b, F64 u)
{
- return a + ((b - a) * u);
+ return a + ((b - a) * u);
}
namespace LLTrace
@@ -45,388 +45,388 @@ namespace LLTrace
///////////////////////////////////////////////////////////////////////
Recording::Recording(EPlayState state)
-: mElapsedSeconds(0),
- mActiveBuffers(NULL)
+: mElapsedSeconds(0),
+ mActiveBuffers(NULL)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mBuffers = new AccumulatorBufferGroup();
- setPlayState(state);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mBuffers = new AccumulatorBufferGroup();
+ setPlayState(state);
}
Recording::Recording( const Recording& other )
-: mActiveBuffers(NULL)
+: mActiveBuffers(NULL)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- *this = other;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ *this = other;
}
Recording& Recording::operator = (const Recording& other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- // this will allow us to seamlessly start without affecting any data we've acquired from other
- setPlayState(PAUSED);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ // this will allow us to seamlessly start without affecting any data we've acquired from other
+ setPlayState(PAUSED);
- const_cast<Recording&>(other).update();
- EPlayState other_play_state = other.getPlayState();
+ const_cast<Recording&>(other).update();
+ EPlayState other_play_state = other.getPlayState();
- mBuffers = other.mBuffers;
+ mBuffers = other.mBuffers;
- // above call will clear mElapsedSeconds as a side effect, so copy it here
- mElapsedSeconds = other.mElapsedSeconds;
- mSamplingTimer = other.mSamplingTimer;
+ // above call will clear mElapsedSeconds as a side effect, so copy it here
+ mElapsedSeconds = other.mElapsedSeconds;
+ mSamplingTimer = other.mSamplingTimer;
- setPlayState(other_play_state);
+ setPlayState(other_play_state);
- return *this;
+ return *this;
}
Recording::~Recording()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- // allow recording destruction without thread recorder running,
- // otherwise thread shutdown could crash if a recording outlives the thread recorder
- // besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
- if (isStarted() && LLTrace::get_thread_recorder() != NULL)
- {
- LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
- }
+ // allow recording destruction without thread recorder running,
+ // otherwise thread shutdown could crash if a recording outlives the thread recorder
+ // besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
+ if (isStarted() && LLTrace::get_thread_recorder() != NULL)
+ {
+ LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+ }
}
// brings recording to front of recorder stack, with up to date info
void Recording::update()
{
#if LL_TRACE_ENABLED
- if (isStarted())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-
- // must have
- llassert(mActiveBuffers != NULL
- && LLTrace::get_thread_recorder() != NULL);
-
- if (!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL)
- {
- AccumulatorBufferGroup* buffers = mBuffers.write();
- LLTrace::get_thread_recorder()->deactivate(buffers);
- mActiveBuffers = LLTrace::get_thread_recorder()->activate(buffers);
- }
-
- mSamplingTimer.reset();
- }
+ if (isStarted())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+
+ // must have
+ llassert(mActiveBuffers != NULL
+ && LLTrace::get_thread_recorder() != NULL);
+
+ if (!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL)
+ {
+ AccumulatorBufferGroup* buffers = mBuffers.write();
+ LLTrace::get_thread_recorder()->deactivate(buffers);
+ mActiveBuffers = LLTrace::get_thread_recorder()->activate(buffers);
+ }
+
+ mSamplingTimer.reset();
+ }
#endif
}
void Recording::handleReset()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
- mBuffers.write()->reset();
+ mBuffers.write()->reset();
- mElapsedSeconds = F64Seconds(0.0);
- mSamplingTimer.reset();
+ mElapsedSeconds = F64Seconds(0.0);
+ mSamplingTimer.reset();
#endif
}
void Recording::handleStart()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
- mSamplingTimer.reset();
- mBuffers.setStayUnique(true);
- // must have thread recorder running on this thread
- llassert(LLTrace::get_thread_recorder() != NULL);
- mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
+ mSamplingTimer.reset();
+ mBuffers.setStayUnique(true);
+ // must have thread recorder running on this thread
+ llassert(LLTrace::get_thread_recorder() != NULL);
+ mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
#endif
}
void Recording::handleStop()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
- mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
- // must have thread recorder running on this thread
- llassert(LLTrace::get_thread_recorder() != NULL);
- LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
- mActiveBuffers = NULL;
- mBuffers.setStayUnique(false);
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+ // must have thread recorder running on this thread
+ llassert(LLTrace::get_thread_recorder() != NULL);
+ LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+ mActiveBuffers = NULL;
+ mBuffers.setStayUnique(false);
#endif
}
void Recording::handleSplitTo(Recording& other)
{
#if LL_TRACE_ENABLED
- mBuffers.write()->handOffTo(*other.mBuffers.write());
+ mBuffers.write()->handOffTo(*other.mBuffers.write());
#endif
}
void Recording::appendRecording( Recording& other )
{
#if LL_TRACE_ENABLED
- update();
- other.update();
- mBuffers.write()->append(*other.mBuffers);
- mElapsedSeconds += other.mElapsedSeconds;
+ update();
+ other.update();
+ mBuffers.write()->append(*other.mBuffers);
+ mElapsedSeconds += other.mElapsedSeconds;
#endif
}
bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
}
F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
- / (F64)LLTrace::BlockTimer::countsPerSecond();
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
+ / (F64)LLTrace::BlockTimer::countsPerSecond();
}
F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond());
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond());
}
S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0);
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0);
}
F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
- / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
+ return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
+ / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
}
F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return F64Seconds((F64)(accumulator.mSelfTimeCounter + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0))
- / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
+ return F64Seconds((F64)(accumulator.mSelfTimeCounter + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0))
+ / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
}
F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
{
- update();
- const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
- const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
- return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value();
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value();
}
bool Recording::hasValue(const StatType<CountAccumulator>& stat)
{
- update();
- const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
- const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
- return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false);
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false);
}
F64 Recording::getSum(const StatType<CountAccumulator>& stat)
{
- update();
- const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
- const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
- return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
}
F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
{
- update();
- const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
- const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
- F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
- return sum / mElapsedSeconds.value();
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
+ return sum / mElapsedSeconds.value();
}
S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
{
- update();
- const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
- const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
- return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
}
F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
}
F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
}
F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- if (active_accumulator && active_accumulator->hasValue())
- {
- F32 t = 0.0f;
- S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
- if (div > 0)
- {
- t = active_accumulator->getSampleCount() / div;
- }
- return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
- }
- else
- {
- return accumulator.getMean();
- }
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F32 t = 0.0f;
+ S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
+ if (div > 0)
+ {
+ t = active_accumulator->getSampleCount() / div;
+ }
+ return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
+ }
+ else
+ {
+ return accumulator.getMean();
+ }
}
F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- if (active_accumulator && active_accumulator->hasValue())
- {
- F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
- return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime()));
- }
- else
- {
- return accumulator.getStandardDeviation();
- }
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
+ return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime()));
+ }
+ else
+ {
+ return accumulator.getStandardDeviation();
+ }
}
F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue());
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue());
}
S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
{
- update();
- const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
- const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
- return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0);
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<EventAccumulator>& stat)
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
}
F64 Recording::getSum( const StatType<EventAccumulator>& stat)
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0));
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0));
}
F64 Recording::getMin( const StatType<EventAccumulator>& stat )
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
}
F64 Recording::getMax( const StatType<EventAccumulator>& stat )
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
}
F64 Recording::getMean( const StatType<EventAccumulator>& stat )
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- if (active_accumulator && active_accumulator->hasValue())
- {
- F32 t = 0.0f;
- S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
- if (div > 0)
- {
- t = active_accumulator->getSampleCount() / div;
- }
- return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
- }
- else
- {
- return accumulator.getMean();
- }
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F32 t = 0.0f;
+ S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
+ if (div > 0)
+ {
+ t = active_accumulator->getSampleCount() / div;
+ }
+ return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
+ }
+ else
+ {
+ return accumulator.getMean();
+ }
}
F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- if (active_accumulator && active_accumulator->hasValue())
- {
- F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
- return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
- }
- else
- {
- return accumulator.getStandardDeviation();
- }
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
+ return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+ }
+ else
+ {
+ return accumulator.getStandardDeviation();
+ }
}
F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue();
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue();
}
S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
{
- update();
- const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
- const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
- return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
}
///////////////////////////////////////////////////////////////////////
@@ -434,408 +434,408 @@ S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
///////////////////////////////////////////////////////////////////////
PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
-: mAutoResize(num_periods == 0),
- mCurPeriod(0),
- mNumRecordedPeriods(0),
- // This guarantee that mRecordingPeriods cannot be empty is essential for
- // code in several methods.
- mRecordingPeriods(num_periods ? num_periods : 1)
+: mAutoResize(num_periods == 0),
+ mCurPeriod(0),
+ mNumRecordedPeriods(0),
+ // This guarantee that mRecordingPeriods cannot be empty is essential for
+ // code in several methods.
+ mRecordingPeriods(num_periods ? num_periods : 1)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- setPlayState(state);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ setPlayState(state);
}
PeriodicRecording::~PeriodicRecording()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
}
void PeriodicRecording::nextPeriod()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (mAutoResize)
- {
- mRecordingPeriods.push_back(Recording());
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ if (mAutoResize)
+ {
+ mRecordingPeriods.push_back(Recording());
+ }
- Recording& old_recording = getCurRecording();
- inci(mCurPeriod);
- old_recording.splitTo(getCurRecording());
+ Recording& old_recording = getCurRecording();
+ inci(mCurPeriod);
+ old_recording.splitTo(getCurRecording());
- // Since mRecordingPeriods always has at least one entry, we can always
- // safely subtract 1 from its size().
- mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
+ // Since mRecordingPeriods always has at least one entry, we can always
+ // safely subtract 1 from its size().
+ mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
}
void PeriodicRecording::appendRecording(Recording& recording)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- getCurRecording().appendRecording(recording);
- nextPeriod();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ getCurRecording().appendRecording(recording);
+ nextPeriod();
}
void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (other.mRecordingPeriods.empty()) return;
-
- getCurRecording().update();
- other.getCurRecording().update();
-
- const auto other_num_recordings = other.getNumRecordedPeriods();
- const auto other_current_recording_index = other.mCurPeriod;
- const auto other_oldest_recording_index = other.previ(other_current_recording_index, other_num_recordings);
-
- // append first recording into our current slot
- getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
-
- // from now on, add new recordings for everything after the first
- auto other_index = other.nexti(other_oldest_recording_index);
-
- if (mAutoResize)
- {
- // push back recordings for everything in the middle
- while (other_index != other_current_recording_index)
- {
- mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
- other.inci(other_index);
- }
-
- // add final recording, if it wasn't already added as the first
- if (other_num_recordings > 1)
- {
- mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
- }
-
- // mRecordingPeriods is never empty()
- mCurPeriod = mRecordingPeriods.size() - 1;
- mNumRecordedPeriods = mCurPeriod;
- }
- else
- {
- auto num_to_copy = llmin(mRecordingPeriods.size(), other_num_recordings);
- // already consumed the first recording from other, so start counting at 1
- for (size_t n = 1, srci = other_index, dsti = mCurPeriod;
- n < num_to_copy;
- ++n, other.inci(srci), inci(dsti))
- {
- mRecordingPeriods[dsti] = other.mRecordingPeriods[srci];
- }
-
- // want argument to % to be positive, otherwise result could be negative and thus out of bounds
- llassert(num_to_copy >= 1);
- // advance to last recording period copied, and make that our current period
- inci(mCurPeriod, num_to_copy - 1);
- mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
- }
-
- // end with fresh period, otherwise next appendPeriodicRecording() will merge the first
- // recording period with the last one appended here
- nextPeriod();
- getCurRecording().setPlayState(getPlayState());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ if (other.mRecordingPeriods.empty()) return;
+
+ getCurRecording().update();
+ other.getCurRecording().update();
+
+ const auto other_num_recordings = other.getNumRecordedPeriods();
+ const auto other_current_recording_index = other.mCurPeriod;
+ const auto other_oldest_recording_index = other.previ(other_current_recording_index, other_num_recordings);
+
+ // append first recording into our current slot
+ getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
+
+ // from now on, add new recordings for everything after the first
+ auto other_index = other.nexti(other_oldest_recording_index);
+
+ if (mAutoResize)
+ {
+ // push back recordings for everything in the middle
+ while (other_index != other_current_recording_index)
+ {
+ mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
+ other.inci(other_index);
+ }
+
+ // add final recording, if it wasn't already added as the first
+ if (other_num_recordings > 1)
+ {
+ mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
+ }
+
+ // mRecordingPeriods is never empty()
+ mCurPeriod = mRecordingPeriods.size() - 1;
+ mNumRecordedPeriods = mCurPeriod;
+ }
+ else
+ {
+ auto num_to_copy = llmin(mRecordingPeriods.size(), other_num_recordings);
+ // already consumed the first recording from other, so start counting at 1
+ for (size_t n = 1, srci = other_index, dsti = mCurPeriod;
+ n < num_to_copy;
+ ++n, other.inci(srci), inci(dsti))
+ {
+ mRecordingPeriods[dsti] = other.mRecordingPeriods[srci];
+ }
+
+ // want argument to % to be positive, otherwise result could be negative and thus out of bounds
+ llassert(num_to_copy >= 1);
+ // advance to last recording period copied, and make that our current period
+ inci(mCurPeriod, num_to_copy - 1);
+ mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
+ }
+
+ // end with fresh period, otherwise next appendPeriodicRecording() will merge the first
+ // recording period with the last one appended here
+ nextPeriod();
+ getCurRecording().setPlayState(getPlayState());
}
F64Seconds PeriodicRecording::getDuration() const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- F64Seconds duration;
- for (size_t n = 0; n < mRecordingPeriods.size(); ++n)
- {
- duration += mRecordingPeriods[nexti(mCurPeriod, n)].getDuration();
- }
- return duration;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ F64Seconds duration;
+ for (size_t n = 0; n < mRecordingPeriods.size(); ++n)
+ {
+ duration += mRecordingPeriods[nexti(mCurPeriod, n)].getDuration();
+ }
+ return duration;
}
LLTrace::Recording PeriodicRecording::snapshotCurRecording() const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- Recording recording_copy(getCurRecording());
- recording_copy.stop();
- return recording_copy;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ Recording recording_copy(getCurRecording());
+ recording_copy.stop();
+ return recording_copy;
}
Recording& PeriodicRecording::getLastRecording()
{
- return getPrevRecording(1);
+ return getPrevRecording(1);
}
const Recording& PeriodicRecording::getLastRecording() const
{
- return getPrevRecording(1);
+ return getPrevRecording(1);
}
Recording& PeriodicRecording::getCurRecording()
{
- return mRecordingPeriods[mCurPeriod];
+ return mRecordingPeriods[mCurPeriod];
}
const Recording& PeriodicRecording::getCurRecording() const
{
- return mRecordingPeriods[mCurPeriod];
+ return mRecordingPeriods[mCurPeriod];
}
Recording& PeriodicRecording::getPrevRecording( size_t offset )
{
- // reuse const implementation, but return non-const reference
- return const_cast<Recording&>(
- const_cast<const PeriodicRecording*>(this)->getPrevRecording(offset));
+ // reuse const implementation, but return non-const reference
+ return const_cast<Recording&>(
+ const_cast<const PeriodicRecording*>(this)->getPrevRecording(offset));
}
const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const
{
- return mRecordingPeriods[previ(mCurPeriod, offset)];
+ return mRecordingPeriods[previ(mCurPeriod, offset)];
}
void PeriodicRecording::handleStart()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- getCurRecording().start();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ getCurRecording().start();
}
void PeriodicRecording::handleStop()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- getCurRecording().pause();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ getCurRecording().pause();
}
void PeriodicRecording::handleReset()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- getCurRecording().stop();
-
- if (mAutoResize)
- {
- mRecordingPeriods.clear();
- mRecordingPeriods.push_back(Recording());
- }
- else
- {
- for (Recording& rec : mRecordingPeriods)
- {
- rec.reset();
- }
- }
- mCurPeriod = 0;
- mNumRecordedPeriods = 0;
- getCurRecording().setPlayState(getPlayState());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ getCurRecording().stop();
+
+ if (mAutoResize)
+ {
+ mRecordingPeriods.clear();
+ mRecordingPeriods.push_back(Recording());
+ }
+ else
+ {
+ for (Recording& rec : mRecordingPeriods)
+ {
+ rec.reset();
+ }
+ }
+ mCurPeriod = 0;
+ mNumRecordedPeriods = 0;
+ getCurRecording().setPlayState(getPlayState());
}
void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- getCurRecording().splitTo(other.getCurRecording());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ getCurRecording().splitTo(other.getCurRecording());
}
F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- bool has_value = false;
- F64 min_val = std::numeric_limits<F64>::max();
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- min_val = llmin(min_val, recording.getMin(stat));
- has_value = true;
- }
- }
+ bool has_value = false;
+ F64 min_val = std::numeric_limits<F64>::max();
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ min_val = llmin(min_val, recording.getMin(stat));
+ has_value = true;
+ }
+ }
- return has_value
- ? min_val
- : NaN;
+ return has_value
+ ? min_val
+ : NaN;
}
F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- bool has_value = false;
- F64 max_val = std::numeric_limits<F64>::min();
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- max_val = llmax(max_val, recording.getMax(stat));
- has_value = true;
- }
- }
+ bool has_value = false;
+ F64 max_val = std::numeric_limits<F64>::min();
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ max_val = llmax(max_val, recording.getMax(stat));
+ has_value = true;
+ }
+ }
- return has_value
- ? max_val
- : NaN;
+ return has_value
+ ? max_val
+ : NaN;
}
// calculates means using aggregates per period
F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- F64 mean = 0;
- S32 valid_period_count = 0;
+ F64 mean = 0;
+ S32 valid_period_count = 0;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- mean += recording.getMean(stat);
- valid_period_count++;
- }
- }
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ mean += recording.getMean(stat);
+ valid_period_count++;
+ }
+ }
- return valid_period_count
- ? mean / (F64)valid_period_count
- : NaN;
+ return valid_period_count
+ ? mean / (F64)valid_period_count
+ : NaN;
}
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- F64 period_mean = getPeriodMean(stat, num_periods);
- F64 sum_of_squares = 0;
- S32 valid_period_count = 0;
+ F64 period_mean = getPeriodMean(stat, num_periods);
+ F64 sum_of_squares = 0;
+ S32 valid_period_count = 0;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- F64 delta = recording.getMean(stat) - period_mean;
- sum_of_squares += delta * delta;
- valid_period_count++;
- }
- }
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ F64 delta = recording.getMean(stat) - period_mean;
+ sum_of_squares += delta * delta;
+ valid_period_count++;
+ }
+ }
- return valid_period_count
- ? sqrt((F64)sum_of_squares / (F64)valid_period_count)
- : NaN;
+ return valid_period_count
+ ? sqrt((F64)sum_of_squares / (F64)valid_period_count)
+ : NaN;
}
F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- bool has_value = false;
- F64 min_val = std::numeric_limits<F64>::max();
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- min_val = llmin(min_val, recording.getMin(stat));
- has_value = true;
- }
- }
+ bool has_value = false;
+ F64 min_val = std::numeric_limits<F64>::max();
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ min_val = llmin(min_val, recording.getMin(stat));
+ has_value = true;
+ }
+ }
- return has_value
- ? min_val
- : NaN;
+ return has_value
+ ? min_val
+ : NaN;
}
F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- bool has_value = false;
- F64 max_val = std::numeric_limits<F64>::min();
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- max_val = llmax(max_val, recording.getMax(stat));
- has_value = true;
- }
- }
+ bool has_value = false;
+ F64 max_val = std::numeric_limits<F64>::min();
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ max_val = llmax(max_val, recording.getMax(stat));
+ has_value = true;
+ }
+ }
- return has_value
- ? max_val
- : NaN;
+ return has_value
+ ? max_val
+ : NaN;
}
F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- S32 valid_period_count = 0;
- F64 mean = 0;
+ S32 valid_period_count = 0;
+ F64 mean = 0;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- mean += recording.getMean(stat);
- valid_period_count++;
- }
- }
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ mean += recording.getMean(stat);
+ valid_period_count++;
+ }
+ }
- return valid_period_count
- ? mean / F64(valid_period_count)
- : NaN;
+ return valid_period_count
+ ? mean / F64(valid_period_count)
+ : NaN;
}
F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- std::vector<F64> buf;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.getDuration() > (F32Seconds)0.f)
- {
- if (recording.hasValue(stat))
- {
- buf.push_back(recording.getMean(stat));
- }
- }
- }
- if (buf.size()==0)
- {
- return 0.0f;
- }
- std::sort(buf.begin(), buf.end());
-
- return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ std::vector<F64> buf;
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.getDuration() > (F32Seconds)0.f)
+ {
+ if (recording.hasValue(stat))
+ {
+ buf.push_back(recording.getMean(stat));
+ }
+ }
+ }
+ if (buf.size()==0)
+ {
+ return 0.0f;
+ }
+ std::sort(buf.begin(), buf.end());
+
+ return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
}
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
- F64 period_mean = getPeriodMean(stat, num_periods);
- S32 valid_period_count = 0;
- F64 sum_of_squares = 0;
+ F64 period_mean = getPeriodMean(stat, num_periods);
+ S32 valid_period_count = 0;
+ F64 sum_of_squares = 0;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- F64 delta = recording.getMean(stat) - period_mean;
- sum_of_squares += delta * delta;
- valid_period_count++;
- }
- }
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ F64 delta = recording.getMean(stat) - period_mean;
+ sum_of_squares += delta * delta;
+ valid_period_count++;
+ }
+ }
- return valid_period_count
- ? sqrt(sum_of_squares / (F64)valid_period_count)
- : NaN;
+ return valid_period_count
+ ? sqrt(sum_of_squares / (F64)valid_period_count)
+ : NaN;
}
///////////////////////////////////////////////////////////////////////
@@ -844,36 +844,36 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
void ExtendableRecording::extend()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- // push the data back to accepted recording
- mAcceptedRecording.appendRecording(mPotentialRecording);
- // flush data, so we can start from scratch
- mPotentialRecording.reset();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ // push the data back to accepted recording
+ mAcceptedRecording.appendRecording(mPotentialRecording);
+ // flush data, so we can start from scratch
+ mPotentialRecording.reset();
}
void ExtendableRecording::handleStart()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mPotentialRecording.start();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mPotentialRecording.start();
}
void ExtendableRecording::handleStop()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mPotentialRecording.pause();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mPotentialRecording.pause();
}
void ExtendableRecording::handleReset()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mAcceptedRecording.reset();
- mPotentialRecording.reset();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mAcceptedRecording.reset();
+ mPotentialRecording.reset();
}
void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mPotentialRecording.splitTo(other.mPotentialRecording);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mPotentialRecording.splitTo(other.mPotentialRecording);
}
///////////////////////////////////////////////////////////////////////
@@ -881,203 +881,203 @@ void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
///////////////////////////////////////////////////////////////////////
ExtendablePeriodicRecording::ExtendablePeriodicRecording()
-: mAcceptedRecording(0),
- mPotentialRecording(0)
+: mAcceptedRecording(0),
+ mPotentialRecording(0)
{}
void ExtendablePeriodicRecording::extend()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- // push the data back to accepted recording
- mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
- // flush data, so we can start from scratch
- mPotentialRecording.reset();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ // push the data back to accepted recording
+ mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
+ // flush data, so we can start from scratch
+ mPotentialRecording.reset();
}
void ExtendablePeriodicRecording::handleStart()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mPotentialRecording.start();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mPotentialRecording.start();
}
void ExtendablePeriodicRecording::handleStop()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mPotentialRecording.pause();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mPotentialRecording.pause();
}
void ExtendablePeriodicRecording::handleReset()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mAcceptedRecording.reset();
- mPotentialRecording.reset();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mAcceptedRecording.reset();
+ mPotentialRecording.reset();
}
void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- mPotentialRecording.splitTo(other.mPotentialRecording);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ mPotentialRecording.splitTo(other.mPotentialRecording);
}
PeriodicRecording& get_frame_recording()
{
- static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED);
- return sRecording;
+ static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED);
+ return sRecording;
}
}
void LLStopWatchControlsMixinCommon::start()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch (mPlayState)
- {
- case STOPPED:
- handleReset();
- handleStart();
- mPlayState = STARTED;
- break;
- case PAUSED:
- handleStart();
- mPlayState = STARTED;
- break;
- case STARTED:
- break;
- default:
- llassert(false);
- break;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleReset();
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case PAUSED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ break;
+ default:
+ llassert(false);
+ break;
+ }
}
void LLStopWatchControlsMixinCommon::stop()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch (mPlayState)
- {
- case STOPPED:
- break;
- case PAUSED:
- mPlayState = STOPPED;
- break;
- case STARTED:
- handleStop();
- mPlayState = STOPPED;
- break;
- default:
- llassert(false);
- break;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch (mPlayState)
+ {
+ case STOPPED:
+ break;
+ case PAUSED:
+ mPlayState = STOPPED;
+ break;
+ case STARTED:
+ handleStop();
+ mPlayState = STOPPED;
+ break;
+ default:
+ llassert(false);
+ break;
+ }
}
void LLStopWatchControlsMixinCommon::pause()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch (mPlayState)
- {
- case STOPPED:
- // stay stopped, don't go to pause
- break;
- case PAUSED:
- break;
- case STARTED:
- handleStop();
- mPlayState = PAUSED;
- break;
- default:
- llassert(false);
- break;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch (mPlayState)
+ {
+ case STOPPED:
+ // stay stopped, don't go to pause
+ break;
+ case PAUSED:
+ break;
+ case STARTED:
+ handleStop();
+ mPlayState = PAUSED;
+ break;
+ default:
+ llassert(false);
+ break;
+ }
}
void LLStopWatchControlsMixinCommon::unpause()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch (mPlayState)
- {
- case STOPPED:
- // stay stopped, don't start
- break;
- case PAUSED:
- handleStart();
- mPlayState = STARTED;
- break;
- case STARTED:
- break;
- default:
- llassert(false);
- break;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch (mPlayState)
+ {
+ case STOPPED:
+ // stay stopped, don't start
+ break;
+ case PAUSED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ break;
+ default:
+ llassert(false);
+ break;
+ }
}
void LLStopWatchControlsMixinCommon::resume()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch (mPlayState)
- {
- case STOPPED:
- handleStart();
- mPlayState = STARTED;
- break;
- case PAUSED:
- handleStart();
- mPlayState = STARTED;
- break;
- case STARTED:
- break;
- default:
- llassert(false);
- break;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case PAUSED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ break;
+ default:
+ llassert(false);
+ break;
+ }
}
void LLStopWatchControlsMixinCommon::restart()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch (mPlayState)
- {
- case STOPPED:
- handleReset();
- handleStart();
- mPlayState = STARTED;
- break;
- case PAUSED:
- handleReset();
- handleStart();
- mPlayState = STARTED;
- break;
- case STARTED:
- handleReset();
- break;
- default:
- llassert(false);
- break;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleReset();
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case PAUSED:
+ handleReset();
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ handleReset();
+ break;
+ default:
+ llassert(false);
+ break;
+ }
}
void LLStopWatchControlsMixinCommon::reset()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- handleReset();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ handleReset();
}
void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state )
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- switch(state)
- {
- case STOPPED:
- stop();
- break;
- case PAUSED:
- pause();
- break;
- case STARTED:
- start();
- break;
- default:
- llassert(false);
- break;
- }
-
- mPlayState = state;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ switch(state)
+ {
+ case STOPPED:
+ stop();
+ break;
+ case PAUSED:
+ pause();
+ break;
+ case STARTED:
+ start();
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+
+ mPlayState = state;
}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 61b9096ae2..985f06cd59 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -38,680 +38,680 @@
class LLStopWatchControlsMixinCommon
{
public:
- virtual ~LLStopWatchControlsMixinCommon() {}
-
- enum EPlayState
- {
- STOPPED,
- PAUSED,
- STARTED
- };
-
- void start(); // moves to started state, resetting if stopped
- void stop(); // moves to stopped state
- void pause(); // moves to paused state, unless stopped
- void unpause(); // moves to started state if paused
- void resume(); // moves to started state, without resetting
- void restart(); // moves to started state, always resetting
- void reset(); // resets
-
- bool isStarted() const { return mPlayState == STARTED; }
- bool isPaused() const { return mPlayState == PAUSED; }
- bool isStopped() const { return mPlayState == STOPPED; }
-
- EPlayState getPlayState() const { return mPlayState; }
- // force play state to specific value by calling appropriate handle* methods
- void setPlayState(EPlayState state);
+ virtual ~LLStopWatchControlsMixinCommon() {}
+
+ enum EPlayState
+ {
+ STOPPED,
+ PAUSED,
+ STARTED
+ };
+
+ void start(); // moves to started state, resetting if stopped
+ void stop(); // moves to stopped state
+ void pause(); // moves to paused state, unless stopped
+ void unpause(); // moves to started state if paused
+ void resume(); // moves to started state, without resetting
+ void restart(); // moves to started state, always resetting
+ void reset(); // resets
+
+ bool isStarted() const { return mPlayState == STARTED; }
+ bool isPaused() const { return mPlayState == PAUSED; }
+ bool isStopped() const { return mPlayState == STOPPED; }
+
+ EPlayState getPlayState() const { return mPlayState; }
+ // force play state to specific value by calling appropriate handle* methods
+ void setPlayState(EPlayState state);
protected:
- LLStopWatchControlsMixinCommon()
- : mPlayState(STOPPED)
- {}
+ LLStopWatchControlsMixinCommon()
+ : mPlayState(STOPPED)
+ {}
private:
- // override these methods to provide started/stopped semantics
+ // override these methods to provide started/stopped semantics
- // activate behavior (without reset)
- virtual void handleStart() = 0;
- // deactivate behavior
- virtual void handleStop() = 0;
- // clear accumulated state, may be called while started
- virtual void handleReset() = 0;
+ // activate behavior (without reset)
+ virtual void handleStart() = 0;
+ // deactivate behavior
+ virtual void handleStop() = 0;
+ // clear accumulated state, may be called while started
+ virtual void handleReset() = 0;
- EPlayState mPlayState;
+ EPlayState mPlayState;
};
template<typename DERIVED>
class LLStopWatchControlsMixin
-: public LLStopWatchControlsMixinCommon
+: public LLStopWatchControlsMixinCommon
{
public:
- typedef LLStopWatchControlsMixin<DERIVED> self_t;
- virtual void splitTo(DERIVED& other)
- {
- EPlayState play_state = getPlayState();
- stop();
- other.reset();
+ typedef LLStopWatchControlsMixin<DERIVED> self_t;
+ virtual void splitTo(DERIVED& other)
+ {
+ EPlayState play_state = getPlayState();
+ stop();
+ other.reset();
- handleSplitTo(other);
+ handleSplitTo(other);
- other.setPlayState(play_state);
- }
+ other.setPlayState(play_state);
+ }
- virtual void splitFrom(DERIVED& other)
- {
- static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this));
- }
+ virtual void splitFrom(DERIVED& other)
+ {
+ static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this));
+ }
private:
- self_t& operator = (const self_t& other)
- {
- // don't do anything, derived class must implement logic
- }
-
- // atomically stop this object while starting the other
- // no data can be missed in between stop and start
- virtual void handleSplitTo(DERIVED& other) {};
+ self_t& operator = (const self_t& other)
+ {
+ // don't do anything, derived class must implement logic
+ }
+
+ // atomically stop this object while starting the other
+ // no data can be missed in between stop and start
+ virtual void handleSplitTo(DERIVED& other) {};
};
namespace LLTrace
{
- template<typename T>
- class StatType;
-
- template<typename T>
- class CountStatHandle;
-
- template<typename T>
- class SampleStatHandle;
-
- template<typename T>
- class EventStatHandle;
-
- template<typename T>
- struct RelatedTypes
- {
- typedef F64 fractional_t;
- typedef T sum_t;
- };
-
- template<typename T, typename UNIT_T>
- struct RelatedTypes<LLUnit<T, UNIT_T> >
- {
- typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t;
- typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t;
- };
-
- template<>
- struct RelatedTypes<bool>
- {
- typedef F64 fractional_t;
- typedef S32 sum_t;
- };
-
- class Recording
- : public LLStopWatchControlsMixin<Recording>
- {
- public:
- Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED);
-
- Recording(const Recording& other);
- ~Recording();
-
- Recording& operator = (const Recording& other);
-
- // accumulate data from subsequent, non-overlapping recording
- void appendRecording(Recording& other);
-
- // grab latest recorded data
- void update();
-
- // ensure that buffers are exclusively owned by this recording
- void makeUnique() { mBuffers.makeUnique(); }
-
- // Timer accessors
- bool hasValue(const StatType<TimeBlockAccumulator>& stat);
- F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat);
- F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
- S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
-
- F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat);
- F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
- F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
-
- // CountStatHandle accessors
- bool hasValue(const StatType<CountAccumulator>& stat);
- F64 getSum(const StatType<CountAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat));
- }
-
- F64 getPerSec(const StatType<CountAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat));
- }
-
- S32 getSampleCount(const StatType<CountAccumulator>& stat);
-
-
- // SampleStatHandle accessors
- bool hasValue(const StatType<SampleAccumulator>& stat);
-
- F64 getMin(const StatType<SampleAccumulator>& stat);
- template <typename T>
- T getMin(const SampleStatHandle<T>& stat)
- {
- return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat));
- }
-
- F64 getMax(const StatType<SampleAccumulator>& stat);
- template <typename T>
- T getMax(const SampleStatHandle<T>& stat)
- {
- return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat));
- }
-
- F64 getMean(const StatType<SampleAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat));
- }
-
- F64 getStandardDeviation(const StatType<SampleAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat));
- }
-
- F64 getLastValue(const StatType<SampleAccumulator>& stat);
- template <typename T>
- T getLastValue(const SampleStatHandle<T>& stat)
- {
- return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat));
- }
-
- S32 getSampleCount(const StatType<SampleAccumulator>& stat);
-
- // EventStatHandle accessors
- bool hasValue(const StatType<EventAccumulator>& stat);
-
- F64 getSum(const StatType<EventAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat));
- }
-
- F64 getMin(const StatType<EventAccumulator>& stat);
- template <typename T>
- T getMin(const EventStatHandle<T>& stat)
- {
- return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat));
- }
-
- F64 getMax(const StatType<EventAccumulator>& stat);
- template <typename T>
- T getMax(const EventStatHandle<T>& stat)
- {
- return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat));
- }
-
- F64 getMean(const StatType<EventAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat));
- }
-
- F64 getStandardDeviation(const StatType<EventAccumulator>& stat);
- template <typename T>
- typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat)
- {
- return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat));
- }
-
- F64 getLastValue(const StatType<EventAccumulator>& stat);
- template <typename T>
- T getLastValue(const EventStatHandle<T>& stat)
- {
- return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat));
- }
-
- S32 getSampleCount(const StatType<EventAccumulator>& stat);
-
- F64Seconds getDuration() const { return mElapsedSeconds; }
-
- protected:
- friend class ThreadRecorder;
-
- // implementation for LLStopWatchControlsMixin
- /*virtual*/ void handleStart();
- /*virtual*/ void handleStop();
- /*virtual*/ void handleReset();
- /*virtual*/ void handleSplitTo(Recording& other);
-
- // returns data for current thread
- class ThreadRecorder* getThreadRecorder();
-
- LLTimer mSamplingTimer;
- F64Seconds mElapsedSeconds;
- LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers;
- AccumulatorBufferGroup* mActiveBuffers;
-
- };
-
- class LL_COMMON_API PeriodicRecording
- : public LLStopWatchControlsMixin<PeriodicRecording>
- {
- public:
- PeriodicRecording(size_t num_periods, EPlayState state = STOPPED);
- ~PeriodicRecording();
-
- void nextPeriod();
- auto getNumRecordedPeriods()
- {
- // current period counts if not active
- return mNumRecordedPeriods + (isStarted() ? 0 : 1);
- }
-
- F64Seconds getDuration() const;
-
- void appendPeriodicRecording(PeriodicRecording& other);
- void appendRecording(Recording& recording);
- Recording& getLastRecording();
- const Recording& getLastRecording() const;
- Recording& getCurRecording();
- const Recording& getCurRecording() const;
- Recording& getPrevRecording(size_t offset);
- const Recording& getPrevRecording(size_t offset) const;
- Recording snapshotCurRecording() const;
-
- template <typename T>
- auto getSampleCount(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- size_t num_samples = 0;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- num_samples += recording.getSampleCount(stat);
- }
- return num_samples;
- }
-
- //
- // PERIODIC MIN
- //
-
- // catch all for stats that have a defined sum
- template <typename T>
- typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- bool has_value = false;
- typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max());
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- min_val = llmin(min_val, recording.getSum(stat));
- has_value = true;
- }
- }
-
- return has_value
- ? min_val
- : T::getDefaultValue();
- }
-
- template<typename T>
- T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
- }
-
- template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- min_val = llmin(min_val, recording.getPerSec(stat));
- }
- return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val;
- }
-
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
-
- //
- // PERIODIC MAX
- //
-
- // catch all for stats that have a defined sum
- template <typename T>
- typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- bool has_value = false;
- typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min());
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.hasValue(stat))
- {
- max_val = llmax(max_val, recording.getSum(stat));
- has_value = true;
- }
- }
-
- return has_value
- ? max_val
- : T::getDefaultValue();
- }
-
- template<typename T>
- T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
- }
-
- template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- F64 max_val = std::numeric_limits<F64>::min();
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- max_val = llmax(max_val, recording.getPerSec(stat));
- }
- return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val;
- }
-
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
-
- //
- // PERIODIC MEAN
- //
-
- // catch all for stats that have a defined sum
- template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
-
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.getDuration() > (F32Seconds)0.f)
- {
- mean += recording.getSum(stat);
- }
- }
- return (num_periods
- ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
- : typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
- }
-
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
- F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
- }
-
- template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
-
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.getDuration() > (F32Seconds)0.f)
- {
- mean += recording.getPerSec(stat);
- }
- }
-
- return (num_periods
- ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
- : typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
- }
-
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
-
- template <typename T>
- typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- num_periods = llmin(num_periods, getNumRecordedPeriods());
-
- std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
- for (size_t i = 1; i <= num_periods; i++)
- {
- Recording& recording = getPrevRecording(i);
- if (recording.getDuration() > (F32Seconds)0.f)
- {
- buf.push_back(recording.getPerSec(stat));
- }
- }
- std::sort(buf.begin(), buf.end());
-
- return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
- }
-
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
- }
-
- //
- // PERIODIC STANDARD DEVIATION
- //
-
- F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
-
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
- }
-
- F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
- template<typename T>
- typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
- }
-
- private:
- // implementation for LLStopWatchControlsMixin
- /*virtual*/ void handleStart();
- /*virtual*/ void handleStop();
- /*virtual*/ void handleReset();
- /*virtual*/ void handleSplitTo(PeriodicRecording& other);
-
- // helper methods for wraparound ring-buffer arithmetic
- inline
- size_t wrapi(size_t i) const
- {
- return i % mRecordingPeriods.size();
- }
-
- inline
- size_t nexti(size_t i, size_t offset=1) const
- {
- return wrapi(i + offset);
- }
-
- inline
- size_t previ(size_t i, size_t offset=1) const
- {
- auto num_periods = mRecordingPeriods.size();
- // constrain offset
- offset = llclamp(offset, 0, num_periods - 1);
- // add size() so expression can't go (unsigned) "negative"
- return wrapi(i + num_periods - offset);
- }
-
- inline
- void inci(size_t& i, size_t offset=1) const
- {
- i = nexti(i, offset);
- }
-
- private:
- std::vector<Recording> mRecordingPeriods;
- const bool mAutoResize;
- size_t mCurPeriod;
- size_t mNumRecordedPeriods;
- };
-
- PeriodicRecording& get_frame_recording();
-
- class ExtendableRecording
- : public LLStopWatchControlsMixin<ExtendableRecording>
- {
- public:
- void extend();
-
- Recording& getAcceptedRecording() { return mAcceptedRecording; }
- const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
-
- Recording& getPotentialRecording() { return mPotentialRecording; }
- const Recording& getPotentialRecording() const { return mPotentialRecording;}
-
- private:
- // implementation for LLStopWatchControlsMixin
- /*virtual*/ void handleStart();
- /*virtual*/ void handleStop();
- /*virtual*/ void handleReset();
- /*virtual*/ void handleSplitTo(ExtendableRecording& other);
-
- private:
- Recording mAcceptedRecording;
- Recording mPotentialRecording;
- };
-
- class ExtendablePeriodicRecording
- : public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
- {
- public:
- ExtendablePeriodicRecording();
- void extend();
-
- PeriodicRecording& getResults() { return mAcceptedRecording; }
- const PeriodicRecording& getResults() const {return mAcceptedRecording;}
-
- void nextPeriod() { mPotentialRecording.nextPeriod(); }
-
- private:
- // implementation for LLStopWatchControlsMixin
- /*virtual*/ void handleStart();
- /*virtual*/ void handleStop();
- /*virtual*/ void handleReset();
- /*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other);
-
- private:
- PeriodicRecording mAcceptedRecording;
- PeriodicRecording mPotentialRecording;
- };
+ template<typename T>
+ class StatType;
+
+ template<typename T>
+ class CountStatHandle;
+
+ template<typename T>
+ class SampleStatHandle;
+
+ template<typename T>
+ class EventStatHandle;
+
+ template<typename T>
+ struct RelatedTypes
+ {
+ typedef F64 fractional_t;
+ typedef T sum_t;
+ };
+
+ template<typename T, typename UNIT_T>
+ struct RelatedTypes<LLUnit<T, UNIT_T> >
+ {
+ typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t;
+ typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t;
+ };
+
+ template<>
+ struct RelatedTypes<bool>
+ {
+ typedef F64 fractional_t;
+ typedef S32 sum_t;
+ };
+
+ class Recording
+ : public LLStopWatchControlsMixin<Recording>
+ {
+ public:
+ Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED);
+
+ Recording(const Recording& other);
+ ~Recording();
+
+ Recording& operator = (const Recording& other);
+
+ // accumulate data from subsequent, non-overlapping recording
+ void appendRecording(Recording& other);
+
+ // grab latest recorded data
+ void update();
+
+ // ensure that buffers are exclusively owned by this recording
+ void makeUnique() { mBuffers.makeUnique(); }
+
+ // Timer accessors
+ bool hasValue(const StatType<TimeBlockAccumulator>& stat);
+ F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat);
+ F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+ S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
+
+ F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat);
+ F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+ F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
+
+ // CountStatHandle accessors
+ bool hasValue(const StatType<CountAccumulator>& stat);
+ F64 getSum(const StatType<CountAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat));
+ }
+
+ F64 getPerSec(const StatType<CountAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat));
+ }
+
+ S32 getSampleCount(const StatType<CountAccumulator>& stat);
+
+
+ // SampleStatHandle accessors
+ bool hasValue(const StatType<SampleAccumulator>& stat);
+
+ F64 getMin(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ T getMin(const SampleStatHandle<T>& stat)
+ {
+ return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getMax(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ T getMax(const SampleStatHandle<T>& stat)
+ {
+ return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getMean(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getStandardDeviation(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getLastValue(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ T getLastValue(const SampleStatHandle<T>& stat)
+ {
+ return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ S32 getSampleCount(const StatType<SampleAccumulator>& stat);
+
+ // EventStatHandle accessors
+ bool hasValue(const StatType<EventAccumulator>& stat);
+
+ F64 getSum(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getMin(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ T getMin(const EventStatHandle<T>& stat)
+ {
+ return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getMax(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ T getMax(const EventStatHandle<T>& stat)
+ {
+ return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getMean(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getStandardDeviation(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getLastValue(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ T getLastValue(const EventStatHandle<T>& stat)
+ {
+ return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ S32 getSampleCount(const StatType<EventAccumulator>& stat);
+
+ F64Seconds getDuration() const { return mElapsedSeconds; }
+
+ protected:
+ friend class ThreadRecorder;
+
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(Recording& other);
+
+ // returns data for current thread
+ class ThreadRecorder* getThreadRecorder();
+
+ LLTimer mSamplingTimer;
+ F64Seconds mElapsedSeconds;
+ LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers;
+ AccumulatorBufferGroup* mActiveBuffers;
+
+ };
+
+ class LL_COMMON_API PeriodicRecording
+ : public LLStopWatchControlsMixin<PeriodicRecording>
+ {
+ public:
+ PeriodicRecording(size_t num_periods, EPlayState state = STOPPED);
+ ~PeriodicRecording();
+
+ void nextPeriod();
+ auto getNumRecordedPeriods()
+ {
+ // current period counts if not active
+ return mNumRecordedPeriods + (isStarted() ? 0 : 1);
+ }
+
+ F64Seconds getDuration() const;
+
+ void appendPeriodicRecording(PeriodicRecording& other);
+ void appendRecording(Recording& recording);
+ Recording& getLastRecording();
+ const Recording& getLastRecording() const;
+ Recording& getCurRecording();
+ const Recording& getCurRecording() const;
+ Recording& getPrevRecording(size_t offset);
+ const Recording& getPrevRecording(size_t offset) const;
+ Recording snapshotCurRecording() const;
+
+ template <typename T>
+ auto getSampleCount(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ size_t num_samples = 0;
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ num_samples += recording.getSampleCount(stat);
+ }
+ return num_samples;
+ }
+
+ //
+ // PERIODIC MIN
+ //
+
+ // catch all for stats that have a defined sum
+ template <typename T>
+ typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max());
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ min_val = llmin(min_val, recording.getSum(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? min_val
+ : T::getDefaultValue();
+ }
+
+ template<typename T>
+ T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ min_val = llmin(min_val, recording.getPerSec(stat));
+ }
+ return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val;
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ //
+ // PERIODIC MAX
+ //
+
+ // catch all for stats that have a defined sum
+ template <typename T>
+ typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min());
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ max_val = llmax(max_val, recording.getSum(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? max_val
+ : T::getDefaultValue();
+ }
+
+ template<typename T>
+ T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64 max_val = std::numeric_limits<F64>::min();
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ max_val = llmax(max_val, recording.getPerSec(stat));
+ }
+ return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val;
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ //
+ // PERIODIC MEAN
+ //
+
+ // catch all for stats that have a defined sum
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
+
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.getDuration() > (F32Seconds)0.f)
+ {
+ mean += recording.getSum(stat);
+ }
+ }
+ return (num_periods
+ ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+ : typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+ F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
+
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.getDuration() > (F32Seconds)0.f)
+ {
+ mean += recording.getPerSec(stat);
+ }
+ }
+
+ return (num_periods
+ ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+ : typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
+ for (size_t i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.getDuration() > (F32Seconds)0.f)
+ {
+ buf.push_back(recording.getPerSec(stat));
+ }
+ }
+ std::sort(buf.begin(), buf.end());
+
+ return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ //
+ // PERIODIC STANDARD DEVIATION
+ //
+
+ F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
+ return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ private:
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(PeriodicRecording& other);
+
+ // helper methods for wraparound ring-buffer arithmetic
+ inline
+ size_t wrapi(size_t i) const
+ {
+ return i % mRecordingPeriods.size();
+ }
+
+ inline
+ size_t nexti(size_t i, size_t offset=1) const
+ {
+ return wrapi(i + offset);
+ }
+
+ inline
+ size_t previ(size_t i, size_t offset=1) const
+ {
+ auto num_periods = mRecordingPeriods.size();
+ // constrain offset
+ offset = llclamp(offset, 0, num_periods - 1);
+ // add size() so expression can't go (unsigned) "negative"
+ return wrapi(i + num_periods - offset);
+ }
+
+ inline
+ void inci(size_t& i, size_t offset=1) const
+ {
+ i = nexti(i, offset);
+ }
+
+ private:
+ std::vector<Recording> mRecordingPeriods;
+ const bool mAutoResize;
+ size_t mCurPeriod;
+ size_t mNumRecordedPeriods;
+ };
+
+ PeriodicRecording& get_frame_recording();
+
+ class ExtendableRecording
+ : public LLStopWatchControlsMixin<ExtendableRecording>
+ {
+ public:
+ void extend();
+
+ Recording& getAcceptedRecording() { return mAcceptedRecording; }
+ const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
+
+ Recording& getPotentialRecording() { return mPotentialRecording; }
+ const Recording& getPotentialRecording() const { return mPotentialRecording;}
+
+ private:
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(ExtendableRecording& other);
+
+ private:
+ Recording mAcceptedRecording;
+ Recording mPotentialRecording;
+ };
+
+ class ExtendablePeriodicRecording
+ : public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
+ {
+ public:
+ ExtendablePeriodicRecording();
+ void extend();
+
+ PeriodicRecording& getResults() { return mAcceptedRecording; }
+ const PeriodicRecording& getResults() const {return mAcceptedRecording;}
+
+ void nextPeriod() { mPotentialRecording.nextPeriod(); }
+
+ private:
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other);
+
+ private:
+ PeriodicRecording mAcceptedRecording;
+ PeriodicRecording mPotentialRecording;
+ };
}
#endif // LL_LLTRACERECORDING_H
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 914bfb55dc..be3e585ef8 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file lltracethreadrecorder.cpp
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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,203 +41,203 @@ static ThreadRecorder* sMasterThreadRecorder = NULL;
///////////////////////////////////////////////////////////////////////
ThreadRecorder::ThreadRecorder()
-: mParentRecorder(NULL)
+: mParentRecorder(NULL)
{
- init();
+ init();
}
void ThreadRecorder::init()
{
#if LL_TRACE_ENABLED
- LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
- //NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
- set_thread_recorder(this);
- BlockTimerStatHandle& root_time_block = BlockTimer::getRootTimeBlock();
+ LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
+ //NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
+ set_thread_recorder(this);
+ BlockTimerStatHandle& root_time_block = BlockTimer::getRootTimeBlock();
- BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
- timer_stack->mTimeBlock = &root_time_block;
- timer_stack->mActiveTimer = NULL;
+ BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ timer_stack->mTimeBlock = &root_time_block;
+ timer_stack->mActiveTimer = NULL;
- mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
+ mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
- mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
+ mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
- activate(&mThreadRecordingBuffers);
+ activate(&mThreadRecordingBuffers);
- // initialize time block parent pointers
- for (auto& base : BlockTimerStatHandle::instance_snapshot())
- {
- // because of indirect derivation from LLInstanceTracker, have to downcast
- BlockTimerStatHandle& time_block = static_cast<BlockTimerStatHandle&>(base);
- TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[time_block.getIndex()];
- tree_node.mBlock = &time_block;
- tree_node.mParent = &root_time_block;
+ // initialize time block parent pointers
+ for (auto& base : BlockTimerStatHandle::instance_snapshot())
+ {
+ // because of indirect derivation from LLInstanceTracker, have to downcast
+ BlockTimerStatHandle& time_block = static_cast<BlockTimerStatHandle&>(base);
+ TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[time_block.getIndex()];
+ tree_node.mBlock = &time_block;
+ tree_node.mParent = &root_time_block;
- time_block.getCurrentAccumulator().mParent = &root_time_block;
- }
+ time_block.getCurrentAccumulator().mParent = &root_time_block;
+ }
- mRootTimer = new BlockTimer(root_time_block);
- timer_stack->mActiveTimer = mRootTimer;
+ mRootTimer = new BlockTimer(root_time_block);
+ timer_stack->mActiveTimer = mRootTimer;
- BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
+ BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
- //claim_alloc(gTraceMemStat, this);
- //claim_alloc(gTraceMemStat, mRootTimer);
- //claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
+ //claim_alloc(gTraceMemStat, this);
+ //claim_alloc(gTraceMemStat, mRootTimer);
+ //claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
#endif
}
ThreadRecorder::ThreadRecorder( ThreadRecorder& parent )
-: mParentRecorder(&parent)
+: mParentRecorder(&parent)
{
- init();
- mParentRecorder->addChildRecorder(this);
+ init();
+ mParentRecorder->addChildRecorder(this);
}
ThreadRecorder::~ThreadRecorder()
{
#if LL_TRACE_ENABLED
- LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
+ LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
- //disclaim_alloc(gTraceMemStat, this);
- //disclaim_alloc(gTraceMemStat, sizeof(BlockTimer));
- //disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
+ //disclaim_alloc(gTraceMemStat, this);
+ //disclaim_alloc(gTraceMemStat, sizeof(BlockTimer));
+ //disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
- deactivate(&mThreadRecordingBuffers);
+ deactivate(&mThreadRecordingBuffers);
- delete mRootTimer;
+ delete mRootTimer;
- if (!mActiveRecordings.empty())
- {
- std::for_each(mActiveRecordings.begin(), mActiveRecordings.end(), DeletePointer());
- mActiveRecordings.clear();
- }
+ if (!mActiveRecordings.empty())
+ {
+ std::for_each(mActiveRecordings.begin(), mActiveRecordings.end(), DeletePointer());
+ mActiveRecordings.clear();
+ }
- set_thread_recorder(NULL);
- delete[] mTimeBlockTreeNodes;
+ set_thread_recorder(NULL);
+ delete[] mTimeBlockTreeNodes;
- if (mParentRecorder)
- {
- mParentRecorder->removeChildRecorder(this);
- }
+ if (mParentRecorder)
+ {
+ mParentRecorder->removeChildRecorder(this);
+ }
#endif
}
TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( size_t index )
{
#if LL_TRACE_ENABLED
- if (0 <= index && index < mNumTimeBlockTreeNodes)
- {
- return &mTimeBlockTreeNodes[index];
- }
+ if (0 <= index && index < mNumTimeBlockTreeNodes)
+ {
+ return &mTimeBlockTreeNodes[index];
+ }
#endif
- return NULL;
+ return NULL;
}
AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* recording)
{
#if LL_TRACE_ENABLED
- ActiveRecording* active_recording = new ActiveRecording(recording);
- if (!mActiveRecordings.empty())
- {
- AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
- prev_active_recording.sync();
- BlockTimer::updateTimes();
- prev_active_recording.handOffTo(active_recording->mPartialRecording);
- }
- mActiveRecordings.push_back(active_recording);
-
- mActiveRecordings.back()->mPartialRecording.makeCurrent();
- return &active_recording->mPartialRecording;
+ ActiveRecording* active_recording = new ActiveRecording(recording);
+ if (!mActiveRecordings.empty())
+ {
+ AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
+ prev_active_recording.sync();
+ BlockTimer::updateTimes();
+ prev_active_recording.handOffTo(active_recording->mPartialRecording);
+ }
+ mActiveRecordings.push_back(active_recording);
+
+ mActiveRecordings.back()->mPartialRecording.makeCurrent();
+ return &active_recording->mPartialRecording;
#else
- return NULL;
+ return NULL;
#endif
}
ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
{
#if LL_TRACE_ENABLED
- if (mActiveRecordings.empty()) return mActiveRecordings.end();
-
- mActiveRecordings.back()->mPartialRecording.sync();
- BlockTimer::updateTimes();
-
- active_recording_list_t::reverse_iterator it, end_it;
- for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
- it != end_it;
- ++it)
- {
- ActiveRecording* cur_recording = *it;
-
- active_recording_list_t::reverse_iterator next_it = it;
- ++next_it;
-
- // if we have another recording further down in the stack...
- if (next_it != mActiveRecordings.rend())
- {
- // ...push our gathered data down to it
- (*next_it)->mPartialRecording.append(cur_recording->mPartialRecording);
- }
-
- // copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
- cur_recording->movePartialToTarget();
-
- if (cur_recording->mTargetRecording == recording)
- {
- // found the recording, so return it
- break;
- }
- }
-
- if (it == end_it)
- {
- LL_WARNS() << "Recording not active on this thread" << LL_ENDL;
- }
-
- return (++it).base();
+ if (mActiveRecordings.empty()) return mActiveRecordings.end();
+
+ mActiveRecordings.back()->mPartialRecording.sync();
+ BlockTimer::updateTimes();
+
+ active_recording_list_t::reverse_iterator it, end_it;
+ for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
+ it != end_it;
+ ++it)
+ {
+ ActiveRecording* cur_recording = *it;
+
+ active_recording_list_t::reverse_iterator next_it = it;
+ ++next_it;
+
+ // if we have another recording further down in the stack...
+ if (next_it != mActiveRecordings.rend())
+ {
+ // ...push our gathered data down to it
+ (*next_it)->mPartialRecording.append(cur_recording->mPartialRecording);
+ }
+
+ // copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
+ cur_recording->movePartialToTarget();
+
+ if (cur_recording->mTargetRecording == recording)
+ {
+ // found the recording, so return it
+ break;
+ }
+ }
+
+ if (it == end_it)
+ {
+ LL_WARNS() << "Recording not active on this thread" << LL_ENDL;
+ }
+
+ return (++it).base();
#else
- return ThreadRecorder::active_recording_list_t::iterator();
+ return ThreadRecorder::active_recording_list_t::iterator();
#endif
}
void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
{
#if LL_TRACE_ENABLED
- active_recording_list_t::iterator recording_it = bringUpToDate(recording);
- // this method should only be called on a thread where the recorder is active
- llassert_always(recording_it != mActiveRecordings.end());
-
- ActiveRecording* recording_to_remove = *recording_it;
- bool was_current = recording_to_remove->mPartialRecording.isCurrent();
- llassert(recording_to_remove->mTargetRecording == recording);
- mActiveRecordings.erase(recording_it);
- if (was_current)
- {
- if (mActiveRecordings.empty())
- {
- AccumulatorBufferGroup::clearCurrent();
- }
- else
- {
- mActiveRecordings.back()->mPartialRecording.makeCurrent();
- }
- }
- delete recording_to_remove;
+ active_recording_list_t::iterator recording_it = bringUpToDate(recording);
+ // this method should only be called on a thread where the recorder is active
+ llassert_always(recording_it != mActiveRecordings.end());
+
+ ActiveRecording* recording_to_remove = *recording_it;
+ bool was_current = recording_to_remove->mPartialRecording.isCurrent();
+ llassert(recording_to_remove->mTargetRecording == recording);
+ mActiveRecordings.erase(recording_it);
+ if (was_current)
+ {
+ if (mActiveRecordings.empty())
+ {
+ AccumulatorBufferGroup::clearCurrent();
+ }
+ else
+ {
+ mActiveRecordings.back()->mPartialRecording.makeCurrent();
+ }
+ }
+ delete recording_to_remove;
#endif
}
-ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target )
-: mTargetRecording(target)
+ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target )
+: mTargetRecording(target)
{}
void ThreadRecorder::ActiveRecording::movePartialToTarget()
{
#if LL_TRACE_ENABLED
- mTargetRecording->append(mPartialRecording);
- // reset based on self to keep history
- mPartialRecording.reset(&mPartialRecording);
+ mTargetRecording->append(mPartialRecording);
+ // reset based on self to keep history
+ mPartialRecording.reset(&mPartialRecording);
#endif
}
@@ -246,30 +246,30 @@ void ThreadRecorder::ActiveRecording::movePartialToTarget()
void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
{
#if LL_TRACE_ENABLED
- { LLMutexLock lock(&mChildListMutex);
- mChildThreadRecorders.push_back(child);
- }
+ { LLMutexLock lock(&mChildListMutex);
+ mChildThreadRecorders.push_back(child);
+ }
#endif
}
// called by child thread
void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
-{
+{
#if LL_TRACE_ENABLED
- { LLMutexLock lock(&mChildListMutex);
- mChildThreadRecorders.remove(child);
- }
+ { LLMutexLock lock(&mChildListMutex);
+ mChildThreadRecorders.remove(child);
+ }
#endif
}
void ThreadRecorder::pushToParent()
{
#if LL_TRACE_ENABLED
- { LLMutexLock lock(&mSharedRecordingMutex);
- LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
- mSharedRecordingBuffers.append(mThreadRecordingBuffers);
- mThreadRecordingBuffers.reset();
- }
+ { LLMutexLock lock(&mSharedRecordingMutex);
+ LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
+ mSharedRecordingBuffers.append(mThreadRecordingBuffers);
+ mThreadRecordingBuffers.reset();
+ }
#endif
}
@@ -278,48 +278,48 @@ void ThreadRecorder::pullFromChildren()
{
#if LL_TRACE_ENABLED
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
- if (mActiveRecordings.empty()) return;
+ if (mActiveRecordings.empty()) return;
- { LLMutexLock lock(&mChildListMutex);
+ { LLMutexLock lock(&mChildListMutex);
- AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
- target_recording_buffers.sync();
- for (LLTrace::ThreadRecorder* rec : mChildThreadRecorders)
- { LLMutexLock lock(&(rec->mSharedRecordingMutex));
+ AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
+ target_recording_buffers.sync();
+ for (LLTrace::ThreadRecorder* rec : mChildThreadRecorders)
+ { LLMutexLock lock(&(rec->mSharedRecordingMutex));
- target_recording_buffers.merge(rec->mSharedRecordingBuffers);
- rec->mSharedRecordingBuffers.reset();
- }
- }
+ target_recording_buffers.merge(rec->mSharedRecordingBuffers);
+ rec->mSharedRecordingBuffers.reset();
+ }
+ }
#endif
}
void set_master_thread_recorder( ThreadRecorder* recorder )
{
- sMasterThreadRecorder = recorder;
+ sMasterThreadRecorder = recorder;
}
ThreadRecorder* get_master_thread_recorder()
{
- return sMasterThreadRecorder;
+ return sMasterThreadRecorder;
}
ThreadRecorder*& get_thread_recorder_ptr()
{
- static thread_local ThreadRecorder* s_thread_recorder;
- return s_thread_recorder;
+ static thread_local ThreadRecorder* s_thread_recorder;
+ return s_thread_recorder;
}
ThreadRecorder* get_thread_recorder()
{
- return get_thread_recorder_ptr();
+ return get_thread_recorder_ptr();
}
void set_thread_recorder( ThreadRecorder* recorder )
{
- get_thread_recorder_ptr() = recorder;
+ get_thread_recorder_ptr() = recorder;
}
}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 8ee6729ac6..e3eadfb0bd 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltrace.h
* @brief Runtime statistics accumulation.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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,67 +35,67 @@
namespace LLTrace
{
- class LL_COMMON_API ThreadRecorder
- {
- protected:
- struct ActiveRecording;
- typedef std::vector<ActiveRecording*> active_recording_list_t;
- public:
- ThreadRecorder();
- explicit ThreadRecorder(ThreadRecorder& parent);
+ class LL_COMMON_API ThreadRecorder
+ {
+ protected:
+ struct ActiveRecording;
+ typedef std::vector<ActiveRecording*> active_recording_list_t;
+ public:
+ ThreadRecorder();
+ explicit ThreadRecorder(ThreadRecorder& parent);
- ~ThreadRecorder();
+ ~ThreadRecorder();
- AccumulatorBufferGroup* activate(AccumulatorBufferGroup* recording);
- void deactivate(AccumulatorBufferGroup* recording);
- active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording);
+ AccumulatorBufferGroup* activate(AccumulatorBufferGroup* recording);
+ void deactivate(AccumulatorBufferGroup* recording);
+ active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording);
- void addChildRecorder(class ThreadRecorder* child);
- void removeChildRecorder(class ThreadRecorder* child);
+ void addChildRecorder(class ThreadRecorder* child);
+ void removeChildRecorder(class ThreadRecorder* child);
- // call this periodically to gather stats data from child threads
- void pullFromChildren();
- void pushToParent();
+ // call this periodically to gather stats data from child threads
+ void pullFromChildren();
+ void pushToParent();
- TimeBlockTreeNode* getTimeBlockTreeNode(size_t index);
+ TimeBlockTreeNode* getTimeBlockTreeNode(size_t index);
- protected:
- void init();
+ protected:
+ void init();
- protected:
- struct ActiveRecording
- {
- ActiveRecording(AccumulatorBufferGroup* target);
+ protected:
+ struct ActiveRecording
+ {
+ ActiveRecording(AccumulatorBufferGroup* target);
- AccumulatorBufferGroup* mTargetRecording;
- AccumulatorBufferGroup mPartialRecording;
+ AccumulatorBufferGroup* mTargetRecording;
+ AccumulatorBufferGroup mPartialRecording;
- void movePartialToTarget();
- };
+ void movePartialToTarget();
+ };
- AccumulatorBufferGroup mThreadRecordingBuffers;
+ AccumulatorBufferGroup mThreadRecordingBuffers;
- BlockTimerStackRecord mBlockTimerStackRecord;
- active_recording_list_t mActiveRecordings;
+ BlockTimerStackRecord mBlockTimerStackRecord;
+ active_recording_list_t mActiveRecordings;
- class BlockTimer* mRootTimer;
- TimeBlockTreeNode* mTimeBlockTreeNodes;
- size_t mNumTimeBlockTreeNodes;
- typedef std::list<class ThreadRecorder*> child_thread_recorder_list_t;
+ class BlockTimer* mRootTimer;
+ TimeBlockTreeNode* mTimeBlockTreeNodes;
+ size_t mNumTimeBlockTreeNodes;
+ typedef std::list<class ThreadRecorder*> child_thread_recorder_list_t;
- child_thread_recorder_list_t mChildThreadRecorders; // list of child thread recorders associated with this master
- LLMutex mChildListMutex; // protects access to child list
- LLMutex mSharedRecordingMutex;
- AccumulatorBufferGroup mSharedRecordingBuffers;
- ThreadRecorder* mParentRecorder;
+ child_thread_recorder_list_t mChildThreadRecorders; // list of child thread recorders associated with this master
+ LLMutex mChildListMutex; // protects access to child list
+ LLMutex mSharedRecordingMutex;
+ AccumulatorBufferGroup mSharedRecordingBuffers;
+ ThreadRecorder* mParentRecorder;
- };
+ };
- ThreadRecorder* get_thread_recorder();
- void set_thread_recorder(ThreadRecorder*);
+ ThreadRecorder* get_thread_recorder();
+ void set_thread_recorder(ThreadRecorder*);
- void set_master_thread_recorder(ThreadRecorder*);
- ThreadRecorder* get_master_thread_recorder();
+ void set_master_thread_recorder(ThreadRecorder*);
+ ThreadRecorder* get_master_thread_recorder();
}
#endif // LL_LLTRACETHREADRECORDER_H
diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h
index ba861ae70b..cef501b987 100644
--- a/indra/llcommon/lltreeiterators.h
+++ b/indra/llcommon/lltreeiterators.h
@@ -33,25 +33,25 @@
* child of its own. Child nodes with multiple parents will be visited
* once for each parent. Cycles in the graph will result in either an
* infinite loop or an out-of-memory crash. You Have Been Warned.
- *
+ *
* $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$
*/
@@ -338,9 +338,9 @@ public:
/// functors to extract the 'child begin' and 'child end' iterators from
/// each node.
LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc)
- : mBeginFunc(beginfunc),
- mEndFunc(endfunc),
- mSkipChildren(false)
+ : mBeginFunc(beginfunc),
+ mEndFunc(endfunc),
+ mSkipChildren(false)
{
// Only push back this node if it's non-NULL!
if (node)
@@ -364,13 +364,13 @@ private:
ptr_type current = mPending.back();
// Remove it from mPending so we don't process it again later
mPending.pop_back();
- if (!mSkipChildren)
- {
- // Add all its children to mPending
- addChildren(current);
- }
- // reset flag after each step
- mSkipChildren = false;
+ if (!mSkipChildren)
+ {
+ // Add all its children to mPending
+ addChildren(current);
+ }
+ // reset flag after each step
+ mSkipChildren = false;
}
/// equality
bool equal(const self_type& that) const { return this->mPending == that.mPending; }
@@ -400,7 +400,7 @@ private:
/// functor to extract end() child iterator
func_type mEndFunc;
/// flag which controls traversal of children (skip children of current node if true)
- bool mSkipChildren;
+ bool mSkipChildren;
};
/**
@@ -446,10 +446,10 @@ public:
/// functors to extract the 'child begin' and 'child end' iterators from
/// each node.
LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc)
- : mBeginFunc(beginfunc),
- mEndFunc(endfunc),
- mSkipAncestors(false)
- {
+ : mBeginFunc(beginfunc),
+ mEndFunc(endfunc),
+ mSkipAncestors(false)
+ {
if (! node)
return;
mPending.push_back(typename list_type::value_type(node, false));
@@ -478,24 +478,24 @@ private:
/// implement dereference/indirection operators
ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.back().first); }
- struct isOpen
- {
- bool operator()(const typename list_type::value_type& item)
- {
- return item.second;
- }
- };
+ struct isOpen
+ {
+ bool operator()(const typename list_type::value_type& item)
+ {
+ return item.second;
+ }
+ };
/// Call this each time we change mPending.back() -- that is, every time
/// we're about to change the value returned by dereference(). If we
/// haven't yet pushed the new node's children, do so now.
void makeCurrent()
{
- if (mSkipAncestors)
- {
- mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end());
- mSkipAncestors = false;
- }
+ if (mSkipAncestors)
+ {
+ mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end());
+ mSkipAncestors = false;
+ }
// Once we've popped the last node, this becomes a no-op.
if (mPending.empty())
@@ -536,13 +536,13 @@ private:
}
/// list of the nodes yet to be processed
- list_type mPending;
+ list_type mPending;
/// functor to extract begin() child iterator
- func_type mBeginFunc;
+ func_type mBeginFunc;
/// functor to extract end() child iterator
- func_type mEndFunc;
- /// flags logic to skip traversal of ancestors of current node
- bool mSkipAncestors;
+ func_type mEndFunc;
+ /// flags logic to skip traversal of ancestors of current node
+ bool mSkipAncestors;
};
/**
diff --git a/indra/llcommon/llunits.h b/indra/llcommon/llunits.h
index 0fcb8281a0..122d4557bf 100644
--- a/indra/llcommon/llunits.h
+++ b/indra/llcommon/llunits.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llunits.h
* @brief Unit definitions
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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$
*/
@@ -51,10 +51,10 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
namespace LLUnits
{
// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
-LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 );
-LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024);
-LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024);
-LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024);
+LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 );
+LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024);
+LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024);
+LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
@@ -65,12 +65,12 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
namespace LLUnits
{
LL_DECLARE_BASE_UNIT(Seconds, "s");
-LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60);
-LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60);
-LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24);
-LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000);
-LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000);
-LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000);
+LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60);
+LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60);
+LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24);
+LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000);
+LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000);
+LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
@@ -84,9 +84,9 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
namespace LLUnits
{
LL_DECLARE_BASE_UNIT(Meters, "m");
-LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000);
-LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
-LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000);
+LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000);
+LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
+LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index 81f244e422..83ce0d05a8 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llunit.h
* @brief Unit conversion classes
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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$
*/
@@ -32,122 +32,122 @@
#include "llerror.h"
//lightweight replacement of type traits for simple type equality check
-template<typename S, typename T>
+template<typename S, typename T>
struct LLIsSameType
{
- static const bool value = false;
+ static const bool value = false;
};
template<typename T>
struct LLIsSameType<T, T>
{
- static const bool value = true;
+ static const bool value = true;
};
// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
template<typename S, typename T>
struct LLResultTypeAdd
{
- typedef LL_TYPEOF(S() + T()) type_t;
+ typedef LL_TYPEOF(S() + T()) type_t;
};
template<typename S, typename T>
struct LLResultTypeSubtract
{
- typedef LL_TYPEOF(S() - T()) type_t;
+ typedef LL_TYPEOF(S() - T()) type_t;
};
template<typename S, typename T>
struct LLResultTypeMultiply
{
- typedef LL_TYPEOF(S() * T()) type_t;
+ typedef LL_TYPEOF(S() * T()) type_t;
};
template<typename S, typename T>
struct LLResultTypeDivide
{
- typedef LL_TYPEOF(S() / T(1)) type_t;
+ typedef LL_TYPEOF(S() / T(1)) type_t;
};
template<typename S, typename T>
struct LLResultTypePromote
{
- typedef LL_TYPEOF((true) ? S() : T()) type_t;
+ typedef LL_TYPEOF((true) ? S() : T()) type_t;
};
template<typename STORAGE_TYPE, typename UNITS>
struct LLUnit
{
- typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
- typedef STORAGE_TYPE storage_t;
- typedef void is_unit_t;
-
- // value initialization
- LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
- : mValue(value)
- {}
-
-
- LL_FORCE_INLINE static self_t convert(self_t v)
- {
- return v;
- }
-
- template<typename FROM_STORAGE_TYPE>
- LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)
- {
- self_t result;
- result.mValue = (STORAGE_TYPE)v.value();
- return result;
- }
-
- template<typename FROM_UNITS>
- LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v)
- {
- self_t result;
- STORAGE_TYPE divisor = ll_convert_units(v, result);
- result.mValue /= divisor;
- return result;
- }
-
- template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
- LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v)
- {
- typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
- LLUnit<result_storage_t, UNITS> result;
- result_storage_t divisor = ll_convert_units(v, result);
- result.value(result.value() / divisor);
- return self_t(result.value());
- }
-
-
- // unit initialization and conversion
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
- : mValue(convert(other).mValue)
- {}
-
- LL_FORCE_INLINE storage_t value() const
- {
- return mValue;
- }
-
- LL_FORCE_INLINE void value(const storage_t& value)
- {
- mValue = value;
- }
-
- template<typename NEW_UNITS>
- storage_t valueInUnits() const
- {
- return LLUnit<storage_t, NEW_UNITS>(*this).value();
- }
-
- template<typename NEW_UNITS>
- void valueInUnits(const storage_t& value) const
- {
- *this = LLUnit<storage_t, NEW_UNITS>(value);
- }
+ typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
+ typedef STORAGE_TYPE storage_t;
+ typedef void is_unit_t;
+
+ // value initialization
+ LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
+ : mValue(value)
+ {}
+
+
+ LL_FORCE_INLINE static self_t convert(self_t v)
+ {
+ return v;
+ }
+
+ template<typename FROM_STORAGE_TYPE>
+ LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)
+ {
+ self_t result;
+ result.mValue = (STORAGE_TYPE)v.value();
+ return result;
+ }
+
+ template<typename FROM_UNITS>
+ LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v)
+ {
+ self_t result;
+ STORAGE_TYPE divisor = ll_convert_units(v, result);
+ result.mValue /= divisor;
+ return result;
+ }
+
+ template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
+ LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v)
+ {
+ typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
+ LLUnit<result_storage_t, UNITS> result;
+ result_storage_t divisor = ll_convert_units(v, result);
+ result.value(result.value() / divisor);
+ return self_t(result.value());
+ }
+
+
+ // unit initialization and conversion
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ : mValue(convert(other).mValue)
+ {}
+
+ LL_FORCE_INLINE storage_t value() const
+ {
+ return mValue;
+ }
+
+ LL_FORCE_INLINE void value(const storage_t& value)
+ {
+ mValue = value;
+ }
+
+ template<typename NEW_UNITS>
+ storage_t valueInUnits() const
+ {
+ return LLUnit<storage_t, NEW_UNITS>(*this).value();
+ }
+
+ template<typename NEW_UNITS>
+ void valueInUnits(const storage_t& value) const
+ {
+ *this = LLUnit<storage_t, NEW_UNITS>(value);
+ }
LL_FORCE_INLINE operator storage_t() const
{
@@ -155,81 +155,81 @@ struct LLUnit
}
/*LL_FORCE_INLINE self_t& operator= (storage_t v)
- {
- value(v);
+ {
+ value(v);
return *this;
- }*/
-
- LL_FORCE_INLINE void operator += (self_t other)
- {
- mValue += convert(other).mValue;
- }
-
- LL_FORCE_INLINE void operator -= (self_t other)
- {
- mValue -= convert(other).mValue;
- }
-
- LL_FORCE_INLINE void operator *= (const storage_t& multiplicand)
- {
- mValue *= multiplicand;
- }
-
- LL_FORCE_INLINE void operator *= (const self_t& multiplicand)
- {
- // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
- }
-
- LL_FORCE_INLINE void operator /= (const storage_t& divisor)
- {
- mValue /= divisor;
- }
-
- void operator /= (const self_t& divisor)
- {
- // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator == (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
- {
- return mValue == convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator != (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
- {
- return mValue != convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator < (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
- {
- return mValue < convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator <= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
- {
- return mValue <= convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator > (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
- {
- return mValue > convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator >= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
- {
- return mValue >= convert(other).value();
- }
+ }*/
+
+ LL_FORCE_INLINE void operator += (self_t other)
+ {
+ mValue += convert(other).mValue;
+ }
+
+ LL_FORCE_INLINE void operator -= (self_t other)
+ {
+ mValue -= convert(other).mValue;
+ }
+
+ LL_FORCE_INLINE void operator *= (const storage_t& multiplicand)
+ {
+ mValue *= multiplicand;
+ }
+
+ LL_FORCE_INLINE void operator *= (const self_t& multiplicand)
+ {
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
+ }
+
+ LL_FORCE_INLINE void operator /= (const storage_t& divisor)
+ {
+ mValue /= divisor;
+ }
+
+ void operator /= (const self_t& divisor)
+ {
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator == (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
+ {
+ return mValue == convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator != (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
+ {
+ return mValue != convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator < (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
+ {
+ return mValue < convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator <= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
+ {
+ return mValue <= convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator > (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
+ {
+ return mValue > convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator >= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
+ {
+ return mValue >= convert(other).value();
+ }
protected:
- storage_t mValue;
+ storage_t mValue;
};
template<typename STORAGE_TYPE, typename UNITS>
@@ -251,161 +251,161 @@ std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
template<typename STORAGE_TYPE, typename UNITS>
struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
{
- typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
- typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
- typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
-
- LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
- : base_t(value)
- {}
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
- : base_t(other)
- {}
-
- // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
- // this allows for interoperability with legacy code
- LL_FORCE_INLINE operator storage_t() const
- {
- return base_t::value();
- }
-
- using base_t::operator +=;
- LL_FORCE_INLINE void operator += (storage_t value)
- {
+ typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
+ typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
+ typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
+
+ LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
+ : base_t(value)
+ {}
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ : base_t(other)
+ {}
+
+ // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
+ // this allows for interoperability with legacy code
+ LL_FORCE_INLINE operator storage_t() const
+ {
+ return base_t::value();
+ }
+
+ using base_t::operator +=;
+ LL_FORCE_INLINE void operator += (storage_t value)
+ {
base_t::mValue += value;
- }
+ }
- // this overload exists to explicitly catch use of another implicit unit
- // without ambiguity between conversion to storage_t vs conversion to base_t
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
- {
+ // this overload exists to explicitly catch use of another implicit unit
+ // without ambiguity between conversion to storage_t vs conversion to base_t
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ {
base_t::mValue += base_t::convert(other).value();
- }
+ }
- using base_t::operator -=;
- LL_FORCE_INLINE void operator -= (storage_t value)
- {
+ using base_t::operator -=;
+ LL_FORCE_INLINE void operator -= (storage_t value)
+ {
base_t::mValue -= value;
- }
+ }
- // this overload exists to explicitly catch use of another implicit unit
- // without ambiguity between conversion to storage_t vs conversion to base_t
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
- {
+ // this overload exists to explicitly catch use of another implicit unit
+ // without ambiguity between conversion to storage_t vs conversion to base_t
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ {
base_t::mValue -= base_t::convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue == base_t::convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue == base_t::convert(other).value();
- }
-
- template<typename STORAGE_T>
- LL_FORCE_INLINE bool operator == (STORAGE_T other) const
- {
- return base_t::mValue == other;
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue != convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue != base_t::convert(other).value();
- }
-
- template<typename STORAGE_T>
- LL_FORCE_INLINE bool operator != (STORAGE_T other) const
- {
- return base_t::mValue != other;
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue < base_t::convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue < base_t::convert(other).value();
- }
-
- template<typename STORAGE_T>
- LL_FORCE_INLINE bool operator < (STORAGE_T other) const
- {
- return base_t::mValue < other;
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue <= base_t::convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue <= base_t::convert(other).value();
- }
-
- template<typename STORAGE_T>
- LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
- {
- return base_t::mValue <= other;
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue > base_t::convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue > base_t::convert(other).value();
- }
-
- template<typename STORAGE_T>
- LL_FORCE_INLINE bool operator > (STORAGE_T other) const
- {
- return base_t::mValue > other;
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue >= base_t::convert(other).value();
- }
-
- template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
- LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
- {
- return base_t::mValue >= base_t::convert(other).value();
- }
-
- template<typename STORAGE_T>
- LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
- {
- return base_t::mValue >= other;
- }
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue == base_t::convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue == base_t::convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator == (STORAGE_T other) const
+ {
+ return base_t::mValue == other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue != convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue != base_t::convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator != (STORAGE_T other) const
+ {
+ return base_t::mValue != other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue < base_t::convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue < base_t::convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator < (STORAGE_T other) const
+ {
+ return base_t::mValue < other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue <= base_t::convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue <= base_t::convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
+ {
+ return base_t::mValue <= other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue > base_t::convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue > base_t::convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator > (STORAGE_T other) const
+ {
+ return base_t::mValue > other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue >= base_t::convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue >= base_t::convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
+ {
+ return base_t::mValue >= other;
+ }
};
template<typename STORAGE_TYPE, typename UNITS>
@@ -427,49 +427,49 @@ std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>&
template<typename S1, typename T1, typename S2, typename T2>
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
{
- S2 divisor(1);
-
- LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
- || !LLIsSameType<T1, typename T1::base_unit_t>::value
- || !LLIsSameType<T2, typename T2::base_unit_t>::value),
- "conversion requires compatible units");
-
- if (LLIsSameType<T1, T2>::value)
- {
- // T1 and T2 same type, just assign
- out.value((S2)in.value());
- }
- else if (T1::sLevel > T2::sLevel)
- {
- // reduce T1
- LLUnit<S2, typename T1::base_unit_t> new_in;
- divisor *= (S2)ll_convert_units(in, new_in);
- divisor *= (S2)ll_convert_units(new_in, out);
- }
- else
- {
- // reduce T2
- LLUnit<S2, typename T2::base_unit_t> new_out;
- divisor *= (S2)ll_convert_units(in, new_out);
- divisor *= (S2)ll_convert_units(new_out, out);
- }
- return divisor;
+ S2 divisor(1);
+
+ LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
+ || !LLIsSameType<T1, typename T1::base_unit_t>::value
+ || !LLIsSameType<T2, typename T2::base_unit_t>::value),
+ "conversion requires compatible units");
+
+ if (LLIsSameType<T1, T2>::value)
+ {
+ // T1 and T2 same type, just assign
+ out.value((S2)in.value());
+ }
+ else if (T1::sLevel > T2::sLevel)
+ {
+ // reduce T1
+ LLUnit<S2, typename T1::base_unit_t> new_in;
+ divisor *= (S2)ll_convert_units(in, new_in);
+ divisor *= (S2)ll_convert_units(new_in, out);
+ }
+ else
+ {
+ // reduce T2
+ LLUnit<S2, typename T2::base_unit_t> new_out;
+ divisor *= (S2)ll_convert_units(in, new_out);
+ divisor *= (S2)ll_convert_units(new_out, out);
+ }
+ return divisor;
}
template<typename T>
struct LLStorageType
{
- typedef T type_t;
+ typedef T type_t;
};
template<typename STORAGE_TYPE, typename UNITS>
struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
{
- typedef STORAGE_TYPE type_t;
+ typedef STORAGE_TYPE type_t;
};
-// all of these operators need to perform type promotion on the storage type of the units, so they
-// cannot be expressed as operations on identical types with implicit unit conversion
+// all of these operators need to perform type promotion on the storage type of the units, so they
+// cannot be expressed as operations on identical types with implicit unit conversion
// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
//
@@ -478,64 +478,64 @@ struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result += second;
- return result;
+ LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += second;
+ return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
{
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
- return LLUnit<STORAGE_TYPE, UNITS>(0);
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
{
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
- return LLUnit<STORAGE_TYPE, UNITS>(0);
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result += second;
- return result;
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += second;
+ return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result += second;
- return result;
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += second;
+ return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
- return result;
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
+ return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
- LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
- result += second;
- return result;
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
+ result += second;
+ return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
- type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
+ type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
{
- LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
- result += second;
- return result;
+ LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
+ result += second;
+ return result;
}
//
@@ -544,63 +544,63 @@ LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<U
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result -= second;
- return result;
+ LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= second;
+ return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
{
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
- return LLUnit<STORAGE_TYPE, UNITS>(0);
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
{
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
- return LLUnit<STORAGE_TYPE, UNITS>(0);
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result -= second;
- return result;
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= second;
+ return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result -= second;
- return result;
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= second;
+ return result;
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
- LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
- result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
- return result;
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
+ return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
- LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
- result -= second;
- return result;
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
+ result -= second;
+ return result;
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
{
- LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
- result -= second;
- return result;
+ LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
+ result -= second;
+ return result;
}
//
@@ -609,41 +609,41 @@ LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageT
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
{
- // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
- return LLUnit<STORAGE_TYPE1, UNITS1>();
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
+ return LLUnit<STORAGE_TYPE1, UNITS1>();
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
- return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
+ return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
{
- return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
+ return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
{
- // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
- LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
- return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
+ return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
- return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
+ return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
{
- return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
+ return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
}
@@ -654,196 +654,196 @@ LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageT
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
- return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
+ return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
- return first.value() / first.convert(second).value();
+ return first.value() / first.convert(second).value();
}
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
{
- return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
+ return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
- return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+ return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
{
- return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+ return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
}
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
{
- return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+ return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
}
-template<typename T>
+template<typename T>
struct LLGetUnitLabel
{
- static const char* getUnitLabel() { return ""; }
+ static const char* getUnitLabel() { return ""; }
};
template<typename T, typename STORAGE_T>
struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
{
- static const char* getUnitLabel() { return T::getUnitLabel(); }
+ static const char* getUnitLabel() { return T::getUnitLabel(); }
};
template<typename T>
struct LLUnitLinearOps
{
- typedef LLUnitLinearOps<T> self_t;
-
- LLUnitLinearOps(T val)
- : mValue(val),
- mDivisor(1)
- {}
-
- template<typename OTHER_T>
- self_t operator * (OTHER_T other)
- {
- return mValue * other;
- }
-
- template<typename OTHER_T>
- self_t operator / (OTHER_T other)
- {
- mDivisor *= other;
- return *this;
- }
-
- template<typename OTHER_T>
- self_t operator + (OTHER_T other)
- {
- mValue += other * mDivisor;
- return *this;
- }
-
- template<typename OTHER_T>
- self_t operator - (OTHER_T other)
- {
- mValue -= other * mDivisor;
- return *this;
- }
-
- T mValue;
- T mDivisor;
+ typedef LLUnitLinearOps<T> self_t;
+
+ LLUnitLinearOps(T val)
+ : mValue(val),
+ mDivisor(1)
+ {}
+
+ template<typename OTHER_T>
+ self_t operator * (OTHER_T other)
+ {
+ return mValue * other;
+ }
+
+ template<typename OTHER_T>
+ self_t operator / (OTHER_T other)
+ {
+ mDivisor *= other;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator + (OTHER_T other)
+ {
+ mValue += other * mDivisor;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator - (OTHER_T other)
+ {
+ mValue -= other * mDivisor;
+ return *this;
+ }
+
+ T mValue;
+ T mDivisor;
};
template<typename T>
struct LLUnitInverseLinearOps
{
- typedef LLUnitInverseLinearOps<T> self_t;
-
- LLUnitInverseLinearOps(T val)
- : mValue(val),
- mDivisor(1),
- mMultiplicand(1)
- {}
-
- template<typename OTHER_T>
- self_t operator * (OTHER_T other)
- {
- mDivisor *= other;
- return *this;
- }
-
- template<typename OTHER_T>
- self_t operator / (OTHER_T other)
- {
- mValue *= other;
- mMultiplicand *= other;
- return *this;
- }
-
- template<typename OTHER_T>
- self_t operator + (OTHER_T other)
- {
- mValue -= other * mMultiplicand;
- return *this;
- }
-
- template<typename OTHER_T>
- self_t operator - (OTHER_T other)
- {
- mValue += other * mMultiplicand;
- return *this;
- }
-
- T mValue;
- T mDivisor;
- T mMultiplicand;
+ typedef LLUnitInverseLinearOps<T> self_t;
+
+ LLUnitInverseLinearOps(T val)
+ : mValue(val),
+ mDivisor(1),
+ mMultiplicand(1)
+ {}
+
+ template<typename OTHER_T>
+ self_t operator * (OTHER_T other)
+ {
+ mDivisor *= other;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator / (OTHER_T other)
+ {
+ mValue *= other;
+ mMultiplicand *= other;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator + (OTHER_T other)
+ {
+ mValue -= other * mMultiplicand;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator - (OTHER_T other)
+ {
+ mValue += other * mMultiplicand;
+ return *this;
+ }
+
+ T mValue;
+ T mDivisor;
+ T mMultiplicand;
};
#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
struct base_unit_name \
{ \
- static const int sLevel = 0; \
- typedef base_unit_name base_unit_t; \
- static const char* getUnitLabel() { return unit_label; } \
- template<typename T> \
- static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
- template<typename STORAGE_T, typename UNIT_T> \
- static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
- { return LLUnit<STORAGE_T, base_unit_name>(value); } \
+ static const int sLevel = 0; \
+ typedef base_unit_name base_unit_t; \
+ static const char* getUnitLabel() { return unit_label; } \
+ template<typename T> \
+ static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
+ template<typename STORAGE_T, typename UNIT_T> \
+ static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
+ { return LLUnit<STORAGE_T, base_unit_name>(value); } \
}
-#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
+#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
struct unit_name \
{ \
- static const int sLevel = base_unit_name::sLevel + 1; \
- typedef base_unit_name base_unit_t; \
- static const char* getUnitLabel() { return unit_label; } \
- template<typename T> \
- static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
- template<typename STORAGE_T, typename UNIT_T> \
- static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
- { return LLUnit<STORAGE_T, unit_name>(value); } \
+ static const int sLevel = base_unit_name::sLevel + 1; \
+ typedef base_unit_name base_unit_t; \
+ static const char* getUnitLabel() { return unit_label; } \
+ template<typename T> \
+ static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
+ template<typename STORAGE_T, typename UNIT_T> \
+ static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
+ { return LLUnit<STORAGE_T, unit_name>(value); } \
}; \
- \
+ \
template<typename S1, typename S2> \
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
{ \
- typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
- LLUnitInverseLinearOps<result_storage_t> result = \
- LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \
- out = LLUnit<S2, base_unit_name>((S2)result.mValue); \
- return result.mDivisor; \
+ typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
+ LLUnitInverseLinearOps<result_storage_t> result = \
+ LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \
+ out = LLUnit<S2, base_unit_name>((S2)result.mValue); \
+ return result.mDivisor; \
} \
\
template<typename S1, typename S2> \
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
{ \
- typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
- LLUnitLinearOps<result_storage_t> result = \
- LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \
- out = LLUnit<S2, unit_name>((S2)result.mValue); \
- return result.mDivisor; \
-}
+ typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
+ LLUnitLinearOps<result_storage_t> result = \
+ LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \
+ out = LLUnit<S2, unit_name>((S2)result.mValue); \
+ return result.mDivisor; \
+}
#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \
- typedef LLUnit<F32, ns::unit_name> F32##unit_name; \
- typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
- typedef LLUnit<F64, ns::unit_name> F64##unit_name; \
- typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
- typedef LLUnit<S32, ns::unit_name> S32##unit_name; \
- typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
- typedef LLUnit<S64, ns::unit_name> S64##unit_name; \
- typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
- typedef LLUnit<U32, ns::unit_name> U32##unit_name; \
- typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
- typedef LLUnit<U64, ns::unit_name> U64##unit_name; \
- typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
+ typedef LLUnit<F32, ns::unit_name> F32##unit_name; \
+ typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
+ typedef LLUnit<F64, ns::unit_name> F64##unit_name; \
+ typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
+ typedef LLUnit<S32, ns::unit_name> S32##unit_name; \
+ typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
+ typedef LLUnit<S64, ns::unit_name> S64##unit_name; \
+ typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
+ typedef LLUnit<U32, ns::unit_name> U32##unit_name; \
+ typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
+ typedef LLUnit<U64, ns::unit_name> U64##unit_name; \
+ typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
#endif //LL_UNITTYPE_H
diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index 4fb92a8f3e..e93238f0e9 100644
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lluri.cpp
* @author Phoenix
* @date 2006-02-08
@@ -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$
*/
@@ -32,7 +32,7 @@
#include "lluri.h"
#include "llsd.h"
#include <iomanip>
-
+
#include "lluuid.h"
// system includes
@@ -43,182 +43,182 @@
// static
void LLURI::encodeCharacter(std::ostream& ostr, std::string::value_type val)
{
- ostr << "%"
+ ostr << "%"
- << std::uppercase
- << std::hex
- << std::setw(2)
- << std::setfill('0')
+ << std::uppercase
+ << std::hex
+ << std::setw(2)
+ << std::setfill('0')
- // VWR-4010 Cannot cast to U32 because sign-extension on
- // chars > 128 will result in FFFFFFC3 instead of F3.
- << static_cast<S32>(static_cast<U8>(val))
+ // VWR-4010 Cannot cast to U32 because sign-extension on
+ // chars > 128 will result in FFFFFFC3 instead of F3.
+ << static_cast<S32>(static_cast<U8>(val))
- // reset stream state
- << std::nouppercase
- << std::dec
- << std::setfill(' ');
+ // reset stream state
+ << std::nouppercase
+ << std::dec
+ << std::setfill(' ');
}
// static
std::string LLURI::escape(
- const std::string& str,
- const std::string& allowed,
- bool is_allowed_sorted)
-{
- // *NOTE: This size determination feels like a good value to
- // me. If someone wante to come up with a more precise heuristic
- // with some data to back up the assertion that 'sort is good'
- // then feel free to change this test a bit.
- if(!is_allowed_sorted && (str.size() > 2 * allowed.size()))
- {
- // if it's already sorted, or if the url is quite long, we
- // want to optimize this process.
- std::string sorted_allowed(allowed);
- std::sort(sorted_allowed.begin(), sorted_allowed.end());
- return escape(str, sorted_allowed, true);
- }
-
- std::ostringstream ostr;
- std::string::const_iterator it = str.begin();
- std::string::const_iterator end = str.end();
- std::string::value_type c;
- if(is_allowed_sorted)
- {
- std::string::const_iterator allowed_begin(allowed.begin());
- std::string::const_iterator allowed_end(allowed.end());
- for(; it != end; ++it)
- {
- c = *it;
- if(std::binary_search(allowed_begin, allowed_end, c))
- {
- ostr << c;
- }
- else
- {
- encodeCharacter(ostr, c);
- }
- }
- }
- else
- {
- for(; it != end; ++it)
- {
- c = *it;
- if(allowed.find(c) == std::string::npos)
- {
- encodeCharacter(ostr, c);
- }
- else
- {
- ostr << c;
- }
- }
- }
- return ostr.str();
+ const std::string& str,
+ const std::string& allowed,
+ bool is_allowed_sorted)
+{
+ // *NOTE: This size determination feels like a good value to
+ // me. If someone wante to come up with a more precise heuristic
+ // with some data to back up the assertion that 'sort is good'
+ // then feel free to change this test a bit.
+ if(!is_allowed_sorted && (str.size() > 2 * allowed.size()))
+ {
+ // if it's already sorted, or if the url is quite long, we
+ // want to optimize this process.
+ std::string sorted_allowed(allowed);
+ std::sort(sorted_allowed.begin(), sorted_allowed.end());
+ return escape(str, sorted_allowed, true);
+ }
+
+ std::ostringstream ostr;
+ std::string::const_iterator it = str.begin();
+ std::string::const_iterator end = str.end();
+ std::string::value_type c;
+ if(is_allowed_sorted)
+ {
+ std::string::const_iterator allowed_begin(allowed.begin());
+ std::string::const_iterator allowed_end(allowed.end());
+ for(; it != end; ++it)
+ {
+ c = *it;
+ if(std::binary_search(allowed_begin, allowed_end, c))
+ {
+ ostr << c;
+ }
+ else
+ {
+ encodeCharacter(ostr, c);
+ }
+ }
+ }
+ else
+ {
+ for(; it != end; ++it)
+ {
+ c = *it;
+ if(allowed.find(c) == std::string::npos)
+ {
+ encodeCharacter(ostr, c);
+ }
+ else
+ {
+ ostr << c;
+ }
+ }
+ }
+ return ostr.str();
}
// static
std::string LLURI::unescape(const std::string& str)
{
- std::ostringstream ostr;
- std::string::const_iterator it = str.begin();
- std::string::const_iterator end = str.end();
- for(; it != end; ++it)
- {
- if((*it) == '%')
- {
- ++it;
- if(it == end) break;
-
- if(is_char_hex(*it))
- {
- U8 c = hex_as_nybble(*it++);
-
- c = c << 4;
- if (it == end) break;
-
- if(is_char_hex(*it))
- {
- c |= hex_as_nybble(*it);
- ostr.put((char)c);
- }
- else
- {
- ostr.put((char)c);
- ostr.put(*it);
- }
- }
- else
- {
- ostr.put('%');
- ostr.put(*it);
- }
- }
- else
- {
- ostr.put(*it);
- }
- }
- return ostr.str();
+ std::ostringstream ostr;
+ std::string::const_iterator it = str.begin();
+ std::string::const_iterator end = str.end();
+ for(; it != end; ++it)
+ {
+ if((*it) == '%')
+ {
+ ++it;
+ if(it == end) break;
+
+ if(is_char_hex(*it))
+ {
+ U8 c = hex_as_nybble(*it++);
+
+ c = c << 4;
+ if (it == end) break;
+
+ if(is_char_hex(*it))
+ {
+ c |= hex_as_nybble(*it);
+ ostr.put((char)c);
+ }
+ else
+ {
+ ostr.put((char)c);
+ ostr.put(*it);
+ }
+ }
+ else
+ {
+ ostr.put('%');
+ ostr.put(*it);
+ }
+ }
+ else
+ {
+ ostr.put(*it);
+ }
+ }
+ return ostr.str();
}
namespace
{
- const std::string unreserved()
- {
- static const std::string s =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "-._~";
- return s;
- }
- const std::string path()
- {
- static const std::string s =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "$-_.+"
- "!*'(),"
- "{}|\\^~[]`"
- "<>#%"
- ";/?:@&=";
- return s;
- }
- const std::string sub_delims()
- {
- static const std::string s = "!$&'()*+,;=";
- return s;
- }
-
- std::string escapeHostAndPort(const std::string& s)
- { return LLURI::escape(s, unreserved() + sub_delims() +":"); }
- std::string escapePathComponent(const std::string& s)
- { return LLURI::escape(s, unreserved() + sub_delims() + ":@"); }
- std::string escapeQueryVariable(const std::string& s)
- { return LLURI::escape(s, unreserved() + ":@!$'()*+,"); } // sub_delims - "&;=" + ":@"
- std::string escapeQueryValue(const std::string& s)
- { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@"
- std::string escapeUriQuery(const std::string& s)
- { return LLURI::escape(s, unreserved() + ":@?&$;*+=%/"); }
- std::string escapeUriData(const std::string& s)
- { return LLURI::escape(s, unreserved() + "%"); }
- std::string escapeUriPath(const std::string& s)
- { return LLURI::escape(s, path()); }
+ const std::string unreserved()
+ {
+ static const std::string s =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._~";
+ return s;
+ }
+ const std::string path()
+ {
+ static const std::string s =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "$-_.+"
+ "!*'(),"
+ "{}|\\^~[]`"
+ "<>#%"
+ ";/?:@&=";
+ return s;
+ }
+ const std::string sub_delims()
+ {
+ static const std::string s = "!$&'()*+,;=";
+ return s;
+ }
+
+ std::string escapeHostAndPort(const std::string& s)
+ { return LLURI::escape(s, unreserved() + sub_delims() +":"); }
+ std::string escapePathComponent(const std::string& s)
+ { return LLURI::escape(s, unreserved() + sub_delims() + ":@"); }
+ std::string escapeQueryVariable(const std::string& s)
+ { return LLURI::escape(s, unreserved() + ":@!$'()*+,"); } // sub_delims - "&;=" + ":@"
+ std::string escapeQueryValue(const std::string& s)
+ { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@"
+ std::string escapeUriQuery(const std::string& s)
+ { return LLURI::escape(s, unreserved() + ":@?&$;*+=%/"); }
+ std::string escapeUriData(const std::string& s)
+ { return LLURI::escape(s, unreserved() + "%"); }
+ std::string escapeUriPath(const std::string& s)
+ { return LLURI::escape(s, path()); }
}
//static
std::string LLURI::escape(const std::string& str)
{
- static std::string default_allowed = unreserved();
- static bool initialized = false;
- if(!initialized)
- {
- std::sort(default_allowed.begin(), default_allowed.end());
- initialized = true;
- }
- return escape(str, default_allowed, true);
+ static std::string default_allowed = unreserved();
+ static bool initialized = false;
+ if(!initialized)
+ {
+ std::sort(default_allowed.begin(), default_allowed.end());
+ initialized = true;
+ }
+ return escape(str, default_allowed, true);
}
//static
@@ -306,126 +306,126 @@ LLURI::LLURI()
LLURI::LLURI(const std::string& escaped_str)
{
- std::string::size_type delim_pos;
- delim_pos = escaped_str.find(':');
- std::string temp;
- if (delim_pos == std::string::npos)
- {
- mScheme = "";
- mEscapedOpaque = escaped_str;
- }
- else
- {
- mScheme = escaped_str.substr(0, delim_pos);
- mEscapedOpaque = escaped_str.substr(delim_pos+1);
- }
-
- parseAuthorityAndPathUsingOpaque();
-
- delim_pos = mEscapedPath.find('?');
- if (delim_pos != std::string::npos)
- {
- mEscapedQuery = mEscapedPath.substr(delim_pos+1);
- mEscapedPath = mEscapedPath.substr(0,delim_pos);
- }
+ std::string::size_type delim_pos;
+ delim_pos = escaped_str.find(':');
+ std::string temp;
+ if (delim_pos == std::string::npos)
+ {
+ mScheme = "";
+ mEscapedOpaque = escaped_str;
+ }
+ else
+ {
+ mScheme = escaped_str.substr(0, delim_pos);
+ mEscapedOpaque = escaped_str.substr(delim_pos+1);
+ }
+
+ parseAuthorityAndPathUsingOpaque();
+
+ delim_pos = mEscapedPath.find('?');
+ if (delim_pos != std::string::npos)
+ {
+ mEscapedQuery = mEscapedPath.substr(delim_pos+1);
+ mEscapedPath = mEscapedPath.substr(0,delim_pos);
+ }
}
static BOOL isDefault(const std::string& scheme, U16 port)
{
- if (scheme == "http")
- return port == 80;
- if (scheme == "https")
- return port == 443;
- if (scheme == "ftp")
- return port == 21;
+ if (scheme == "http")
+ return port == 80;
+ if (scheme == "https")
+ return port == 443;
+ if (scheme == "ftp")
+ return port == 21;
- return FALSE;
+ return FALSE;
}
void LLURI::parseAuthorityAndPathUsingOpaque()
{
- if (mScheme == "http" || mScheme == "https" ||
- mScheme == "ftp" || mScheme == "secondlife" ||
- mScheme == "x-grid-location-info")
- {
- if (mEscapedOpaque.substr(0,2) != "//")
- {
- return;
- }
-
- std::string::size_type delim_pos, delim_pos2;
- delim_pos = mEscapedOpaque.find('/', 2);
- delim_pos2 = mEscapedOpaque.find('?', 2);
- // no path, no query
- if (delim_pos == std::string::npos &&
- delim_pos2 == std::string::npos)
- {
- mEscapedAuthority = mEscapedOpaque.substr(2);
- mEscapedPath = "";
- }
- // path exist, no query
- else if (delim_pos2 == std::string::npos)
- {
- mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos-2);
- mEscapedPath = mEscapedOpaque.substr(delim_pos);
- }
- // no path, only query
- else if (delim_pos == std::string::npos ||
- delim_pos2 < delim_pos)
- {
- mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos2-2);
- // query part will be broken out later
- mEscapedPath = mEscapedOpaque.substr(delim_pos2);
- }
- // path and query
- else
- {
- mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos-2);
- // query part will be broken out later
- mEscapedPath = mEscapedOpaque.substr(delim_pos);
- }
- }
- else if (mScheme == "about")
- {
- mEscapedPath = mEscapedOpaque;
- }
+ if (mScheme == "http" || mScheme == "https" ||
+ mScheme == "ftp" || mScheme == "secondlife" ||
+ mScheme == "x-grid-location-info")
+ {
+ if (mEscapedOpaque.substr(0,2) != "//")
+ {
+ return;
+ }
+
+ std::string::size_type delim_pos, delim_pos2;
+ delim_pos = mEscapedOpaque.find('/', 2);
+ delim_pos2 = mEscapedOpaque.find('?', 2);
+ // no path, no query
+ if (delim_pos == std::string::npos &&
+ delim_pos2 == std::string::npos)
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2);
+ mEscapedPath = "";
+ }
+ // path exist, no query
+ else if (delim_pos2 == std::string::npos)
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos-2);
+ mEscapedPath = mEscapedOpaque.substr(delim_pos);
+ }
+ // no path, only query
+ else if (delim_pos == std::string::npos ||
+ delim_pos2 < delim_pos)
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos2-2);
+ // query part will be broken out later
+ mEscapedPath = mEscapedOpaque.substr(delim_pos2);
+ }
+ // path and query
+ else
+ {
+ mEscapedAuthority = mEscapedOpaque.substr(2,delim_pos-2);
+ // query part will be broken out later
+ mEscapedPath = mEscapedOpaque.substr(delim_pos);
+ }
+ }
+ else if (mScheme == "about")
+ {
+ mEscapedPath = mEscapedOpaque;
+ }
}
LLURI::LLURI(const std::string& scheme,
- const std::string& userName,
- const std::string& password,
- const std::string& hostName,
- U16 port,
- const std::string& escapedPath,
- const std::string& escapedQuery)
- : mScheme(scheme),
- mEscapedPath(escapedPath),
- mEscapedQuery(escapedQuery)
-{
- std::ostringstream auth;
- std::ostringstream opaque;
-
- opaque << "//";
-
- if (!userName.empty())
- {
- auth << escape(userName);
- if (!password.empty())
- {
- auth << ':' << escape(password);
- }
- auth << '@';
- }
- auth << hostName;
- if (!isDefault(scheme, port))
- {
- auth << ':' << port;
- }
- mEscapedAuthority = auth.str();
-
- opaque << mEscapedAuthority << escapedPath << escapedQuery;
-
- mEscapedOpaque = opaque.str();
+ const std::string& userName,
+ const std::string& password,
+ const std::string& hostName,
+ U16 port,
+ const std::string& escapedPath,
+ const std::string& escapedQuery)
+ : mScheme(scheme),
+ mEscapedPath(escapedPath),
+ mEscapedQuery(escapedQuery)
+{
+ std::ostringstream auth;
+ std::ostringstream opaque;
+
+ opaque << "//";
+
+ if (!userName.empty())
+ {
+ auth << escape(userName);
+ if (!password.empty())
+ {
+ auth << ':' << escape(password);
+ }
+ auth << '@';
+ }
+ auth << hostName;
+ if (!isDefault(scheme, port))
+ {
+ auth << ':' << port;
+ }
+ mEscapedAuthority = auth.str();
+
+ opaque << mEscapedAuthority << escapedPath << escapedQuery;
+
+ mEscapedOpaque = opaque.str();
}
LLURI::~LLURI()
@@ -434,325 +434,325 @@ LLURI::~LLURI()
// static
LLURI LLURI::buildHTTP(const std::string& prefix,
- const LLSD& path)
-{
- LLURI result;
-
- // TODO: deal with '/' '?' '#' in host_port
- if (prefix.find("://") != prefix.npos)
- {
- // it is a prefix
- result = LLURI(prefix);
- }
- else
- {
- // it is just a host and optional port
- result.mScheme = "http";
- result.mEscapedAuthority = escapeHostAndPort(prefix);
- }
-
- if (path.isArray())
- {
- // break out and escape each path component
- for (LLSD::array_const_iterator it = path.beginArray();
- it != path.endArray();
- ++it)
- {
- LL_DEBUGS() << "PATH: inserting " << it->asString() << LL_ENDL;
- result.mEscapedPath += "/" + escapePathComponent(it->asString());
- }
- }
- else if (path.isString())
- {
- std::string pathstr(path);
- // Trailing slash is significant in HTTP land. If caller specified,
- // make a point of preserving.
- std::string last_slash;
- std::string::size_type len(pathstr.length());
- if (len && pathstr[len-1] == '/')
- {
- last_slash = "/";
- }
-
- // Escape every individual path component, recombining with slashes.
- for (boost::split_iterator<std::string::const_iterator>
- ti(pathstr, boost::first_finder("/")), tend;
- ti != tend; ++ti)
- {
- // Eliminate a leading slash or duplicate slashes anywhere. (Extra
- // slashes show up here as empty components.) This test also
- // eliminates a trailing slash, hence last_slash above.
- if (! ti->empty())
- {
- result.mEscapedPath
- += "/" + escapePathComponent(std::string(ti->begin(), ti->end()));
- }
- }
-
- // Reinstate trailing slash, if any.
- result.mEscapedPath += last_slash;
- }
- else if(path.isUndefined())
- {
- // do nothing
- }
- else
- {
- LL_WARNS() << "Valid path arguments to buildHTTP are array, string, or undef, you passed type"
- << path.type() << LL_ENDL;
- }
- result.mEscapedOpaque = "//" + result.mEscapedAuthority +
- result.mEscapedPath;
- return result;
+ const LLSD& path)
+{
+ LLURI result;
+
+ // TODO: deal with '/' '?' '#' in host_port
+ if (prefix.find("://") != prefix.npos)
+ {
+ // it is a prefix
+ result = LLURI(prefix);
+ }
+ else
+ {
+ // it is just a host and optional port
+ result.mScheme = "http";
+ result.mEscapedAuthority = escapeHostAndPort(prefix);
+ }
+
+ if (path.isArray())
+ {
+ // break out and escape each path component
+ for (LLSD::array_const_iterator it = path.beginArray();
+ it != path.endArray();
+ ++it)
+ {
+ LL_DEBUGS() << "PATH: inserting " << it->asString() << LL_ENDL;
+ result.mEscapedPath += "/" + escapePathComponent(it->asString());
+ }
+ }
+ else if (path.isString())
+ {
+ std::string pathstr(path);
+ // Trailing slash is significant in HTTP land. If caller specified,
+ // make a point of preserving.
+ std::string last_slash;
+ std::string::size_type len(pathstr.length());
+ if (len && pathstr[len-1] == '/')
+ {
+ last_slash = "/";
+ }
+
+ // Escape every individual path component, recombining with slashes.
+ for (boost::split_iterator<std::string::const_iterator>
+ ti(pathstr, boost::first_finder("/")), tend;
+ ti != tend; ++ti)
+ {
+ // Eliminate a leading slash or duplicate slashes anywhere. (Extra
+ // slashes show up here as empty components.) This test also
+ // eliminates a trailing slash, hence last_slash above.
+ if (! ti->empty())
+ {
+ result.mEscapedPath
+ += "/" + escapePathComponent(std::string(ti->begin(), ti->end()));
+ }
+ }
+
+ // Reinstate trailing slash, if any.
+ result.mEscapedPath += last_slash;
+ }
+ else if(path.isUndefined())
+ {
+ // do nothing
+ }
+ else
+ {
+ LL_WARNS() << "Valid path arguments to buildHTTP are array, string, or undef, you passed type"
+ << path.type() << LL_ENDL;
+ }
+ result.mEscapedOpaque = "//" + result.mEscapedAuthority +
+ result.mEscapedPath;
+ return result;
}
// static
LLURI LLURI::buildHTTP(const std::string& prefix,
- const LLSD& path,
- const LLSD& query)
+ const LLSD& path,
+ const LLSD& query)
{
- LLURI uri = buildHTTP(prefix, path);
- // break out and escape each query component
- uri.mEscapedQuery = mapToQueryString(query);
- uri.mEscapedOpaque += uri.mEscapedQuery ;
- uri.mEscapedQuery.erase(0,1); // trim the leading '?'
- return uri;
+ LLURI uri = buildHTTP(prefix, path);
+ // break out and escape each query component
+ uri.mEscapedQuery = mapToQueryString(query);
+ uri.mEscapedOpaque += uri.mEscapedQuery ;
+ uri.mEscapedQuery.erase(0,1); // trim the leading '?'
+ return uri;
}
// static
LLURI LLURI::buildHTTP(const std::string& host,
- const U32& port,
- const LLSD& path)
+ const U32& port,
+ const LLSD& path)
{
- return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path);
+ return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path);
}
// static
LLURI LLURI::buildHTTP(const std::string& host,
- const U32& port,
- const LLSD& path,
- const LLSD& query)
+ const U32& port,
+ const LLSD& path,
+ const LLSD& query)
{
- return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path, query);
+ return LLURI::buildHTTP(llformat("%s:%u", host.c_str(), port), path, query);
}
std::string LLURI::asString() const
{
- if (mScheme.empty())
- {
- return mEscapedOpaque;
- }
- else
- {
- return mScheme + ":" + mEscapedOpaque;
- }
+ if (mScheme.empty())
+ {
+ return mEscapedOpaque;
+ }
+ else
+ {
+ return mScheme + ":" + mEscapedOpaque;
+ }
}
std::string LLURI::scheme() const
{
- return mScheme;
+ return mScheme;
}
std::string LLURI::opaque() const
{
- return unescape(mEscapedOpaque);
+ return unescape(mEscapedOpaque);
}
std::string LLURI::authority() const
{
- return unescape(mEscapedAuthority);
+ return unescape(mEscapedAuthority);
}
namespace {
- void findAuthorityParts(const std::string& authority,
- std::string& user,
- std::string& host,
- std::string& port)
- {
- std::string::size_type start_pos = authority.find('@');
- if (start_pos == std::string::npos)
- {
- user = "";
- start_pos = 0;
- }
- else
- {
- user = authority.substr(0, start_pos);
- start_pos += 1;
- }
-
- std::string::size_type end_pos = authority.find(':', start_pos);
- if (end_pos == std::string::npos)
- {
- host = authority.substr(start_pos);
- port = "";
- }
- else
- {
- host = authority.substr(start_pos, end_pos - start_pos);
- port = authority.substr(end_pos + 1);
- }
- }
-}
-
+ void findAuthorityParts(const std::string& authority,
+ std::string& user,
+ std::string& host,
+ std::string& port)
+ {
+ std::string::size_type start_pos = authority.find('@');
+ if (start_pos == std::string::npos)
+ {
+ user = "";
+ start_pos = 0;
+ }
+ else
+ {
+ user = authority.substr(0, start_pos);
+ start_pos += 1;
+ }
+
+ std::string::size_type end_pos = authority.find(':', start_pos);
+ if (end_pos == std::string::npos)
+ {
+ host = authority.substr(start_pos);
+ port = "";
+ }
+ else
+ {
+ host = authority.substr(start_pos, end_pos - start_pos);
+ port = authority.substr(end_pos + 1);
+ }
+ }
+}
+
std::string LLURI::hostName() const
{
- std::string user, host, port;
- findAuthorityParts(mEscapedAuthority, user, host, port);
- return unescape(host);
+ std::string user, host, port;
+ findAuthorityParts(mEscapedAuthority, user, host, port);
+ return unescape(host);
}
std::string LLURI::userName() const
{
- std::string user, userPass, host, port;
- findAuthorityParts(mEscapedAuthority, userPass, host, port);
- std::string::size_type pos = userPass.find(':');
- if (pos != std::string::npos)
- {
- user = userPass.substr(0, pos);
- }
- return unescape(user);
+ std::string user, userPass, host, port;
+ findAuthorityParts(mEscapedAuthority, userPass, host, port);
+ std::string::size_type pos = userPass.find(':');
+ if (pos != std::string::npos)
+ {
+ user = userPass.substr(0, pos);
+ }
+ return unescape(user);
}
std::string LLURI::password() const
{
- std::string pass, userPass, host, port;
- findAuthorityParts(mEscapedAuthority, userPass, host, port);
- std::string::size_type pos = userPass.find(':');
- if (pos != std::string::npos)
- {
- pass = userPass.substr(pos + 1);
- }
- return unescape(pass);
+ std::string pass, userPass, host, port;
+ findAuthorityParts(mEscapedAuthority, userPass, host, port);
+ std::string::size_type pos = userPass.find(':');
+ if (pos != std::string::npos)
+ {
+ pass = userPass.substr(pos + 1);
+ }
+ return unescape(pass);
}
BOOL LLURI::defaultPort() const
{
- return isDefault(mScheme, hostPort());
+ return isDefault(mScheme, hostPort());
}
U16 LLURI::hostPort() const
{
- std::string user, host, port;
- findAuthorityParts(mEscapedAuthority, user, host, port);
- if (port.empty())
- {
- if (mScheme == "http")
- return 80;
- if (mScheme == "https")
- return 443;
- if (mScheme == "ftp")
- return 21;
- return 0;
- }
- return atoi(port.c_str());
-}
+ std::string user, host, port;
+ findAuthorityParts(mEscapedAuthority, user, host, port);
+ if (port.empty())
+ {
+ if (mScheme == "http")
+ return 80;
+ if (mScheme == "https")
+ return 443;
+ if (mScheme == "ftp")
+ return 21;
+ return 0;
+ }
+ return atoi(port.c_str());
+}
std::string LLURI::path() const
{
- return unescape(mEscapedPath);
+ return unescape(mEscapedPath);
}
LLSD LLURI::pathArray() const
{
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
- tokenizer tokens(mEscapedPath, sep);
- tokenizer::iterator it = tokens.begin();
- tokenizer::iterator end = tokens.end();
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
+ tokenizer tokens(mEscapedPath, sep);
+ tokenizer::iterator it = tokens.begin();
+ tokenizer::iterator end = tokens.end();
- LLSD params;
- for (const std::string& str : tokens)
- {
- params.append(str);
- }
- return params;
+ LLSD params;
+ for (const std::string& str : tokens)
+ {
+ params.append(str);
+ }
+ return params;
}
std::string LLURI::query() const
{
- return unescape(mEscapedQuery);
+ return unescape(mEscapedQuery);
}
LLSD LLURI::queryMap() const
{
- return queryMap(mEscapedQuery);
+ return queryMap(mEscapedQuery);
}
// static
LLSD LLURI::queryMap(std::string escaped_query_string)
{
- LL_DEBUGS() << "LLURI::queryMap query params: " << escaped_query_string << LL_ENDL;
-
- LLSD result = LLSD::emptyArray();
- while(!escaped_query_string.empty())
- {
- // get tuple first
- std::string tuple;
- std::string::size_type tuple_begin = escaped_query_string.find('&');
- if (tuple_begin != std::string::npos)
- {
- tuple = escaped_query_string.substr(0, tuple_begin);
- escaped_query_string = escaped_query_string.substr(tuple_begin+1);
- }
- else
- {
- tuple = escaped_query_string;
- escaped_query_string = "";
- }
- if (tuple.empty()) continue;
-
- // parse tuple
- std::string::size_type key_end = tuple.find('=');
- if (key_end != std::string::npos)
- {
- std::string key = unescape(tuple.substr(0,key_end));
- std::string value = unescape(tuple.substr(key_end+1));
- LL_DEBUGS() << "inserting key " << key << " value " << value << LL_ENDL;
- result[key] = value;
- }
- else
- {
- LL_DEBUGS() << "inserting key " << unescape(tuple) << " value true" << LL_ENDL;
- result[unescape(tuple)] = true;
- }
- }
- return result;
+ LL_DEBUGS() << "LLURI::queryMap query params: " << escaped_query_string << LL_ENDL;
+
+ LLSD result = LLSD::emptyArray();
+ while(!escaped_query_string.empty())
+ {
+ // get tuple first
+ std::string tuple;
+ std::string::size_type tuple_begin = escaped_query_string.find('&');
+ if (tuple_begin != std::string::npos)
+ {
+ tuple = escaped_query_string.substr(0, tuple_begin);
+ escaped_query_string = escaped_query_string.substr(tuple_begin+1);
+ }
+ else
+ {
+ tuple = escaped_query_string;
+ escaped_query_string = "";
+ }
+ if (tuple.empty()) continue;
+
+ // parse tuple
+ std::string::size_type key_end = tuple.find('=');
+ if (key_end != std::string::npos)
+ {
+ std::string key = unescape(tuple.substr(0,key_end));
+ std::string value = unescape(tuple.substr(key_end+1));
+ LL_DEBUGS() << "inserting key " << key << " value " << value << LL_ENDL;
+ result[key] = value;
+ }
+ else
+ {
+ LL_DEBUGS() << "inserting key " << unescape(tuple) << " value true" << LL_ENDL;
+ result[unescape(tuple)] = true;
+ }
+ }
+ return result;
}
std::string LLURI::mapToQueryString(const LLSD& queryMap)
{
- std::string query_string;
- if (queryMap.isMap())
- {
- bool first_element = true;
- LLSD::map_const_iterator iter = queryMap.beginMap();
- LLSD::map_const_iterator end = queryMap.endMap();
- std::ostringstream ostr;
- for (; iter != end; ++iter)
- {
- if(first_element)
- {
- ostr << "?";
- first_element = false;
- }
- else
- {
- ostr << "&";
- }
- ostr << escapeQueryVariable(iter->first);
- if(iter->second.isDefined())
- {
- ostr << "=" << escapeQueryValue(iter->second.asString());
- }
- }
- query_string = ostr.str();
- }
- return query_string;
+ std::string query_string;
+ if (queryMap.isMap())
+ {
+ bool first_element = true;
+ LLSD::map_const_iterator iter = queryMap.beginMap();
+ LLSD::map_const_iterator end = queryMap.endMap();
+ std::ostringstream ostr;
+ for (; iter != end; ++iter)
+ {
+ if(first_element)
+ {
+ ostr << "?";
+ first_element = false;
+ }
+ else
+ {
+ ostr << "&";
+ }
+ ostr << escapeQueryVariable(iter->first);
+ if(iter->second.isDefined())
+ {
+ ostr << "=" << escapeQueryValue(iter->second.asString());
+ }
+ }
+ query_string = ostr.str();
+ }
+ return query_string;
}
bool operator!=(const LLURI& first, const LLURI& second)
{
- return (first.asString() != second.asString());
+ return (first.asString() != second.asString());
}
diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h
index b8fca0ca51..95c119dee9 100644
--- a/indra/llcommon/lluri.h
+++ b/indra/llcommon/lluri.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lluri.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 @@ class LLSD;
class LLUUID;
class LLApp;
-/**
+/**
*
* LLURI instances are immutable
* See: http://www.ietf.org/rfc/rfc3986.txt
@@ -47,144 +47,144 @@ public:
LLURI();
LLURI(const std::string& escaped_str);
LLURI(const std::string& scheme,
- const std::string& userName,
- const std::string& password,
- const std::string& hostName,
- U16 hostPort,
- const std::string& escapedPath,
- const std::string& escapedQuery);
-
+ const std::string& userName,
+ const std::string& password,
+ const std::string& hostName,
+ U16 hostPort,
+ const std::string& escapedPath,
+ const std::string& escapedQuery);
+
// construct from escaped string, as would be transmitted on the net
- ~LLURI();
-
- static LLURI buildHTTP(
- const std::string& prefix,
- const LLSD& path);
-
- static LLURI buildHTTP(
- const std::string& prefix,
- const LLSD& path,
- const LLSD& query);
- ///< prefix is either a full URL prefix of the form
- /// "http://example.com:8080", or it can be simply a host and
- /// optional port like "example.com" or "example.com:8080", in
- /// these cases, the "http://" will be added
-
- static LLURI buildHTTP(
- const std::string& host,
- const U32& port,
- const LLSD& path);
- static LLURI buildHTTP(
- const std::string& host,
- const U32& port,
- const LLSD& path,
- const LLSD& query);
-
- std::string asString() const;
- ///< the whole URI, escaped as needed
-
- /** @name Parts of a URI */
- //@{
- // These functions return parts of the decoded URI. The returned
- // strings are un-escaped as needed
-
- // for all schemes
- std::string scheme() const; ///< ex.: "http", note lack of colon
- std::string opaque() const; ///< everything after the colon
-
+ ~LLURI();
+
+ static LLURI buildHTTP(
+ const std::string& prefix,
+ const LLSD& path);
+
+ static LLURI buildHTTP(
+ const std::string& prefix,
+ const LLSD& path,
+ const LLSD& query);
+ ///< prefix is either a full URL prefix of the form
+ /// "http://example.com:8080", or it can be simply a host and
+ /// optional port like "example.com" or "example.com:8080", in
+ /// these cases, the "http://" will be added
+
+ static LLURI buildHTTP(
+ const std::string& host,
+ const U32& port,
+ const LLSD& path);
+ static LLURI buildHTTP(
+ const std::string& host,
+ const U32& port,
+ const LLSD& path,
+ const LLSD& query);
+
+ std::string asString() const;
+ ///< the whole URI, escaped as needed
+
+ /** @name Parts of a URI */
+ //@{
+ // These functions return parts of the decoded URI. The returned
+ // strings are un-escaped as needed
+
+ // for all schemes
+ std::string scheme() const; ///< ex.: "http", note lack of colon
+ std::string opaque() const; ///< everything after the colon
+
// for schemes that follow path like syntax (http, https, ftp)
- std::string authority() const; // ex.: "host.com:80"
- std::string hostName() const; // ex.: "host.com"
+ std::string authority() const; // ex.: "host.com:80"
+ std::string hostName() const; // ex.: "host.com"
std::string userName() const;
std::string password() const;
- U16 hostPort() const; // ex.: 80, will include implicit port
- BOOL defaultPort() const; // true if port is default for scheme
+ U16 hostPort() const; // ex.: 80, will include implicit port
+ BOOL defaultPort() const; // true if port is default for scheme
const std::string& escapedPath() const { return mEscapedPath; }
- std::string path() const; // ex.: "/abc/def", includes leading slash
- LLSD pathArray() const; // above decoded into an array of strings
- std::string query() const; // ex.: "x=34", section after "?"
+ std::string path() const; // ex.: "/abc/def", includes leading slash
+ LLSD pathArray() const; // above decoded into an array of strings
+ std::string query() const; // ex.: "x=34", section after "?"
const std::string& escapedQuery() const { return mEscapedQuery; }
- LLSD queryMap() const; // above decoded into a map
+ LLSD queryMap() const; // above decoded into a map
static LLSD queryMap(std::string escaped_query_string);
- /**
- * @brief given a name value map, return a serialized query string.
- *
-
- * @param query_map a map of name value. every value must be
- * representable as a string.
- * @return Returns an url query string of '?n1=v1&n2=v2&...'
- */
- static std::string mapToQueryString(const LLSD& query_map);
-
- /** @name Escaping Utilities */
- //@{
- /**
- * @brief 'Escape' symbol into stream
- *
- * @param ostr Output stream.
- * @param val Symbol to encode.
- */
- static void encodeCharacter(std::ostream& ostr, std::string::value_type val);
-
- /**
- * @brief Escape the string passed except for unreserved
- *
- * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
- * 0123456789
- * -._~
- *
- * @see http://www.ietf.org/rfc/rfc1738.txt
- *
- * @param str The raw URI to escape.
- * @return Returns the rfc 1738 escaped uri or an empty string.
- */
- static std::string escape(const std::string& str);
-
- /**
- * @brief Escape a string with a specified set of allowed characters.
- *
- * Escape a string by urlencoding all the characters that aren't
- * in the allowed string.
- * @param str The raw URI to escape.
- * @param allowed Character array of allowed characters
- * @param is_allowed_sorted Optimization hint if allowed array is sorted.
- * @return Returns the escaped uri or an empty string.
- */
- static std::string escape(
- const std::string& str,
- const std::string& allowed,
- bool is_allowed_sorted = false);
-
- /**
- * @brief Break string into data part and path or sheme
- * and escape path (if present) and data.
- * Data part is not allowed to have path related symbols
- * @param str The raw URI to escape.
- */
- static std::string escapePathAndData(const std::string &str);
-
- /**
- * @brief unescape an escaped URI string.
- *
- * @param str The escped URI to unescape.
- * @return Returns the unescaped uri or an empty string.
- */
- static std::string unescape(const std::string& str);
- //@}
+ /**
+ * @brief given a name value map, return a serialized query string.
+ *
+
+ * @param query_map a map of name value. every value must be
+ * representable as a string.
+ * @return Returns an url query string of '?n1=v1&n2=v2&...'
+ */
+ static std::string mapToQueryString(const LLSD& query_map);
+
+ /** @name Escaping Utilities */
+ //@{
+ /**
+ * @brief 'Escape' symbol into stream
+ *
+ * @param ostr Output stream.
+ * @param val Symbol to encode.
+ */
+ static void encodeCharacter(std::ostream& ostr, std::string::value_type val);
+
+ /**
+ * @brief Escape the string passed except for unreserved
+ *
+ * ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+ * 0123456789
+ * -._~
+ *
+ * @see http://www.ietf.org/rfc/rfc1738.txt
+ *
+ * @param str The raw URI to escape.
+ * @return Returns the rfc 1738 escaped uri or an empty string.
+ */
+ static std::string escape(const std::string& str);
+
+ /**
+ * @brief Escape a string with a specified set of allowed characters.
+ *
+ * Escape a string by urlencoding all the characters that aren't
+ * in the allowed string.
+ * @param str The raw URI to escape.
+ * @param allowed Character array of allowed characters
+ * @param is_allowed_sorted Optimization hint if allowed array is sorted.
+ * @return Returns the escaped uri or an empty string.
+ */
+ static std::string escape(
+ const std::string& str,
+ const std::string& allowed,
+ bool is_allowed_sorted = false);
+
+ /**
+ * @brief Break string into data part and path or sheme
+ * and escape path (if present) and data.
+ * Data part is not allowed to have path related symbols
+ * @param str The raw URI to escape.
+ */
+ static std::string escapePathAndData(const std::string &str);
+
+ /**
+ * @brief unescape an escaped URI string.
+ *
+ * @param str The escped URI to unescape.
+ * @return Returns the unescaped uri or an empty string.
+ */
+ static std::string unescape(const std::string& str);
+ //@}
private:
- // only "http", "https", "ftp", and "secondlife" schemes are parsed
- // secondlife scheme parses authority as "" and includes it as part of
- // the path. See lluri_tut.cpp
- // i.e. secondlife://app/login has mAuthority = "" and mPath = "/app/login"
- void parseAuthorityAndPathUsingOpaque();
- std::string mScheme;
- std::string mEscapedOpaque;
- std::string mEscapedAuthority;
- std::string mEscapedPath;
- std::string mEscapedQuery;
+ // only "http", "https", "ftp", and "secondlife" schemes are parsed
+ // secondlife scheme parses authority as "" and includes it as part of
+ // the path. See lluri_tut.cpp
+ // i.e. secondlife://app/login has mAuthority = "" and mPath = "/app/login"
+ void parseAuthorityAndPathUsingOpaque();
+ std::string mScheme;
+ std::string mEscapedOpaque;
+ std::string mEscapedAuthority;
+ std::string mEscapedPath;
+ std::string mEscapedQuery;
};
// this operator required for tut
diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp
index f79a98a56d..2ebb7fc742 100644
--- a/indra/llcommon/lluriparser.cpp
+++ b/indra/llcommon/lluriparser.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lluriparser.cpp
* @author Protey
* @date 2014-10-07
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2014, 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,129 +36,129 @@
LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedTmp(false), mRes(0)
{
- if (u.find("://") == std::string::npos)
- {
- mNormalizedUri = "http://";
- mTmpScheme = true;
- }
+ if (u.find("://") == std::string::npos)
+ {
+ mNormalizedUri = "http://";
+ mTmpScheme = true;
+ }
- mNormalizedUri += u.c_str();
+ mNormalizedUri += u.c_str();
- mRes = parse();
+ mRes = parse();
}
LLUriParser::~LLUriParser()
{
- uriFreeUriMembersA(&mUri);
+ uriFreeUriMembersA(&mUri);
}
S32 LLUriParser::parse()
{
- mRes = uriParseSingleUriA(&mUri, mNormalizedUri.c_str(), NULL);
- return mRes;
+ mRes = uriParseSingleUriA(&mUri, mNormalizedUri.c_str(), NULL);
+ return mRes;
}
const char * LLUriParser::scheme() const
{
- return mScheme.c_str();
+ return mScheme.c_str();
}
void LLUriParser::sheme(const std::string& s)
{
- mTmpScheme = !s.size();
- mScheme = s;
+ mTmpScheme = !s.size();
+ mScheme = s;
}
const char * LLUriParser::port() const
{
- return mPort.c_str();
+ return mPort.c_str();
}
void LLUriParser::port(const std::string& s)
{
- mPort = s;
+ mPort = s;
}
const char * LLUriParser::host() const
{
- return mHost.c_str();
+ return mHost.c_str();
}
void LLUriParser::host(const std::string& s)
{
- mHost = s;
+ mHost = s;
}
const char * LLUriParser::path() const
{
- return mPath.c_str();
+ return mPath.c_str();
}
void LLUriParser::path(const std::string& s)
{
- mPath = s;
+ mPath = s;
}
const char * LLUriParser::query() const
{
- return mQuery.c_str();
+ return mQuery.c_str();
}
void LLUriParser::query(const std::string& s)
{
- mQuery = s;
+ mQuery = s;
}
const char * LLUriParser::fragment() const
{
- return mFragment.c_str();
+ return mFragment.c_str();
}
void LLUriParser::fragment(const std::string& s)
{
- mFragment = s;
+ mFragment = s;
}
void LLUriParser::textRangeToString(UriTextRangeA& textRange, std::string& str)
{
- if (textRange.first != NULL && textRange.afterLast != NULL && textRange.first < textRange.afterLast)
- {
- const ptrdiff_t len = textRange.afterLast - textRange.first;
- str.assign(textRange.first, static_cast<std::string::size_type>(len));
- }
- else
- {
- str = LLStringUtil::null;
- }
+ if (textRange.first != NULL && textRange.afterLast != NULL && textRange.first < textRange.afterLast)
+ {
+ const ptrdiff_t len = textRange.afterLast - textRange.first;
+ str.assign(textRange.first, static_cast<std::string::size_type>(len));
+ }
+ else
+ {
+ str = LLStringUtil::null;
+ }
}
void LLUriParser::extractParts()
{
- if (mTmpScheme || mNormalizedTmp)
- {
- mScheme.clear();
- }
- else
- {
- textRangeToString(mUri.scheme, mScheme);
- }
-
- textRangeToString(mUri.hostText, mHost);
- textRangeToString(mUri.portText, mPort);
- textRangeToString(mUri.query, mQuery);
- textRangeToString(mUri.fragment, mFragment);
-
- UriPathSegmentA * pathHead = mUri.pathHead;
- while (pathHead)
- {
- std::string partOfPath;
- textRangeToString(pathHead->text, partOfPath);
-
- mPath += '/';
- mPath += partOfPath;
-
- pathHead = pathHead->next;
- }
+ if (mTmpScheme || mNormalizedTmp)
+ {
+ mScheme.clear();
+ }
+ else
+ {
+ textRangeToString(mUri.scheme, mScheme);
+ }
+
+ textRangeToString(mUri.hostText, mHost);
+ textRangeToString(mUri.portText, mPort);
+ textRangeToString(mUri.query, mQuery);
+ textRangeToString(mUri.fragment, mFragment);
+
+ UriPathSegmentA * pathHead = mUri.pathHead;
+ while (pathHead)
+ {
+ std::string partOfPath;
+ textRangeToString(pathHead->text, partOfPath);
+
+ mPath += '/';
+ mPath += partOfPath;
+
+ pathHead = pathHead->next;
+ }
}
#if LL_DARWIN
@@ -177,14 +177,14 @@ void uri_signal_handler(int signal)
S32 LLUriParser::normalize()
{
- mNormalizedTmp = mTmpScheme;
- if (!mRes)
- {
+ mNormalizedTmp = mTmpScheme;
+ if (!mRes)
+ {
#if LL_DARWIN
sighandler_t last_sigill_handler, last_sigbus_handler;
- last_sigill_handler = signal(SIGILL, &uri_signal_handler); // illegal instruction
+ last_sigill_handler = signal(SIGILL, &uri_signal_handler); // illegal instruction
last_sigbus_handler = signal(SIGBUS, &uri_signal_handler);
-
+
if (setjmp(return_to_normalize))
{
// Issue: external library crashed via signal
@@ -230,79 +230,79 @@ S32 LLUriParser::normalize()
}
}
}
- }
+ }
- if(mTmpScheme && mNormalizedUri.size() > 7)
- {
- mNormalizedUri = mNormalizedUri.substr(7);
- mTmpScheme = false;
- }
+ if(mTmpScheme && mNormalizedUri.size() > 7)
+ {
+ mNormalizedUri = mNormalizedUri.substr(7);
+ mTmpScheme = false;
+ }
- return mRes;
+ return mRes;
}
void LLUriParser::glue(std::string& uri) const
{
- std::string first_part;
- glueFirst(first_part);
+ std::string first_part;
+ glueFirst(first_part);
- std::string second_part;
- glueSecond(second_part);
+ std::string second_part;
+ glueSecond(second_part);
- uri = first_part + second_part;
+ uri = first_part + second_part;
}
void LLUriParser::glueFirst(std::string& uri, bool use_scheme) const
{
- if (use_scheme && mScheme.size())
- {
- uri = mScheme;
- uri += "://";
- }
- else
- {
- uri.clear();
- }
-
- uri += mHost;
+ if (use_scheme && mScheme.size())
+ {
+ uri = mScheme;
+ uri += "://";
+ }
+ else
+ {
+ uri.clear();
+ }
+
+ uri += mHost;
}
void LLUriParser::glueSecond(std::string& uri) const
{
- if (mPort.size())
- {
- uri = ':';
- uri += mPort;
- }
- else
- {
- uri.clear();
- }
-
- uri += mPath;
-
- if (mQuery.size())
- {
- uri += '?';
- uri += mQuery;
- }
-
- if (mFragment.size())
- {
- uri += '#';
- uri += mFragment;
- }
+ if (mPort.size())
+ {
+ uri = ':';
+ uri += mPort;
+ }
+ else
+ {
+ uri.clear();
+ }
+
+ uri += mPath;
+
+ if (mQuery.size())
+ {
+ uri += '?';
+ uri += mQuery;
+ }
+
+ if (mFragment.size())
+ {
+ uri += '#';
+ uri += mFragment;
+ }
}
bool LLUriParser::test() const
{
- std::string uri;
- glue(uri);
+ std::string uri;
+ glue(uri);
- return uri == mNormalizedUri;
+ return uri == mNormalizedUri;
}
const char * LLUriParser::normalizedUri() const
{
- return mNormalizedUri.c_str();
+ return mNormalizedUri.c_str();
}
diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h
index 92626b9054..77eb4031d5 100644
--- a/indra/llcommon/lluriparser.h
+++ b/indra/llcommon/lluriparser.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lluriparser.h
* @author Protey
* @date 20146-10-07
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2014, 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,52 +35,52 @@
class LL_COMMON_API LLUriParser
{
public:
- LLUriParser(const std::string& u);
- ~LLUriParser();
+ LLUriParser(const std::string& u);
+ ~LLUriParser();
- const char * scheme() const;
- void sheme (const std::string& s);
+ const char * scheme() const;
+ void sheme (const std::string& s);
- const char * port() const;
- void port (const std::string& s);
+ const char * port() const;
+ void port (const std::string& s);
- const char * host() const;
- void host (const std::string& s);
+ const char * host() const;
+ void host (const std::string& s);
- const char * path() const;
- void path (const std::string& s);
+ const char * path() const;
+ void path (const std::string& s);
- const char * query() const;
- void query (const std::string& s);
+ const char * query() const;
+ void query (const std::string& s);
- const char * fragment() const;
- void fragment (const std::string& s);
+ const char * fragment() const;
+ void fragment (const std::string& s);
- const char * normalizedUri() const;
+ const char * normalizedUri() const;
- void extractParts();
- void glue(std::string& uri) const;
- void glueFirst(std::string& uri, bool use_scheme = true) const;
- void glueSecond(std::string& uri) const;
- bool test() const;
- S32 normalize();
+ void extractParts();
+ void glue(std::string& uri) const;
+ void glueFirst(std::string& uri, bool use_scheme = true) const;
+ void glueSecond(std::string& uri) const;
+ bool test() const;
+ S32 normalize();
private:
- S32 parse();
- void textRangeToString(UriTextRangeA& textRange, std::string& str);
- std::string mScheme;
- std::string mHost;
- std::string mPort;
- std::string mPath;
- std::string mQuery;
- std::string mFragment;
- std::string mNormalizedUri;
+ S32 parse();
+ void textRangeToString(UriTextRangeA& textRange, std::string& str);
+ std::string mScheme;
+ std::string mHost;
+ std::string mPort;
+ std::string mPath;
+ std::string mQuery;
+ std::string mFragment;
+ std::string mNormalizedUri;
- UriUriA mUri;
+ UriUriA mUri;
- S32 mRes;
- bool mTmpScheme;
- bool mNormalizedTmp;
+ S32 mRes;
+ bool mTmpScheme;
+ bool mNormalizedTmp;
};
#endif // LL_LLURIPARSER_H
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 200add404f..ab66fa6ddc 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -50,7 +50,7 @@
const LLUUID LLUUID::null;
const LLTransactionID LLTransactionID::tnull;
-// static
+// static
LLMutex* LLUUID::mMutex = NULL;
@@ -187,7 +187,7 @@ void LLUUID::toString(char* out) const
void LLUUID::toCompressedString(std::string& out) const
{
char bytes[UUID_BYTES + 1];
- memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */
+ memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */
bytes[UUID_BYTES] = '\0';
out.assign(bytes, UUID_BYTES);
}
@@ -195,7 +195,7 @@ void LLUUID::toCompressedString(std::string& out) const
// *TODO: deprecate
void LLUUID::toCompressedString(char* out) const
{
- memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
+ memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
out[UUID_BYTES] = '\0';
}
@@ -227,11 +227,11 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
return TRUE;
}
- if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
+ if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
{
// I'm a moron. First implementation didn't have the right UUID format.
// Shouldn't see any of these any more
- if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
+ if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
{
if (emit)
{
@@ -323,10 +323,10 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
BOOL LLUUID::validate(const std::string& in_string)
{
BOOL broken_format = FALSE;
- if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
+ if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
{
// I'm a moron. First implementation didn't have the right UUID format.
- if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
+ if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
{
broken_format = TRUE;
}
@@ -431,7 +431,7 @@ std::ostream& operator<<(std::ostream& s, const LLUUID& uuid)
std::istream& operator>>(std::istream& s, LLUUID& uuid)
{
U32 i;
- char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
+ char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
for (i = 0; i < UUID_STR_LENGTH - 1; i++)
{
s >> uuid_str[i];
@@ -459,7 +459,7 @@ static void get_random_bytes(void* buf, int nbytes)
return;
}
-#if LL_WINDOWS
+#if LL_WINDOWS
typedef struct _ASTAT_
{
@@ -468,7 +468,7 @@ typedef struct _ASTAT_
}ASTAT, * PASTAT;
// static
-S32 LLUUID::getNodeID(unsigned char* node_id)
+S32 LLUUID::getNodeID(unsigned char* node_id)
{
ASTAT Adapter;
NCB Ncb;
@@ -495,14 +495,14 @@ S32 LLUUID::getNodeID(unsigned char* node_id)
Ncb.ncb_command = NCBASTAT;
Ncb.ncb_lana_num = lenum.lana[i];
- strcpy((char*)Ncb.ncb_callname, "* "); /* Flawfinder: ignore */
+ strcpy((char*)Ncb.ncb_callname, "* "); /* Flawfinder: ignore */
Ncb.ncb_buffer = (unsigned char*)&Adapter;
Ncb.ncb_length = sizeof(Adapter);
uRetCode = Netbios(&Ncb);
if (uRetCode == 0)
{
- memcpy(node_id, Adapter.adapt.adapter_address, 6); /* Flawfinder: ignore */
+ memcpy(node_id, Adapter.adapt.adapter_address, 6); /* Flawfinder: ignore */
retval = 1;
}
}
@@ -545,19 +545,19 @@ S32 LLUUID::getNodeID(unsigned char* node_id)
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
{
- // printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family);
+ // printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family);
for (i = 0; i < ifa->ifa_addr->sa_len; i++)
{
- // printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]);
+ // printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]);
}
- // printf("\n");
+ // printf("\n");
if (ifa->ifa_addr->sa_family == AF_LINK)
{
// This is a link-level address
struct sockaddr_dl* lla = (struct sockaddr_dl*)ifa->ifa_addr;
- // printf("\tLink level address, type %02X\n", lla->sdl_type);
+ // printf("\tLink level address, type %02X\n", lla->sdl_type);
if (lla->sdl_type == IFT_ETHER)
{
@@ -614,11 +614,11 @@ S32 LLUUID::getNodeID(unsigned char* node_id)
// static
S32 LLUUID::getNodeID(unsigned char* node_id)
{
- int sd;
- struct ifreq ifr, * ifrp;
- struct ifconf ifc;
+ int sd;
+ struct ifreq ifr, * ifrp;
+ struct ifconf ifc;
char buf[1024];
- int n, i;
+ int n, i;
unsigned char* a;
/*
@@ -651,7 +651,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id)
n = ifc.ifc_len;
for (i = 0; i < n; i += ifreq_size(*ifr)) {
ifrp = (struct ifreq*)((char*)ifc.ifc_buf + i);
- strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */
+ strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */
#ifdef SIOCGIFHWADDR
if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
continue;
@@ -673,7 +673,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id)
if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
continue;
if (node_id) {
- memcpy(node_id, a, 6); /* Flawfinder: ignore */
+ memcpy(node_id, a, 6); /* Flawfinder: ignore */
close(sd);
return 1;
}
@@ -784,7 +784,7 @@ void LLUUID::generate()
// Create a UUID.
uuid_time_t timestamp;
- static unsigned char node_id[6]; /* Flawfinder: ignore */
+ static unsigned char node_id[6]; /* Flawfinder: ignore */
static int has_init = 0;
// Create a UUID.
@@ -826,16 +826,16 @@ void LLUUID::generate()
// if clock hasn't changed or went backward, change clockseq
if (cmpTime(&timestamp, &time_last) != 1)
{
- LLMutexLock lock(mMutex);
+ LLMutexLock lock(mMutex);
clock_seq = (clock_seq + 1) & 0x3FFF;
if (clock_seq == 0)
clock_seq++;
- our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time
+ our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time
}
time_last = timestamp;
- memcpy(mData + 10, node_id, 6); /* Flawfinder: ignore */
+ memcpy(mData + 10, node_id, 6); /* Flawfinder: ignore */
U32 tmp;
tmp = timestamp.low;
mData[3] = (unsigned char)tmp;
@@ -872,7 +872,7 @@ void LLUUID::generate(const std::string& hash_string)
U32 LLUUID::getRandomSeed()
{
- static unsigned char seed[16]; /* Flawfinder: ignore */
+ static unsigned char seed[16]; /* Flawfinder: ignore */
getNodeID(&seed[0]);
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 80597fa186..eea5e39c61 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file lluuid.h
*
* $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$
*/
@@ -37,104 +37,104 @@ class LLMutex;
const S32 UUID_BYTES = 16;
const S32 UUID_WORDS = 4;
-const S32 UUID_STR_LENGTH = 37; // actually wrong, should be 36 and use size below
+const S32 UUID_STR_LENGTH = 37; // actually wrong, should be 36 and use size below
const S32 UUID_STR_SIZE = 37;
const S32 UUID_BASE85_LENGTH = 21; // including the trailing NULL.
struct uuid_time_t {
- U32 high;
- U32 low;
- };
+ U32 high;
+ U32 low;
+ };
class LL_COMMON_API LLUUID
{
public:
- //
- // CREATORS
- //
- LLUUID();
- explicit LLUUID(const char *in_string); // Convert from string.
- explicit LLUUID(const std::string& in_string); // Convert from string.
- ~LLUUID() = default;
-
- //
- // MANIPULATORS
- //
- void generate(); // Generate a new UUID
- void generate(const std::string& stream); //Generate a new UUID based on hash of input stream
-
- static LLUUID generateNewID(std::string stream = ""); //static version of above for use in initializer expressions such as constructor params, etc.
-
- BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings
- BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings
- void setNull(); // Faster than setting to LLUUID::null.
+ //
+ // CREATORS
+ //
+ LLUUID();
+ explicit LLUUID(const char *in_string); // Convert from string.
+ explicit LLUUID(const std::string& in_string); // Convert from string.
+ ~LLUUID() = default;
+
+ //
+ // MANIPULATORS
+ //
+ void generate(); // Generate a new UUID
+ void generate(const std::string& stream); //Generate a new UUID based on hash of input stream
+
+ static LLUUID generateNewID(std::string stream = ""); //static version of above for use in initializer expressions such as constructor params, etc.
+
+ BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings
+ BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings
+ void setNull(); // Faster than setting to LLUUID::null.
S32 cmpTime(uuid_time_t *t1, uuid_time_t *t2);
- static void getSystemTime(uuid_time_t *timestamp);
- void getCurrentTime(uuid_time_t *timestamp);
-
- //
- // ACCESSORS
- //
- BOOL isNull() const; // Faster than comparing to LLUUID::null.
- BOOL notNull() const; // Faster than comparing to LLUUID::null.
- // JC: This is dangerous. It allows UUIDs to be cast automatically
- // to integers, among other things. Use isNull() or notNull().
- // operator bool() const;
-
- // JC: These must return real bool's (not BOOLs) or else use of the STL
- // will generate bool-to-int performance warnings.
- bool operator==(const LLUUID &rhs) const;
- bool operator!=(const LLUUID &rhs) const;
- bool operator<(const LLUUID &rhs) const;
- bool operator>(const LLUUID &rhs) const;
-
- // xor functions. Useful since any two random uuids xored together
- // will yield a determinate third random unique id that can be
- // used as a key in a single uuid that represents 2.
- const LLUUID& operator^=(const LLUUID& rhs);
- LLUUID operator^(const LLUUID& rhs) const;
-
- // similar to functions above, but not invertible
- // yields a third random UUID that can be reproduced from the two inputs
- // but which, given the result and one of the inputs can't be used to
- // deduce the other input
- LLUUID combine(const LLUUID& other) const;
- void combine(const LLUUID& other, LLUUID& result) const;
-
- friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
- friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
-
- void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
- void toString(std::string& out) const;
- void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
- void toCompressedString(std::string& out) const;
-
- std::string asString() const;
- std::string getString() const;
-
- U16 getCRC16() const;
- U32 getCRC32() const;
-
- // Returns a 64 bits digest of the UUID, by XORing its two 64 bits long
- // words. HB
- inline U64 getDigest64() const
- {
- U64* tmp = (U64*)mData;
- return tmp[0] ^ tmp[1];
- }
-
- static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.
-
- static const LLUUID null;
- static LLMutex * mMutex;
-
- static U32 getRandomSeed();
- static S32 getNodeID(unsigned char * node_id);
-
- static BOOL parseUUID(const std::string& buf, LLUUID* value);
-
- U8 mData[UUID_BYTES];
+ static void getSystemTime(uuid_time_t *timestamp);
+ void getCurrentTime(uuid_time_t *timestamp);
+
+ //
+ // ACCESSORS
+ //
+ BOOL isNull() const; // Faster than comparing to LLUUID::null.
+ BOOL notNull() const; // Faster than comparing to LLUUID::null.
+ // JC: This is dangerous. It allows UUIDs to be cast automatically
+ // to integers, among other things. Use isNull() or notNull().
+ // operator bool() const;
+
+ // JC: These must return real bool's (not BOOLs) or else use of the STL
+ // will generate bool-to-int performance warnings.
+ bool operator==(const LLUUID &rhs) const;
+ bool operator!=(const LLUUID &rhs) const;
+ bool operator<(const LLUUID &rhs) const;
+ bool operator>(const LLUUID &rhs) const;
+
+ // xor functions. Useful since any two random uuids xored together
+ // will yield a determinate third random unique id that can be
+ // used as a key in a single uuid that represents 2.
+ const LLUUID& operator^=(const LLUUID& rhs);
+ LLUUID operator^(const LLUUID& rhs) const;
+
+ // similar to functions above, but not invertible
+ // yields a third random UUID that can be reproduced from the two inputs
+ // but which, given the result and one of the inputs can't be used to
+ // deduce the other input
+ LLUUID combine(const LLUUID& other) const;
+ void combine(const LLUUID& other, LLUUID& result) const;
+
+ friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
+ friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
+
+ void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
+ void toString(std::string& out) const;
+ void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
+ void toCompressedString(std::string& out) const;
+
+ std::string asString() const;
+ std::string getString() const;
+
+ U16 getCRC16() const;
+ U32 getCRC32() const;
+
+ // Returns a 64 bits digest of the UUID, by XORing its two 64 bits long
+ // words. HB
+ inline U64 getDigest64() const
+ {
+ U64* tmp = (U64*)mData;
+ return tmp[0] ^ tmp[1];
+ }
+
+ static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.
+
+ static const LLUUID null;
+ static LLMutex * mMutex;
+
+ static U32 getRandomSeed();
+ static S32 getNodeID(unsigned char * node_id);
+
+ static BOOL parseUUID(const std::string& buf, LLUUID* value);
+
+ U8 mData[UUID_BYTES];
};
static_assert(std::is_trivially_copyable<LLUUID>::value, "LLUUID must be trivial copy");
static_assert(std::is_trivially_move_assignable<LLUUID>::value, "LLUUID must be trivial move");
@@ -151,10 +151,10 @@ typedef std::set<LLUUID> uuid_set_t;
// verify.)
struct lluuid_less
{
- bool operator()(const LLUUID& lhs, const LLUUID& rhs) const
- {
- return (lhs < rhs) ? true : false;
- }
+ bool operator()(const LLUUID& lhs, const LLUUID& rhs) const
+ {
+ return (lhs < rhs) ? true : false;
+ }
};
typedef std::set<LLUUID, lluuid_less> uuid_list_t;
@@ -167,28 +167,28 @@ typedef LLUUID LLAssetID;
class LL_COMMON_API LLTransactionID : public LLUUID
{
public:
- LLTransactionID() : LLUUID() { }
-
- static const LLTransactionID tnull;
- LLAssetID makeAssetID(const LLUUID& session) const;
+ LLTransactionID() : LLUUID() { }
+
+ static const LLTransactionID tnull;
+ LLAssetID makeAssetID(const LLUUID& session) const;
};
// std::hash implementation for LLUUID
namespace std
{
- template<> struct hash<LLUUID>
- {
- inline size_t operator()(const LLUUID& id) const noexcept
- {
- return (size_t)id.getDigest64();
- }
- };
+ template<> struct hash<LLUUID>
+ {
+ inline size_t operator()(const LLUUID& id) const noexcept
+ {
+ return (size_t)id.getDigest64();
+ }
+ };
}
// For use with boost containers.
inline size_t hash_value(const LLUUID& id) noexcept
{
- return (size_t)id.getDigest64();
+ return (size_t)id.getDigest64();
}
#endif // LL_LLUUID_H
diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h
index 8cfa40ada8..f679adc200 100644
--- a/indra/llcommon/llwin32headers.h
+++ b/indra/llcommon/llwin32headers.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llwin32headers.h
* @brief sanitized include of windows header files
*
* $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$
*/
diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h
index 314e7a85d1..97c8edb8cf 100644
--- a/indra/llcommon/llwin32headerslean.h
+++ b/indra/llcommon/llwin32headerslean.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llwin32headerslean.h
* @brief sanitized include of windows header files
*
* $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$
*/
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 06c74bdba0..67df2b5840 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file llworkerthread.cpp
*
* $LicenseInfo:firstyear=2004&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,134 +35,134 @@
// Run on MAIN thread
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
- LLQueuedThread(name, threaded, should_pause)
+ LLQueuedThread(name, threaded, should_pause)
{
- mDeleteMutex = new LLMutex();
+ mDeleteMutex = new LLMutex();
- if(!mLocalAPRFilePoolp)
- {
- mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
- }
+ if(!mLocalAPRFilePoolp)
+ {
+ mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
+ }
}
LLWorkerThread::~LLWorkerThread()
{
- // Delete any workers in the delete queue (should be safe - had better be!)
- if (!mDeleteList.empty())
- {
- LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
- << " entries in delete list." << LL_ENDL;
- }
-
- delete mDeleteMutex;
-
- // ~LLQueuedThread() will be called here
+ // Delete any workers in the delete queue (should be safe - had better be!)
+ if (!mDeleteList.empty())
+ {
+ LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << LL_ENDL;
+ }
+
+ delete mDeleteMutex;
+
+ // ~LLQueuedThread() will be called here
}
//called only in destructor.
void LLWorkerThread::clearDeleteList()
{
- // Delete any workers in the delete queue (should be safe - had better be!)
- if (!mDeleteList.empty())
- {
- LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
- << " entries in delete list." << LL_ENDL;
-
- mDeleteMutex->lock();
- for (LLWorkerClass* worker : mDeleteList)
- {
- worker->mRequestHandle = LLWorkerThread::nullHandle();
- worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
- worker->clearFlags(LLWorkerClass::WCF_WORKING);
- delete worker;
- }
- mDeleteList.clear() ;
- mDeleteMutex->unlock() ;
- }
+ // Delete any workers in the delete queue (should be safe - had better be!)
+ if (!mDeleteList.empty())
+ {
+ LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << LL_ENDL;
+
+ mDeleteMutex->lock();
+ for (LLWorkerClass* worker : mDeleteList)
+ {
+ worker->mRequestHandle = LLWorkerThread::nullHandle();
+ worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ worker->clearFlags(LLWorkerClass::WCF_WORKING);
+ delete worker;
+ }
+ mDeleteList.clear() ;
+ mDeleteMutex->unlock() ;
+ }
}
// virtual
size_t LLWorkerThread::update(F32 max_time_ms)
{
- auto res = LLQueuedThread::update(max_time_ms);
- // Delete scheduled workers
- std::vector<LLWorkerClass*> delete_list;
- std::vector<LLWorkerClass*> abort_list;
- mDeleteMutex->lock();
- for (delete_list_t::iterator iter = mDeleteList.begin();
- iter != mDeleteList.end(); )
- {
- delete_list_t::iterator curiter = iter++;
- LLWorkerClass* worker = *curiter;
- if (worker->deleteOK())
- {
- if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
- {
+ auto res = LLQueuedThread::update(max_time_ms);
+ // Delete scheduled workers
+ std::vector<LLWorkerClass*> delete_list;
+ std::vector<LLWorkerClass*> abort_list;
+ mDeleteMutex->lock();
+ for (delete_list_t::iterator iter = mDeleteList.begin();
+ iter != mDeleteList.end(); )
+ {
+ delete_list_t::iterator curiter = iter++;
+ LLWorkerClass* worker = *curiter;
+ if (worker->deleteOK())
+ {
+ if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
+ {
worker->setFlags(LLWorkerClass::WCF_DELETE_REQUESTED);
- delete_list.push_back(worker);
- mDeleteList.erase(curiter);
- }
- else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED))
- {
- abort_list.push_back(worker);
- }
- }
- }
- mDeleteMutex->unlock();
- // abort and delete after releasing mutex
- for (LLWorkerClass* worker : abort_list)
- {
- worker->abortWork(false);
- }
- for (LLWorkerClass* worker : delete_list)
- {
- if (worker->mRequestHandle)
- {
- // Finished but not completed
- completeRequest(worker->mRequestHandle);
- worker->mRequestHandle = LLWorkerThread::nullHandle();
- worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
- }
- delete worker;
- }
- // delete and aborted entries mean there's still work to do
- res += delete_list.size() + abort_list.size();
- return res;
+ delete_list.push_back(worker);
+ mDeleteList.erase(curiter);
+ }
+ else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED))
+ {
+ abort_list.push_back(worker);
+ }
+ }
+ }
+ mDeleteMutex->unlock();
+ // abort and delete after releasing mutex
+ for (LLWorkerClass* worker : abort_list)
+ {
+ worker->abortWork(false);
+ }
+ for (LLWorkerClass* worker : delete_list)
+ {
+ if (worker->mRequestHandle)
+ {
+ // Finished but not completed
+ completeRequest(worker->mRequestHandle);
+ worker->mRequestHandle = LLWorkerThread::nullHandle();
+ worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ }
+ delete worker;
+ }
+ // delete and aborted entries mean there's still work to do
+ res += delete_list.size() + abort_list.size();
+ return res;
}
//----------------------------------------------------------------------------
LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param)
{
- handle_t handle = generateHandle();
-
- WorkRequest* req = new WorkRequest(handle, workerclass, param);
-
- bool res = addRequest(req);
- if (!res)
- {
- LL_ERRS() << "add called after LLWorkerThread::cleanupClass()" << LL_ENDL;
- req->deleteRequest();
- handle = nullHandle();
- }
-
- return handle;
+ handle_t handle = generateHandle();
+
+ WorkRequest* req = new WorkRequest(handle, workerclass, param);
+
+ bool res = addRequest(req);
+ if (!res)
+ {
+ LL_ERRS() << "add called after LLWorkerThread::cleanupClass()" << LL_ENDL;
+ req->deleteRequest();
+ handle = nullHandle();
+ }
+
+ return handle;
}
void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)
{
- mDeleteMutex->lock();
- mDeleteList.push_back(workerclass);
- mDeleteMutex->unlock();
+ mDeleteMutex->lock();
+ mDeleteList.push_back(workerclass);
+ mDeleteMutex->unlock();
}
//============================================================================
// Runs on its OWN thread
LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) :
- LLQueuedThread::QueuedRequest(handle),
- mWorkerClass(workerclass),
- mParam(param)
+ LLQueuedThread::QueuedRequest(handle),
+ mWorkerClass(workerclass),
+ mParam(param)
{
}
@@ -173,75 +173,75 @@ LLWorkerThread::WorkRequest::~WorkRequest()
// virtual (required for access by LLWorkerThread)
void LLWorkerThread::WorkRequest::deleteRequest()
{
- LLQueuedThread::QueuedRequest::deleteRequest();
-}
+ LLQueuedThread::QueuedRequest::deleteRequest();
+}
// virtual
bool LLWorkerThread::WorkRequest::processRequest()
{
LL_PROFILE_ZONE_SCOPED;
- LLWorkerClass* workerclass = getWorkerClass();
- workerclass->setWorking(true);
- bool complete = workerclass->doWork(getParam());
- workerclass->setWorking(false);
- return complete;
+ LLWorkerClass* workerclass = getWorkerClass();
+ workerclass->setWorking(true);
+ bool complete = workerclass->doWork(getParam());
+ workerclass->setWorking(false);
+ return complete;
}
// virtual
void LLWorkerThread::WorkRequest::finishRequest(bool completed)
{
LL_PROFILE_ZONE_SCOPED;
- LLWorkerClass* workerclass = getWorkerClass();
- workerclass->finishWork(getParam(), completed);
- U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED);
- workerclass->setFlags(flags);
+ LLWorkerClass* workerclass = getWorkerClass();
+ workerclass->finishWork(getParam(), completed);
+ U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED);
+ workerclass->setFlags(flags);
}
//============================================================================
// LLWorkerClass:: operates in main thread
LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& name)
- : mWorkerThread(workerthread),
- mWorkerClassName(name),
- mRequestHandle(LLWorkerThread::nullHandle()),
- mMutex(),
- mWorkFlags(0)
+ : mWorkerThread(workerthread),
+ mWorkerClassName(name),
+ mRequestHandle(LLWorkerThread::nullHandle()),
+ mMutex(),
+ mWorkFlags(0)
{
- if (!mWorkerThread)
- {
- LL_ERRS() << "LLWorkerClass() called with NULL workerthread: " << name << LL_ENDL;
- }
+ if (!mWorkerThread)
+ {
+ LL_ERRS() << "LLWorkerClass() called with NULL workerthread: " << name << LL_ENDL;
+ }
}
LLWorkerClass::~LLWorkerClass()
{
- llassert_always(!(mWorkFlags & WCF_WORKING));
- llassert_always(mWorkFlags & WCF_DELETE_REQUESTED);
- llassert_always(!mMutex.isLocked());
- if (mRequestHandle != LLWorkerThread::nullHandle())
- {
- LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
- if (!workreq)
- {
- LL_ERRS() << "LLWorkerClass destroyed with stale work handle" << LL_ENDL;
- }
- if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
- workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
- {
- LL_ERRS() << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << LL_ENDL;
- }
- }
+ llassert_always(!(mWorkFlags & WCF_WORKING));
+ llassert_always(mWorkFlags & WCF_DELETE_REQUESTED);
+ llassert_always(!mMutex.isLocked());
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
+ if (!workreq)
+ {
+ LL_ERRS() << "LLWorkerClass destroyed with stale work handle" << LL_ENDL;
+ }
+ if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
+ workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
+ {
+ LL_ERRS() << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << LL_ENDL;
+ }
+ }
}
void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread)
{
- mMutex.lock();
- if (mRequestHandle != LLWorkerThread::nullHandle())
- {
- LL_ERRS() << "LLWorkerClass attempt to change WorkerThread with active worker!" << LL_ENDL;
- }
- mWorkerThread = workerthread;
- mMutex.unlock();
+ mMutex.lock();
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LL_ERRS() << "LLWorkerClass attempt to change WorkerThread with active worker!" << LL_ENDL;
+ }
+ mWorkerThread = workerthread;
+ mMutex.unlock();
}
//----------------------------------------------------------------------------
@@ -254,7 +254,7 @@ void LLWorkerClass::finishWork(S32 param, bool success)
//virtual
bool LLWorkerClass::deleteOK()
{
- return true; // default always OK
+ return true; // default always OK
}
//----------------------------------------------------------------------------
@@ -262,31 +262,31 @@ bool LLWorkerClass::deleteOK()
// Called from worker thread
void LLWorkerClass::setWorking(bool working)
{
- mMutex.lock();
- if (working)
- {
- llassert_always(!(mWorkFlags & WCF_WORKING));
- setFlags(WCF_WORKING);
- }
- else
- {
- llassert_always((mWorkFlags & WCF_WORKING));
- clearFlags(WCF_WORKING);
- }
- mMutex.unlock();
+ mMutex.lock();
+ if (working)
+ {
+ llassert_always(!(mWorkFlags & WCF_WORKING));
+ setFlags(WCF_WORKING);
+ }
+ else
+ {
+ llassert_always((mWorkFlags & WCF_WORKING));
+ clearFlags(WCF_WORKING);
+ }
+ mMutex.unlock();
}
//----------------------------------------------------------------------------
bool LLWorkerClass::yield()
{
- LLThread::yield();
- mWorkerThread->checkPause();
- bool res;
- mMutex.lock();
- res = (getFlags() & WCF_ABORT_REQUESTED) ? true : false;
- mMutex.unlock();
- return res;
+ LLThread::yield();
+ mWorkerThread->checkPause();
+ bool res;
+ mMutex.lock();
+ res = (getFlags() & WCF_ABORT_REQUESTED) ? true : false;
+ mMutex.unlock();
+ return res;
}
//----------------------------------------------------------------------------
@@ -294,104 +294,104 @@ bool LLWorkerClass::yield()
// calls startWork, adds doWork() to queue
void LLWorkerClass::addWork(S32 param)
{
- mMutex.lock();
- llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
- if (mRequestHandle != LLWorkerThread::nullHandle())
- {
- LL_ERRS() << "LLWorkerClass attempt to add work with active worker!" << LL_ENDL;
- }
+ mMutex.lock();
+ llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LL_ERRS() << "LLWorkerClass attempt to add work with active worker!" << LL_ENDL;
+ }
#if _DEBUG
-// LL_INFOS() << "addWork: " << mWorkerClassName << " Param: " << param << LL_ENDL;
+// LL_INFOS() << "addWork: " << mWorkerClassName << " Param: " << param << LL_ENDL;
#endif
- startWork(param);
- clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
- setFlags(WCF_HAVE_WORK);
- mRequestHandle = mWorkerThread->addWorkRequest(this, param);
- mMutex.unlock();
+ startWork(param);
+ clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
+ setFlags(WCF_HAVE_WORK);
+ mRequestHandle = mWorkerThread->addWorkRequest(this, param);
+ mMutex.unlock();
}
void LLWorkerClass::abortWork(bool autocomplete)
{
- mMutex.lock();
+ mMutex.lock();
#if _DEBUG
-// LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle);
-// if (workreq)
-// LL_INFOS() << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << LL_ENDL;
+// LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle);
+// if (workreq)
+// LL_INFOS() << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << LL_ENDL;
#endif
- if (mRequestHandle != LLWorkerThread::nullHandle())
- {
- mWorkerThread->abortRequest(mRequestHandle, autocomplete);
- setFlags(WCF_ABORT_REQUESTED);
- }
- mMutex.unlock();
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ mWorkerThread->abortRequest(mRequestHandle, autocomplete);
+ setFlags(WCF_ABORT_REQUESTED);
+ }
+ mMutex.unlock();
}
// if doWork is complete or aborted, call endWork() and return true
bool LLWorkerClass::checkWork(bool aborting)
{
- LLMutexLock lock(&mMutex);
- bool complete = false, abort = false;
- if (mRequestHandle != LLWorkerThread::nullHandle())
- {
- LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
- if(!workreq)
- {
- if(mWorkerThread->isQuitting() || mWorkerThread->isStopped()) //the mWorkerThread is not running
- {
- mRequestHandle = LLWorkerThread::nullHandle();
- clearFlags(WCF_HAVE_WORK);
- }
- else
- {
- llassert_always(workreq);
- }
- return true ;
- }
-
- LLQueuedThread::status_t status = workreq->getStatus();
- if (status == LLWorkerThread::STATUS_ABORTED)
- {
- complete = true;
- abort = true;
- }
- else if (status == LLWorkerThread::STATUS_COMPLETE)
- {
- complete = true;
- }
- else
- {
- llassert_always(!aborting || (workreq->getFlags() & LLQueuedThread::FLAG_ABORT));
- }
- if (complete)
- {
- llassert_always(!(getFlags(WCF_WORKING)));
- endWork(workreq->getParam(), abort);
- mWorkerThread->completeRequest(mRequestHandle);
- mRequestHandle = LLWorkerThread::nullHandle();
- clearFlags(WCF_HAVE_WORK);
- }
- }
- else
- {
- complete = true;
- }
- return complete;
+ LLMutexLock lock(&mMutex);
+ bool complete = false, abort = false;
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
+ if(!workreq)
+ {
+ if(mWorkerThread->isQuitting() || mWorkerThread->isStopped()) //the mWorkerThread is not running
+ {
+ mRequestHandle = LLWorkerThread::nullHandle();
+ clearFlags(WCF_HAVE_WORK);
+ }
+ else
+ {
+ llassert_always(workreq);
+ }
+ return true ;
+ }
+
+ LLQueuedThread::status_t status = workreq->getStatus();
+ if (status == LLWorkerThread::STATUS_ABORTED)
+ {
+ complete = true;
+ abort = true;
+ }
+ else if (status == LLWorkerThread::STATUS_COMPLETE)
+ {
+ complete = true;
+ }
+ else
+ {
+ llassert_always(!aborting || (workreq->getFlags() & LLQueuedThread::FLAG_ABORT));
+ }
+ if (complete)
+ {
+ llassert_always(!(getFlags(WCF_WORKING)));
+ endWork(workreq->getParam(), abort);
+ mWorkerThread->completeRequest(mRequestHandle);
+ mRequestHandle = LLWorkerThread::nullHandle();
+ clearFlags(WCF_HAVE_WORK);
+ }
+ }
+ else
+ {
+ complete = true;
+ }
+ return complete;
}
void LLWorkerClass::scheduleDelete()
{
- bool do_delete = false;
- mMutex.lock();
- if (!(getFlags(WCF_DELETE_REQUESTED)))
- {
- setFlags(WCF_DELETE_REQUESTED);
- do_delete = true;
- }
- mMutex.unlock();
- if (do_delete)
- {
- mWorkerThread->deleteWorker(this);
- }
+ bool do_delete = false;
+ mMutex.lock();
+ if (!(getFlags(WCF_DELETE_REQUESTED)))
+ {
+ setFlags(WCF_DELETE_REQUESTED);
+ do_delete = true;
+ }
+ mMutex.unlock();
+ if (do_delete)
+ {
+ mWorkerThread->deleteWorker(this);
+ }
}
//============================================================================
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index bf94c84090..01c96852d3 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llworkerthread.h
*
* $LicenseInfo:firstyear=2004&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$
*/
@@ -48,55 +48,55 @@ class LLWorkerClass;
class LL_COMMON_API LLWorkerThread : public LLQueuedThread
{
- friend class LLWorkerClass;
+ friend class LLWorkerClass;
public:
- class WorkRequest : public LLQueuedThread::QueuedRequest
- {
- protected:
- virtual ~WorkRequest(); // use deleteRequest()
-
- public:
- WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param);
-
- S32 getParam()
- {
- return mParam;
- }
- LLWorkerClass* getWorkerClass()
- {
- return mWorkerClass;
- }
-
- /*virtual*/ bool processRequest();
- /*virtual*/ void finishRequest(bool completed);
- /*virtual*/ void deleteRequest();
-
- private:
- LLWorkerClass* mWorkerClass;
- S32 mParam;
- };
+ class WorkRequest : public LLQueuedThread::QueuedRequest
+ {
+ protected:
+ virtual ~WorkRequest(); // use deleteRequest()
+
+ public:
+ WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param);
+
+ S32 getParam()
+ {
+ return mParam;
+ }
+ LLWorkerClass* getWorkerClass()
+ {
+ return mWorkerClass;
+ }
+
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
+ /*virtual*/ void deleteRequest();
+
+ private:
+ LLWorkerClass* mWorkerClass;
+ S32 mParam;
+ };
protected:
- void clearDeleteList() ;
+ void clearDeleteList() ;
private:
- typedef std::list<LLWorkerClass*> delete_list_t;
- delete_list_t mDeleteList;
- LLMutex* mDeleteMutex;
-
+ typedef std::list<LLWorkerClass*> delete_list_t;
+ delete_list_t mDeleteList;
+ LLMutex* mDeleteMutex;
+
public:
- LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false);
- ~LLWorkerThread();
+ LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false);
+ ~LLWorkerThread();
- /*virtual*/ size_t update(F32 max_time_ms);
-
- handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param);
-
- S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug
+ /*virtual*/ size_t update(F32 max_time_ms);
+
+ handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param);
+
+ S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug
private:
- void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
-
+ void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
+
};
//============================================================================
@@ -118,81 +118,81 @@ private:
class LL_COMMON_API LLWorkerClass
{
- friend class LLWorkerThread;
- friend class LLWorkerThread::WorkRequest;
+ friend class LLWorkerThread;
+ friend class LLWorkerThread::WorkRequest;
public:
- typedef LLWorkerThread::handle_t handle_t;
- enum FLAGS
- {
- WCF_HAVE_WORK = 0x01,
- WCF_WORKING = 0x02,
- WCF_WORK_FINISHED = 0x10,
- WCF_WORK_ABORTED = 0x20,
- WCF_DELETE_REQUESTED = 0x40,
- WCF_ABORT_REQUESTED = 0x80
- };
-
+ typedef LLWorkerThread::handle_t handle_t;
+ enum FLAGS
+ {
+ WCF_HAVE_WORK = 0x01,
+ WCF_WORKING = 0x02,
+ WCF_WORK_FINISHED = 0x10,
+ WCF_WORK_ABORTED = 0x20,
+ WCF_DELETE_REQUESTED = 0x40,
+ WCF_ABORT_REQUESTED = 0x80
+ };
+
public:
- LLWorkerClass(LLWorkerThread* workerthread, const std::string& name);
- virtual ~LLWorkerClass();
-
- // pure virtual, called from WORKER THREAD, returns TRUE if done
- virtual bool doWork(S32 param)=0; // Called from WorkRequest::processRequest()
- // virtual, called from finishRequest() after completed or aborted
- virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
- // virtual, returns true if safe to delete the worker
- virtual bool deleteOK(); // called from update() (WORK THREAD)
-
- // schedlueDelete(): schedules deletion once aborted or completed
- void scheduleDelete();
-
- bool haveWork() { return getFlags(WCF_HAVE_WORK); } // may still be true if aborted
- bool isWorking() { return getFlags(WCF_WORKING); }
- bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
-
- const std::string& getName() const { return mWorkerClassName; }
+ LLWorkerClass(LLWorkerThread* workerthread, const std::string& name);
+ virtual ~LLWorkerClass();
+
+ // pure virtual, called from WORKER THREAD, returns TRUE if done
+ virtual bool doWork(S32 param)=0; // Called from WorkRequest::processRequest()
+ // virtual, called from finishRequest() after completed or aborted
+ virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
+ // virtual, returns true if safe to delete the worker
+ virtual bool deleteOK(); // called from update() (WORK THREAD)
+
+ // schedlueDelete(): schedules deletion once aborted or completed
+ void scheduleDelete();
+
+ bool haveWork() { return getFlags(WCF_HAVE_WORK); } // may still be true if aborted
+ bool isWorking() { return getFlags(WCF_WORKING); }
+ bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
+
+ const std::string& getName() const { return mWorkerClassName; }
protected:
- // called from WORKER THREAD
- void setWorking(bool working);
-
- // Call from doWork only to avoid eating up cpu time.
- // Returns true if work has been aborted
- // yields the current thread and calls mWorkerThread->checkPause()
- bool yield();
-
- void setWorkerThread(LLWorkerThread* workerthread);
-
- // addWork(): calls startWork, adds doWork() to queue
- void addWork(S32 param);
-
- // abortWork(): requests that work be aborted
- void abortWork(bool autocomplete);
-
- // checkWork(): if doWork is complete or aborted, call endWork() and return true
- bool checkWork(bool aborting = false);
+ // called from WORKER THREAD
+ void setWorking(bool working);
+
+ // Call from doWork only to avoid eating up cpu time.
+ // Returns true if work has been aborted
+ // yields the current thread and calls mWorkerThread->checkPause()
+ bool yield();
+
+ void setWorkerThread(LLWorkerThread* workerthread);
+
+ // addWork(): calls startWork, adds doWork() to queue
+ void addWork(S32 param);
+
+ // abortWork(): requests that work be aborted
+ void abortWork(bool autocomplete);
+
+ // checkWork(): if doWork is complete or aborted, call endWork() and return true
+ bool checkWork(bool aborting = false);
private:
- void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; }
- void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; }
- U32 getFlags() { return mWorkFlags; }
+ void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; }
+ void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; }
+ U32 getFlags() { return mWorkFlags; }
public:
- bool getFlags(U32 flags) { return mWorkFlags & flags ? true : false; }
-
+ bool getFlags(U32 flags) { return mWorkFlags & flags ? true : false; }
+
private:
- // pure virtuals
- virtual void startWork(S32 param)=0; // called from addWork() (MAIN THREAD)
- virtual void endWork(S32 param, bool aborted)=0; // called from doWork() (MAIN THREAD)
-
+ // pure virtuals
+ virtual void startWork(S32 param)=0; // called from addWork() (MAIN THREAD)
+ virtual void endWork(S32 param, bool aborted)=0; // called from doWork() (MAIN THREAD)
+
protected:
- LLWorkerThread* mWorkerThread;
- std::string mWorkerClassName;
- handle_t mRequestHandle;
+ LLWorkerThread* mWorkerThread;
+ std::string mWorkerClassName;
+ handle_t mRequestHandle;
private:
- LLMutex mMutex;
- LLAtomicU32 mWorkFlags;
+ LLMutex mMutex;
+ LLAtomicU32 mWorkFlags;
};
//============================================================================
diff --git a/indra/llcommon/lockstatic.h b/indra/llcommon/lockstatic.h
index 96c53c6473..7cc9b7eec0 100644
--- a/indra/llcommon/lockstatic.h
+++ b/indra/llcommon/lockstatic.h
@@ -4,7 +4,7 @@
* @date 2019-12-03
* @brief LockStatic class provides mutex-guarded access to the specified
* static data.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/mutex.h b/indra/llcommon/mutex.h
index 90d0942270..82e46315e2 100644
--- a/indra/llcommon/mutex.h
+++ b/indra/llcommon/mutex.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2019-12-03
* @brief Wrap <mutex> in odious boilerplate
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h
index 3aba9dda00..28e50b3d21 100644
--- a/indra/llcommon/stdtypes.h
+++ b/indra/llcommon/stdtypes.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file stdtypes.h
* @brief Basic type declarations for cross platform compatibility.
*
* $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$
*/
@@ -32,12 +32,12 @@
#include <limits>
#include <type_traits>
-typedef signed char S8;
-typedef unsigned char U8;
-typedef signed short S16;
-typedef unsigned short U16;
-typedef signed int S32;
-typedef unsigned int U32;
+typedef signed char S8;
+typedef unsigned char U8;
+typedef signed short S16;
+typedef unsigned short U16;
+typedef signed int S32;
+typedef unsigned int U32;
// to express an index that might go negative
// (ssize_t is provided by SOME compilers, don't collide)
@@ -52,9 +52,9 @@ typedef typename std::make_signed<std::size_t>::type llssize;
// The version of clang available with VS 2019 also defines wchar_t as __wchar_t
// which is also 16 bits.
// In any case, llwchar should be a UTF-32 type.
-typedef U32 llwchar;
+typedef U32 llwchar;
#else
-typedef wchar_t llwchar;
+typedef wchar_t llwchar;
// What we'd actually want is a simple module-scope 'if constexpr' to test
// std::is_same<wchar_t, llwchar>::value and use that to define, or not
// define, string conversion specializations. Since we don't have that, we'll
@@ -63,63 +63,63 @@ typedef wchar_t llwchar;
#endif
#if LL_WINDOWS
-typedef signed __int64 S64;
+typedef signed __int64 S64;
// probably should be 'hyper' or similiar
-#define S64L(a) (a)
-typedef unsigned __int64 U64;
-#define U64L(a) (a)
+#define S64L(a) (a)
+typedef unsigned __int64 U64;
+#define U64L(a) (a)
#else
-typedef long long int S64;
-typedef long long unsigned int U64;
+typedef long long int S64;
+typedef long long unsigned int U64;
#if LL_DARWIN || LL_LINUX
-#define S64L(a) (a##LL)
-#define U64L(a) (a##ULL)
+#define S64L(a) (a##LL)
+#define U64L(a) (a##ULL)
#endif
#endif
-typedef float F32;
-typedef double F64;
+typedef float F32;
+typedef double F64;
-typedef S32 BOOL;
-typedef U8 KEY;
-typedef U32 MASK;
-typedef U32 TPACKETID;
+typedef S32 BOOL;
+typedef U8 KEY;
+typedef U32 MASK;
+typedef U32 TPACKETID;
// Use #define instead of consts to avoid conversion headaches
-#define S8_MAX (SCHAR_MAX)
-#define U8_MAX (UCHAR_MAX)
-#define S16_MAX (SHRT_MAX)
-#define U16_MAX (USHRT_MAX)
-#define S32_MAX (INT_MAX)
-#define U32_MAX (UINT_MAX)
-#define F32_MAX (FLT_MAX)
-#define F64_MAX (DBL_MAX)
-
-#define S8_MIN (SCHAR_MIN)
-#define U8_MIN (0)
-#define S16_MIN (SHRT_MIN)
-#define U16_MIN (0)
-#define S32_MIN (INT_MIN)
-#define U32_MIN (0)
-#define F32_MIN (FLT_MIN)
-#define F64_MIN (DBL_MIN)
+#define S8_MAX (SCHAR_MAX)
+#define U8_MAX (UCHAR_MAX)
+#define S16_MAX (SHRT_MAX)
+#define U16_MAX (USHRT_MAX)
+#define S32_MAX (INT_MAX)
+#define U32_MAX (UINT_MAX)
+#define F32_MAX (FLT_MAX)
+#define F64_MAX (DBL_MAX)
+
+#define S8_MIN (SCHAR_MIN)
+#define U8_MIN (0)
+#define S16_MIN (SHRT_MIN)
+#define U16_MIN (0)
+#define S32_MIN (INT_MIN)
+#define U32_MIN (0)
+#define F32_MIN (FLT_MIN)
+#define F64_MIN (DBL_MIN)
#ifndef TRUE
-#define TRUE (1)
+#define TRUE (1)
#endif
#ifndef FALSE
-#define FALSE (0)
+#define FALSE (0)
#endif
#ifndef NULL
-#define NULL (0)
+#define NULL (0)
#endif
typedef U8 LLPCode;
-#define LL_ARRAY_SIZE( _kArray ) ( sizeof( (_kArray) ) / sizeof( _kArray[0] ) )
+#define LL_ARRAY_SIZE( _kArray ) ( sizeof( (_kArray) ) / sizeof( _kArray[0] ) )
#if LL_LINUX && __GNUC__ <= 2
typedef int intptr_t;
diff --git a/indra/llcommon/string_table.h b/indra/llcommon/string_table.h
index fe6416fb50..bb525f884b 100644
--- a/indra/llcommon/string_table.h
+++ b/indra/llcommon/string_table.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file string_table.h
* @brief Legacy wrapper header.
*
* $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$
*/
diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h
index c0b13135f9..536a18abc1 100644
--- a/indra/llcommon/stringize.h
+++ b/indra/llcommon/stringize.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-12-17
* @brief stringize(item) template function and STRINGIZE(expression) macro
- *
+ *
* $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$
*/
diff --git a/indra/llcommon/tests/StringVec.h b/indra/llcommon/tests/StringVec.h
index a380b00a05..4311cba992 100644
--- a/indra/llcommon/tests/StringVec.h
+++ b/indra/llcommon/tests/StringVec.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-24
* @brief Extend TUT ensure_equals() to handle std::vector<std::string>
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/apply_test.cpp b/indra/llcommon/tests/apply_test.cpp
index 56b497e0c8..6d213c2db9 100644
--- a/indra/llcommon/tests/apply_test.cpp
+++ b/indra/llcommon/tests/apply_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-12-19
* @brief Test for apply.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp
index 9bfd567068..2810f926af 100644
--- a/indra/llcommon/tests/bitpack_test.cpp
+++ b/indra/llcommon/tests/bitpack_test.cpp
@@ -7,25 +7,25 @@
* $LicenseInfo:firstyear=2007&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$
*/
-
+
#include "linden_common.h"
#include "../llbitpack.h"
@@ -35,84 +35,84 @@
namespace tut
{
- struct bit_pack
- {
- };
- typedef test_group<bit_pack> bit_pack_t;
- typedef bit_pack_t::object bit_pack_object_t;
- tut::bit_pack_t tut_bit_pack("LLBitPack");
-
- // pack -> unpack
- template<> template<>
- void bit_pack_object_t::test<1>()
- {
- U8 packbuffer[255];
- U8 unpackbuffer[255];
- int pack_bufsize = 0;
- int unpack_bufsize = 0;
-
- LLBitPack bitpack(packbuffer, 255);
-
- char str[] = "SecondLife is a 3D virtual world";
- int len = sizeof(str);
- pack_bufsize = bitpack.bitPack((U8*) str, len*8);
- pack_bufsize = bitpack.flushBitPack();
-
- LLBitPack bitunpack(packbuffer, pack_bufsize*8);
- unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, len*8);
- ensure("bitPack: unpack size should be same as string size prior to pack", len == unpack_bufsize);
- ensure_memory_matches("str->bitPack->bitUnpack should be equal to string", str, len, unpackbuffer, unpack_bufsize);
- }
-
- // pack large, unpack in individual bytes
- template<> template<>
- void bit_pack_object_t::test<2>()
- {
- U8 packbuffer[255];
- U8 unpackbuffer[255];
- int pack_bufsize = 0;
-
- LLBitPack bitpack(packbuffer, 255);
-
- char str[] = "SecondLife";
- int len = sizeof(str);
- pack_bufsize = bitpack.bitPack((U8*) str, len*8);
- pack_bufsize = bitpack.flushBitPack();
-
- LLBitPack bitunpack(packbuffer, pack_bufsize*8);
- bitunpack.bitUnpack(&unpackbuffer[0], 8);
- ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]);
- bitunpack.bitUnpack(&unpackbuffer[0], 8);
- ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]);
- bitunpack.bitUnpack(&unpackbuffer[0], 8);
- ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]);
- bitunpack.bitUnpack(&unpackbuffer[0], 8);
- ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]);
- bitunpack.bitUnpack(&unpackbuffer[0], 8);
- ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]);
- bitunpack.bitUnpack(&unpackbuffer[0], 8);
- ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]);
- bitunpack.bitUnpack(unpackbuffer, 8*4); // Life
- ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4);
- }
-
- // U32 packing
- template<> template<>
- void bit_pack_object_t::test<3>()
- {
- U8 packbuffer[255];
- int pack_bufsize = 0;
-
- LLBitPack bitpack(packbuffer, 255);
- U32 num = 0x41fab67a;
- pack_bufsize = bitpack.bitPack((U8*)&num, 8*sizeof(U32));
- pack_bufsize = bitpack.flushBitPack();
-
- LLBitPack bitunpack(packbuffer, pack_bufsize*8);
- U32 res = 0;
- // since packing and unpacking is done on same machine in the unit test run,
- // endianness should not matter
- bitunpack.bitUnpack((U8*) &res, sizeof(res)*8);
- ensure("U32->bitPack->bitUnpack->U32 should be equal", num == res);
- }
+ struct bit_pack
+ {
+ };
+ typedef test_group<bit_pack> bit_pack_t;
+ typedef bit_pack_t::object bit_pack_object_t;
+ tut::bit_pack_t tut_bit_pack("LLBitPack");
+
+ // pack -> unpack
+ template<> template<>
+ void bit_pack_object_t::test<1>()
+ {
+ U8 packbuffer[255];
+ U8 unpackbuffer[255];
+ int pack_bufsize = 0;
+ int unpack_bufsize = 0;
+
+ LLBitPack bitpack(packbuffer, 255);
+
+ char str[] = "SecondLife is a 3D virtual world";
+ int len = sizeof(str);
+ pack_bufsize = bitpack.bitPack((U8*) str, len*8);
+ pack_bufsize = bitpack.flushBitPack();
+
+ LLBitPack bitunpack(packbuffer, pack_bufsize*8);
+ unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, len*8);
+ ensure("bitPack: unpack size should be same as string size prior to pack", len == unpack_bufsize);
+ ensure_memory_matches("str->bitPack->bitUnpack should be equal to string", str, len, unpackbuffer, unpack_bufsize);
+ }
+
+ // pack large, unpack in individual bytes
+ template<> template<>
+ void bit_pack_object_t::test<2>()
+ {
+ U8 packbuffer[255];
+ U8 unpackbuffer[255];
+ int pack_bufsize = 0;
+
+ LLBitPack bitpack(packbuffer, 255);
+
+ char str[] = "SecondLife";
+ int len = sizeof(str);
+ pack_bufsize = bitpack.bitPack((U8*) str, len*8);
+ pack_bufsize = bitpack.flushBitPack();
+
+ LLBitPack bitunpack(packbuffer, pack_bufsize*8);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]);
+ bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]);
+ bitunpack.bitUnpack(unpackbuffer, 8*4); // Life
+ ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4);
+ }
+
+ // U32 packing
+ template<> template<>
+ void bit_pack_object_t::test<3>()
+ {
+ U8 packbuffer[255];
+ int pack_bufsize = 0;
+
+ LLBitPack bitpack(packbuffer, 255);
+ U32 num = 0x41fab67a;
+ pack_bufsize = bitpack.bitPack((U8*)&num, 8*sizeof(U32));
+ pack_bufsize = bitpack.flushBitPack();
+
+ LLBitPack bitunpack(packbuffer, pack_bufsize*8);
+ U32 res = 0;
+ // since packing and unpacking is done on same machine in the unit test run,
+ // endianness should not matter
+ bitunpack.bitUnpack((U8*) &res, sizeof(res)*8);
+ ensure("U32->bitPack->bitUnpack->U32 should be equal", num == res);
+ }
}
diff --git a/indra/llcommon/tests/classic_callback_test.cpp b/indra/llcommon/tests/classic_callback_test.cpp
index c060775c24..fe79179ce6 100644
--- a/indra/llcommon/tests/classic_callback_test.cpp
+++ b/indra/llcommon/tests/classic_callback_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-09-22
* @brief Test ClassicCallback and HeapClassicCallback.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp
index 4b3e07fa75..3deb864c0c 100644
--- a/indra/llcommon/tests/commonmisc_test.cpp
+++ b/indra/llcommon/tests/commonmisc_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file common.cpp
* @author Phoenix
* @date 2005-10-12
@@ -7,27 +7,27 @@
* $LicenseInfo:firstyear=2005&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$
*/
-/**
- *
+/**
+ *
* THOROUGH_DESCRIPTION of common.cpp
*
*/
@@ -54,388 +54,388 @@
namespace tut
{
- struct sd_data
- {
- };
- typedef test_group<sd_data> sd_test;
- typedef sd_test::object sd_object;
- tut::sd_test sd("LLSD");
-
- template<> template<>
- void sd_object::test<1>()
- {
- std::ostringstream resp;
- resp << "{'connect':true, 'position':[r128,r128,r128], 'look_at':[r0,r1,r0], 'agent_access':'M', 'region_x':i8192, 'region_y':i8192}";
- std::string str = resp.str();
- LLMemoryStream mstr((U8*)str.c_str(), str.size());
- LLSD response;
- S32 count = LLSDSerialize::fromNotation(response, mstr, str.size());
- ensure("stream parsed", response.isDefined());
- ensure_equals("stream parse count", count, 13);
- ensure_equals("sd type", response.type(), LLSD::TypeMap);
- ensure_equals("map element count", response.size(), 6);
- ensure_equals("value connect", response["connect"].asBoolean(), true);
- ensure_equals("value region_x", response["region_x"].asInteger(),8192);
- ensure_equals("value region_y", response["region_y"].asInteger(),8192);
- }
-
- template<> template<>
- void sd_object::test<2>()
- {
- const std::string decoded("random");
- //const std::string encoded("cmFuZG9t\n");
- const std::string streamed("b(6)\"random\"");
- typedef std::vector<U8> buf_t;
- buf_t buf;
- std::copy(
- decoded.begin(),
- decoded.end(),
- std::back_insert_iterator<buf_t>(buf));
- LLSD sd;
- sd = buf;
- std::stringstream str;
- S32 count = LLSDSerialize::toNotation(sd, str);
- ensure_equals("output count", count, 1);
- std::string actual(str.str());
- ensure_equals("formatted binary encoding", actual, streamed);
- sd.clear();
- LLSDSerialize::fromNotation(sd, str, str.str().size());
- std::vector<U8> after;
- after = sd.asBinary();
- ensure_equals("binary decoded size", after.size(), decoded.size());
- ensure("binary decoding", (0 == memcmp(
- &after[0],
- decoded.c_str(),
- decoded.size())));
- }
-
- template<> template<>
- void sd_object::test<3>()
- {
- for(S32 i = 0; i < 100; ++i)
- {
- // gen up a starting point
- typedef std::vector<U8> buf_t;
- buf_t source;
- srand(i); /* Flawfinder: ignore */
- S32 size = rand() % 1000 + 10;
- std::generate_n(
- std::back_insert_iterator<buf_t>(source),
- size,
- rand);
- LLSD sd(source);
- std::stringstream str;
- S32 count = LLSDSerialize::toNotation(sd, str);
- sd.clear();
- ensure_equals("format count", count, 1);
- LLSD sd2;
- count = LLSDSerialize::fromNotation(sd2, str, str.str().size());
- ensure_equals("parse count", count, 1);
- buf_t dest = sd2.asBinary();
- str.str("");
- str << "binary encoding size " << i;
- ensure_equals(str.str().c_str(), dest.size(), source.size());
- str.str("");
- str << "binary encoding " << i;
- ensure(str.str().c_str(), (source == dest));
- }
- }
-
- template<> template<>
- void sd_object::test<4>()
- {
- std::ostringstream ostr;
- ostr << "{'task_id':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n"
- << "{\n\tname\tObject|\n}\n";
- std::string expected = ostr.str();
- std::stringstream serialized;
- serialized << "'" << LLSDNotationFormatter::escapeString(expected)
- << "'";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(
- sd,
- serialized,
- serialized.str().size());
- ensure_equals("parse count", count, 1);
- ensure_equals("String streaming", sd.asString(), expected);
- }
-
- template<> template<>
- void sd_object::test<5>()
- {
- for(S32 i = 0; i < 100; ++i)
- {
- // gen up a starting point
- typedef std::vector<U8> buf_t;
- buf_t source;
- srand(666 + i); /* Flawfinder: ignore */
- S32 size = rand() % 1000 + 10;
- std::generate_n(
- std::back_insert_iterator<buf_t>(source),
- size,
- rand);
- std::stringstream str;
- str << "b(" << size << ")\"";
- str.write((const char*)&source[0], size);
- str << "\"";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
- ensure_equals("binary parse", count, 1);
- buf_t actual = sd.asBinary();
- ensure_equals("binary size", actual.size(), (size_t)size);
- ensure("binary data", (0 == memcmp(&source[0], &actual[0], size)));
- }
- }
-
- template<> template<>
- void sd_object::test<6>()
- {
- std::string expected("'{\"task_id\":u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}'\t\n\t\t");
- std::stringstream str;
- str << "s(" << expected.size() << ")'";
- str.write(expected.c_str(), expected.size());
- str << "'";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
- ensure_equals("parse count", count, 1);
- std::string actual = sd.asString();
- ensure_equals("string sizes", actual.size(), expected.size());
- ensure_equals("string content", actual, expected);
- }
-
- template<> template<>
- void sd_object::test<7>()
- {
- std::string msg("come on in");
- std::stringstream stream;
- stream << "{'connect':1, 'message':'" << msg << "',"
- << " 'position':[r45.65,r100.1,r25.5],"
- << " 'look_at':[r0,r1,r0],"
- << " 'agent_access':'PG'}";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(
- sd,
- stream,
- stream.str().size());
- ensure_equals("parse count", count, 12);
- ensure_equals("bool value", sd["connect"].asBoolean(), true);
- ensure_equals("message value", sd["message"].asString(), msg);
- ensure_equals("pos x", sd["position"][0].asReal(), 45.65);
- ensure_equals("pos y", sd["position"][1].asReal(), 100.1);
- ensure_equals("pos z", sd["position"][2].asReal(), 25.5);
- ensure_equals("look x", sd["look_at"][0].asReal(), 0.0);
- ensure_equals("look y", sd["look_at"][1].asReal(), 1.0);
- ensure_equals("look z", sd["look_at"][2].asReal(), 0.0);
- }
-
- template<> template<>
- void sd_object::test<8>()
- {
- std::stringstream resp;
- resp << "{'label':'short string test', 'singlechar':'a', 'empty':'', 'endoftest':'end' }";
- LLSD response;
- S32 count = LLSDSerialize::fromNotation(
- response,
- resp,
- resp.str().size());
- ensure_equals("parse count", count, 5);
- ensure_equals("sd type", response.type(), LLSD::TypeMap);
- ensure_equals("map element count", response.size(), 4);
- ensure_equals("singlechar", response["singlechar"].asString(), "a");
- ensure_equals("empty", response["empty"].asString(), "");
- }
-
- template<> template<>
- void sd_object::test<9>()
- {
- std::ostringstream resp;
- resp << "{'label':'short binary test', 'singlebinary':b(1)\"A\", 'singlerawstring':s(1)\"A\", 'endoftest':'end' }";
- std::string str = resp.str();
- LLSD sd;
- LLMemoryStream mstr((U8*)str.c_str(), str.size());
- S32 count = LLSDSerialize::fromNotation(sd, mstr, str.size());
- ensure_equals("parse count", count, 5);
- ensure("sd created", sd.isDefined());
- ensure_equals("sd type", sd.type(), LLSD::TypeMap);
- ensure_equals("map element count", sd.size(), 4);
- ensure_equals(
- "label",
- sd["label"].asString(),
- "short binary test");
- std::vector<U8> bin = sd["singlebinary"].asBinary();
- std::vector<U8> expected;
- expected.resize(1);
- expected[0] = 'A';
- ensure("single binary", (0 == memcmp(&bin[0], &expected[0], 1)));
- ensure_equals(
- "single string",
- sd["singlerawstring"].asString(),
- std::string("A"));
- ensure_equals("end", sd["endoftest"].asString(), "end");
- }
-
- template<> template<>
- void sd_object::test<10>()
- {
-
- std::string message("parcel '' is naughty.");
- std::stringstream str;
- str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
- << "'}";
- std::string expected_str("{'message':'parcel \\'\\' is naughty.'}");
- std::string actual_str = str.str();
- ensure_equals("stream contents", actual_str, expected_str);
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, str, actual_str.size());
- ensure_equals("parse count", count, 2);
- ensure("valid parse", sd.isDefined());
- std::string actual = sd["message"].asString();
- ensure_equals("message contents", actual, message);
- }
-
- template<> template<>
- void sd_object::test<11>()
- {
- std::string expected("\"\"\"\"''''''\"");
- std::stringstream str;
- str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
- ensure_equals("parse count", count, 1);
- ensure_equals("string value", sd.asString(), expected);
- }
-
- template<> template<>
- void sd_object::test<12>()
- {
- std::string expected("mytest\\");
- std::stringstream str;
- str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
- ensure_equals("parse count", count, 1);
- ensure_equals("string value", sd.asString(), expected);
- }
-
- template<> template<>
- void sd_object::test<13>()
- {
- for(S32 i = 0; i < 1000; ++i)
- {
- // gen up a starting point
- std::string expected;
- srand(1337 + i); /* Flawfinder: ignore */
- S32 size = rand() % 30 + 5;
- std::generate_n(
- std::back_insert_iterator<std::string>(expected),
- size,
- rand);
- std::stringstream str;
- str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
- LLSD sd;
- S32 count = LLSDSerialize::fromNotation(sd, str, expected.size());
- ensure_equals("parse count", count, 1);
- std::string actual = sd.asString();
+ struct sd_data
+ {
+ };
+ typedef test_group<sd_data> sd_test;
+ typedef sd_test::object sd_object;
+ tut::sd_test sd("LLSD");
+
+ template<> template<>
+ void sd_object::test<1>()
+ {
+ std::ostringstream resp;
+ resp << "{'connect':true, 'position':[r128,r128,r128], 'look_at':[r0,r1,r0], 'agent_access':'M', 'region_x':i8192, 'region_y':i8192}";
+ std::string str = resp.str();
+ LLMemoryStream mstr((U8*)str.c_str(), str.size());
+ LLSD response;
+ S32 count = LLSDSerialize::fromNotation(response, mstr, str.size());
+ ensure("stream parsed", response.isDefined());
+ ensure_equals("stream parse count", count, 13);
+ ensure_equals("sd type", response.type(), LLSD::TypeMap);
+ ensure_equals("map element count", response.size(), 6);
+ ensure_equals("value connect", response["connect"].asBoolean(), true);
+ ensure_equals("value region_x", response["region_x"].asInteger(),8192);
+ ensure_equals("value region_y", response["region_y"].asInteger(),8192);
+ }
+
+ template<> template<>
+ void sd_object::test<2>()
+ {
+ const std::string decoded("random");
+ //const std::string encoded("cmFuZG9t\n");
+ const std::string streamed("b(6)\"random\"");
+ typedef std::vector<U8> buf_t;
+ buf_t buf;
+ std::copy(
+ decoded.begin(),
+ decoded.end(),
+ std::back_insert_iterator<buf_t>(buf));
+ LLSD sd;
+ sd = buf;
+ std::stringstream str;
+ S32 count = LLSDSerialize::toNotation(sd, str);
+ ensure_equals("output count", count, 1);
+ std::string actual(str.str());
+ ensure_equals("formatted binary encoding", actual, streamed);
+ sd.clear();
+ LLSDSerialize::fromNotation(sd, str, str.str().size());
+ std::vector<U8> after;
+ after = sd.asBinary();
+ ensure_equals("binary decoded size", after.size(), decoded.size());
+ ensure("binary decoding", (0 == memcmp(
+ &after[0],
+ decoded.c_str(),
+ decoded.size())));
+ }
+
+ template<> template<>
+ void sd_object::test<3>()
+ {
+ for(S32 i = 0; i < 100; ++i)
+ {
+ // gen up a starting point
+ typedef std::vector<U8> buf_t;
+ buf_t source;
+ srand(i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ LLSD sd(source);
+ std::stringstream str;
+ S32 count = LLSDSerialize::toNotation(sd, str);
+ sd.clear();
+ ensure_equals("format count", count, 1);
+ LLSD sd2;
+ count = LLSDSerialize::fromNotation(sd2, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ buf_t dest = sd2.asBinary();
+ str.str("");
+ str << "binary encoding size " << i;
+ ensure_equals(str.str().c_str(), dest.size(), source.size());
+ str.str("");
+ str << "binary encoding " << i;
+ ensure(str.str().c_str(), (source == dest));
+ }
+ }
+
+ template<> template<>
+ void sd_object::test<4>()
+ {
+ std::ostringstream ostr;
+ ostr << "{'task_id':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n"
+ << "{\n\tname\tObject|\n}\n";
+ std::string expected = ostr.str();
+ std::stringstream serialized;
+ serialized << "'" << LLSDNotationFormatter::escapeString(expected)
+ << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(
+ sd,
+ serialized,
+ serialized.str().size());
+ ensure_equals("parse count", count, 1);
+ ensure_equals("String streaming", sd.asString(), expected);
+ }
+
+ template<> template<>
+ void sd_object::test<5>()
+ {
+ for(S32 i = 0; i < 100; ++i)
+ {
+ // gen up a starting point
+ typedef std::vector<U8> buf_t;
+ buf_t source;
+ srand(666 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ std::stringstream str;
+ str << "b(" << size << ")\"";
+ str.write((const char*)&source[0], size);
+ str << "\"";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("binary parse", count, 1);
+ buf_t actual = sd.asBinary();
+ ensure_equals("binary size", actual.size(), (size_t)size);
+ ensure("binary data", (0 == memcmp(&source[0], &actual[0], size)));
+ }
+ }
+
+ template<> template<>
+ void sd_object::test<6>()
+ {
+ std::string expected("'{\"task_id\":u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}'\t\n\t\t");
+ std::stringstream str;
+ str << "s(" << expected.size() << ")'";
+ str.write(expected.c_str(), expected.size());
+ str << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ std::string actual = sd.asString();
+ ensure_equals("string sizes", actual.size(), expected.size());
+ ensure_equals("string content", actual, expected);
+ }
+
+ template<> template<>
+ void sd_object::test<7>()
+ {
+ std::string msg("come on in");
+ std::stringstream stream;
+ stream << "{'connect':1, 'message':'" << msg << "',"
+ << " 'position':[r45.65,r100.1,r25.5],"
+ << " 'look_at':[r0,r1,r0],"
+ << " 'agent_access':'PG'}";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(
+ sd,
+ stream,
+ stream.str().size());
+ ensure_equals("parse count", count, 12);
+ ensure_equals("bool value", sd["connect"].asBoolean(), true);
+ ensure_equals("message value", sd["message"].asString(), msg);
+ ensure_equals("pos x", sd["position"][0].asReal(), 45.65);
+ ensure_equals("pos y", sd["position"][1].asReal(), 100.1);
+ ensure_equals("pos z", sd["position"][2].asReal(), 25.5);
+ ensure_equals("look x", sd["look_at"][0].asReal(), 0.0);
+ ensure_equals("look y", sd["look_at"][1].asReal(), 1.0);
+ ensure_equals("look z", sd["look_at"][2].asReal(), 0.0);
+ }
+
+ template<> template<>
+ void sd_object::test<8>()
+ {
+ std::stringstream resp;
+ resp << "{'label':'short string test', 'singlechar':'a', 'empty':'', 'endoftest':'end' }";
+ LLSD response;
+ S32 count = LLSDSerialize::fromNotation(
+ response,
+ resp,
+ resp.str().size());
+ ensure_equals("parse count", count, 5);
+ ensure_equals("sd type", response.type(), LLSD::TypeMap);
+ ensure_equals("map element count", response.size(), 4);
+ ensure_equals("singlechar", response["singlechar"].asString(), "a");
+ ensure_equals("empty", response["empty"].asString(), "");
+ }
+
+ template<> template<>
+ void sd_object::test<9>()
+ {
+ std::ostringstream resp;
+ resp << "{'label':'short binary test', 'singlebinary':b(1)\"A\", 'singlerawstring':s(1)\"A\", 'endoftest':'end' }";
+ std::string str = resp.str();
+ LLSD sd;
+ LLMemoryStream mstr((U8*)str.c_str(), str.size());
+ S32 count = LLSDSerialize::fromNotation(sd, mstr, str.size());
+ ensure_equals("parse count", count, 5);
+ ensure("sd created", sd.isDefined());
+ ensure_equals("sd type", sd.type(), LLSD::TypeMap);
+ ensure_equals("map element count", sd.size(), 4);
+ ensure_equals(
+ "label",
+ sd["label"].asString(),
+ "short binary test");
+ std::vector<U8> bin = sd["singlebinary"].asBinary();
+ std::vector<U8> expected;
+ expected.resize(1);
+ expected[0] = 'A';
+ ensure("single binary", (0 == memcmp(&bin[0], &expected[0], 1)));
+ ensure_equals(
+ "single string",
+ sd["singlerawstring"].asString(),
+ std::string("A"));
+ ensure_equals("end", sd["endoftest"].asString(), "end");
+ }
+
+ template<> template<>
+ void sd_object::test<10>()
+ {
+
+ std::string message("parcel '' is naughty.");
+ std::stringstream str;
+ str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
+ << "'}";
+ std::string expected_str("{'message':'parcel \\'\\' is naughty.'}");
+ std::string actual_str = str.str();
+ ensure_equals("stream contents", actual_str, expected_str);
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, actual_str.size());
+ ensure_equals("parse count", count, 2);
+ ensure("valid parse", sd.isDefined());
+ std::string actual = sd["message"].asString();
+ ensure_equals("message contents", actual, message);
+ }
+
+ template<> template<>
+ void sd_object::test<11>()
+ {
+ std::string expected("\"\"\"\"''''''\"");
+ std::stringstream str;
+ str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ ensure_equals("string value", sd.asString(), expected);
+ }
+
+ template<> template<>
+ void sd_object::test<12>()
+ {
+ std::string expected("mytest\\");
+ std::stringstream str;
+ str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ ensure_equals("string value", sd.asString(), expected);
+ }
+
+ template<> template<>
+ void sd_object::test<13>()
+ {
+ for(S32 i = 0; i < 1000; ++i)
+ {
+ // gen up a starting point
+ std::string expected;
+ srand(1337 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 30 + 5;
+ std::generate_n(
+ std::back_insert_iterator<std::string>(expected),
+ size,
+ rand);
+ std::stringstream str;
+ str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, expected.size());
+ ensure_equals("parse count", count, 1);
+ std::string actual = sd.asString();
/*
- if(actual != expected)
- {
- LL_WARNS() << "iteration " << i << LL_ENDL;
- std::ostringstream e_str;
- std::string::iterator iter = expected.begin();
- std::string::iterator end = expected.end();
- for(; iter != end; ++iter)
- {
- e_str << (S32)((U8)(*iter)) << " ";
- }
- e_str << std::endl;
- llsd_serialize_string(e_str, expected);
- LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
- LL_WARNS() << "expected: " << e_str.str() << LL_ENDL;
-
- std::ostringstream a_str;
- iter = actual.begin();
- end = actual.end();
- for(; iter != end; ++iter)
- {
- a_str << (S32)((U8)(*iter)) << " ";
- }
- a_str << std::endl;
- llsd_serialize_string(a_str, actual);
- LL_WARNS() << "actual size: " << actual.size() << LL_ENDL;
- LL_WARNS() << "actual: " << a_str.str() << LL_ENDL;
- }
+ if(actual != expected)
+ {
+ LL_WARNS() << "iteration " << i << LL_ENDL;
+ std::ostringstream e_str;
+ std::string::iterator iter = expected.begin();
+ std::string::iterator end = expected.end();
+ for(; iter != end; ++iter)
+ {
+ e_str << (S32)((U8)(*iter)) << " ";
+ }
+ e_str << std::endl;
+ llsd_serialize_string(e_str, expected);
+ LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
+ LL_WARNS() << "expected: " << e_str.str() << LL_ENDL;
+
+ std::ostringstream a_str;
+ iter = actual.begin();
+ end = actual.end();
+ for(; iter != end; ++iter)
+ {
+ a_str << (S32)((U8)(*iter)) << " ";
+ }
+ a_str << std::endl;
+ llsd_serialize_string(a_str, actual);
+ LL_WARNS() << "actual size: " << actual.size() << LL_ENDL;
+ LL_WARNS() << "actual: " << a_str.str() << LL_ENDL;
+ }
*/
- ensure_equals("string value", actual, expected);
- }
- }
+ ensure_equals("string value", actual, expected);
+ }
+ }
- template<> template<>
- void sd_object::test<14>()
- {
+ template<> template<>
+ void sd_object::test<14>()
+ {
//#if LL_WINDOWS && _MSC_VER >= 1400
// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
//#endif
- std::string param = "[{'version':i1},{'data':{'binary_bucket':b(0)\"\"},'from_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'from_name':'Phoenix Linden','id':u004e45e5-5576-277a-fba7-859d6a4cb5c8,'message':'hey','offline':i0,'timestamp':i0,'to_id':u3c5f1bb4-5182-7546-6401-1d329b4ff2f8,'type':i0},{'agent_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'god_level':i0,'limited_to_estate':i1}]";
- std::istringstream istr;
- istr.str(param);
- LLSD param_sd;
- LLSDSerialize::fromNotation(param_sd, istr, param.size());
- ensure_equals("parsed type", param_sd.type(), LLSD::TypeArray);
- LLSD version_sd = param_sd[0];
- ensure_equals("version type", version_sd.type(), LLSD::TypeMap);
- ensure("has version", version_sd.has("version"));
- ensure_equals("version number", version_sd["version"].asInteger(), 1);
- LLSD src_sd = param_sd[1];
- ensure_equals("src type", src_sd.type(), LLSD::TypeMap);
- LLSD dst_sd = param_sd[2];
- ensure_equals("dst type", dst_sd.type(), LLSD::TypeMap);
- }
-
- template<> template<>
- void sd_object::test<15>()
- {
- std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
- std::istringstream istr;
- istr.str(val);
- LLSD sd;
- LLSDSerialize::fromNotation(sd, istr, val.size());
- ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
- ensure_equals("parsed size", sd.size(), 1);
- LLSD failures = sd[0]["failures"];
- ensure("no failures.", failures.isUndefined());
- LLSD success = sd[0]["successfuls"];
- ensure_equals("success type", success.type(), LLSD::TypeArray);
- ensure_equals("success size", success.size(), 1);
- ensure_equals("success instance type", success[0].type(), LLSD::TypeUUID);
- }
-
- template<> template<>
- void sd_object::test<16>()
- {
- std::string val = "[f,t,0,1,{'foo':t,'bar':f}]";
- std::istringstream istr;
- istr.str(val);
- LLSD sd;
- LLSDSerialize::fromNotation(sd, istr, val.size());
- ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
- ensure_equals("parsed size", sd.size(), 5);
- ensure_equals("element 0 false", sd[0].asBoolean(), false);
- ensure_equals("element 1 true", sd[1].asBoolean(), true);
- ensure_equals("element 2 false", sd[2].asBoolean(), false);
- ensure_equals("element 3 true", sd[3].asBoolean(), true);
- LLSD map = sd[4];
- ensure_equals("element 4 type", map.type(), LLSD::TypeMap);
- ensure_equals("map foo type", map["foo"].type(), LLSD::TypeBoolean);
- ensure_equals("map foo value", map["foo"].asBoolean(), true);
- ensure_equals("map bar type", map["bar"].type(), LLSD::TypeBoolean);
- ensure_equals("map bar value", map["bar"].asBoolean(), false);
- }
+ std::string param = "[{'version':i1},{'data':{'binary_bucket':b(0)\"\"},'from_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'from_name':'Phoenix Linden','id':u004e45e5-5576-277a-fba7-859d6a4cb5c8,'message':'hey','offline':i0,'timestamp':i0,'to_id':u3c5f1bb4-5182-7546-6401-1d329b4ff2f8,'type':i0},{'agent_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'god_level':i0,'limited_to_estate':i1}]";
+ std::istringstream istr;
+ istr.str(param);
+ LLSD param_sd;
+ LLSDSerialize::fromNotation(param_sd, istr, param.size());
+ ensure_equals("parsed type", param_sd.type(), LLSD::TypeArray);
+ LLSD version_sd = param_sd[0];
+ ensure_equals("version type", version_sd.type(), LLSD::TypeMap);
+ ensure("has version", version_sd.has("version"));
+ ensure_equals("version number", version_sd["version"].asInteger(), 1);
+ LLSD src_sd = param_sd[1];
+ ensure_equals("src type", src_sd.type(), LLSD::TypeMap);
+ LLSD dst_sd = param_sd[2];
+ ensure_equals("dst type", dst_sd.type(), LLSD::TypeMap);
+ }
+
+ template<> template<>
+ void sd_object::test<15>()
+ {
+ std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
+ ensure_equals("parsed size", sd.size(), 1);
+ LLSD failures = sd[0]["failures"];
+ ensure("no failures.", failures.isUndefined());
+ LLSD success = sd[0]["successfuls"];
+ ensure_equals("success type", success.type(), LLSD::TypeArray);
+ ensure_equals("success size", success.size(), 1);
+ ensure_equals("success instance type", success[0].type(), LLSD::TypeUUID);
+ }
+
+ template<> template<>
+ void sd_object::test<16>()
+ {
+ std::string val = "[f,t,0,1,{'foo':t,'bar':f}]";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
+ ensure_equals("parsed size", sd.size(), 5);
+ ensure_equals("element 0 false", sd[0].asBoolean(), false);
+ ensure_equals("element 1 true", sd[1].asBoolean(), true);
+ ensure_equals("element 2 false", sd[2].asBoolean(), false);
+ ensure_equals("element 3 true", sd[3].asBoolean(), true);
+ LLSD map = sd[4];
+ ensure_equals("element 4 type", map.type(), LLSD::TypeMap);
+ ensure_equals("map foo type", map["foo"].type(), LLSD::TypeBoolean);
+ ensure_equals("map foo value", map["foo"].asBoolean(), true);
+ ensure_equals("map bar type", map["bar"].type(), LLSD::TypeBoolean);
+ ensure_equals("map bar value", map["bar"].asBoolean(), false);
+ }
/*
- template<> template<>
- void sd_object::test<16>()
- {
- }
+ template<> template<>
+ void sd_object::test<16>()
+ {
+ }
*/
}
@@ -445,227 +445,227 @@ namespace tut
namespace tut
{
- struct mem_data
- {
- };
- typedef test_group<mem_data> mem_test;
- typedef mem_test::object mem_object;
- tut::mem_test mem_stream("LLMemoryStream");
-
- template<> template<>
- void mem_object::test<1>()
- {
- const char HELLO_WORLD[] = "hello world";
- LLMemoryStream mem((U8*)&HELLO_WORLD[0], strlen(HELLO_WORLD)); /* Flawfinder: ignore */
- std::string hello;
- std::string world;
- mem >> hello >> world;
- ensure_equals("first word", hello, std::string("hello"));
- ensure_equals("second word", world, std::string("world"));
- }
+ struct mem_data
+ {
+ };
+ typedef test_group<mem_data> mem_test;
+ typedef mem_test::object mem_object;
+ tut::mem_test mem_stream("LLMemoryStream");
+
+ template<> template<>
+ void mem_object::test<1>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ LLMemoryStream mem((U8*)&HELLO_WORLD[0], strlen(HELLO_WORLD)); /* Flawfinder: ignore */
+ std::string hello;
+ std::string world;
+ mem >> hello >> world;
+ ensure_equals("first word", hello, std::string("hello"));
+ ensure_equals("second word", world, std::string("world"));
+ }
}
namespace tut
{
- struct U64_data
- {
- };
- typedef test_group<U64_data> U64_test;
- typedef U64_test::object U64_object;
- tut::U64_test U64_testcase("U64_conversion");
-
- // U64_to_str
- template<> template<>
- void U64_object::test<1>()
- {
- U64 val;
- std::string val_str;
- char result[256];
- std::string result_str;
-
- val = U64L(18446744073709551610); // slightly less than MAX_U64
- val_str = "18446744073709551610";
-
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.1", val_str, result_str);
-
- val = 0;
- val_str = "0";
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.2", val_str, result_str);
-
- val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
- val_str = "18446744073709551615";
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.3", val_str, result_str);
-
- // overflow - will result in warning at compile time
- val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
- val_str = "0";
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.4", val_str, result_str);
-
- val = U64L(-1); // 0xFFFFFFFFFFFFFFFF == 18446744073709551615
- val_str = "18446744073709551615";
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.5", val_str, result_str);
-
- val = U64L(10000000000000000000); // testing preserving of 0s
- val_str = "10000000000000000000";
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.6", val_str, result_str);
-
- val = 1; // testing no leading 0s
- val_str = "1";
- U64_to_str(val, result, sizeof(result));
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.7", val_str, result_str);
-
- val = U64L(18446744073709551615); // testing exact sized buffer for result
- val_str = "18446744073709551615";
- memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
- U64_to_str(val, result, sizeof("18446744073709551615")); //pass in the exact size
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.8", val_str, result_str);
-
- val = U64L(18446744073709551615); // testing smaller sized buffer for result
- val_str = "1844";
- memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
- U64_to_str(val, result, 5); //pass in a size of 5. should only copy first 4 integers and add a null terminator
- result_str = (const char*) result;
- ensure_equals("U64_to_str converted 1.9", val_str, result_str);
- }
-
- // str_to_U64
- template<> template<>
- void U64_object::test<2>()
- {
- U64 val;
- U64 result;
-
- val = U64L(18446744073709551610); // slightly less than MAX_U64
- result = str_to_U64("18446744073709551610");
- ensure_equals("str_to_U64 converted 2.1", val, result);
-
- val = U64L(0); // empty string
- result = str_to_U64(LLStringUtil::null);
- ensure_equals("str_to_U64 converted 2.2", val, result);
-
- val = U64L(0); // 0
- result = str_to_U64("0");
- ensure_equals("str_to_U64 converted 2.3", val, result);
-
- val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
- result = str_to_U64("18446744073709551615");
- ensure_equals("str_to_U64 converted 2.4", val, result);
-
- // overflow - will result in warning at compile time
- val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
- result = str_to_U64("18446744073709551616");
- ensure_equals("str_to_U64 converted 2.5", val, result);
-
- val = U64L(1234); // process till first non-integral character
- result = str_to_U64("1234A5678");
- ensure_equals("str_to_U64 converted 2.6", val, result);
-
- val = U64L(5678); // skip all non-integral characters
- result = str_to_U64("ABCD5678");
- ensure_equals("str_to_U64 converted 2.7", val, result);
-
- // should it skip negative sign and process
- // rest of string or return 0
- val = U64L(1234); // skip initial negative sign
- result = str_to_U64("-1234");
- ensure_equals("str_to_U64 converted 2.8", val, result);
-
- val = U64L(5678); // stop at negative sign in the middle
- result = str_to_U64("5678-1234");
- ensure_equals("str_to_U64 converted 2.9", val, result);
-
- val = U64L(0); // no integers
- result = str_to_U64("AaCD");
- ensure_equals("str_to_U64 converted 2.10", val, result);
- }
-
- // U64_to_F64
- template<> template<>
- void U64_object::test<3>()
- {
- F64 val;
- F64 result;
-
- result = 18446744073709551610.0;
- val = U64_to_F64(U64L(18446744073709551610));
- ensure_equals("U64_to_F64 converted 3.1", val, result);
-
- result = 18446744073709551615.0; // 0xFFFFFFFFFFFFFFFF
- val = U64_to_F64(U64L(18446744073709551615));
- ensure_equals("U64_to_F64 converted 3.2", val, result);
-
- result = 0.0; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
- // overflow - will result in warning at compile time
- val = U64_to_F64(U64L(18446744073709551615)+1);
- ensure_equals("U64_to_F64 converted 3.3", val, result);
-
- result = 0.0; // 0
- val = U64_to_F64(U64L(0));
- ensure_equals("U64_to_F64 converted 3.4", val, result);
-
- result = 1.0; // odd
- val = U64_to_F64(U64L(1));
- ensure_equals("U64_to_F64 converted 3.5", val, result);
-
- result = 2.0; // even
- val = U64_to_F64(U64L(2));
- ensure_equals("U64_to_F64 converted 3.6", val, result);
-
- result = U64L(0x7FFFFFFFFFFFFFFF) * 1.0L; // 0x7FFFFFFFFFFFFFFF
- val = U64_to_F64(U64L(0x7FFFFFFFFFFFFFFF));
- ensure_equals("U64_to_F64 converted 3.7", val, result);
- }
-
- // llstrtou64
- // seems to be deprecated - could not find it being used
- // anywhere in the tarball - skipping unit tests for now
+ struct U64_data
+ {
+ };
+ typedef test_group<U64_data> U64_test;
+ typedef U64_test::object U64_object;
+ tut::U64_test U64_testcase("U64_conversion");
+
+ // U64_to_str
+ template<> template<>
+ void U64_object::test<1>()
+ {
+ U64 val;
+ std::string val_str;
+ char result[256];
+ std::string result_str;
+
+ val = U64L(18446744073709551610); // slightly less than MAX_U64
+ val_str = "18446744073709551610";
+
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.1", val_str, result_str);
+
+ val = 0;
+ val_str = "0";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.2", val_str, result_str);
+
+ val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
+ val_str = "18446744073709551615";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.3", val_str, result_str);
+
+ // overflow - will result in warning at compile time
+ val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
+ val_str = "0";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.4", val_str, result_str);
+
+ val = U64L(-1); // 0xFFFFFFFFFFFFFFFF == 18446744073709551615
+ val_str = "18446744073709551615";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.5", val_str, result_str);
+
+ val = U64L(10000000000000000000); // testing preserving of 0s
+ val_str = "10000000000000000000";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.6", val_str, result_str);
+
+ val = 1; // testing no leading 0s
+ val_str = "1";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.7", val_str, result_str);
+
+ val = U64L(18446744073709551615); // testing exact sized buffer for result
+ val_str = "18446744073709551615";
+ memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
+ U64_to_str(val, result, sizeof("18446744073709551615")); //pass in the exact size
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.8", val_str, result_str);
+
+ val = U64L(18446744073709551615); // testing smaller sized buffer for result
+ val_str = "1844";
+ memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
+ U64_to_str(val, result, 5); //pass in a size of 5. should only copy first 4 integers and add a null terminator
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.9", val_str, result_str);
+ }
+
+ // str_to_U64
+ template<> template<>
+ void U64_object::test<2>()
+ {
+ U64 val;
+ U64 result;
+
+ val = U64L(18446744073709551610); // slightly less than MAX_U64
+ result = str_to_U64("18446744073709551610");
+ ensure_equals("str_to_U64 converted 2.1", val, result);
+
+ val = U64L(0); // empty string
+ result = str_to_U64(LLStringUtil::null);
+ ensure_equals("str_to_U64 converted 2.2", val, result);
+
+ val = U64L(0); // 0
+ result = str_to_U64("0");
+ ensure_equals("str_to_U64 converted 2.3", val, result);
+
+ val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
+ result = str_to_U64("18446744073709551615");
+ ensure_equals("str_to_U64 converted 2.4", val, result);
+
+ // overflow - will result in warning at compile time
+ val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
+ result = str_to_U64("18446744073709551616");
+ ensure_equals("str_to_U64 converted 2.5", val, result);
+
+ val = U64L(1234); // process till first non-integral character
+ result = str_to_U64("1234A5678");
+ ensure_equals("str_to_U64 converted 2.6", val, result);
+
+ val = U64L(5678); // skip all non-integral characters
+ result = str_to_U64("ABCD5678");
+ ensure_equals("str_to_U64 converted 2.7", val, result);
+
+ // should it skip negative sign and process
+ // rest of string or return 0
+ val = U64L(1234); // skip initial negative sign
+ result = str_to_U64("-1234");
+ ensure_equals("str_to_U64 converted 2.8", val, result);
+
+ val = U64L(5678); // stop at negative sign in the middle
+ result = str_to_U64("5678-1234");
+ ensure_equals("str_to_U64 converted 2.9", val, result);
+
+ val = U64L(0); // no integers
+ result = str_to_U64("AaCD");
+ ensure_equals("str_to_U64 converted 2.10", val, result);
+ }
+
+ // U64_to_F64
+ template<> template<>
+ void U64_object::test<3>()
+ {
+ F64 val;
+ F64 result;
+
+ result = 18446744073709551610.0;
+ val = U64_to_F64(U64L(18446744073709551610));
+ ensure_equals("U64_to_F64 converted 3.1", val, result);
+
+ result = 18446744073709551615.0; // 0xFFFFFFFFFFFFFFFF
+ val = U64_to_F64(U64L(18446744073709551615));
+ ensure_equals("U64_to_F64 converted 3.2", val, result);
+
+ result = 0.0; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
+ // overflow - will result in warning at compile time
+ val = U64_to_F64(U64L(18446744073709551615)+1);
+ ensure_equals("U64_to_F64 converted 3.3", val, result);
+
+ result = 0.0; // 0
+ val = U64_to_F64(U64L(0));
+ ensure_equals("U64_to_F64 converted 3.4", val, result);
+
+ result = 1.0; // odd
+ val = U64_to_F64(U64L(1));
+ ensure_equals("U64_to_F64 converted 3.5", val, result);
+
+ result = 2.0; // even
+ val = U64_to_F64(U64L(2));
+ ensure_equals("U64_to_F64 converted 3.6", val, result);
+
+ result = U64L(0x7FFFFFFFFFFFFFFF) * 1.0L; // 0x7FFFFFFFFFFFFFFF
+ val = U64_to_F64(U64L(0x7FFFFFFFFFFFFFFF));
+ ensure_equals("U64_to_F64 converted 3.7", val, result);
+ }
+
+ // llstrtou64
+ // seems to be deprecated - could not find it being used
+ // anywhere in the tarball - skipping unit tests for now
}
namespace tut
{
- struct hash_data
- {
- };
- typedef test_group<hash_data> hash_test;
- typedef hash_test::object hash_object;
- tut::hash_test hash_tester("LLHash");
+ struct hash_data
+ {
+ };
+ typedef test_group<hash_data> hash_test;
+ typedef hash_test::object hash_object;
+ tut::hash_test hash_tester("LLHash");
+
+ template<> template<>
+ void hash_object::test<1>()
+ {
+ const char * str1 = "test string one";
+ const char * same_as_str1 = "test string one";
+
+ size_t hash1 = llhash(str1);
+ size_t same_as_hash1 = llhash(same_as_str1);
- template<> template<>
- void hash_object::test<1>()
- {
- const char * str1 = "test string one";
- const char * same_as_str1 = "test string one";
- size_t hash1 = llhash(str1);
- size_t same_as_hash1 = llhash(same_as_str1);
+ ensure("Hashes from identical strings should be equal", hash1 == same_as_hash1);
+ char str[100];
+ strcpy( str, "Another test" );
- ensure("Hashes from identical strings should be equal", hash1 == same_as_hash1);
-
- char str[100];
- strcpy( str, "Another test" );
+ size_t hash2 = llhash(str);
- size_t hash2 = llhash(str);
-
- strcpy( str, "Different string, same pointer" );
+ strcpy( str, "Different string, same pointer" );
- size_t hash3 = llhash(str);
+ size_t hash3 = llhash(str);
- ensure("Hashes from same pointer but different string should not be equal", hash2 != hash3);
- }
+ ensure("Hashes from same pointer but different string should not be equal", hash2 != hash3);
+ }
}
diff --git a/indra/llcommon/tests/lazyeventapi_test.cpp b/indra/llcommon/tests/lazyeventapi_test.cpp
index 31b2d6d17f..f3fcf84e49 100644
--- a/indra/llcommon/tests/lazyeventapi_test.cpp
+++ b/indra/llcommon/tests/lazyeventapi_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-06-18
* @brief Test for lazyeventapi.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/listener.h b/indra/llcommon/tests/listener.h
index 6072060bb6..887a2c9082 100644
--- a/indra/llcommon/tests/listener.h
+++ b/indra/llcommon/tests/listener.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-03-06
* @brief Useful for tests of the LLEventPump family of classes
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/tests/llallocator_heap_profile_test.cpp b/indra/llcommon/tests/llallocator_heap_profile_test.cpp
index 44a9705803..da8b54ffc0 100644
--- a/indra/llcommon/tests/llallocator_heap_profile_test.cpp
+++ b/indra/llcommon/tests/llallocator_heap_profile_test.cpp
@@ -3,25 +3,25 @@
* @author Brad Kittenbrink
* @date 2008-02-
* @brief Test for llallocator_heap_profile.cpp.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/tests/llallocator_test.cpp b/indra/llcommon/tests/llallocator_test.cpp
index 4e62eaee67..a7573641c7 100644
--- a/indra/llcommon/tests/llallocator_test.cpp
+++ b/indra/llcommon/tests/llallocator_test.cpp
@@ -3,25 +3,25 @@
* @author Brad Kittenbrink
* @date 2008-02-
* @brief Test for llallocator.cpp.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -71,7 +71,7 @@ namespace tut
delete [] test_alloc;
- llallocator.getProfile();
+ llallocator.getProfile();
// *NOTE - this test isn't ensuring anything right now other than no
// exceptions are thrown.
diff --git a/indra/llcommon/tests/llbase64_test.cpp b/indra/llcommon/tests/llbase64_test.cpp
index d0394150fa..69b062fc0c 100644
--- a/indra/llcommon/tests/llbase64_test.cpp
+++ b/indra/llcommon/tests/llbase64_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbase64_test.cpp
* @author James Cook
* @date 2007-02-04
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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,42 +36,42 @@
namespace tut
{
- struct base64_data
- {
- };
- typedef test_group<base64_data> base64_test;
- typedef base64_test::object base64_object;
- tut::base64_test base64("LLBase64");
+ struct base64_data
+ {
+ };
+ typedef test_group<base64_data> base64_test;
+ typedef base64_test::object base64_object;
+ tut::base64_test base64("LLBase64");
- template<> template<>
- void base64_object::test<1>()
- {
- std::string result;
+ template<> template<>
+ void base64_object::test<1>()
+ {
+ std::string result;
- result = LLBase64::encode(NULL, 0);
- ensure("encode nothing", (result == "") );
+ result = LLBase64::encode(NULL, 0);
+ ensure("encode nothing", (result == "") );
- LLUUID nothing;
- result = LLBase64::encode(&nothing.mData[0], UUID_BYTES);
- ensure("encode blank uuid",
- (result == "AAAAAAAAAAAAAAAAAAAAAA==") );
+ LLUUID nothing;
+ result = LLBase64::encode(&nothing.mData[0], UUID_BYTES);
+ ensure("encode blank uuid",
+ (result == "AAAAAAAAAAAAAAAAAAAAAA==") );
- LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
- result = LLBase64::encode(&id.mData[0], UUID_BYTES);
- ensure("encode random uuid",
- (result == "UmoeB6Gduu2ExP8IpIjRXg==") );
+ LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
+ result = LLBase64::encode(&id.mData[0], UUID_BYTES);
+ ensure("encode random uuid",
+ (result == "UmoeB6Gduu2ExP8IpIjRXg==") );
- }
+ }
- template<> template<>
- void base64_object::test<2>()
- {
- std::string result;
+ template<> template<>
+ void base64_object::test<2>()
+ {
+ std::string result;
- U8 blob[40] = { 115, 223, 172, 255, 140, 70, 49, 125, 236, 155, 45, 199, 101, 17, 164, 131, 230, 19, 80, 64, 112, 53, 135, 98, 237, 12, 26, 72, 126, 14, 145, 143, 118, 196, 11, 177, 132, 169, 195, 134 };
- result = LLBase64::encode(&blob[0], 40);
- ensure("encode 40 bytes",
- (result == "c9+s/4xGMX3smy3HZRGkg+YTUEBwNYdi7QwaSH4OkY92xAuxhKnDhg==") );
- }
+ U8 blob[40] = { 115, 223, 172, 255, 140, 70, 49, 125, 236, 155, 45, 199, 101, 17, 164, 131, 230, 19, 80, 64, 112, 53, 135, 98, 237, 12, 26, 72, 126, 14, 145, 143, 118, 196, 11, 177, 132, 169, 195, 134 };
+ result = LLBase64::encode(&blob[0], 40);
+ ensure("encode 40 bytes",
+ (result == "c9+s/4xGMX3smy3HZRGkg+YTUEBwNYdi7QwaSH4OkY92xAuxhKnDhg==") );
+ }
}
diff --git a/indra/llcommon/tests/llcond_test.cpp b/indra/llcommon/tests/llcond_test.cpp
index 478149eacf..f2a302ed13 100644
--- a/indra/llcommon/tests/llcond_test.cpp
+++ b/indra/llcommon/tests/llcond_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2019-07-18
* @brief Test for llcond.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
@@ -38,7 +38,7 @@ namespace tut
{
set_test_name("Immediate gratification");
cond.set_one(1);
- ensure("wait_for_equal() failed",
+ ensure("wait_for_equal() failed",
cond.wait_for_equal(F32Milliseconds(1), 1));
ensure("wait_for_unequal() should have failed",
! cond.wait_for_unequal(F32Milliseconds(1), 1));
diff --git a/indra/llcommon/tests/lldate_test.cpp b/indra/llcommon/tests/lldate_test.cpp
index 7c95ccb91f..6d38b71649 100644
--- a/indra/llcommon/tests/lldate_test.cpp
+++ b/indra/llcommon/tests/lldate_test.cpp
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -34,180 +34,180 @@
#include "../test/lltut.h"
-#define VALID_DATE "2003-04-30T04:00:00Z"
-#define VALID_DATE_LEAP "2004-02-29T04:00:00Z"
-#define VALID_DATE_HOUR_BOUNDARY "2003-04-30T23:59:59Z"
-#define VALID_DATE_FRACTIONAL_SECS "2007-09-26T20:31:33.70Z"
+#define VALID_DATE "2003-04-30T04:00:00Z"
+#define VALID_DATE_LEAP "2004-02-29T04:00:00Z"
+#define VALID_DATE_HOUR_BOUNDARY "2003-04-30T23:59:59Z"
+#define VALID_DATE_FRACTIONAL_SECS "2007-09-26T20:31:33.70Z"
// invalid format
-#define INVALID_DATE_MISSING_YEAR "-04-30T22:59:59Z"
-#define INVALID_DATE_MISSING_MONTH "1900-0430T22:59:59Z"
-#define INVALID_DATE_MISSING_DATE "1900-0430-T22:59:59Z"
-#define INVALID_DATE_MISSING_T "1900-04-30-22:59:59Z"
-#define INVALID_DATE_MISSING_HOUR "1900-04-30T:59:59Z"
-#define INVALID_DATE_MISSING_MIN "1900-04-30T01::59Z"
-#define INVALID_DATE_MISSING_SEC "1900-04-30T01:59Z"
-#define INVALID_DATE_MISSING_Z "1900-04-30T01:59:23"
-#define INVALID_DATE_EMPTY ""
+#define INVALID_DATE_MISSING_YEAR "-04-30T22:59:59Z"
+#define INVALID_DATE_MISSING_MONTH "1900-0430T22:59:59Z"
+#define INVALID_DATE_MISSING_DATE "1900-0430-T22:59:59Z"
+#define INVALID_DATE_MISSING_T "1900-04-30-22:59:59Z"
+#define INVALID_DATE_MISSING_HOUR "1900-04-30T:59:59Z"
+#define INVALID_DATE_MISSING_MIN "1900-04-30T01::59Z"
+#define INVALID_DATE_MISSING_SEC "1900-04-30T01:59Z"
+#define INVALID_DATE_MISSING_Z "1900-04-30T01:59:23"
+#define INVALID_DATE_EMPTY ""
// invalid values
// apr 1.1.1 seems to not care about constraining the date to valid
// dates. Put these back when the parser checks.
#define LL_DATE_PARSER_CHECKS_BOUNDARY 0
-//#define INVALID_DATE_24HOUR_BOUNDARY "2003-04-30T24:00:00Z"
-//#define INVALID_DATE_LEAP "2003-04-29T04:00:00Z"
-//#define INVALID_DATE_HOUR "2003-04-30T24:59:59Z"
-//#define INVALID_DATE_MIN "2003-04-30T22:69:59Z"
-//#define INVALID_DATE_SEC "2003-04-30T22:59:69Z"
-//#define INVALID_DATE_YEAR "0-04-30T22:59:59Z"
-//#define INVALID_DATE_MONTH "2003-13-30T22:59:59Z"
-//#define INVALID_DATE_DAY "2003-04-35T22:59:59Z"
+//#define INVALID_DATE_24HOUR_BOUNDARY "2003-04-30T24:00:00Z"
+//#define INVALID_DATE_LEAP "2003-04-29T04:00:00Z"
+//#define INVALID_DATE_HOUR "2003-04-30T24:59:59Z"
+//#define INVALID_DATE_MIN "2003-04-30T22:69:59Z"
+//#define INVALID_DATE_SEC "2003-04-30T22:59:69Z"
+//#define INVALID_DATE_YEAR "0-04-30T22:59:59Z"
+//#define INVALID_DATE_MONTH "2003-13-30T22:59:59Z"
+//#define INVALID_DATE_DAY "2003-04-35T22:59:59Z"
namespace tut
{
- struct date_test
- {
+ struct date_test
+ {
- };
- typedef test_group<date_test> date_test_t;
- typedef date_test_t::object date_test_object_t;
- tut::date_test_t tut_date_test("LLDate");
+ };
+ typedef test_group<date_test> date_test_t;
+ typedef date_test_t::object date_test_object_t;
+ tut::date_test_t tut_date_test("LLDate");
- /* format validation */
- template<> template<>
- void date_test_object_t::test<1>()
- {
- LLDate date(VALID_DATE);
- std::string expected_string;
- bool result;
- expected_string = VALID_DATE;
- ensure_equals("Valid Date failed" , expected_string, date.asString());
+ /* format validation */
+ template<> template<>
+ void date_test_object_t::test<1>()
+ {
+ LLDate date(VALID_DATE);
+ std::string expected_string;
+ bool result;
+ expected_string = VALID_DATE;
+ ensure_equals("Valid Date failed" , expected_string, date.asString());
- result = date.fromString(VALID_DATE_LEAP);
- expected_string = VALID_DATE_LEAP;
- ensure_equals("VALID_DATE_LEAP failed" , expected_string, date.asString());
+ result = date.fromString(VALID_DATE_LEAP);
+ expected_string = VALID_DATE_LEAP;
+ ensure_equals("VALID_DATE_LEAP failed" , expected_string, date.asString());
- result = date.fromString(VALID_DATE_HOUR_BOUNDARY);
- expected_string = VALID_DATE_HOUR_BOUNDARY;
- ensure_equals("VALID_DATE_HOUR_BOUNDARY failed" , expected_string, date.asString());
+ result = date.fromString(VALID_DATE_HOUR_BOUNDARY);
+ expected_string = VALID_DATE_HOUR_BOUNDARY;
+ ensure_equals("VALID_DATE_HOUR_BOUNDARY failed" , expected_string, date.asString());
- result = date.fromString(VALID_DATE_FRACTIONAL_SECS);
- expected_string = VALID_DATE_FRACTIONAL_SECS;
- ensure_equals("VALID_DATE_FRACTIONAL_SECS failed" , expected_string, date.asString());
+ result = date.fromString(VALID_DATE_FRACTIONAL_SECS);
+ expected_string = VALID_DATE_FRACTIONAL_SECS;
+ ensure_equals("VALID_DATE_FRACTIONAL_SECS failed" , expected_string, date.asString());
- result = date.fromString(INVALID_DATE_MISSING_YEAR);
- ensure_equals("INVALID_DATE_MISSING_YEAR should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_YEAR);
+ ensure_equals("INVALID_DATE_MISSING_YEAR should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_MONTH);
- ensure_equals("INVALID_DATE_MISSING_MONTH should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_MONTH);
+ ensure_equals("INVALID_DATE_MISSING_MONTH should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_DATE);
- ensure_equals("INVALID_DATE_MISSING_DATE should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_DATE);
+ ensure_equals("INVALID_DATE_MISSING_DATE should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_T);
- ensure_equals("INVALID_DATE_MISSING_T should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_T);
+ ensure_equals("INVALID_DATE_MISSING_T should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_HOUR);
- ensure_equals("INVALID_DATE_MISSING_HOUR should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_HOUR);
+ ensure_equals("INVALID_DATE_MISSING_HOUR should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_MIN);
- ensure_equals("INVALID_DATE_MISSING_MIN should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_MIN);
+ ensure_equals("INVALID_DATE_MISSING_MIN should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_SEC);
- ensure_equals("INVALID_DATE_MISSING_SEC should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_SEC);
+ ensure_equals("INVALID_DATE_MISSING_SEC should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MISSING_Z);
- ensure_equals("INVALID_DATE_MISSING_Z should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MISSING_Z);
+ ensure_equals("INVALID_DATE_MISSING_Z should have failed" , result, false);
- result = date.fromString(INVALID_DATE_EMPTY);
- ensure_equals("INVALID_DATE_EMPTY should have failed" , result, false);
- }
+ result = date.fromString(INVALID_DATE_EMPTY);
+ ensure_equals("INVALID_DATE_EMPTY should have failed" , result, false);
+ }
- /* Invalid Value Handling */
- template<> template<>
- void date_test_object_t::test<2>()
- {
+ /* Invalid Value Handling */
+ template<> template<>
+ void date_test_object_t::test<2>()
+ {
#if LL_DATE_PARSER_CHECKS_BOUNDARY
- LLDate date;
- std::string expected_string;
- bool result;
+ LLDate date;
+ std::string expected_string;
+ bool result;
- result = date.fromString(INVALID_DATE_24HOUR_BOUNDARY);
- ensure_equals("INVALID_DATE_24HOUR_BOUNDARY should have failed" , result, false);
- ensure_equals("INVALID_DATE_24HOUR_BOUNDARY date still set to old value on failure!" , date.secondsSinceEpoch(), 0);
+ result = date.fromString(INVALID_DATE_24HOUR_BOUNDARY);
+ ensure_equals("INVALID_DATE_24HOUR_BOUNDARY should have failed" , result, false);
+ ensure_equals("INVALID_DATE_24HOUR_BOUNDARY date still set to old value on failure!" , date.secondsSinceEpoch(), 0);
- result = date.fromString(INVALID_DATE_LEAP);
- ensure_equals("INVALID_DATE_LEAP should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_LEAP);
+ ensure_equals("INVALID_DATE_LEAP should have failed" , result, false);
- result = date.fromString(INVALID_DATE_HOUR);
- ensure_equals("INVALID_DATE_HOUR should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_HOUR);
+ ensure_equals("INVALID_DATE_HOUR should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MIN);
- ensure_equals("INVALID_DATE_MIN should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MIN);
+ ensure_equals("INVALID_DATE_MIN should have failed" , result, false);
- result = date.fromString(INVALID_DATE_SEC);
- ensure_equals("INVALID_DATE_SEC should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_SEC);
+ ensure_equals("INVALID_DATE_SEC should have failed" , result, false);
- result = date.fromString(INVALID_DATE_YEAR);
- ensure_equals("INVALID_DATE_YEAR should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_YEAR);
+ ensure_equals("INVALID_DATE_YEAR should have failed" , result, false);
- result = date.fromString(INVALID_DATE_MONTH);
- ensure_equals("INVALID_DATE_MONTH should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_MONTH);
+ ensure_equals("INVALID_DATE_MONTH should have failed" , result, false);
- result = date.fromString(INVALID_DATE_DAY);
- ensure_equals("INVALID_DATE_DAY should have failed" , result, false);
+ result = date.fromString(INVALID_DATE_DAY);
+ ensure_equals("INVALID_DATE_DAY should have failed" , result, false);
#endif
- }
-
- /* API checks */
- template<> template<>
- void date_test_object_t::test<3>()
- {
- LLDate date;
- std::istringstream stream(VALID_DATE);
- std::string expected_string = VALID_DATE;
- date.fromStream(stream);
- ensure_equals("fromStream failed", date.asString(), expected_string);
- }
-
- template<> template<>
- void date_test_object_t::test<4>()
- {
- LLDate date1(VALID_DATE);
- LLDate date2(date1);
- ensure_equals("LLDate(const LLDate& date) constructor failed", date1.asString(), date2.asString());
- }
-
- template<> template<>
- void date_test_object_t::test<5>()
- {
- LLDate date1(VALID_DATE);
- LLDate date2(date1.secondsSinceEpoch());
- ensure_equals("secondsSinceEpoch not equal",date1.secondsSinceEpoch(), date2.secondsSinceEpoch());
- ensure_equals("LLDate created using secondsSinceEpoch not equal", date1.asString(), date2.asString());
- }
-
- template<> template<>
- void date_test_object_t::test<6>()
- {
- LLDate date(VALID_DATE);
- std::ostringstream stream;
- stream << date;
- std::string expected_str = VALID_DATE;
- ensure_equals("ostringstream failed", expected_str, stream.str());
- }
-
- template<> template<>
- void date_test_object_t::test<7>()
- {
- LLDate date;
- std::istringstream stream(VALID_DATE);
- stream >> date;
- std::string expected_str = VALID_DATE;
- std::ostringstream out_stream;
+ }
+
+ /* API checks */
+ template<> template<>
+ void date_test_object_t::test<3>()
+ {
+ LLDate date;
+ std::istringstream stream(VALID_DATE);
+ std::string expected_string = VALID_DATE;
+ date.fromStream(stream);
+ ensure_equals("fromStream failed", date.asString(), expected_string);
+ }
+
+ template<> template<>
+ void date_test_object_t::test<4>()
+ {
+ LLDate date1(VALID_DATE);
+ LLDate date2(date1);
+ ensure_equals("LLDate(const LLDate& date) constructor failed", date1.asString(), date2.asString());
+ }
+
+ template<> template<>
+ void date_test_object_t::test<5>()
+ {
+ LLDate date1(VALID_DATE);
+ LLDate date2(date1.secondsSinceEpoch());
+ ensure_equals("secondsSinceEpoch not equal",date1.secondsSinceEpoch(), date2.secondsSinceEpoch());
+ ensure_equals("LLDate created using secondsSinceEpoch not equal", date1.asString(), date2.asString());
+ }
+
+ template<> template<>
+ void date_test_object_t::test<6>()
+ {
+ LLDate date(VALID_DATE);
+ std::ostringstream stream;
+ stream << date;
+ std::string expected_str = VALID_DATE;
+ ensure_equals("ostringstream failed", expected_str, stream.str());
+ }
+
+ template<> template<>
+ void date_test_object_t::test<7>()
+ {
+ LLDate date;
+ std::istringstream stream(VALID_DATE);
+ stream >> date;
+ std::string expected_str = VALID_DATE;
+ std::ostringstream out_stream;
out_stream << date;
- ensure_equals("<< failed", date.asString(),expected_str);
- ensure_equals("<< to >> failed", stream.str(),out_stream.str());
- }
+ ensure_equals("<< failed", date.asString(),expected_str);
+ ensure_equals("<< to >> failed", stream.str(),out_stream.str());
+ }
}
diff --git a/indra/llcommon/tests/lldeadmantimer_test.cpp b/indra/llcommon/tests/lldeadmantimer_test.cpp
index 23167762c3..01e6e8e2f7 100644
--- a/indra/llcommon/tests/lldeadmantimer_test.cpp
+++ b/indra/llcommon/tests/lldeadmantimer_test.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldeadmantimer_test.cpp
* @brief Tests for the LLDeadmanTimer class.
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2013, 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$
*/
@@ -37,12 +37,12 @@
static LLDeadmanTimer::time_type float_time_to_u64(F64 delta)
{
- return LLDeadmanTimer::time_type(delta * get_timer_info().mClockFrequency);
+ return LLDeadmanTimer::time_type(delta * get_timer_info().mClockFrequency);
}
static F64 u64_time_to_float(LLDeadmanTimer::time_type delta)
{
- return delta * get_timer_info().mClockFrequencyInv;
+ return delta * get_timer_info().mClockFrequencyInv;
}
@@ -51,11 +51,11 @@ namespace tut
struct deadmantimer_test
{
- deadmantimer_test()
- {
- // LLTimer internals updating
- get_timer_info().update();
- }
+ deadmantimer_test()
+ {
+ // LLTimer internals updating
+ get_timer_info().update();
+ }
};
typedef test_group<deadmantimer_test> deadmantimer_group_t;
@@ -66,31 +66,31 @@ tut::deadmantimer_group_t deadmantimer_instance("LLDeadmanTimer");
template<> template<>
void deadmantimer_object_t::test<1>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(10.0, false);
-
- ensure_equals("WOCM isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count), false);
- ensure_approximately_equals("WOCM t1 - isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WOCM t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WOCM t1 - isExpired() does not modify count", count, U64L(8));
- }
-
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(10.0, true);
-
- ensure_equals("WCM isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false);
- ensure_approximately_equals("WCM t1 - isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WCM t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WCM t1 - isExpired() does not modify count", count, U64L(8));
- ensure_equals("WCM t1 - isExpired() does not modify user_cpu", user_cpu, U64L(29000));
- ensure_equals("WCM t1 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(10.0, false);
+
+ ensure_equals("WOCM isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count), false);
+ ensure_approximately_equals("WOCM t1 - isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WOCM t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WOCM t1 - isExpired() does not modify count", count, U64L(8));
+ }
+
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(10.0, true);
+
+ ensure_equals("WCM isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false);
+ ensure_approximately_equals("WCM t1 - isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WCM t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WCM t1 - isExpired() does not modify count", count, U64L(8));
+ ensure_equals("WCM t1 - isExpired() does not modify user_cpu", user_cpu, U64L(29000));
+ ensure_equals("WCM t1 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
+ }
}
@@ -98,25 +98,25 @@ void deadmantimer_object_t::test<1>()
template<> template<>
void deadmantimer_object_t::test<2>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(0.0, false); // Zero is pre-expired
-
- ensure_equals("WOCM isExpired() still returns false with 0.0 time ctor()",
- timer.isExpired(0, started, stopped, count), false);
- }
-
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(0.0, true); // Zero is pre-expired
-
- ensure_equals("WCM isExpired() still returns false with 0.0 time ctor()",
- timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false);
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(0.0, false); // Zero is pre-expired
+
+ ensure_equals("WOCM isExpired() still returns false with 0.0 time ctor()",
+ timer.isExpired(0, started, stopped, count), false);
+ }
+
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(0.0, true); // Zero is pre-expired
+
+ ensure_equals("WCM isExpired() still returns false with 0.0 time ctor()",
+ timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false);
+ }
}
@@ -125,28 +125,28 @@ void deadmantimer_object_t::test<2>()
template<> template<>
void deadmantimer_object_t::test<3>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(0.0, false);
-
- timer.start(0);
- ensure_equals("WOCM isExpired() returns true with 0.0 horizon time",
- timer.isExpired(0, started, stopped, count), true);
- ensure_approximately_equals("WOCM expired timer with no bell ringing has stopped == started", started, stopped, 8);
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(0.0, true);
-
- timer.start(0);
- ensure_equals("WCM isExpired() returns true with 0.0 horizon time",
- timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), true);
- ensure_approximately_equals("WCM expired timer with no bell ringing has stopped == started", started, stopped, 8);
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(0.0, false);
+
+ timer.start(0);
+ ensure_equals("WOCM isExpired() returns true with 0.0 horizon time",
+ timer.isExpired(0, started, stopped, count), true);
+ ensure_approximately_equals("WOCM expired timer with no bell ringing has stopped == started", started, stopped, 8);
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(0.0, true);
+
+ timer.start(0);
+ ensure_equals("WCM isExpired() returns true with 0.0 horizon time",
+ timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), true);
+ ensure_approximately_equals("WCM expired timer with no bell ringing has stopped == started", started, stopped, 8);
+ }
}
@@ -154,30 +154,30 @@ void deadmantimer_object_t::test<3>()
template<> template<>
void deadmantimer_object_t::test<4>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(0.0, false);
-
- timer.start(0);
- timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1);
- ensure_equals("WOCM isExpired() returns true with 0.0 horizon time after bell ring",
- timer.isExpired(0, started, stopped, count), true);
- ensure_approximately_equals("WOCM ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8);
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(0.0, true);
-
- timer.start(0);
- timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1);
- ensure_equals("WCM isExpired() returns true with 0.0 horizon time after bell ring",
- timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), true);
- ensure_approximately_equals("WCM ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8);
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(0.0, false);
+
+ timer.start(0);
+ timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1);
+ ensure_equals("WOCM isExpired() returns true with 0.0 horizon time after bell ring",
+ timer.isExpired(0, started, stopped, count), true);
+ ensure_approximately_equals("WOCM ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8);
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(0.0, true);
+
+ timer.start(0);
+ timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1);
+ ensure_equals("WCM isExpired() returns true with 0.0 horizon time after bell ring",
+ timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), true);
+ ensure_approximately_equals("WCM ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8);
+ }
}
@@ -185,34 +185,34 @@ void deadmantimer_object_t::test<4>()
template<> template<>
void deadmantimer_object_t::test<5>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(10.0, false);
-
- timer.start(0);
- ensure_equals("WOCM isExpired() returns false after starting with 10.0 horizon time",
- timer.isExpired(0, started, stopped, count), false);
- ensure_approximately_equals("WOCM t5 - isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WOCM t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WOCM t5 - isExpired() does not modify count", count, U64L(8));
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(10.0, true);
-
- timer.start(0);
- ensure_equals("WCM isExpired() returns false after starting with 10.0 horizon time",
- timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false);
- ensure_approximately_equals("WCM t5 - isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WCM t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WCM t5 - isExpired() does not modify count", count, U64L(8));
- ensure_equals("WCM t5 - isExpired() does not modify user_cpu", user_cpu, U64L(29000));
- ensure_equals("WCM t5 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(10.0, false);
+
+ timer.start(0);
+ ensure_equals("WOCM isExpired() returns false after starting with 10.0 horizon time",
+ timer.isExpired(0, started, stopped, count), false);
+ ensure_approximately_equals("WOCM t5 - isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WOCM t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WOCM t5 - isExpired() does not modify count", count, U64L(8));
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(10.0, true);
+
+ timer.start(0);
+ ensure_equals("WCM isExpired() returns false after starting with 10.0 horizon time",
+ timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false);
+ ensure_approximately_equals("WCM t5 - isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WCM t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WCM t5 - isExpired() does not modify count", count, U64L(8));
+ ensure_equals("WCM t5 - isExpired() does not modify user_cpu", user_cpu, U64L(29000));
+ ensure_equals("WCM t5 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
+ }
}
@@ -220,46 +220,46 @@ void deadmantimer_object_t::test<5>()
template<> template<>
void deadmantimer_object_t::test<6>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(10.0, false);
-
- // Would like to do subtraction on current time but can't because
- // the implementation on Windows is zero-based. We wrap around
- // the backside resulting in a large U64 number.
-
- LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
- LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0));
- timer.start(the_past);
- ensure_equals("WOCM t6 - isExpired() returns false with 10.0 horizon time starting 5.0 in past",
- timer.isExpired(now, started, stopped, count), false);
- ensure_approximately_equals("WOCM t6 - isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WOCM t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WOCM t6 - isExpired() does not modify count", count, U64L(8));
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(10.0, true);
-
- // Would like to do subtraction on current time but can't because
- // the implementation on Windows is zero-based. We wrap around
- // the backside resulting in a large U64 number.
-
- LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
- LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0));
- timer.start(the_past);
- ensure_equals("WCM t6 - isExpired() returns false with 10.0 horizon time starting 5.0 in past",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
- ensure_approximately_equals("WCM t6 - isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WCM t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("t6 - isExpired() does not modify count", count, U64L(8));
- ensure_equals("WCM t6 - isExpired() does not modify user_cpu", user_cpu, U64L(29000));
- ensure_equals("WCM t6 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(10.0, false);
+
+ // Would like to do subtraction on current time but can't because
+ // the implementation on Windows is zero-based. We wrap around
+ // the backside resulting in a large U64 number.
+
+ LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
+ LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0));
+ timer.start(the_past);
+ ensure_equals("WOCM t6 - isExpired() returns false with 10.0 horizon time starting 5.0 in past",
+ timer.isExpired(now, started, stopped, count), false);
+ ensure_approximately_equals("WOCM t6 - isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WOCM t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WOCM t6 - isExpired() does not modify count", count, U64L(8));
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(10.0, true);
+
+ // Would like to do subtraction on current time but can't because
+ // the implementation on Windows is zero-based. We wrap around
+ // the backside resulting in a large U64 number.
+
+ LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
+ LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0));
+ timer.start(the_past);
+ ensure_equals("WCM t6 - isExpired() returns false with 10.0 horizon time starting 5.0 in past",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+ ensure_approximately_equals("WCM t6 - isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WCM t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("t6 - isExpired() does not modify count", count, U64L(8));
+ ensure_equals("WCM t6 - isExpired() does not modify user_cpu", user_cpu, U64L(29000));
+ ensure_equals("WCM t6 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
+ }
}
@@ -267,40 +267,40 @@ void deadmantimer_object_t::test<6>()
template<> template<>
void deadmantimer_object_t::test<7>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(10.0, false);
-
- // Would like to do subtraction on current time but can't because
- // the implementation on Windows is zero-based. We wrap around
- // the backside resulting in a large U64 number.
-
- LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
- LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
- timer.start(the_past);
- ensure_equals("WOCM t7 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
- timer.isExpired(now,started, stopped, count), true);
- ensure_approximately_equals("WOCM t7 - starting before horizon still gives equal started / stopped", started, stopped, 8);
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(10.0, true);
-
- // Would like to do subtraction on current time but can't because
- // the implementation on Windows is zero-based. We wrap around
- // the backside resulting in a large U64 number.
-
- LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
- LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
- timer.start(the_past);
- ensure_equals("WCM t7 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
- timer.isExpired(now,started, stopped, count, user_cpu, sys_cpu), true);
- ensure_approximately_equals("WOCM t7 - starting before horizon still gives equal started / stopped", started, stopped, 8);
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(10.0, false);
+
+ // Would like to do subtraction on current time but can't because
+ // the implementation on Windows is zero-based. We wrap around
+ // the backside resulting in a large U64 number.
+
+ LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
+ LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
+ timer.start(the_past);
+ ensure_equals("WOCM t7 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
+ timer.isExpired(now,started, stopped, count), true);
+ ensure_approximately_equals("WOCM t7 - starting before horizon still gives equal started / stopped", started, stopped, 8);
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(10.0, true);
+
+ // Would like to do subtraction on current time but can't because
+ // the implementation on Windows is zero-based. We wrap around
+ // the backside resulting in a large U64 number.
+
+ LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
+ LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
+ timer.start(the_past);
+ ensure_equals("WCM t7 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
+ timer.isExpired(now,started, stopped, count, user_cpu, sys_cpu), true);
+ ensure_approximately_equals("WOCM t7 - starting before horizon still gives equal started / stopped", started, stopped, 8);
+ }
}
@@ -308,60 +308,60 @@ void deadmantimer_object_t::test<7>()
template<> template<>
void deadmantimer_object_t::test<8>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(10.0, false);
-
- // Would like to do subtraction on current time but can't because
- // the implementation on Windows is zero-based. We wrap around
- // the backside resulting in a large U64 number.
-
- LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
- LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
- timer.start(the_past);
- ensure_equals("WOCM t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
- timer.isExpired(now, started, stopped, count), true);
-
- started = 42.0;
- stopped = 97.0;
- count = U64L(8);
- ensure_equals("WOCM t8 - second isExpired() returns false after true",
- timer.isExpired(now, started, stopped, count), false);
- ensure_approximately_equals("WOCM t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WOCM t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WOCM t8 - 2nd isExpired() does not modify count", count, U64L(8));
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(10.0, true);
-
- // Would like to do subtraction on current time but can't because
- // the implementation on Windows is zero-based. We wrap around
- // the backside resulting in a large U64 number.
-
- LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
- LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
- timer.start(the_past);
- ensure_equals("WCM t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
-
- started = 42.0;
- stopped = 97.0;
- count = U64L(8);
- user_cpu = 29000;
- sys_cpu = 57000;
- ensure_equals("WCM t8 - second isExpired() returns false after true",
- timer.isExpired(now, started, stopped, count), false);
- ensure_approximately_equals("WCM t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2);
- ensure_approximately_equals("WCM t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2);
- ensure_equals("WCM t8 - 2nd isExpired() does not modify count", count, U64L(8));
- ensure_equals("WCM t8 - 2nd isExpired() does not modify user_cpu", user_cpu, U64L(29000));
- ensure_equals("WCM t8 - 2nd isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(10.0, false);
+
+ // Would like to do subtraction on current time but can't because
+ // the implementation on Windows is zero-based. We wrap around
+ // the backside resulting in a large U64 number.
+
+ LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
+ LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
+ timer.start(the_past);
+ ensure_equals("WOCM t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
+ timer.isExpired(now, started, stopped, count), true);
+
+ started = 42.0;
+ stopped = 97.0;
+ count = U64L(8);
+ ensure_equals("WOCM t8 - second isExpired() returns false after true",
+ timer.isExpired(now, started, stopped, count), false);
+ ensure_approximately_equals("WOCM t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WOCM t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WOCM t8 - 2nd isExpired() does not modify count", count, U64L(8));
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(10.0, true);
+
+ // Would like to do subtraction on current time but can't because
+ // the implementation on Windows is zero-based. We wrap around
+ // the backside resulting in a large U64 number.
+
+ LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow());
+ LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0));
+ timer.start(the_past);
+ ensure_equals("WCM t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
+
+ started = 42.0;
+ stopped = 97.0;
+ count = U64L(8);
+ user_cpu = 29000;
+ sys_cpu = 57000;
+ ensure_equals("WCM t8 - second isExpired() returns false after true",
+ timer.isExpired(now, started, stopped, count), false);
+ ensure_approximately_equals("WCM t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2);
+ ensure_approximately_equals("WCM t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2);
+ ensure_equals("WCM t8 - 2nd isExpired() does not modify count", count, U64L(8));
+ ensure_equals("WCM t8 - 2nd isExpired() does not modify user_cpu", user_cpu, U64L(29000));
+ ensure_equals("WCM t8 - 2nd isExpired() does not modify sys_cpu", sys_cpu, U64L(57000));
+ }
}
@@ -369,92 +369,92 @@ void deadmantimer_object_t::test<8>()
template<> template<>
void deadmantimer_object_t::test<9>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(5.0, false);
-
- LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
- F64 real_start(u64_time_to_float(now));
- timer.start(0);
-
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- ensure_equals("WOCM t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
- timer.isExpired(now, started, stopped, count), false);
- F64 last_good_ring(u64_time_to_float(now));
-
- // Jump forward and expire
- now += float_time_to_u64(10.0);
- ensure_equals("WOCM t9 - 5.0 horizon timer expires on 10-second jump",
- timer.isExpired(now, started, stopped, count), true);
- ensure_approximately_equals("WOCM t9 - started matches start() time", started, real_start, 4);
- ensure_approximately_equals("WOCM t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
- ensure_equals("WOCM t9 - 10 good ringBell()s", count, U64L(10));
- ensure_equals("WOCM t9 - single read only", timer.isExpired(now, started, stopped, count), false);
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
- LLDeadmanTimer timer(5.0, true);
-
- LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
- F64 real_start(u64_time_to_float(now));
- timer.start(0);
-
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- ensure_equals("WCM t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
- F64 last_good_ring(u64_time_to_float(now));
-
- // Jump forward and expire
- now += float_time_to_u64(10.0);
- ensure_equals("WCM t9 - 5.0 horizon timer expires on 10-second jump",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
- ensure_approximately_equals("WCM t9 - started matches start() time", started, real_start, 4);
- ensure_approximately_equals("WCM t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
- ensure_equals("WCM t9 - 10 good ringBell()s", count, U64L(10));
- ensure_equals("WCM t9 - single read only", timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(5.0, false);
+
+ LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
+ F64 real_start(u64_time_to_float(now));
+ timer.start(0);
+
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ ensure_equals("WOCM t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
+ timer.isExpired(now, started, stopped, count), false);
+ F64 last_good_ring(u64_time_to_float(now));
+
+ // Jump forward and expire
+ now += float_time_to_u64(10.0);
+ ensure_equals("WOCM t9 - 5.0 horizon timer expires on 10-second jump",
+ timer.isExpired(now, started, stopped, count), true);
+ ensure_approximately_equals("WOCM t9 - started matches start() time", started, real_start, 4);
+ ensure_approximately_equals("WOCM t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
+ ensure_equals("WOCM t9 - 10 good ringBell()s", count, U64L(10));
+ ensure_equals("WOCM t9 - single read only", timer.isExpired(now, started, stopped, count), false);
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+ LLDeadmanTimer timer(5.0, true);
+
+ LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
+ F64 real_start(u64_time_to_float(now));
+ timer.start(0);
+
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ ensure_equals("WCM t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+ F64 last_good_ring(u64_time_to_float(now));
+
+ // Jump forward and expire
+ now += float_time_to_u64(10.0);
+ ensure_equals("WCM t9 - 5.0 horizon timer expires on 10-second jump",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
+ ensure_approximately_equals("WCM t9 - started matches start() time", started, real_start, 4);
+ ensure_approximately_equals("WCM t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
+ ensure_equals("WCM t9 - 10 good ringBell()s", count, U64L(10));
+ ensure_equals("WCM t9 - single read only", timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+ }
}
@@ -462,165 +462,165 @@ void deadmantimer_object_t::test<9>()
template<> template<>
void deadmantimer_object_t::test<10>()
{
- {
- // Without cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8));
- LLDeadmanTimer timer(5.0, false);
-
- LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
- F64 real_start(u64_time_to_float(now));
- timer.start(0);
-
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- ensure_equals("WOCM t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
- timer.isExpired(now, started, stopped, count), false);
- F64 last_good_ring(u64_time_to_float(now));
-
- // Jump forward and expire
- now += float_time_to_u64(10.0);
- ensure_equals("WOCM t10 - 5.0 horizon timer expires on 10-second jump",
- timer.isExpired(now, started, stopped, count), true);
- ensure_approximately_equals("WOCM t10 - started matches start() time", started, real_start, 4);
- ensure_approximately_equals("WOCM t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
- ensure_equals("WOCM t10 - 10 good ringBell()s", count, U64L(10));
- ensure_equals("WOCM t10 - single read only", timer.isExpired(now, started, stopped, count), false);
-
- // Jump forward and restart
- now += float_time_to_u64(1.0);
- real_start = u64_time_to_float(now);
- timer.start(now);
-
- // Run a modified bell ring sequence
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- ensure_equals("WOCM t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings",
- timer.isExpired(now, started, stopped, count), false);
- last_good_ring = u64_time_to_float(now);
-
- // Jump forward and expire
- now += float_time_to_u64(10.0);
- ensure_equals("WOCM t10 - 5.0 horizon timer expires on 8-second jump",
- timer.isExpired(now, started, stopped, count), true);
- ensure_approximately_equals("WOCM t10 - 2nd started matches start() time", started, real_start, 4);
- ensure_approximately_equals("WOCM t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4);
- ensure_equals("WOCM t10 - 8 good ringBell()s", count, U64L(8));
- ensure_equals("WOCM t10 - single read only - 2nd start",
- timer.isExpired(now, started, stopped, count), false);
- }
- {
- // With cpu metrics
- F64 started(42.0), stopped(97.0);
- U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
-
- LLDeadmanTimer timer(5.0, true);
-
- LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
- F64 real_start(u64_time_to_float(now));
- timer.start(0);
-
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- ensure_equals("WCM t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
- F64 last_good_ring(u64_time_to_float(now));
-
- // Jump forward and expire
- now += float_time_to_u64(10.0);
- ensure_equals("WCM t10 - 5.0 horizon timer expires on 10-second jump",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
- ensure_approximately_equals("WCM t10 - started matches start() time", started, real_start, 4);
- ensure_approximately_equals("WCM t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
- ensure_equals("WCM t10 - 10 good ringBell()s", count, U64L(10));
- ensure_equals("WCM t10 - single read only", timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
-
- // Jump forward and restart
- now += float_time_to_u64(1.0);
- real_start = u64_time_to_float(now);
- timer.start(now);
-
- // Run a modified bell ring sequence
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- now += float_time_to_u64(1.0);
- timer.ringBell(now, 1);
- ensure_equals("WCM t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
- last_good_ring = u64_time_to_float(now);
-
- // Jump forward and expire
- now += float_time_to_u64(10.0);
- ensure_equals("WCM t10 - 5.0 horizon timer expires on 8-second jump",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
- ensure_approximately_equals("WCM t10 - 2nd started matches start() time", started, real_start, 4);
- ensure_approximately_equals("WCM t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4);
- ensure_equals("WCM t10 - 8 good ringBell()s", count, U64L(8));
- ensure_equals("WCM t10 - single read only - 2nd start",
- timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
- }
+ {
+ // Without cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8));
+ LLDeadmanTimer timer(5.0, false);
+
+ LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
+ F64 real_start(u64_time_to_float(now));
+ timer.start(0);
+
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ ensure_equals("WOCM t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
+ timer.isExpired(now, started, stopped, count), false);
+ F64 last_good_ring(u64_time_to_float(now));
+
+ // Jump forward and expire
+ now += float_time_to_u64(10.0);
+ ensure_equals("WOCM t10 - 5.0 horizon timer expires on 10-second jump",
+ timer.isExpired(now, started, stopped, count), true);
+ ensure_approximately_equals("WOCM t10 - started matches start() time", started, real_start, 4);
+ ensure_approximately_equals("WOCM t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
+ ensure_equals("WOCM t10 - 10 good ringBell()s", count, U64L(10));
+ ensure_equals("WOCM t10 - single read only", timer.isExpired(now, started, stopped, count), false);
+
+ // Jump forward and restart
+ now += float_time_to_u64(1.0);
+ real_start = u64_time_to_float(now);
+ timer.start(now);
+
+ // Run a modified bell ring sequence
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ ensure_equals("WOCM t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings",
+ timer.isExpired(now, started, stopped, count), false);
+ last_good_ring = u64_time_to_float(now);
+
+ // Jump forward and expire
+ now += float_time_to_u64(10.0);
+ ensure_equals("WOCM t10 - 5.0 horizon timer expires on 8-second jump",
+ timer.isExpired(now, started, stopped, count), true);
+ ensure_approximately_equals("WOCM t10 - 2nd started matches start() time", started, real_start, 4);
+ ensure_approximately_equals("WOCM t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4);
+ ensure_equals("WOCM t10 - 8 good ringBell()s", count, U64L(8));
+ ensure_equals("WOCM t10 - single read only - 2nd start",
+ timer.isExpired(now, started, stopped, count), false);
+ }
+ {
+ // With cpu metrics
+ F64 started(42.0), stopped(97.0);
+ U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000);
+
+ LLDeadmanTimer timer(5.0, true);
+
+ LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow());
+ F64 real_start(u64_time_to_float(now));
+ timer.start(0);
+
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ ensure_equals("WCM t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+ F64 last_good_ring(u64_time_to_float(now));
+
+ // Jump forward and expire
+ now += float_time_to_u64(10.0);
+ ensure_equals("WCM t10 - 5.0 horizon timer expires on 10-second jump",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
+ ensure_approximately_equals("WCM t10 - started matches start() time", started, real_start, 4);
+ ensure_approximately_equals("WCM t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4);
+ ensure_equals("WCM t10 - 10 good ringBell()s", count, U64L(10));
+ ensure_equals("WCM t10 - single read only", timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+
+ // Jump forward and restart
+ now += float_time_to_u64(1.0);
+ real_start = u64_time_to_float(now);
+ timer.start(now);
+
+ // Run a modified bell ring sequence
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ now += float_time_to_u64(1.0);
+ timer.ringBell(now, 1);
+ ensure_equals("WCM t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+ last_good_ring = u64_time_to_float(now);
+
+ // Jump forward and expire
+ now += float_time_to_u64(10.0);
+ ensure_equals("WCM t10 - 5.0 horizon timer expires on 8-second jump",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true);
+ ensure_approximately_equals("WCM t10 - 2nd started matches start() time", started, real_start, 4);
+ ensure_approximately_equals("WCM t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4);
+ ensure_equals("WCM t10 - 8 good ringBell()s", count, U64L(8));
+ ensure_equals("WCM t10 - single read only - 2nd start",
+ timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false);
+ }
}
diff --git a/indra/llcommon/tests/lldependencies_test.cpp b/indra/llcommon/tests/lldependencies_test.cpp
index b5e189a465..84eb41b5fe 100644
--- a/indra/llcommon/tests/lldependencies_test.cpp
+++ b/indra/llcommon/tests/lldependencies_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-09-17
* @brief Test of lldependencies.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$
*/
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index b4cdbdc6bf..3ec429530c 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,95 +96,95 @@ 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() { return (int) mMessages.size(); }
- void clearMessages() { mMessages.clear(); }
-
- std::string message(int n)
- {
- std::ostringstream test_name;
- test_name << "testing message " << n << ", not enough messages";
-
- tut::ensure(test_name.str(), n < countMessages());
- return mMessages[n];
- }
-
- private:
- typedef std::vector<std::string> MessageVector;
- MessageVector mMessages;
- };
-
- struct ErrorTestData
- {
- LLError::RecorderPtr mRecorder;
- LLError::SettingsStoragePtr mPriorErrorSettings;
-
- 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 std::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages();
- }
-
- void clearMessages()
- {
- std::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages();
- }
-
- void setWantsTime(bool t)
+ 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() { return (int) mMessages.size(); }
+ void clearMessages() { mMessages.clear(); }
+
+ std::string message(int n)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n << ", not enough messages";
+
+ tut::ensure(test_name.str(), n < countMessages());
+ return mMessages[n];
+ }
+
+ private:
+ typedef std::vector<std::string> MessageVector;
+ MessageVector mMessages;
+ };
+
+ struct ErrorTestData
+ {
+ LLError::RecorderPtr mRecorder;
+ LLError::SettingsStoragePtr mPriorErrorSettings;
+
+ 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 std::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages();
+ }
+
+ void clearMessages()
+ {
+ std::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages();
+ }
+
+ void setWantsTime(bool t)
{
std::dynamic_pointer_cast<TestRecorder>(mRecorder)->showTime(t);
}
- void setWantsMultiline(bool t)
+ void setWantsMultiline(bool t)
{
std::dynamic_pointer_cast<TestRecorder>(mRecorder)->showMultiline(t);
}
- std::string message(int n)
- {
- return std::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n);
- }
+ std::string message(int n)
+ {
+ return std::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n);
+ }
- void ensure_message_count(int expectedCount)
- {
- ensure_equals("message count", countMessages(), expectedCount);
- }
+ 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";
+ test_name << "testing message " << msgnum << ", not enough messages";
tut::ensure(test_name.str(), msgnum < countMessages());
std::string msg(message(msgnum));
@@ -204,7 +204,7 @@ namespace tut
on_field++;
}
// except function, which may have embedded spaces so ends with " : "
- else if ( ( on_field == FUNCTION_FIELD )
+ else if ( ( on_field == FUNCTION_FIELD )
&& ( ':' == msg[scan+1] && ' ' == msg[scan+2] )
)
{
@@ -220,9 +220,9 @@ namespace tut
{
fieldlen = msg.find(' ', start_field) - start_field;
}
- else if ( fieldnum == FUNCTION_FIELD )
+ else if ( fieldnum == FUNCTION_FIELD )
{
- fieldlen = msg.find(" : ", start_field) - start_field;
+ fieldlen = msg.find(" : ", start_field) - start_field;
}
else if ( MSG_FIELD == fieldnum ) // no delimiter, just everything to the end
{
@@ -231,8 +231,8 @@ namespace tut
return msg.substr(start_field, fieldlen);
}
-
- void ensure_message_field_equals(int msgnum, LogFieldIndex fieldnum, const std::string& expectedText)
+
+ 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) << "\"\n ";
@@ -240,105 +240,105 @@ namespace tut
ensure_equals(test_name.str(), message_field(msgnum, fieldnum), expectedText);
}
- void ensure_message_does_not_contain(int n, const std::string& expectedText)
- {
- std::ostringstream test_name;
- test_name << "testing message " << n;
+ void ensure_message_does_not_contain(int n, const std::string& expectedText)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n;
- ensure_does_not_contain(test_name.str(), message(n), expectedText);
- }
- };
+ ensure_does_not_contain(test_name.str(), message(n), expectedText);
+ }
+ };
- typedef test_group<ErrorTestData> ErrorTestGroup;
- typedef ErrorTestGroup::object ErrorTestObject;
+ typedef test_group<ErrorTestData> ErrorTestGroup;
+ typedef ErrorTestGroup::object ErrorTestObject;
- ErrorTestGroup errorTestGroup("error");
+ ErrorTestGroup errorTestGroup("error");
- template<> template<>
- void ErrorTestObject::test<1>()
- // basic test of output
- {
- LL_INFOS() << "test" << LL_ENDL;
- LL_INFOS() << "bob" << LL_ENDL;
+ 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");
- }
+ 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#");
- ensure_message_count(4);
-
- LLError::setDefaultLevel(LLError::LEVEL_INFO);
- writeSome();
- ensure_message_field_equals(4, MSG_FIELD, "two");
- ensure_message_field_equals(5, MSG_FIELD, "three");
- ensure_message_field_equals(6, MSG_FIELD, "four");
- ensure_message_count(7);
-
- LLError::setDefaultLevel(LLError::LEVEL_WARN);
- writeSome();
- ensure_message_field_equals(7, MSG_FIELD, "three");
- ensure_message_field_equals(8, MSG_FIELD, "four");
- ensure_message_count(9);
-
- LLError::setDefaultLevel(LLError::LEVEL_ERROR);
- writeSome();
- ensure_message_field_equals(9, MSG_FIELD, "four");
- ensure_message_count(10);
-
- LLError::setDefaultLevel(LLError::LEVEL_NONE);
- writeSome();
- ensure_message_count(10);
- }
-
- 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");
- ensure_message_count(4);
- }
-
- template<> template<>
- void ErrorTestObject::test<4>()
- // file abbreviation
- {
- std::string prev, abbreviateFile = __FILE__;
+ 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#");
+ ensure_message_count(4);
+
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+ writeSome();
+ ensure_message_field_equals(4, MSG_FIELD, "two");
+ ensure_message_field_equals(5, MSG_FIELD, "three");
+ ensure_message_field_equals(6, MSG_FIELD, "four");
+ ensure_message_count(7);
+
+ LLError::setDefaultLevel(LLError::LEVEL_WARN);
+ writeSome();
+ ensure_message_field_equals(7, MSG_FIELD, "three");
+ ensure_message_field_equals(8, MSG_FIELD, "four");
+ ensure_message_count(9);
+
+ LLError::setDefaultLevel(LLError::LEVEL_ERROR);
+ writeSome();
+ ensure_message_field_equals(9, MSG_FIELD, "four");
+ ensure_message_count(10);
+
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+ writeSome();
+ ensure_message_count(10);
+ }
+
+ 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");
+ ensure_message_count(4);
+ }
+
+ template<> template<>
+ void ErrorTestObject::test<4>()
+ // file abbreviation
+ {
+ std::string prev, abbreviateFile = __FILE__;
do
{
prev = abbreviateFile;
@@ -354,169 +354,169 @@ namespace tut
// 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");
+ ensure_ends_with("file name abbreviation",
+ abbreviateFile,
+ "llcommon/tests/llerror_test.cpp"
+ );
+ ensure_does_not_contain("file name abbreviation",
+ abbreviateFile, "indra");
- std::string someFile =
+ 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
@@ -540,7 +540,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");
@@ -554,324 +554,324 @@ 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");
- ensure_message_count(1);
-
- 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");
+ ensure_message_count(1);
+
+ 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");
- ensure_message_field_equals(2, MSG_FIELD, "buy iron");
- ensure_message_field_equals(3, MSG_FIELD, "bad word");
- ensure_message_field_equals(4, MSG_FIELD, "big easy");
- ensure_message_count(5);
- }
-
- 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");
+ ensure_message_field_equals(2, MSG_FIELD, "buy iron");
+ ensure_message_field_equals(3, MSG_FIELD, "bad word");
+ ensure_message_field_equals(4, MSG_FIELD, "big easy");
+ ensure_message_count(5);
+ }
+
+ 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");
- ensure_message_field_equals(5, MSG_FIELD, "bad word");
- ensure_message_field_equals(6, MSG_FIELD, "big easy");
- ensure_message_count(7);
- }
+ 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");
+ ensure_message_field_equals(5, MSG_FIELD, "bad word");
+ ensure_message_field_equals(6, MSG_FIELD, "big easy");
+ ensure_message_count(7);
+ }
}
namespace tut
@@ -919,16 +919,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/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index 01104545c6..a3c54ffaa2 100644
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-04-22
* @brief Test for coroutine.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp
index b0c532887c..a99acba848 100644
--- a/indra/llcommon/tests/lleventdispatcher_test.cpp
+++ b/indra/llcommon/tests/lleventdispatcher_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2011-01-20
* @brief Test for lleventdispatcher.
- *
+ *
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Copyright (c) 2011, Linden Research, Inc.
* $/LicenseInfo$
@@ -470,7 +470,7 @@ namespace tut
params["a"], "\n"
"params[\"b\"]:\n",
params["b"]);
- // default LLSD::Binary value
+ // default LLSD::Binary value
std::vector<U8> binary;
for (size_t ix = 0, h = 0xaa; ix < 6; ++ix, h += 0x11)
{
diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp
index fa2cb03e95..a01d7fe415 100644
--- a/indra/llcommon/tests/lleventfilter_test.cpp
+++ b/indra/llcommon/tests/lleventfilter_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-03-06
* @brief Test for lleventfilter.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/tests/llframetimer_test.cpp b/indra/llcommon/tests/llframetimer_test.cpp
index be372bb855..b9a8c91abf 100644
--- a/indra/llcommon/tests/llframetimer_test.cpp
+++ b/indra/llcommon/tests/llframetimer_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lltiming_test.cpp
* @date 2006-07-23
* @brief Tests the timers.
@@ -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$
*/
@@ -34,88 +34,88 @@
namespace tut
{
- struct frametimer_test
- {
- frametimer_test()
- {
- LLFrameTimer::updateFrameTime();
- }
- };
- typedef test_group<frametimer_test> frametimer_group_t;
- typedef frametimer_group_t::object frametimer_object_t;
- tut::frametimer_group_t frametimer_instance("LLFrameTimer");
+ struct frametimer_test
+ {
+ frametimer_test()
+ {
+ LLFrameTimer::updateFrameTime();
+ }
+ };
+ typedef test_group<frametimer_test> frametimer_group_t;
+ typedef frametimer_group_t::object frametimer_object_t;
+ tut::frametimer_group_t frametimer_instance("LLFrameTimer");
+
+ template<> template<>
+ void frametimer_object_t::test<1>()
+ {
+ F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
+ LLFrameTimer timer;
+ timer.setExpiryAt(seconds_since_epoch);
+ F64 expires_at = timer.expiresAt();
+ ensure_distance(
+ "set expiry matches get expiry",
+ expires_at,
+ seconds_since_epoch,
+ 0.001);
+ }
- template<> template<>
- void frametimer_object_t::test<1>()
- {
- F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
- LLFrameTimer timer;
- timer.setExpiryAt(seconds_since_epoch);
- F64 expires_at = timer.expiresAt();
- ensure_distance(
- "set expiry matches get expiry",
- expires_at,
- seconds_since_epoch,
- 0.001);
- }
+ template<> template<>
+ void frametimer_object_t::test<2>()
+ {
+ F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
+ seconds_since_epoch += 10.0;
+ LLFrameTimer timer;
+ timer.setExpiryAt(seconds_since_epoch);
+ F64 expires_at = timer.expiresAt();
+ ensure_distance(
+ "set expiry matches get expiry 1",
+ expires_at,
+ seconds_since_epoch,
+ 0.001);
+ seconds_since_epoch += 10.0;
+ timer.setExpiryAt(seconds_since_epoch);
+ expires_at = timer.expiresAt();
+ ensure_distance(
+ "set expiry matches get expiry 2",
+ expires_at,
+ seconds_since_epoch,
+ 0.001);
+ }
+ template<> template<>
+ void frametimer_object_t::test<3>()
+ {
+ clock_t t1 = clock();
+ ms_sleep(200);
+ clock_t t2 = clock();
+ clock_t elapsed = t2 - t1 + 1;
+ std::cout << "Note: using clock(), ms_sleep() actually took " << (long)elapsed << "ms" << std::endl;
- template<> template<>
- void frametimer_object_t::test<2>()
- {
- F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
- seconds_since_epoch += 10.0;
- LLFrameTimer timer;
- timer.setExpiryAt(seconds_since_epoch);
- F64 expires_at = timer.expiresAt();
- ensure_distance(
- "set expiry matches get expiry 1",
- expires_at,
- seconds_since_epoch,
- 0.001);
- seconds_since_epoch += 10.0;
- timer.setExpiryAt(seconds_since_epoch);
- expires_at = timer.expiresAt();
- ensure_distance(
- "set expiry matches get expiry 2",
- expires_at,
- seconds_since_epoch,
- 0.001);
- }
- template<> template<>
- void frametimer_object_t::test<3>()
- {
- clock_t t1 = clock();
- ms_sleep(200);
- clock_t t2 = clock();
- clock_t elapsed = t2 - t1 + 1;
- std::cout << "Note: using clock(), ms_sleep() actually took " << (long)elapsed << "ms" << std::endl;
+ F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
+ seconds_since_epoch += 2.0;
+ LLFrameTimer timer;
+ timer.setExpiryAt(seconds_since_epoch);
+ /*
+ * Note that the ms_sleep(200) below is only guaranteed to return
+ * in 200ms _or_more_, so it should be true that by the 10th
+ * iteration we've gotten to the 2 seconds requested above
+ * and the timer should expire, but it can expire in fewer iterations
+ * if one or more of the ms_sleep calls takes longer.
+ * (as it did when we moved to Mac OS X 10.10)
+ */
+ int iterations_until_expiration = 0;
+ while ( !timer.hasExpired() )
+ {
+ ms_sleep(200);
+ LLFrameTimer::updateFrameTime();
+ iterations_until_expiration++;
+ }
+ ensure("timer took too long to expire", iterations_until_expiration <= 10);
+ }
- F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
- seconds_since_epoch += 2.0;
- LLFrameTimer timer;
- timer.setExpiryAt(seconds_since_epoch);
- /*
- * Note that the ms_sleep(200) below is only guaranteed to return
- * in 200ms _or_more_, so it should be true that by the 10th
- * iteration we've gotten to the 2 seconds requested above
- * and the timer should expire, but it can expire in fewer iterations
- * if one or more of the ms_sleep calls takes longer.
- * (as it did when we moved to Mac OS X 10.10)
- */
- int iterations_until_expiration = 0;
- while ( !timer.hasExpired() )
- {
- ms_sleep(200);
- LLFrameTimer::updateFrameTime();
- iterations_until_expiration++;
- }
- ensure("timer took too long to expire", iterations_until_expiration <= 10);
- }
-
/*
- template<> template<>
- void frametimer_object_t::test<4>()
- {
- }
+ template<> template<>
+ void frametimer_object_t::test<4>()
+ {
+ }
*/
}
diff --git a/indra/llcommon/tests/llheteromap_test.cpp b/indra/llcommon/tests/llheteromap_test.cpp
index 686bffb878..cabfb91593 100644
--- a/indra/llcommon/tests/llheteromap_test.cpp
+++ b/indra/llcommon/tests/llheteromap_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2016-10-12
* @brief Test for llheteromap.
- *
+ *
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index 95af9c2a50..c6eb0fdf75 100644
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-11-10
* @brief Test for llinstancetracker.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -170,7 +170,7 @@ namespace tut
{
Unkeyed one, two, three;
typedef std::set<Unkeyed*> KeySet;
-
+
KeySet instances;
instances.insert(&one);
instances.insert(&two);
diff --git a/indra/llcommon/tests/lllazy_test.cpp b/indra/llcommon/tests/lllazy_test.cpp
index 542306ee22..923fe952a9 100644
--- a/indra/llcommon/tests/lllazy_test.cpp
+++ b/indra/llcommon/tests/lllazy_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-01-28
* @brief Tests of lllazy.h.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index 7197dedfbf..fa48bcdefd 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-02-21
* @brief Test for llleap.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/llmainthreadtask_test.cpp b/indra/llcommon/tests/llmainthreadtask_test.cpp
index 69b11ccafb..9ccf391327 100644
--- a/indra/llcommon/tests/llmainthreadtask_test.cpp
+++ b/indra/llcommon/tests/llmainthreadtask_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2019-12-05
* @brief Test for llmainthreadtask.
- *
+ *
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Copyright (c) 2019, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/llmemtype_test.cpp b/indra/llcommon/tests/llmemtype_test.cpp
index 1f050d6dc7..2d64d342ae 100644
--- a/indra/llcommon/tests/llmemtype_test.cpp
+++ b/indra/llcommon/tests/llmemtype_test.cpp
@@ -3,25 +3,25 @@
* @author Palmer Truelson
* @date 2008-03-
* @brief Test for llmemtype.cpp.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,14 +37,14 @@ std::stack<S32> memTypeStack;
void LLAllocator::pushMemType(S32 i)
{
- memTypeStack.push(i);
+ memTypeStack.push(i);
}
S32 LLAllocator::popMemType(void)
{
- S32 ret = memTypeStack.top();
- memTypeStack.pop();
- return ret;
+ S32 ret = memTypeStack.top();
+ memTypeStack.pop();
+ return ret;
}
namespace tut
@@ -69,49 +69,49 @@ namespace tut
ensure("Simplest test ever", true);
}
- // test with no scripts
- template<> template<>
- void object::test<2>()
- {
- {
- LLMemType m1(LLMemType::MTYPE_INIT);
- }
- ensure("Test that you can construct and destruct the mem type");
- }
-
- // test creation and stack testing
- template<> template<>
- void object::test<3>()
- {
- {
- ensure("Test that creation and destruction properly inc/dec the stack");
- ensure_equals(memTypeStack.size(), 0);
- {
- LLMemType m1(LLMemType::MTYPE_INIT);
- ensure_equals(memTypeStack.size(), 1);
- LLMemType m2(LLMemType::MTYPE_STARTUP);
- ensure_equals(memTypeStack.size(), 2);
- }
- ensure_equals(memTypeStack.size(), 0);
- }
- }
-
- // test with no scripts
- template<> template<>
- void object::test<4>()
- {
- // catch the begining and end
- std::string test_name = LLMemType::getNameFromID(LLMemType::MTYPE_INIT.mID);
- ensure_equals("Init name", test_name, "Init");
-
- std::string test_name2 = LLMemType::getNameFromID(LLMemType::MTYPE_VOLUME.mID);
- ensure_equals("Volume name", test_name2, "Volume");
-
- std::string test_name3 = LLMemType::getNameFromID(LLMemType::MTYPE_OTHER.mID);
- ensure_equals("Other name", test_name3, "Other");
+ // test with no scripts
+ template<> template<>
+ void object::test<2>()
+ {
+ {
+ LLMemType m1(LLMemType::MTYPE_INIT);
+ }
+ ensure("Test that you can construct and destruct the mem type");
+ }
+
+ // test creation and stack testing
+ template<> template<>
+ void object::test<3>()
+ {
+ {
+ ensure("Test that creation and destruction properly inc/dec the stack");
+ ensure_equals(memTypeStack.size(), 0);
+ {
+ LLMemType m1(LLMemType::MTYPE_INIT);
+ ensure_equals(memTypeStack.size(), 1);
+ LLMemType m2(LLMemType::MTYPE_STARTUP);
+ ensure_equals(memTypeStack.size(), 2);
+ }
+ ensure_equals(memTypeStack.size(), 0);
+ }
+ }
+
+ // test with no scripts
+ template<> template<>
+ void object::test<4>()
+ {
+ // catch the begining and end
+ std::string test_name = LLMemType::getNameFromID(LLMemType::MTYPE_INIT.mID);
+ ensure_equals("Init name", test_name, "Init");
+
+ std::string test_name2 = LLMemType::getNameFromID(LLMemType::MTYPE_VOLUME.mID);
+ ensure_equals("Volume name", test_name2, "Volume");
+
+ std::string test_name3 = LLMemType::getNameFromID(LLMemType::MTYPE_OTHER.mID);
+ ensure_equals("Other name", test_name3, "Other");
std::string test_name4 = LLMemType::getNameFromID(-1);
ensure_equals("Invalid name", test_name4, "INVALID");
- }
+ }
};
diff --git a/indra/llcommon/tests/llpounceable_test.cpp b/indra/llcommon/tests/llpounceable_test.cpp
index 2f4915ce11..b3024966c5 100644
--- a/indra/llcommon/tests/llpounceable_test.cpp
+++ b/indra/llcommon/tests/llpounceable_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2015-05-22
* @brief Test for llpounceable.
- *
+ *
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Copyright (c) 2015, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 628f046f55..6e8422ca0c 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2011-12-19
* @brief Test for llprocess.
- *
+ *
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Copyright (c) 2011, Linden Research, Inc.
* $/LicenseInfo$
@@ -1075,7 +1075,7 @@ namespace tut
{
EventListener(LLEventPump& pump)
{
- mConnection =
+ mConnection =
pump.listen("EventListener", boost::bind(&EventListener::tick, this, _1));
}
diff --git a/indra/llcommon/tests/llprocessor_test.cpp b/indra/llcommon/tests/llprocessor_test.cpp
index 884e1b5e5b..a2467d9205 100644
--- a/indra/llcommon/tests/llprocessor_test.cpp
+++ b/indra/llcommon/tests/llprocessor_test.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llprocessor_test.cpp
* @date 2010-06-01
*
* $LicenseInfo:firstyear=2010&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$
*/
@@ -32,30 +32,30 @@
namespace tut
{
- struct processor
- {
- };
-
- typedef test_group<processor> processor_t;
- typedef processor_t::object processor_object_t;
- tut::processor_t tut_processor("LLProcessor");
-
- template<> template<>
- void processor_object_t::test<1>()
- {
- set_test_name("LLProcessorInfo regression test");
-
- LLProcessorInfo pi;
- F64 freq = pi.getCPUFrequency();
- //bool sse = pi.hasSSE();
- //bool sse2 = pi.hasSSE2();
- //bool alitvec = pi.hasAltivec();
- std::string family = pi.getCPUFamilyName();
- std::string brand = pi.getCPUBrandName();
- //std::string steam = pi.getCPUFeatureDescription();
-
- ensure_not_equals("Unknown Brand name", brand, "Unknown");
- ensure_not_equals("Unknown Family name", family, "Unknown");
- ensure("Reasonable CPU Frequency > 100 && < 10000", freq > 100 && freq < 10000);
- }
+ struct processor
+ {
+ };
+
+ typedef test_group<processor> processor_t;
+ typedef processor_t::object processor_object_t;
+ tut::processor_t tut_processor("LLProcessor");
+
+ template<> template<>
+ void processor_object_t::test<1>()
+ {
+ set_test_name("LLProcessorInfo regression test");
+
+ LLProcessorInfo pi;
+ F64 freq = pi.getCPUFrequency();
+ //bool sse = pi.hasSSE();
+ //bool sse2 = pi.hasSSE2();
+ //bool alitvec = pi.hasAltivec();
+ std::string family = pi.getCPUFamilyName();
+ std::string brand = pi.getCPUBrandName();
+ //std::string steam = pi.getCPUFeatureDescription();
+
+ ensure_not_equals("Unknown Brand name", brand, "Unknown");
+ ensure_not_equals("Unknown Family name", family, "Unknown");
+ ensure("Reasonable CPU Frequency > 100 && < 10000", freq > 100 && freq < 10000);
+ }
}
diff --git a/indra/llcommon/tests/llprocinfo_test.cpp b/indra/llcommon/tests/llprocinfo_test.cpp
index 12d5a695ee..6a151048c2 100644
--- a/indra/llcommon/tests/llprocinfo_test.cpp
+++ b/indra/llcommon/tests/llprocinfo_test.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llprocinfo_test.cpp
* @brief Tests for the LLProcInfo class.
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2013, 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$
*/
@@ -40,9 +40,9 @@ namespace tut
struct procinfo_test
{
- procinfo_test()
- {
- }
+ procinfo_test()
+ {
+ }
};
typedef test_group<procinfo_test> procinfo_group_t;
@@ -54,14 +54,14 @@ tut::procinfo_group_t procinfo_instance("LLProcInfo");
template<> template<>
void procinfo_object_t::test<1>()
{
- LLProcInfo::time_type user(bad_user), system(bad_system);
+ LLProcInfo::time_type user(bad_user), system(bad_system);
+
+ set_test_name("getCPUUsage() basic function");
- set_test_name("getCPUUsage() basic function");
+ LLProcInfo::getCPUUsage(user, system);
- LLProcInfo::getCPUUsage(user, system);
-
- ensure_not_equals("getCPUUsage() writes to its user argument", user, bad_user);
- ensure_not_equals("getCPUUsage() writes to its system argument", system, bad_system);
+ ensure_not_equals("getCPUUsage() writes to its user argument", user, bad_user);
+ ensure_not_equals("getCPUUsage() writes to its system argument", system, bad_system);
}
@@ -69,22 +69,22 @@ void procinfo_object_t::test<1>()
template<> template<>
void procinfo_object_t::test<2>()
{
- LLProcInfo::time_type user(bad_user), system(bad_system);
- LLProcInfo::time_type user2(bad_user), system2(bad_system);
-
- set_test_name("getCPUUsage() increases over time");
-
- LLProcInfo::getCPUUsage(user, system);
-
- for (int i(0); i < 100000; ++i)
- {
- ms_sleep(0);
- }
-
- LLProcInfo::getCPUUsage(user2, system2);
-
- ensure_equals("getCPUUsage() user value doesn't decrease over time", user2 >= user, true);
- ensure_equals("getCPUUsage() system value doesn't decrease over time", system2 >= system, true);
+ LLProcInfo::time_type user(bad_user), system(bad_system);
+ LLProcInfo::time_type user2(bad_user), system2(bad_system);
+
+ set_test_name("getCPUUsage() increases over time");
+
+ LLProcInfo::getCPUUsage(user, system);
+
+ for (int i(0); i < 100000; ++i)
+ {
+ ms_sleep(0);
+ }
+
+ LLProcInfo::getCPUUsage(user2, system2);
+
+ ensure_equals("getCPUUsage() user value doesn't decrease over time", user2 >= user, true);
+ ensure_equals("getCPUUsage() system value doesn't decrease over time", system2 >= system, true);
}
diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp
index ac5a33d0ba..a0dd4ef576 100644
--- a/indra/llcommon/tests/llrand_test.cpp
+++ b/indra/llcommon/tests/llrand_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llrandom_test.cpp
* @author Phoenix
* @date 2007-01-25
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -49,76 +49,76 @@ void ensure_in_range(const std::string_view& name,
namespace tut
{
- struct random
- {
- };
+ struct random
+ {
+ };
- typedef test_group<random> random_t;
- typedef random_t::object random_object_t;
- tut::random_t tut_random("LLSeedRand");
+ typedef test_group<random> random_t;
+ typedef random_t::object random_object_t;
+ tut::random_t tut_random("LLSeedRand");
- template<> template<>
- void random_object_t::test<1>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- ensure_in_range("frand", ll_frand(), 0.0f, 1.0f);
- }
- }
+ template<> template<>
+ void random_object_t::test<1>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ ensure_in_range("frand", ll_frand(), 0.0f, 1.0f);
+ }
+ }
- template<> template<>
- void random_object_t::test<2>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- ensure_in_range("drand", ll_drand(), 0.0, 1.0);
- }
- }
+ template<> template<>
+ void random_object_t::test<2>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ ensure_in_range("drand", ll_drand(), 0.0, 1.0);
+ }
+ }
- template<> template<>
- void random_object_t::test<3>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- ensure_in_range("frand(2.0f)", ll_frand(2.0f) - 1.0f, -1.0f, 1.0f);
- }
- }
+ template<> template<>
+ void random_object_t::test<3>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ ensure_in_range("frand(2.0f)", ll_frand(2.0f) - 1.0f, -1.0f, 1.0f);
+ }
+ }
- template<> template<>
- void random_object_t::test<4>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- // Negate the result so we don't have to allow a templated low-end
- // comparison as well.
- ensure_in_range("-frand(-7.0)", -ll_frand(-7.0), 0.0f, 7.0f);
- }
- }
+ template<> template<>
+ void random_object_t::test<4>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ // Negate the result so we don't have to allow a templated low-end
+ // comparison as well.
+ ensure_in_range("-frand(-7.0)", -ll_frand(-7.0), 0.0f, 7.0f);
+ }
+ }
- template<> template<>
- void random_object_t::test<5>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- ensure_in_range("-drand(-2.0)", -ll_drand(-2.0), 0.0, 2.0);
- }
- }
+ template<> template<>
+ void random_object_t::test<5>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ ensure_in_range("-drand(-2.0)", -ll_drand(-2.0), 0.0, 2.0);
+ }
+ }
- template<> template<>
- void random_object_t::test<6>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- ensure_in_range("rand(100)", ll_rand(100), 0, 100);
- }
- }
+ template<> template<>
+ void random_object_t::test<6>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ ensure_in_range("rand(100)", ll_rand(100), 0, 100);
+ }
+ }
- template<> template<>
- void random_object_t::test<7>()
- {
- for(S32 ii = 0; ii < 100000; ++ii)
- {
- ensure_in_range("-rand(-127)", -ll_rand(-127), 0, 127);
- }
- }
+ template<> template<>
+ void random_object_t::test<7>()
+ {
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ ensure_in_range("-rand(-127)", -ll_rand(-127), 0, 127);
+ }
+ }
}
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index ac40125f75..56fdc51e82 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$
*/
@@ -64,313 +64,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"
@@ -390,437 +390,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>()
@@ -858,272 +858,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;
@@ -1168,7 +1168,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;
@@ -1259,536 +1259,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"
@@ -2130,7 +2130,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.");
diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp
index 6f8aaaa0cb..adf5804272 100644
--- a/indra/llcommon/tests/llsingleton_test.cpp
+++ b/indra/llcommon/tests/llsingleton_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsingleton_test.cpp
* @date 2011-08-11
* @brief Unit test for the LLSingleton class
diff --git a/indra/llcommon/tests/llstreamqueue_test.cpp b/indra/llcommon/tests/llstreamqueue_test.cpp
index 8af057328b..82b451119e 100644
--- a/indra/llcommon/tests/llstreamqueue_test.cpp
+++ b/indra/llcommon/tests/llstreamqueue_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2012-01-05
* @brief Test for llstreamqueue.
- *
+ *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Copyright (c) 2012, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp
index a7aa347222..3fadfa5334 100644
--- a/indra/llcommon/tests/llstring_test.cpp
+++ b/indra/llcommon/tests/llstring_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llstring_test.cpp
* @author Adroit, Steve Linden, Tofu Linden
* @date 2006-12-24
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2007&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$
*/
@@ -37,835 +37,835 @@ using boost::assign::list_of;
namespace tut
{
- struct string_index
- {
- };
- typedef test_group<string_index> string_index_t;
- typedef string_index_t::object string_index_object_t;
- tut::string_index_t tut_string_index("LLString");
-
- template<> template<>
- void string_index_object_t::test<1>()
- {
- std::string llstr1;
- ensure("Empty std::string", (llstr1.size() == 0) && llstr1.empty());
-
- std::string llstr2("Hello");
- ensure("std::string = Hello", (!strcmp(llstr2.c_str(), "Hello")) && (llstr2.size() == 5) && !llstr2.empty());
-
- std::string llstr3(llstr2);
- ensure("std::string = std::string(std::string)", (!strcmp(llstr3.c_str(), "Hello")) && (llstr3.size() == 5) && !llstr3.empty());
-
- std::string str("Hello World");
- std::string llstr4(str, 6);
- ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (!strcmp(llstr4.c_str(), "World")) && (llstr4.size() == 5) && !llstr4.empty());
-
- std::string llstr5(str, str.size());
- ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (llstr5.size() == 0) && llstr5.empty());
-
- std::string llstr6(5, 'A');
- ensure("std::string = std::string(count, c)", (!strcmp(llstr6.c_str(), "AAAAA")) && (llstr6.size() == 5) && !llstr6.empty());
-
- std::string llstr7("Hello World", 5);
- ensure("std::string(s, n)", (!strcmp(llstr7.c_str(), "Hello")) && (llstr7.size() == 5) && !llstr7.empty());
-
- std::string llstr8("Hello World", 6, 5);
- ensure("std::string(s, n, count)", (!strcmp(llstr8.c_str(), "World")) && (llstr8.size() == 5) && !llstr8.empty());
-
- std::string llstr9("Hello World", sizeof("Hello World")-1, 5); // go past end
- ensure("std::string(s, n, count) goes past end", (llstr9.size() == 0) && llstr9.empty());
- }
-
- template<> template<>
- void string_index_object_t::test<3>()
- {
- std::string str("Len=5");
- ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE &&
- LLStringUtil::isValidIndex(str, 5) == TRUE &&
- LLStringUtil::isValidIndex(str, 6) == FALSE);
-
- std::string str1;
- ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE);
- }
-
- template<> template<>
- void string_index_object_t::test<4>()
- {
- std::string str_val(" Testing the extra whitespaces ");
- LLStringUtil::trimHead(str_val);
- ensure_equals("1: trimHead failed", str_val, "Testing the extra whitespaces ");
-
- std::string str_val1("\n\t\r\n Testing the extra whitespaces ");
- LLStringUtil::trimHead(str_val1);
- ensure_equals("2: trimHead failed", str_val1, "Testing the extra whitespaces ");
- }
-
- template<> template<>
- void string_index_object_t::test<5>()
- {
- std::string str_val(" Testing the extra whitespaces ");
- LLStringUtil::trimTail(str_val);
- ensure_equals("1: trimTail failed", str_val, " Testing the extra whitespaces");
-
- std::string str_val1("\n Testing the extra whitespaces \n\t\r\n ");
- LLStringUtil::trimTail(str_val1);
- ensure_equals("2: trimTail failed", str_val1, "\n Testing the extra whitespaces");
- }
-
-
- template<> template<>
- void string_index_object_t::test<6>()
- {
- std::string str_val(" \t \r Testing the extra \r\n whitespaces \n \t ");
- LLStringUtil::trim(str_val);
- ensure_equals("1: trim failed", str_val, "Testing the extra \r\n whitespaces");
- }
-
- template<> template<>
- void string_index_object_t::test<7>()
- {
- std::string str("Second LindenLabs");
- LLStringUtil::truncate(str, 6);
- ensure_equals("1: truncate", str, "Second");
-
- // further truncate more than the length
- LLStringUtil::truncate(str, 0);
- ensure_equals("2: truncate", str, "");
- }
-
- template<> template<>
- void string_index_object_t::test<8>()
- {
- std::string str_val("SecondLife Source");
- LLStringUtil::toUpper(str_val);
- ensure_equals("toUpper failed", str_val, "SECONDLIFE SOURCE");
- }
-
- template<> template<>
- void string_index_object_t::test<9>()
- {
- std::string str_val("SecondLife Source");
- LLStringUtil::toLower(str_val);
- ensure_equals("toLower failed", str_val, "secondlife source");
- }
-
- template<> template<>
- void string_index_object_t::test<10>()
- {
- std::string str_val("Second");
- ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE);
- ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE);
- std::string str_val2("");
- ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE);
- }
-
- template<> template<>
- void string_index_object_t::test<11>()
- {
- std::string str_val("Hello.\n\n Lindenlabs. \n This is \na simple test.\n");
- std::string orig_str_val(str_val);
- LLStringUtil::addCRLF(str_val);
- ensure_equals("addCRLF failed", str_val, "Hello.\r\n\r\n Lindenlabs. \r\n This is \r\na simple test.\r\n");
- LLStringUtil::removeCRLF(str_val);
- ensure_equals("removeCRLF failed", str_val, orig_str_val);
- }
-
- template<> template<>
- void string_index_object_t::test<12>()
- {
- std::string str_val("Hello.\n\n\t \t Lindenlabs. \t\t");
- std::string orig_str_val(str_val);
- LLStringUtil::replaceTabsWithSpaces(str_val, 1);
- ensure_equals("replaceTabsWithSpaces failed", str_val, "Hello.\n\n Lindenlabs. ");
- LLStringUtil::replaceTabsWithSpaces(orig_str_val, 0);
- ensure_equals("replaceTabsWithSpaces failed for 0", orig_str_val, "Hello.\n\n Lindenlabs. ");
-
- str_val = "\t\t\t\t";
- LLStringUtil::replaceTabsWithSpaces(str_val, 0);
- ensure_equals("replaceTabsWithSpaces failed for all tabs", str_val, "");
- }
-
- template<> template<>
- void string_index_object_t::test<13>()
- {
- std::string str_val("Hello.\n\n\t\t\r\nLindenlabsX.");
- LLStringUtil::replaceNonstandardASCII(str_val, 'X');
- ensure_equals("replaceNonstandardASCII failed", str_val, "Hello.\n\nXXX\nLindenlabsX.");
- }
-
- template<> template<>
- void string_index_object_t::test<14>()
- {
- std::string str_val("Hello.\n\t\r\nABCDEFGHIABABAB");
- LLStringUtil::replaceChar(str_val, 'A', 'X');
- ensure_equals("1: replaceChar failed", str_val, "Hello.\n\t\r\nXBCDEFGHIXBXBXB");
- std::string str_val1("Hello.\n\t\r\nABCDEFGHIABABAB");
- }
-
- template<> template<>
- void string_index_object_t::test<15>()
- {
- std::string str_val("Hello.\n\r\t");
- ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE);
-
- str_val = "ABC ";
- ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE);
- }
-
- template<> template<>
- void string_index_object_t::test<16>()
- {
- std::string str_val("Hello.\n\r\t Again!");
- LLStringUtil::stripNonprintable(str_val);
- ensure_equals("stripNonprintable failed", str_val, "Hello. Again!");
-
- str_val = "\r\n\t\t";
- LLStringUtil::stripNonprintable(str_val);
- ensure_equals("stripNonprintable resulting in empty string failed", str_val, "");
-
- str_val = "";
- LLStringUtil::stripNonprintable(str_val);
- ensure_equals("stripNonprintable of empty string resulting in empty string failed", str_val, "");
- }
-
- template<> template<>
- void string_index_object_t::test<17>()
- {
- BOOL value;
- std::string str_val("1");
- ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value);
- str_val = "T";
- ensure("convertToBOOL T failed", LLStringUtil::convertToBOOL(str_val, value) && value);
- str_val = "t";
- ensure("convertToBOOL t failed", LLStringUtil::convertToBOOL(str_val, value) && value);
- str_val = "TRUE";
- ensure("convertToBOOL TRUE failed", LLStringUtil::convertToBOOL(str_val, value) && value);
- str_val = "True";
- ensure("convertToBOOL True failed", LLStringUtil::convertToBOOL(str_val, value) && value);
- str_val = "true";
- ensure("convertToBOOL true failed", LLStringUtil::convertToBOOL(str_val, value) && value);
-
- str_val = "0";
- ensure("convertToBOOL 0 failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
- str_val = "F";
- ensure("convertToBOOL F failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
- str_val = "f";
- ensure("convertToBOOL f failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
- str_val = "FALSE";
- ensure("convertToBOOL FASLE failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
- str_val = "False";
- ensure("convertToBOOL False failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
- str_val = "false";
- ensure("convertToBOOL false failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
-
- str_val = "Tblah";
- ensure("convertToBOOL false failed", !LLStringUtil::convertToBOOL(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<18>()
- {
- U8 value;
- std::string str_val("255");
- ensure("1: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 255);
-
- str_val = "0";
- ensure("2: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 0);
-
- str_val = "-1";
- ensure("3: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
-
- str_val = "256"; // bigger than MAX_U8
- ensure("4: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<19>()
- {
- S8 value;
- std::string str_val("127");
- ensure("1: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 127);
-
- str_val = "0";
- ensure("2: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 0);
-
- str_val = "-128";
- ensure("3: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == -128);
-
- str_val = "128"; // bigger than MAX_S8
- ensure("4: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
-
- str_val = "-129";
- ensure("5: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<20>()
- {
- S16 value;
- std::string str_val("32767");
- ensure("1: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 32767);
-
- str_val = "0";
- ensure("2: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 0);
-
- str_val = "-32768";
- ensure("3: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == -32768);
-
- str_val = "32768";
- ensure("4: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
-
- str_val = "-32769";
- ensure("5: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<21>()
- {
- U16 value;
- std::string str_val("65535"); //0xFFFF
- ensure("1: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 65535);
-
- str_val = "0";
- ensure("2: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 0);
-
- str_val = "-1";
- ensure("3: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
-
- str_val = "65536";
- ensure("4: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<22>()
- {
- U32 value;
- std::string str_val("4294967295"); //0xFFFFFFFF
- ensure("1: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 4294967295UL);
-
- str_val = "0";
- ensure("2: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 0);
-
- str_val = "4294967296";
- ensure("3: convertToU32 failed", !LLStringUtil::convertToU32(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<23>()
- {
- S32 value;
- std::string str_val("2147483647"); //0x7FFFFFFF
- ensure("1: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 2147483647);
-
- str_val = "0";
- ensure("2: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 0);
-
- // Avoid "unary minus operator applied to unsigned type" warning on VC++. JC
- S32 min_val = -2147483647 - 1;
- str_val = "-2147483648";
- ensure("3: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == min_val);
-
- str_val = "2147483648";
- ensure("4: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
-
- str_val = "-2147483649";
- ensure("5: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
- }
-
- template<> template<>
- void string_index_object_t::test<24>()
- {
- F32 value;
- std::string str_val("2147483647"); //0x7FFFFFFF
- ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647);
-
- str_val = "0";
- ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0);
-
- /* Need to find max/min F32 values
- str_val = "-2147483648";
- ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
-
- str_val = "2147483648";
- ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
-
- str_val = "-2147483649";
- ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
- */
- }
-
- template<> template<>
- void string_index_object_t::test<25>()
- {
- F64 value;
- std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF
- ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL);
-
- str_val = "0";
- ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F);
-
- /* Need to find max/min F64 values
- str_val = "-2147483648";
- ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
-
- str_val = "2147483648";
- ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
-
- str_val = "-2147483649";
- ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
- */
- }
-
- template<> template<>
- void string_index_object_t::test<26>()
- {
- const char* str1 = NULL;
- const char* str2 = NULL;
-
- ensure("1: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
- str2 = "A";
- ensure("2: compareStrings failed", LLStringUtil::compareStrings(str1, str2) > 0);
- ensure("3: compareStrings failed", LLStringUtil::compareStrings(str2, str1) < 0);
-
- str1 = "A is smaller than B";
- str2 = "B is greater than A";
- ensure("4: compareStrings failed", LLStringUtil::compareStrings(str1, str2) < 0);
-
- str2 = "A is smaller than B";
- ensure("5: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
- }
-
- template<> template<>
- void string_index_object_t::test<27>()
- {
- const char* str1 = NULL;
- const char* str2 = NULL;
-
- ensure("1: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
- str2 = "A";
- ensure("2: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) > 0);
- ensure("3: compareInsensitive failed", LLStringUtil::compareInsensitive(str2, str1) < 0);
-
- str1 = "A is equal to a";
- str2 = "a is EQUAL to A";
- ensure("4: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
- }
-
- template<> template<>
- void string_index_object_t::test<28>()
- {
- std::string lhs_str("PROgraM12files");
- std::string rhs_str("PROgram12Files");
- ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0);
- ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE);
-
- lhs_str = "PROgram12Files";
- rhs_str = "PROgram12Files";
- ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0);
- ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
-
- lhs_str = "PROgram12Files";
- rhs_str = "PROgRAM12FILES";
- ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0);
- ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
- }
-
- template<> template<>
- void string_index_object_t::test<29>()
- {
- char str1[] = "First String...";
- char str2[100];
-
- LLStringUtil::copy(str2, str1, 100);
- ensure("LLStringUtil::copy with enough dest length failed", strcmp(str2, str1) == 0);
- LLStringUtil::copy(str2, str1, sizeof("First"));
- ensure("LLStringUtil::copy with less dest length failed", strcmp(str2, "First") == 0);
- }
-
- template<> template<>
- void string_index_object_t::test<30>()
- {
- std::string str1 = "This is the sentence...";
- std::string str2 = "This is the ";
- std::string str3 = "first ";
- std::string str4 = "This is the first sentence...";
- std::string str5 = "This is the sentence...first ";
- std::string dest;
-
- dest = str1;
- LLStringUtil::copyInto(dest, str3, str2.length());
- ensure("LLStringUtil::copyInto insert failed", dest == str4);
-
- dest = str1;
- LLStringUtil::copyInto(dest, str3, dest.length());
- ensure("LLStringUtil::copyInto append failed", dest == str5);
- }
-
- template<> template<>
- void string_index_object_t::test<31>()
- {
- std::string stripped;
-
- // Plain US ASCII text, including spaces and punctuation,
- // should not be altered.
- std::string simple_text = "Hello, world!";
- stripped = LLStringFn::strip_invalid_xml(simple_text);
- ensure("Simple text passed unchanged", stripped == simple_text);
-
- // Control characters should be removed
- // except for 0x09, 0x0a, 0x0d
- std::string control_chars;
- for (char c = 0x01; c < 0x20; c++)
- {
- control_chars.push_back(c);
- }
- std::string allowed_control_chars;
- allowed_control_chars.push_back( (char)0x09 );
- allowed_control_chars.push_back( (char)0x0a );
- allowed_control_chars.push_back( (char)0x0d );
-
- stripped = LLStringFn::strip_invalid_xml(control_chars);
- ensure("Only tab, LF, CR control characters allowed",
- stripped == allowed_control_chars);
-
- // UTF-8 should be passed intact, including high byte
- // characters. Try Francais (with C squiggle cedilla)
- std::string french = "Fran";
- french.push_back( (char)0xC3 );
- french.push_back( (char)0xA7 );
- french += "ais";
- stripped = LLStringFn::strip_invalid_xml( french );
- ensure("UTF-8 high byte text is allowed", french == stripped );
- }
-
- template<> template<>
- void string_index_object_t::test<32>()
- {
- // Test LLStringUtil::format() string interpolation
- LLStringUtil::format_map_t fmt_map;
- std::string s;
- int subcount;
-
- fmt_map["[TRICK1]"] = "[A]";
- fmt_map["[A]"] = "a";
- fmt_map["[B]"] = "b";
- fmt_map["[AAA]"] = "aaa";
- fmt_map["[BBB]"] = "bbb";
- fmt_map["[TRICK2]"] = "[A]";
- fmt_map["[EXPLOIT]"] = "!!!!!!!!!!!![EXPLOIT]!!!!!!!!!!!!";
- fmt_map["[KEYLONGER]"] = "short";
- fmt_map["[KEYSHORTER]"] = "Am I not a long string?";
- fmt_map["?"] = "?";
- fmt_map["[DELETE]"] = "";
- fmt_map["[]"] = "[]"; // doesn't do a substitution, but shouldn't crash either
-
- for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
- {
- // Test when source string is entirely one key
- std::string s1 = (std::string)iter->first;
- std::string s2 = (std::string)iter->second;
- subcount = LLStringUtil::format(s1, fmt_map);
- ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2);
- if (s1 == "?" || s1 == "[]") // no interp expected
- {
- ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount);
- }
- else
- {
- ensure_equals("LLStringUtil::format: Raw interpolation result count", 1, subcount);
- }
- }
-
- for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
- {
- // Test when source string is one key, duplicated
- std::string s1 = (std::string)iter->first;
- std::string s2 = (std::string)iter->second;
- s = s1 + s1 + s1 + s1;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2);
- if (s1 == "?" || s1 == "[]") // no interp expected
- {
- ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount);
- }
- else
- {
- ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 4, subcount);
- }
- }
-
- // Test when source string has no keys
- std::string srcs = "!!!!!!!!!!!!!!!!";
- s = srcs;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure_equals("LLStringUtil::format: No key test result", s, srcs);
- ensure_equals("LLStringUtil::format: No key test result count", 0, subcount);
-
- // Test when source string has no keys and is empty
- std::string srcs3;
- s = srcs3;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure("LLStringUtil::format: No key test3 result", s.empty());
- ensure_equals("LLStringUtil::format: No key test3 result count", 0, subcount);
-
- // Test a substitution where a key is substituted with blankness
- std::string srcs2 = "[DELETE]";
- s = srcs2;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure("LLStringUtil::format: Delete key test2 result", s.empty());
- ensure_equals("LLStringUtil::format: Delete key test2 result count", 1, subcount);
-
- // Test an assorted substitution
- std::string srcs4 = "[TRICK1][A][B][AAA][BBB][TRICK2][KEYLONGER][KEYSHORTER]?[DELETE]";
- s = srcs4;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure_equals("LLStringUtil::format: Assorted Test1 result", s, "[A]abaaabbb[A]shortAm I not a long string??");
- ensure_equals("LLStringUtil::format: Assorted Test1 result count", 9, subcount);
-
- // Test an assorted substitution
- std::string srcs5 = "[DELETE]?[KEYSHORTER][KEYLONGER][TRICK2][BBB][AAA][B][A][TRICK1]";
- s = srcs5;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]");
- ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
-
- // Test on nested brackets
- std::string srcs6 = "[[TRICK1]][[A]][[B]][[AAA]][[BBB]][[TRICK2]][[KEYLONGER]][[KEYSHORTER]]?[[DELETE]]";
- s = srcs6;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "[[A]][a][b][aaa][bbb][[A]][short][Am I not a long string?]?[]");
- ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
-
-
- // Test an assorted substitution
- std::string srcs8 = "foo[DELETE]bar?";
- s = srcs8;
- subcount = LLStringUtil::format(s, fmt_map);
- ensure_equals("LLStringUtil::format: Assorted Test3 result", s, "foobar?");
- ensure_equals("LLStringUtil::format: Assorted Test3 result count", 1, subcount);
- }
-
- template<> template<>
- void string_index_object_t::test<33>()
- {
- // Test LLStringUtil::format() string interpolation
- LLStringUtil::format_map_t blank_fmt_map;
- std::string s;
- int subcount;
-
- // Test substituting out of a blank format_map
- std::string srcs6 = "12345";
- s = srcs6;
- subcount = LLStringUtil::format(s, blank_fmt_map);
- ensure_equals("LLStringUtil::format: Blankfmt Test1 result", s, "12345");
- ensure_equals("LLStringUtil::format: Blankfmt Test1 result count", 0, subcount);
-
- // Test substituting a blank string out of a blank format_map
- std::string srcs7;
- s = srcs7;
- subcount = LLStringUtil::format(s, blank_fmt_map);
- ensure("LLStringUtil::format: Blankfmt Test2 result", s.empty());
- ensure_equals("LLStringUtil::format: Blankfmt Test2 result count", 0, subcount);
- }
-
- template<> template<>
- void string_index_object_t::test<34>()
- {
- // Test that incorrect LLStringUtil::format() use does not explode.
- LLStringUtil::format_map_t nasty_fmt_map;
- std::string s;
- int subcount;
-
- nasty_fmt_map[""] = "never used"; // see, this is nasty.
-
- // Test substituting out of a nasty format_map
- std::string srcs6 = "12345";
- s = srcs6;
- subcount = LLStringUtil::format(s, nasty_fmt_map);
- ensure_equals("LLStringUtil::format: Nastyfmt Test1 result", s, "12345");
- ensure_equals("LLStringUtil::format: Nastyfmt Test1 result count", 0, subcount);
-
- // Test substituting a blank string out of a nasty format_map
- std::string srcs7;
- s = srcs7;
- subcount = LLStringUtil::format(s, nasty_fmt_map);
- ensure("LLStringUtil::format: Nastyfmt Test2 result", s.empty());
- ensure_equals("LLStringUtil::format: Nastyfmt Test2 result count", 0, subcount);
- }
-
- template<> template<>
- void string_index_object_t::test<35>()
- {
- // Make sure startsWith works
- std::string string("anybody in there?");
- std::string substr("anybody");
- ensure("startsWith works.", LLStringUtil::startsWith(string, substr));
- }
-
- template<> template<>
- void string_index_object_t::test<36>()
- {
- // Make sure startsWith correctly fails
- std::string string("anybody in there?");
- std::string substr("there");
- ensure("startsWith fails.", !LLStringUtil::startsWith(string, substr));
- }
-
- template<> template<>
- void string_index_object_t::test<37>()
- {
- // startsWith fails on empty strings
- std::string value("anybody in there?");
- std::string empty;
- ensure("empty string.", !LLStringUtil::startsWith(value, empty));
- ensure("empty substr.", !LLStringUtil::startsWith(empty, value));
- ensure("empty everything.", !LLStringUtil::startsWith(empty, empty));
- }
-
- template<> template<>
- void string_index_object_t::test<38>()
- {
- // Make sure endsWith works correctly
- std::string string("anybody in there?");
- std::string substr("there?");
- ensure("endsWith works.", LLStringUtil::endsWith(string, substr));
- }
-
- template<> template<>
- void string_index_object_t::test<39>()
- {
- // Make sure endsWith correctly fails
- std::string string("anybody in there?");
- std::string substr("anybody");
- ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
- substr = "there";
- ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
- substr = "ther?";
- ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
- }
-
- template<> template<>
- void string_index_object_t::test<40>()
- {
- // endsWith fails on empty strings
- std::string value("anybody in there?");
- std::string empty;
- ensure("empty string.", !LLStringUtil::endsWith(value, empty));
- ensure("empty substr.", !LLStringUtil::endsWith(empty, value));
- ensure("empty everything.", !LLStringUtil::endsWith(empty, empty));
- }
-
- template<> template<>
- void string_index_object_t::test<41>()
- {
- set_test_name("getTokens(\"delims\")");
- ensure_equals("empty string", LLStringUtil::getTokens("", " "), StringVec());
- ensure_equals("only delims",
- LLStringUtil::getTokens(" \r\n ", " \r\n"), StringVec());
- ensure_equals("sequence of delims",
- LLStringUtil::getTokens(",,, one ,,,", ","), list_of("one"));
- // nat considers this a dubious implementation side effect, but I'd
- // hate to change it now...
- ensure_equals("noncontiguous tokens",
- LLStringUtil::getTokens(", ,, , one ,,,", ","), list_of("")("")("one"));
- ensure_equals("space-padded tokens",
- LLStringUtil::getTokens(", one , two ,", ","), list_of("one")("two"));
- ensure_equals("no delims", LLStringUtil::getTokens("one", ","), list_of("one"));
- }
-
- // Shorthand for verifying that getTokens() behaves the same when you
- // don't pass a string of escape characters, when you pass an empty string
- // (different overloads), and when you pass a string of characters that
- // aren't actually present.
- void ensure_getTokens(const std::string& desc,
- const std::string& string,
- const std::string& drop_delims,
- const std::string& keep_delims,
- const std::string& quotes,
- const std::vector<std::string>& expect)
- {
- ensure_equals(desc + " - no esc",
- LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes),
- expect);
- ensure_equals(desc + " - empty esc",
- LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, ""),
- expect);
- ensure_equals(desc + " - unused esc",
- LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, "!"),
- expect);
- }
-
- void ensure_getTokens(const std::string& desc,
- const std::string& string,
- const std::string& drop_delims,
- const std::string& keep_delims,
- const std::vector<std::string>& expect)
- {
- ensure_getTokens(desc, string, drop_delims, keep_delims, "", expect);
- }
-
- template<> template<>
- void string_index_object_t::test<42>()
- {
- set_test_name("getTokens(\"delims\", etc.)");
- // Signatures to test in this method:
- // getTokens(string, drop_delims, keep_delims [, quotes [, escapes]])
- // If you omit keep_delims, you get the older function (test above).
-
- // cases like the getTokens(string, delims) tests above
- ensure_getTokens("empty string", "", " ", "", StringVec());
- ensure_getTokens("only delims",
- " \r\n ", " \r\n", "", StringVec());
- ensure_getTokens("sequence of delims",
- ",,, one ,,,", ", ", "", list_of("one"));
- // Note contrast with the case in the previous method
- ensure_getTokens("noncontiguous tokens",
- ", ,, , one ,,,", ", ", "", list_of("one"));
- ensure_getTokens("space-padded tokens",
- ", one , two ,", ", ", "",
+ struct string_index
+ {
+ };
+ typedef test_group<string_index> string_index_t;
+ typedef string_index_t::object string_index_object_t;
+ tut::string_index_t tut_string_index("LLString");
+
+ template<> template<>
+ void string_index_object_t::test<1>()
+ {
+ std::string llstr1;
+ ensure("Empty std::string", (llstr1.size() == 0) && llstr1.empty());
+
+ std::string llstr2("Hello");
+ ensure("std::string = Hello", (!strcmp(llstr2.c_str(), "Hello")) && (llstr2.size() == 5) && !llstr2.empty());
+
+ std::string llstr3(llstr2);
+ ensure("std::string = std::string(std::string)", (!strcmp(llstr3.c_str(), "Hello")) && (llstr3.size() == 5) && !llstr3.empty());
+
+ std::string str("Hello World");
+ std::string llstr4(str, 6);
+ ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (!strcmp(llstr4.c_str(), "World")) && (llstr4.size() == 5) && !llstr4.empty());
+
+ std::string llstr5(str, str.size());
+ ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (llstr5.size() == 0) && llstr5.empty());
+
+ std::string llstr6(5, 'A');
+ ensure("std::string = std::string(count, c)", (!strcmp(llstr6.c_str(), "AAAAA")) && (llstr6.size() == 5) && !llstr6.empty());
+
+ std::string llstr7("Hello World", 5);
+ ensure("std::string(s, n)", (!strcmp(llstr7.c_str(), "Hello")) && (llstr7.size() == 5) && !llstr7.empty());
+
+ std::string llstr8("Hello World", 6, 5);
+ ensure("std::string(s, n, count)", (!strcmp(llstr8.c_str(), "World")) && (llstr8.size() == 5) && !llstr8.empty());
+
+ std::string llstr9("Hello World", sizeof("Hello World")-1, 5); // go past end
+ ensure("std::string(s, n, count) goes past end", (llstr9.size() == 0) && llstr9.empty());
+ }
+
+ template<> template<>
+ void string_index_object_t::test<3>()
+ {
+ std::string str("Len=5");
+ ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE &&
+ LLStringUtil::isValidIndex(str, 5) == TRUE &&
+ LLStringUtil::isValidIndex(str, 6) == FALSE);
+
+ std::string str1;
+ ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<4>()
+ {
+ std::string str_val(" Testing the extra whitespaces ");
+ LLStringUtil::trimHead(str_val);
+ ensure_equals("1: trimHead failed", str_val, "Testing the extra whitespaces ");
+
+ std::string str_val1("\n\t\r\n Testing the extra whitespaces ");
+ LLStringUtil::trimHead(str_val1);
+ ensure_equals("2: trimHead failed", str_val1, "Testing the extra whitespaces ");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<5>()
+ {
+ std::string str_val(" Testing the extra whitespaces ");
+ LLStringUtil::trimTail(str_val);
+ ensure_equals("1: trimTail failed", str_val, " Testing the extra whitespaces");
+
+ std::string str_val1("\n Testing the extra whitespaces \n\t\r\n ");
+ LLStringUtil::trimTail(str_val1);
+ ensure_equals("2: trimTail failed", str_val1, "\n Testing the extra whitespaces");
+ }
+
+
+ template<> template<>
+ void string_index_object_t::test<6>()
+ {
+ std::string str_val(" \t \r Testing the extra \r\n whitespaces \n \t ");
+ LLStringUtil::trim(str_val);
+ ensure_equals("1: trim failed", str_val, "Testing the extra \r\n whitespaces");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<7>()
+ {
+ std::string str("Second LindenLabs");
+ LLStringUtil::truncate(str, 6);
+ ensure_equals("1: truncate", str, "Second");
+
+ // further truncate more than the length
+ LLStringUtil::truncate(str, 0);
+ ensure_equals("2: truncate", str, "");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<8>()
+ {
+ std::string str_val("SecondLife Source");
+ LLStringUtil::toUpper(str_val);
+ ensure_equals("toUpper failed", str_val, "SECONDLIFE SOURCE");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<9>()
+ {
+ std::string str_val("SecondLife Source");
+ LLStringUtil::toLower(str_val);
+ ensure_equals("toLower failed", str_val, "secondlife source");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<10>()
+ {
+ std::string str_val("Second");
+ ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE);
+ ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE);
+ std::string str_val2("");
+ ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<11>()
+ {
+ std::string str_val("Hello.\n\n Lindenlabs. \n This is \na simple test.\n");
+ std::string orig_str_val(str_val);
+ LLStringUtil::addCRLF(str_val);
+ ensure_equals("addCRLF failed", str_val, "Hello.\r\n\r\n Lindenlabs. \r\n This is \r\na simple test.\r\n");
+ LLStringUtil::removeCRLF(str_val);
+ ensure_equals("removeCRLF failed", str_val, orig_str_val);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<12>()
+ {
+ std::string str_val("Hello.\n\n\t \t Lindenlabs. \t\t");
+ std::string orig_str_val(str_val);
+ LLStringUtil::replaceTabsWithSpaces(str_val, 1);
+ ensure_equals("replaceTabsWithSpaces failed", str_val, "Hello.\n\n Lindenlabs. ");
+ LLStringUtil::replaceTabsWithSpaces(orig_str_val, 0);
+ ensure_equals("replaceTabsWithSpaces failed for 0", orig_str_val, "Hello.\n\n Lindenlabs. ");
+
+ str_val = "\t\t\t\t";
+ LLStringUtil::replaceTabsWithSpaces(str_val, 0);
+ ensure_equals("replaceTabsWithSpaces failed for all tabs", str_val, "");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<13>()
+ {
+ std::string str_val("Hello.\n\n\t\t\r\nLindenlabsX.");
+ LLStringUtil::replaceNonstandardASCII(str_val, 'X');
+ ensure_equals("replaceNonstandardASCII failed", str_val, "Hello.\n\nXXX\nLindenlabsX.");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<14>()
+ {
+ std::string str_val("Hello.\n\t\r\nABCDEFGHIABABAB");
+ LLStringUtil::replaceChar(str_val, 'A', 'X');
+ ensure_equals("1: replaceChar failed", str_val, "Hello.\n\t\r\nXBCDEFGHIXBXBXB");
+ std::string str_val1("Hello.\n\t\r\nABCDEFGHIABABAB");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<15>()
+ {
+ std::string str_val("Hello.\n\r\t");
+ ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE);
+
+ str_val = "ABC ";
+ ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<16>()
+ {
+ std::string str_val("Hello.\n\r\t Again!");
+ LLStringUtil::stripNonprintable(str_val);
+ ensure_equals("stripNonprintable failed", str_val, "Hello. Again!");
+
+ str_val = "\r\n\t\t";
+ LLStringUtil::stripNonprintable(str_val);
+ ensure_equals("stripNonprintable resulting in empty string failed", str_val, "");
+
+ str_val = "";
+ LLStringUtil::stripNonprintable(str_val);
+ ensure_equals("stripNonprintable of empty string resulting in empty string failed", str_val, "");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<17>()
+ {
+ BOOL value;
+ std::string str_val("1");
+ ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "T";
+ ensure("convertToBOOL T failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "t";
+ ensure("convertToBOOL t failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "TRUE";
+ ensure("convertToBOOL TRUE failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "True";
+ ensure("convertToBOOL True failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "true";
+ ensure("convertToBOOL true failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+
+ str_val = "0";
+ ensure("convertToBOOL 0 failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "F";
+ ensure("convertToBOOL F failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "f";
+ ensure("convertToBOOL f failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "FALSE";
+ ensure("convertToBOOL FASLE failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "False";
+ ensure("convertToBOOL False failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "false";
+ ensure("convertToBOOL false failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+
+ str_val = "Tblah";
+ ensure("convertToBOOL false failed", !LLStringUtil::convertToBOOL(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<18>()
+ {
+ U8 value;
+ std::string str_val("255");
+ ensure("1: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 255);
+
+ str_val = "0";
+ ensure("2: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 0);
+
+ str_val = "-1";
+ ensure("3: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
+
+ str_val = "256"; // bigger than MAX_U8
+ ensure("4: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<19>()
+ {
+ S8 value;
+ std::string str_val("127");
+ ensure("1: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 127);
+
+ str_val = "0";
+ ensure("2: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 0);
+
+ str_val = "-128";
+ ensure("3: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == -128);
+
+ str_val = "128"; // bigger than MAX_S8
+ ensure("4: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
+
+ str_val = "-129";
+ ensure("5: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<20>()
+ {
+ S16 value;
+ std::string str_val("32767");
+ ensure("1: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 32767);
+
+ str_val = "0";
+ ensure("2: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 0);
+
+ str_val = "-32768";
+ ensure("3: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == -32768);
+
+ str_val = "32768";
+ ensure("4: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
+
+ str_val = "-32769";
+ ensure("5: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<21>()
+ {
+ U16 value;
+ std::string str_val("65535"); //0xFFFF
+ ensure("1: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 65535);
+
+ str_val = "0";
+ ensure("2: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 0);
+
+ str_val = "-1";
+ ensure("3: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
+
+ str_val = "65536";
+ ensure("4: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<22>()
+ {
+ U32 value;
+ std::string str_val("4294967295"); //0xFFFFFFFF
+ ensure("1: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 4294967295UL);
+
+ str_val = "0";
+ ensure("2: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 0);
+
+ str_val = "4294967296";
+ ensure("3: convertToU32 failed", !LLStringUtil::convertToU32(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<23>()
+ {
+ S32 value;
+ std::string str_val("2147483647"); //0x7FFFFFFF
+ ensure("1: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 2147483647);
+
+ str_val = "0";
+ ensure("2: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 0);
+
+ // Avoid "unary minus operator applied to unsigned type" warning on VC++. JC
+ S32 min_val = -2147483647 - 1;
+ str_val = "-2147483648";
+ ensure("3: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == min_val);
+
+ str_val = "2147483648";
+ ensure("4: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
+
+ str_val = "-2147483649";
+ ensure("5: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<24>()
+ {
+ F32 value;
+ std::string str_val("2147483647"); //0x7FFFFFFF
+ ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647);
+
+ str_val = "0";
+ ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0);
+
+ /* Need to find max/min F32 values
+ str_val = "-2147483648";
+ ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
+
+ str_val = "2147483648";
+ ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+
+ str_val = "-2147483649";
+ ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+ */
+ }
+
+ template<> template<>
+ void string_index_object_t::test<25>()
+ {
+ F64 value;
+ std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF
+ ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL);
+
+ str_val = "0";
+ ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F);
+
+ /* Need to find max/min F64 values
+ str_val = "-2147483648";
+ ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
+
+ str_val = "2147483648";
+ ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+
+ str_val = "-2147483649";
+ ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+ */
+ }
+
+ template<> template<>
+ void string_index_object_t::test<26>()
+ {
+ const char* str1 = NULL;
+ const char* str2 = NULL;
+
+ ensure("1: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
+ str2 = "A";
+ ensure("2: compareStrings failed", LLStringUtil::compareStrings(str1, str2) > 0);
+ ensure("3: compareStrings failed", LLStringUtil::compareStrings(str2, str1) < 0);
+
+ str1 = "A is smaller than B";
+ str2 = "B is greater than A";
+ ensure("4: compareStrings failed", LLStringUtil::compareStrings(str1, str2) < 0);
+
+ str2 = "A is smaller than B";
+ ensure("5: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<27>()
+ {
+ const char* str1 = NULL;
+ const char* str2 = NULL;
+
+ ensure("1: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
+ str2 = "A";
+ ensure("2: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) > 0);
+ ensure("3: compareInsensitive failed", LLStringUtil::compareInsensitive(str2, str1) < 0);
+
+ str1 = "A is equal to a";
+ str2 = "a is EQUAL to A";
+ ensure("4: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<28>()
+ {
+ std::string lhs_str("PROgraM12files");
+ std::string rhs_str("PROgram12Files");
+ ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0);
+ ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE);
+
+ lhs_str = "PROgram12Files";
+ rhs_str = "PROgram12Files";
+ ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0);
+ ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
+
+ lhs_str = "PROgram12Files";
+ rhs_str = "PROgRAM12FILES";
+ ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0);
+ ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<29>()
+ {
+ char str1[] = "First String...";
+ char str2[100];
+
+ LLStringUtil::copy(str2, str1, 100);
+ ensure("LLStringUtil::copy with enough dest length failed", strcmp(str2, str1) == 0);
+ LLStringUtil::copy(str2, str1, sizeof("First"));
+ ensure("LLStringUtil::copy with less dest length failed", strcmp(str2, "First") == 0);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<30>()
+ {
+ std::string str1 = "This is the sentence...";
+ std::string str2 = "This is the ";
+ std::string str3 = "first ";
+ std::string str4 = "This is the first sentence...";
+ std::string str5 = "This is the sentence...first ";
+ std::string dest;
+
+ dest = str1;
+ LLStringUtil::copyInto(dest, str3, str2.length());
+ ensure("LLStringUtil::copyInto insert failed", dest == str4);
+
+ dest = str1;
+ LLStringUtil::copyInto(dest, str3, dest.length());
+ ensure("LLStringUtil::copyInto append failed", dest == str5);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<31>()
+ {
+ std::string stripped;
+
+ // Plain US ASCII text, including spaces and punctuation,
+ // should not be altered.
+ std::string simple_text = "Hello, world!";
+ stripped = LLStringFn::strip_invalid_xml(simple_text);
+ ensure("Simple text passed unchanged", stripped == simple_text);
+
+ // Control characters should be removed
+ // except for 0x09, 0x0a, 0x0d
+ std::string control_chars;
+ for (char c = 0x01; c < 0x20; c++)
+ {
+ control_chars.push_back(c);
+ }
+ std::string allowed_control_chars;
+ allowed_control_chars.push_back( (char)0x09 );
+ allowed_control_chars.push_back( (char)0x0a );
+ allowed_control_chars.push_back( (char)0x0d );
+
+ stripped = LLStringFn::strip_invalid_xml(control_chars);
+ ensure("Only tab, LF, CR control characters allowed",
+ stripped == allowed_control_chars);
+
+ // UTF-8 should be passed intact, including high byte
+ // characters. Try Francais (with C squiggle cedilla)
+ std::string french = "Fran";
+ french.push_back( (char)0xC3 );
+ french.push_back( (char)0xA7 );
+ french += "ais";
+ stripped = LLStringFn::strip_invalid_xml( french );
+ ensure("UTF-8 high byte text is allowed", french == stripped );
+ }
+
+ template<> template<>
+ void string_index_object_t::test<32>()
+ {
+ // Test LLStringUtil::format() string interpolation
+ LLStringUtil::format_map_t fmt_map;
+ std::string s;
+ int subcount;
+
+ fmt_map["[TRICK1]"] = "[A]";
+ fmt_map["[A]"] = "a";
+ fmt_map["[B]"] = "b";
+ fmt_map["[AAA]"] = "aaa";
+ fmt_map["[BBB]"] = "bbb";
+ fmt_map["[TRICK2]"] = "[A]";
+ fmt_map["[EXPLOIT]"] = "!!!!!!!!!!!![EXPLOIT]!!!!!!!!!!!!";
+ fmt_map["[KEYLONGER]"] = "short";
+ fmt_map["[KEYSHORTER]"] = "Am I not a long string?";
+ fmt_map["?"] = "?";
+ fmt_map["[DELETE]"] = "";
+ fmt_map["[]"] = "[]"; // doesn't do a substitution, but shouldn't crash either
+
+ for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
+ {
+ // Test when source string is entirely one key
+ std::string s1 = (std::string)iter->first;
+ std::string s2 = (std::string)iter->second;
+ subcount = LLStringUtil::format(s1, fmt_map);
+ ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2);
+ if (s1 == "?" || s1 == "[]") // no interp expected
+ {
+ ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount);
+ }
+ else
+ {
+ ensure_equals("LLStringUtil::format: Raw interpolation result count", 1, subcount);
+ }
+ }
+
+ for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
+ {
+ // Test when source string is one key, duplicated
+ std::string s1 = (std::string)iter->first;
+ std::string s2 = (std::string)iter->second;
+ s = s1 + s1 + s1 + s1;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2);
+ if (s1 == "?" || s1 == "[]") // no interp expected
+ {
+ ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount);
+ }
+ else
+ {
+ ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 4, subcount);
+ }
+ }
+
+ // Test when source string has no keys
+ std::string srcs = "!!!!!!!!!!!!!!!!";
+ s = srcs;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: No key test result", s, srcs);
+ ensure_equals("LLStringUtil::format: No key test result count", 0, subcount);
+
+ // Test when source string has no keys and is empty
+ std::string srcs3;
+ s = srcs3;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure("LLStringUtil::format: No key test3 result", s.empty());
+ ensure_equals("LLStringUtil::format: No key test3 result count", 0, subcount);
+
+ // Test a substitution where a key is substituted with blankness
+ std::string srcs2 = "[DELETE]";
+ s = srcs2;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure("LLStringUtil::format: Delete key test2 result", s.empty());
+ ensure_equals("LLStringUtil::format: Delete key test2 result count", 1, subcount);
+
+ // Test an assorted substitution
+ std::string srcs4 = "[TRICK1][A][B][AAA][BBB][TRICK2][KEYLONGER][KEYSHORTER]?[DELETE]";
+ s = srcs4;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test1 result", s, "[A]abaaabbb[A]shortAm I not a long string??");
+ ensure_equals("LLStringUtil::format: Assorted Test1 result count", 9, subcount);
+
+ // Test an assorted substitution
+ std::string srcs5 = "[DELETE]?[KEYSHORTER][KEYLONGER][TRICK2][BBB][AAA][B][A][TRICK1]";
+ s = srcs5;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]");
+ ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
+
+ // Test on nested brackets
+ std::string srcs6 = "[[TRICK1]][[A]][[B]][[AAA]][[BBB]][[TRICK2]][[KEYLONGER]][[KEYSHORTER]]?[[DELETE]]";
+ s = srcs6;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "[[A]][a][b][aaa][bbb][[A]][short][Am I not a long string?]?[]");
+ ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
+
+
+ // Test an assorted substitution
+ std::string srcs8 = "foo[DELETE]bar?";
+ s = srcs8;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test3 result", s, "foobar?");
+ ensure_equals("LLStringUtil::format: Assorted Test3 result count", 1, subcount);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<33>()
+ {
+ // Test LLStringUtil::format() string interpolation
+ LLStringUtil::format_map_t blank_fmt_map;
+ std::string s;
+ int subcount;
+
+ // Test substituting out of a blank format_map
+ std::string srcs6 = "12345";
+ s = srcs6;
+ subcount = LLStringUtil::format(s, blank_fmt_map);
+ ensure_equals("LLStringUtil::format: Blankfmt Test1 result", s, "12345");
+ ensure_equals("LLStringUtil::format: Blankfmt Test1 result count", 0, subcount);
+
+ // Test substituting a blank string out of a blank format_map
+ std::string srcs7;
+ s = srcs7;
+ subcount = LLStringUtil::format(s, blank_fmt_map);
+ ensure("LLStringUtil::format: Blankfmt Test2 result", s.empty());
+ ensure_equals("LLStringUtil::format: Blankfmt Test2 result count", 0, subcount);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<34>()
+ {
+ // Test that incorrect LLStringUtil::format() use does not explode.
+ LLStringUtil::format_map_t nasty_fmt_map;
+ std::string s;
+ int subcount;
+
+ nasty_fmt_map[""] = "never used"; // see, this is nasty.
+
+ // Test substituting out of a nasty format_map
+ std::string srcs6 = "12345";
+ s = srcs6;
+ subcount = LLStringUtil::format(s, nasty_fmt_map);
+ ensure_equals("LLStringUtil::format: Nastyfmt Test1 result", s, "12345");
+ ensure_equals("LLStringUtil::format: Nastyfmt Test1 result count", 0, subcount);
+
+ // Test substituting a blank string out of a nasty format_map
+ std::string srcs7;
+ s = srcs7;
+ subcount = LLStringUtil::format(s, nasty_fmt_map);
+ ensure("LLStringUtil::format: Nastyfmt Test2 result", s.empty());
+ ensure_equals("LLStringUtil::format: Nastyfmt Test2 result count", 0, subcount);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<35>()
+ {
+ // Make sure startsWith works
+ std::string string("anybody in there?");
+ std::string substr("anybody");
+ ensure("startsWith works.", LLStringUtil::startsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<36>()
+ {
+ // Make sure startsWith correctly fails
+ std::string string("anybody in there?");
+ std::string substr("there");
+ ensure("startsWith fails.", !LLStringUtil::startsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<37>()
+ {
+ // startsWith fails on empty strings
+ std::string value("anybody in there?");
+ std::string empty;
+ ensure("empty string.", !LLStringUtil::startsWith(value, empty));
+ ensure("empty substr.", !LLStringUtil::startsWith(empty, value));
+ ensure("empty everything.", !LLStringUtil::startsWith(empty, empty));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<38>()
+ {
+ // Make sure endsWith works correctly
+ std::string string("anybody in there?");
+ std::string substr("there?");
+ ensure("endsWith works.", LLStringUtil::endsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<39>()
+ {
+ // Make sure endsWith correctly fails
+ std::string string("anybody in there?");
+ std::string substr("anybody");
+ ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
+ substr = "there";
+ ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
+ substr = "ther?";
+ ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<40>()
+ {
+ // endsWith fails on empty strings
+ std::string value("anybody in there?");
+ std::string empty;
+ ensure("empty string.", !LLStringUtil::endsWith(value, empty));
+ ensure("empty substr.", !LLStringUtil::endsWith(empty, value));
+ ensure("empty everything.", !LLStringUtil::endsWith(empty, empty));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<41>()
+ {
+ set_test_name("getTokens(\"delims\")");
+ ensure_equals("empty string", LLStringUtil::getTokens("", " "), StringVec());
+ ensure_equals("only delims",
+ LLStringUtil::getTokens(" \r\n ", " \r\n"), StringVec());
+ ensure_equals("sequence of delims",
+ LLStringUtil::getTokens(",,, one ,,,", ","), list_of("one"));
+ // nat considers this a dubious implementation side effect, but I'd
+ // hate to change it now...
+ ensure_equals("noncontiguous tokens",
+ LLStringUtil::getTokens(", ,, , one ,,,", ","), list_of("")("")("one"));
+ ensure_equals("space-padded tokens",
+ LLStringUtil::getTokens(", one , two ,", ","), list_of("one")("two"));
+ ensure_equals("no delims", LLStringUtil::getTokens("one", ","), list_of("one"));
+ }
+
+ // Shorthand for verifying that getTokens() behaves the same when you
+ // don't pass a string of escape characters, when you pass an empty string
+ // (different overloads), and when you pass a string of characters that
+ // aren't actually present.
+ void ensure_getTokens(const std::string& desc,
+ const std::string& string,
+ const std::string& drop_delims,
+ const std::string& keep_delims,
+ const std::string& quotes,
+ const std::vector<std::string>& expect)
+ {
+ ensure_equals(desc + " - no esc",
+ LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes),
+ expect);
+ ensure_equals(desc + " - empty esc",
+ LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, ""),
+ expect);
+ ensure_equals(desc + " - unused esc",
+ LLStringUtil::getTokens(string, drop_delims, keep_delims, quotes, "!"),
+ expect);
+ }
+
+ void ensure_getTokens(const std::string& desc,
+ const std::string& string,
+ const std::string& drop_delims,
+ const std::string& keep_delims,
+ const std::vector<std::string>& expect)
+ {
+ ensure_getTokens(desc, string, drop_delims, keep_delims, "", expect);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<42>()
+ {
+ set_test_name("getTokens(\"delims\", etc.)");
+ // Signatures to test in this method:
+ // getTokens(string, drop_delims, keep_delims [, quotes [, escapes]])
+ // If you omit keep_delims, you get the older function (test above).
+
+ // cases like the getTokens(string, delims) tests above
+ ensure_getTokens("empty string", "", " ", "", StringVec());
+ ensure_getTokens("only delims",
+ " \r\n ", " \r\n", "", StringVec());
+ ensure_getTokens("sequence of delims",
+ ",,, one ,,,", ", ", "", list_of("one"));
+ // Note contrast with the case in the previous method
+ ensure_getTokens("noncontiguous tokens",
+ ", ,, , one ,,,", ", ", "", list_of("one"));
+ ensure_getTokens("space-padded tokens",
+ ", one , two ,", ", ", "",
list_of("one")("two"));
- ensure_getTokens("no delims", "one", ",", "", list_of("one"));
-
- // drop_delims vs. keep_delims
- ensure_getTokens("arithmetic",
- " ab+def / xx* yy ", " ", "+-*/",
- list_of("ab")("+")("def")("/")("xx")("*")("yy"));
-
- // quotes
- ensure_getTokens("no quotes",
- "She said, \"Don't go.\"", " ", ",", "",
- list_of("She")("said")(",")("\"Don't")("go.\""));
- ensure_getTokens("quotes",
- "She said, \"Don't go.\"", " ", ",", "\"",
- list_of("She")("said")(",")("Don't go."));
- ensure_getTokens("quotes and delims",
- "run c:/'Documents and Settings'/someone", " ", "", "'",
- list_of("run")("c:/Documents and Settings/someone"));
- ensure_getTokens("unmatched quote",
- "baby don't leave", " ", "", "'",
- list_of("baby")("don't")("leave"));
- ensure_getTokens("adjacent quoted",
- "abc'def \"ghi'\"jkl' mno\"pqr", " ", "", "\"'",
- list_of("abcdef \"ghijkl' mnopqr"));
- ensure_getTokens("quoted empty string",
- "--set SomeVar ''", " ", "", "'",
- list_of("--set")("SomeVar")(""));
-
- // escapes
- // Don't use backslash as an escape for these tests -- you'll go nuts
- // between the C++ string scanner and getTokens() escapes. Test with
- // something else!
- ensure_equals("escaped delims",
- LLStringUtil::getTokens("^ a - dog^-gone^ phrase", " ", "-", "", "^"),
- list_of(" a")("-")("dog-gone phrase"));
- ensure_equals("escaped quotes",
- LLStringUtil::getTokens("say: 'this isn^'t w^orking'.", " ", "", "'", "^"),
- list_of("say:")("this isn't working."));
- ensure_equals("escaped escape",
- LLStringUtil::getTokens("want x^^2", " ", "", "", "^"),
- list_of("want")("x^2"));
- ensure_equals("escape at end",
- LLStringUtil::getTokens("it's^ up there^", " ", "", "'", "^"),
- list_of("it's up")("there^"));
+ ensure_getTokens("no delims", "one", ",", "", list_of("one"));
+
+ // drop_delims vs. keep_delims
+ ensure_getTokens("arithmetic",
+ " ab+def / xx* yy ", " ", "+-*/",
+ list_of("ab")("+")("def")("/")("xx")("*")("yy"));
+
+ // quotes
+ ensure_getTokens("no quotes",
+ "She said, \"Don't go.\"", " ", ",", "",
+ list_of("She")("said")(",")("\"Don't")("go.\""));
+ ensure_getTokens("quotes",
+ "She said, \"Don't go.\"", " ", ",", "\"",
+ list_of("She")("said")(",")("Don't go."));
+ ensure_getTokens("quotes and delims",
+ "run c:/'Documents and Settings'/someone", " ", "", "'",
+ list_of("run")("c:/Documents and Settings/someone"));
+ ensure_getTokens("unmatched quote",
+ "baby don't leave", " ", "", "'",
+ list_of("baby")("don't")("leave"));
+ ensure_getTokens("adjacent quoted",
+ "abc'def \"ghi'\"jkl' mno\"pqr", " ", "", "\"'",
+ list_of("abcdef \"ghijkl' mnopqr"));
+ ensure_getTokens("quoted empty string",
+ "--set SomeVar ''", " ", "", "'",
+ list_of("--set")("SomeVar")(""));
+
+ // escapes
+ // Don't use backslash as an escape for these tests -- you'll go nuts
+ // between the C++ string scanner and getTokens() escapes. Test with
+ // something else!
+ ensure_equals("escaped delims",
+ LLStringUtil::getTokens("^ a - dog^-gone^ phrase", " ", "-", "", "^"),
+ list_of(" a")("-")("dog-gone phrase"));
+ ensure_equals("escaped quotes",
+ LLStringUtil::getTokens("say: 'this isn^'t w^orking'.", " ", "", "'", "^"),
+ list_of("say:")("this isn't working."));
+ ensure_equals("escaped escape",
+ LLStringUtil::getTokens("want x^^2", " ", "", "", "^"),
+ list_of("want")("x^2"));
+ ensure_equals("escape at end",
+ LLStringUtil::getTokens("it's^ up there^", " ", "", "'", "^"),
+ list_of("it's up")("there^"));
}
}
diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp
index 0a9d85ad00..8851f87b91 100644
--- a/indra/llcommon/tests/lltrace_test.cpp
+++ b/indra/llcommon/tests/lltrace_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsingleton_test.cpp
* @date 2011-08-11
* @brief Unit test for the LLSingleton class
@@ -34,14 +34,14 @@
namespace LLUnits
{
- // using powers of 2 to allow strict floating point equality
- LL_DECLARE_BASE_UNIT(Ounces, "oz");
- LL_DECLARE_DERIVED_UNIT(TallCup, "", Ounces, / 12);
- LL_DECLARE_DERIVED_UNIT(GrandeCup, "", Ounces, / 16);
- LL_DECLARE_DERIVED_UNIT(VentiCup, "", Ounces, / 20);
-
- LL_DECLARE_BASE_UNIT(Grams, "g");
- LL_DECLARE_DERIVED_UNIT(Milligrams, "mg", Grams, * 1000);
+ // using powers of 2 to allow strict floating point equality
+ LL_DECLARE_BASE_UNIT(Ounces, "oz");
+ LL_DECLARE_DERIVED_UNIT(TallCup, "", Ounces, / 12);
+ LL_DECLARE_DERIVED_UNIT(GrandeCup, "", Ounces, / 16);
+ LL_DECLARE_DERIVED_UNIT(VentiCup, "", Ounces, / 20);
+
+ LL_DECLARE_BASE_UNIT(Grams, "g");
+ LL_DECLARE_DERIVED_UNIT(Milligrams, "mg", Grams, * 1000);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ounces);
@@ -54,89 +54,89 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milligrams);
namespace tut
{
- using namespace LLTrace;
- struct trace
- {
- ThreadRecorder mRecorder;
- };
-
- typedef test_group<trace> trace_t;
- typedef trace_t::object trace_object_t;
- tut::trace_t tut_singleton("LLTrace");
-
- static CountStatHandle<S32> sCupsOfCoffeeConsumed("coffeeconsumed", "Delicious cup of dark roast.");
- static SampleStatHandle<F32Milligrams> sCaffeineLevelStat("caffeinelevel", "Coffee buzz quotient");
- static EventStatHandle<S32Ounces> sOuncesPerCup("cupsize", "Large, huge, or ginormous");
-
- static F32 sCaffeineLevel(0.f);
- const F32Milligrams sCaffeinePerOz(18.f);
-
- void drink_coffee(S32 num_cups, S32Ounces cup_size)
- {
- add(sCupsOfCoffeeConsumed, num_cups);
- for (S32 i = 0; i < num_cups; i++)
- {
- record(sOuncesPerCup, cup_size);
- }
-
- sCaffeineLevel += F32Ounces(num_cups * cup_size).value() * sCaffeinePerOz.value();
- sample(sCaffeineLevelStat, sCaffeineLevel);
- }
-
- // basic data collection
- template<> template<>
- void trace_object_t::test<1>()
- {
- sample(sCaffeineLevelStat, sCaffeineLevel);
-
- Recording all_day;
- Recording at_work;
- Recording after_3pm;
-
- all_day.start();
- {
- // warm up with one grande cup
- drink_coffee(1, S32TallCup(1));
-
- // go to work
- at_work.start();
- {
- // drink 3 tall cups, 1 after 3 pm
- drink_coffee(2, S32GrandeCup(1));
- after_3pm.start();
- drink_coffee(1, S32GrandeCup(1));
- }
- at_work.stop();
- drink_coffee(1, S32VentiCup(1));
- }
- // don't need to stop recordings to get accurate values out of them
- //after_3pm.stop();
- //all_day.stop();
-
- ensure("count stats are counted when recording is active",
- at_work.getSum(sCupsOfCoffeeConsumed) == 3
- && all_day.getSum(sCupsOfCoffeeConsumed) == 5
- && after_3pm.getSum(sCupsOfCoffeeConsumed) == 2);
- ensure("measurement sums are counted when recording is active",
- at_work.getSum(sOuncesPerCup) == S32Ounces(48)
- && all_day.getSum(sOuncesPerCup) == S32Ounces(80)
- && after_3pm.getSum(sOuncesPerCup) == S32Ounces(36));
- ensure("measurement min is specific to when recording is active",
- at_work.getMin(sOuncesPerCup) == S32GrandeCup(1)
- && all_day.getMin(sOuncesPerCup) == S32TallCup(1)
- && after_3pm.getMin(sOuncesPerCup) == S32GrandeCup(1));
- ensure("measurement max is specific to when recording is active",
- at_work.getMax(sOuncesPerCup) == S32GrandeCup(1)
- && all_day.getMax(sOuncesPerCup) == S32VentiCup(1)
- && after_3pm.getMax(sOuncesPerCup) == S32VentiCup(1));
- ensure("sample min is specific to when recording is active",
- at_work.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1)).value()
- && all_day.getMin(sCaffeineLevelStat) == F32Milligrams(0.f)
- && after_3pm.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(2)).value());
- ensure("sample max is specific to when recording is active",
- at_work.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3)).value()
- && all_day.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value()
- && after_3pm.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value());
- }
+ using namespace LLTrace;
+ struct trace
+ {
+ ThreadRecorder mRecorder;
+ };
+
+ typedef test_group<trace> trace_t;
+ typedef trace_t::object trace_object_t;
+ tut::trace_t tut_singleton("LLTrace");
+
+ static CountStatHandle<S32> sCupsOfCoffeeConsumed("coffeeconsumed", "Delicious cup of dark roast.");
+ static SampleStatHandle<F32Milligrams> sCaffeineLevelStat("caffeinelevel", "Coffee buzz quotient");
+ static EventStatHandle<S32Ounces> sOuncesPerCup("cupsize", "Large, huge, or ginormous");
+
+ static F32 sCaffeineLevel(0.f);
+ const F32Milligrams sCaffeinePerOz(18.f);
+
+ void drink_coffee(S32 num_cups, S32Ounces cup_size)
+ {
+ add(sCupsOfCoffeeConsumed, num_cups);
+ for (S32 i = 0; i < num_cups; i++)
+ {
+ record(sOuncesPerCup, cup_size);
+ }
+
+ sCaffeineLevel += F32Ounces(num_cups * cup_size).value() * sCaffeinePerOz.value();
+ sample(sCaffeineLevelStat, sCaffeineLevel);
+ }
+
+ // basic data collection
+ template<> template<>
+ void trace_object_t::test<1>()
+ {
+ sample(sCaffeineLevelStat, sCaffeineLevel);
+
+ Recording all_day;
+ Recording at_work;
+ Recording after_3pm;
+
+ all_day.start();
+ {
+ // warm up with one grande cup
+ drink_coffee(1, S32TallCup(1));
+
+ // go to work
+ at_work.start();
+ {
+ // drink 3 tall cups, 1 after 3 pm
+ drink_coffee(2, S32GrandeCup(1));
+ after_3pm.start();
+ drink_coffee(1, S32GrandeCup(1));
+ }
+ at_work.stop();
+ drink_coffee(1, S32VentiCup(1));
+ }
+ // don't need to stop recordings to get accurate values out of them
+ //after_3pm.stop();
+ //all_day.stop();
+
+ ensure("count stats are counted when recording is active",
+ at_work.getSum(sCupsOfCoffeeConsumed) == 3
+ && all_day.getSum(sCupsOfCoffeeConsumed) == 5
+ && after_3pm.getSum(sCupsOfCoffeeConsumed) == 2);
+ ensure("measurement sums are counted when recording is active",
+ at_work.getSum(sOuncesPerCup) == S32Ounces(48)
+ && all_day.getSum(sOuncesPerCup) == S32Ounces(80)
+ && after_3pm.getSum(sOuncesPerCup) == S32Ounces(36));
+ ensure("measurement min is specific to when recording is active",
+ at_work.getMin(sOuncesPerCup) == S32GrandeCup(1)
+ && all_day.getMin(sOuncesPerCup) == S32TallCup(1)
+ && after_3pm.getMin(sOuncesPerCup) == S32GrandeCup(1));
+ ensure("measurement max is specific to when recording is active",
+ at_work.getMax(sOuncesPerCup) == S32GrandeCup(1)
+ && all_day.getMax(sOuncesPerCup) == S32VentiCup(1)
+ && after_3pm.getMax(sOuncesPerCup) == S32VentiCup(1));
+ ensure("sample min is specific to when recording is active",
+ at_work.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1)).value()
+ && all_day.getMin(sCaffeineLevelStat) == F32Milligrams(0.f)
+ && after_3pm.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(2)).value());
+ ensure("sample max is specific to when recording is active",
+ at_work.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3)).value()
+ && all_day.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value()
+ && after_3pm.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value());
+ }
}
diff --git a/indra/llcommon/tests/lltreeiterators_test.cpp b/indra/llcommon/tests/lltreeiterators_test.cpp
index b9c7a70c07..7a2adfd8ba 100644
--- a/indra/llcommon/tests/lltreeiterators_test.cpp
+++ b/indra/llcommon/tests/lltreeiterators_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-08-20
* @brief Test of lltreeiterators.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$
*/
@@ -1045,7 +1045,7 @@ bool LLTreeWalkIter_test(const std::string& itername, const std::string& nodenam
{
std::cout << itername << '<' << nodename << ">(NULL)\n";
return false;
- }
+ }
return true;
}
@@ -1107,7 +1107,7 @@ namespace tut
TreeNodePtr tnroot(example_tree<TreeNode>());
TreeNodePtr tnB2b(get_B2b<TreeNode, TreeNode::child_iterator>
(tnroot, boost::bind(&TreeNode::child_begin, _1)));
-
+
std::string desc1("for (TreeNodePr : getRootRange<LLTreeIter::UP>(tnB2b))");
// std::cout << desc1 << "\n";
// Although we've commented out the output statement, ensure that the
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 57cf9810af..49f2d3085a 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsingleton_test.cpp
* @date 2011-08-11
* @brief Unit test for the LLSingleton class
@@ -32,10 +32,10 @@
namespace LLUnits
{
- // using powers of 2 to allow strict floating point equality
- LL_DECLARE_BASE_UNIT(Quatloos, "Quat");
- LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, / 4);
- LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, * 16);
+ // using powers of 2 to allow strict floating point equality
+ LL_DECLARE_BASE_UNIT(Quatloos, "Quat");
+ LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, / 4);
+ LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, * 16);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos);
@@ -44,9 +44,9 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Solari);
namespace LLUnits
{
- LL_DECLARE_BASE_UNIT(Celcius, "c");
- LL_DECLARE_DERIVED_UNIT(Fahrenheit, "f", Celcius, * 9 / 5 + 32);
- LL_DECLARE_DERIVED_UNIT(Kelvin, "k", Celcius, + 273.15f);
+ LL_DECLARE_BASE_UNIT(Celcius, "c");
+ LL_DECLARE_DERIVED_UNIT(Fahrenheit, "f", Celcius, * 9 / 5 + 32);
+ LL_DECLARE_DERIVED_UNIT(Kelvin, "k", Celcius, + 273.15f);
}
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Celcius);
@@ -56,333 +56,333 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kelvin);
namespace tut
{
- using namespace LLUnits;
- struct units
- {
- };
-
- typedef test_group<units> units_t;
- typedef units_t::object units_object_t;
- tut::units_t tut_singleton("LLUnit");
-
- // storage type conversions
- template<> template<>
- void units_object_t::test<1>()
- {
- LLUnit<F32, Quatloos> float_quatloos;
- ensure("default float unit is zero", float_quatloos == F32Quatloos(0.f));
-
- LLUnit<F32, Quatloos> float_initialize_quatloos(1);
- ensure("non-zero initialized unit", float_initialize_quatloos == F32Quatloos(1.f));
-
- LLUnit<S32, Quatloos> int_quatloos;
- ensure("default int unit is zero", int_quatloos == S32Quatloos(0));
-
- int_quatloos = S32Quatloos(42);
- ensure("int assignment is preserved", int_quatloos == S32Quatloos(42));
- float_quatloos = int_quatloos;
- ensure("float assignment from int preserves value", float_quatloos == F32Quatloos(42.f));
-
- int_quatloos = float_quatloos;
- ensure("int assignment from float preserves value", int_quatloos == S32Quatloos(42));
-
- float_quatloos = F32Quatloos(42.1f);
- int_quatloos = float_quatloos;
- ensure("int units truncate float units on assignment", int_quatloos == S32Quatloos(42));
-
- LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
- ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == S32Quatloos(42));
-
- S32Solari int_solari(1);
-
- float_quatloos = int_solari;
- ensure("fractional units are preserved in conversion from integer to float type", float_quatloos == F32Quatloos(0.25f));
-
- int_quatloos = S32Quatloos(1);
- F32Solari float_solari = int_quatloos;
- ensure("can convert with fractional intermediates from integer to float type", float_solari == F32Solari(4.f));
- }
-
- // conversions to/from base unit
- template<> template<>
- void units_object_t::test<2>()
- {
- LLUnit<F32, Quatloos> quatloos(1.f);
- LLUnit<F32, Latinum> latinum_bars(quatloos);
- ensure("conversion between units is automatic via initialization", latinum_bars == F32Latinum(1.f / 4.f));
-
- latinum_bars = S32Latinum(256);
- quatloos = latinum_bars;
- ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == S32Quatloos(1024));
-
- LLUnit<S32, Quatloos> single_quatloo(1);
- LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
- ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == F32Latinum(0.25f));
- }
-
- // conversions across non-base units
- template<> template<>
- void units_object_t::test<3>()
- {
- LLUnit<F32, Quatloos> quatloos(1024);
- LLUnit<F32, Solari> solari(quatloos);
- ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == S32Solari(4096));
-
- LLUnit<F32, Latinum> latinum_bars = solari;
- ensure("Non base units can be converted between each other", latinum_bars == S32Latinum(256));
- }
-
- // math operations
- template<> template<>
- void units_object_t::test<4>()
- {
- // exercise math operations
- LLUnit<F32, Quatloos> quatloos(1.f);
- quatloos *= 4.f;
- ensure(quatloos == S32Quatloos(4));
- quatloos = quatloos * 2;
- ensure(quatloos == S32Quatloos(8));
- quatloos = 2.f * quatloos;
- ensure(quatloos == S32Quatloos(16));
-
- quatloos += F32Quatloos(4.f);
- ensure(quatloos == S32Quatloos(20));
- quatloos += S32Quatloos(4);
- ensure(quatloos == S32Quatloos(24));
- quatloos = quatloos + S32Quatloos(4);
- ensure(quatloos == S32Quatloos(28));
- quatloos = S32Quatloos(4) + quatloos;
- ensure(quatloos == S32Quatloos(32));
- quatloos += quatloos * 3;
- ensure(quatloos == S32Quatloos(128));
-
- quatloos -= quatloos / 4 * 3;
- ensure(quatloos == S32Quatloos(32));
- quatloos = quatloos - S32Quatloos(8);
- ensure(quatloos == S32Quatloos(24));
- quatloos -= S32Quatloos(4);
- ensure(quatloos == S32Quatloos(20));
- quatloos -= F32Quatloos(4.f);
- ensure(quatloos == S32Quatloos(16));
-
- quatloos /= 2.f;
- ensure(quatloos == S32Quatloos(8));
- quatloos = quatloos / 4;
- ensure(quatloos == S32Quatloos(2));
-
- F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
- ensure(ratio == 1);
- ratio = quatloos / LLUnit<F32, Solari>(8.f);
- ensure(ratio == 1);
-
- quatloos += LLUnit<F32, Solari>(8.f);
- ensure(quatloos == S32Quatloos(4));
- quatloos -= LLUnit<F32, Latinum>(1.f);
- ensure(quatloos == S32Quatloos(0));
- }
-
- // comparison operators
- template<> template<>
- void units_object_t::test<5>()
- {
- LLUnit<S32, Quatloos> quatloos(1);
- ensure("can perform less than comparison against same type", quatloos < S32Quatloos(2));
- ensure("can perform less than comparison against different storage type", quatloos < F32Quatloos(2.f));
- ensure("can perform less than comparison against different units", quatloos < S32Latinum(5));
- ensure("can perform less than comparison against different storage type and units", quatloos < F32Latinum(5.f));
-
- ensure("can perform greater than comparison against same type", quatloos > S32Quatloos(0));
- ensure("can perform greater than comparison against different storage type", quatloos > F32Quatloos(0.f));
- ensure("can perform greater than comparison against different units", quatloos > S32Latinum(0));
- ensure("can perform greater than comparison against different storage type and units", quatloos > F32Latinum(0.f));
-
- }
-
- bool accept_explicit_quatloos(S32Quatloos q)
- {
- return true;
- }
-
- bool accept_implicit_quatloos(S32Quatloos q)
- {
- return true;
- }
-
- // signature compatibility
- template<> template<>
- void units_object_t::test<6>()
- {
- S32Quatloos quatloos(1);
- ensure("can pass unit values as argument", accept_explicit_quatloos(S32Quatloos(1)));
- ensure("can pass unit values as argument", accept_explicit_quatloos(quatloos));
- }
-
- // implicit units
- template<> template<>
- void units_object_t::test<7>()
- {
- LLUnit<F32, Quatloos> quatloos;
- LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + S32Quatloos(1);
- ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
-
- quatloos = quatloos_implicit;
- ensure("can assign implicit unit to explicit unit", quatloos == S32Quatloos(1));
- quatloos += quatloos_implicit;
- ensure("can perform math operation using mixture of implicit and explicit units", quatloos == S32Quatloos(2));
-
- // math operations on implicits
- quatloos_implicit = 1;
- ensure(quatloos_implicit == 1);
-
- quatloos_implicit += 2;
- ensure(quatloos_implicit == 3);
-
- quatloos_implicit *= 2;
- ensure(quatloos_implicit == 6);
-
- quatloos_implicit -= 1;
- ensure(quatloos_implicit == 5);
-
- quatloos_implicit /= 5;
- ensure(quatloos_implicit == 1);
-
- quatloos_implicit = quatloos_implicit + 3 + quatloos_implicit;
- ensure(quatloos_implicit == 5);
-
- quatloos_implicit = 10 - quatloos_implicit - 1;
- ensure(quatloos_implicit == 4);
-
- quatloos_implicit = 2 * quatloos_implicit * 2;
- ensure(quatloos_implicit == 16);
-
- F32 one_half = quatloos_implicit / (quatloos_implicit * 2);
- ensure(one_half == 0.5f);
-
- // implicit conversion to POD
- F32 float_val = quatloos_implicit;
- ensure("implicit units convert implicitly to regular values", float_val == 16);
-
- S32 int_val = quatloos_implicit;
- ensure("implicit units convert implicitly to regular values", int_val == 16);
-
- // conversion of implicits
- LLUnitImplicit<F32, Latinum> latinum_implicit(2);
- ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
-
- quatloos_implicit += F32Quatloos(10);
- ensure("can add-assign explicit units", quatloos_implicit == 26);
-
- quatloos_implicit -= F32Quatloos(10);
- ensure("can subtract-assign explicit units", quatloos_implicit == 16);
-
- // comparisons
- ensure("can compare greater than implicit unit", quatloos_implicit > F32QuatloosImplicit(0.f));
- ensure("can compare greater than non-implicit unit", quatloos_implicit > F32Quatloos(0.f));
- ensure("can compare greater than or equal to implicit unit", quatloos_implicit >= F32QuatloosImplicit(0.f));
- ensure("can compare greater than or equal to non-implicit unit", quatloos_implicit >= F32Quatloos(0.f));
- ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(20.f));
- ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(20.f));
- ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(20.f));
- ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(20.f));
- }
-
- // precision tests
- template<> template<>
- void units_object_t::test<8>()
- {
- U32Bytes max_bytes(U32_MAX);
- S32Megabytes mega_bytes = max_bytes;
- ensure("max available precision is used when converting units", mega_bytes == (S32Megabytes)4095);
-
- mega_bytes = (S32Megabytes)-5 + (U32Megabytes)1;
- ensure("can mix signed and unsigned in units addition", mega_bytes == (S32Megabytes)-4);
-
- mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;
- ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4);
- }
-
- // default units
- template<> template<>
- void units_object_t::test<9>()
- {
- U32Gigabytes GB(1);
- U32Megabytes MB(GB);
- U32Kilobytes KB(GB);
- U32Bytes B(GB);
-
- ensure("GB -> MB conversion", MB.value() == 1024);
- ensure("GB -> KB conversion", KB.value() == 1024 * 1024);
- ensure("GB -> B conversion", B.value() == 1024 * 1024 * 1024);
-
- KB = U32Kilobytes(1);
- U32Kilobits Kb(KB);
- U32Bits b(KB);
- ensure("KB -> Kb conversion", Kb.value() == 8);
- ensure("KB -> b conversion", b.value() == 8 * 1024);
-
- U32Days days(1);
- U32Hours hours(days);
- U32Minutes minutes(days);
- U32Seconds seconds(days);
- U32Milliseconds ms(days);
-
- ensure("days -> hours conversion", hours.value() == 24);
- ensure("days -> minutes conversion", minutes.value() == 24 * 60);
- ensure("days -> seconds conversion", seconds.value() == 24 * 60 * 60);
- ensure("days -> ms conversion", ms.value() == 24 * 60 * 60 * 1000);
-
- U32Kilometers km(1);
- U32Meters m(km);
- U32Centimeters cm(km);
- U32Millimeters mm(km);
-
- ensure("km -> m conversion", m.value() == 1000);
- ensure("km -> cm conversion", cm.value() == 1000 * 100);
- ensure("km -> mm conversion", mm.value() == 1000 * 1000);
-
- U32Gigahertz GHz(1);
- U32Megahertz MHz(GHz);
- U32Kilohertz KHz(GHz);
- U32Hertz Hz(GHz);
-
- ensure("GHz -> MHz conversion", MHz.value() == 1000);
- ensure("GHz -> KHz conversion", KHz.value() == 1000 * 1000);
- ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000);
-
- F32Radians rad(6.2831853071795f);
- S32Degrees deg(rad);
- ensure("radians -> degrees conversion", deg.value() == 360);
-
- F32Percent percent(50);
- F32Ratio ratio(percent);
- ensure("percent -> ratio conversion", ratio.value() == 0.5f);
-
- U32Kilotriangles ktris(1);
- U32Triangles tris(ktris);
- ensure("kilotriangles -> triangles conversion", tris.value() == 1000);
- }
-
- bool value_near(F32 value, F32 target, F32 threshold)
- {
- return fabsf(value - target) < threshold;
- }
-
- // linear transforms
- template<> template<>
- void units_object_t::test<10>()
- {
- F32Celcius float_celcius(100);
- F32Fahrenheit float_fahrenheit(float_celcius);
- ensure("floating point celcius -> fahrenheit conversion using linear transform", value_near(float_fahrenheit.value(), 212, 0.1f) );
-
- float_celcius = float_fahrenheit;
- ensure("floating point fahrenheit -> celcius conversion using linear transform (round trip)", value_near(float_celcius.value(), 100.f, 0.1f) );
-
- S32Celcius int_celcius(100);
- S32Fahrenheit int_fahrenheit(int_celcius);
- ensure("integer celcius -> fahrenheit conversion using linear transform", int_fahrenheit.value() == 212);
-
- int_celcius = int_fahrenheit;
- ensure("integer fahrenheit -> celcius conversion using linear transform (round trip)", int_celcius.value() == 100);
- }
+ using namespace LLUnits;
+ struct units
+ {
+ };
+
+ typedef test_group<units> units_t;
+ typedef units_t::object units_object_t;
+ tut::units_t tut_singleton("LLUnit");
+
+ // storage type conversions
+ template<> template<>
+ void units_object_t::test<1>()
+ {
+ LLUnit<F32, Quatloos> float_quatloos;
+ ensure("default float unit is zero", float_quatloos == F32Quatloos(0.f));
+
+ LLUnit<F32, Quatloos> float_initialize_quatloos(1);
+ ensure("non-zero initialized unit", float_initialize_quatloos == F32Quatloos(1.f));
+
+ LLUnit<S32, Quatloos> int_quatloos;
+ ensure("default int unit is zero", int_quatloos == S32Quatloos(0));
+
+ int_quatloos = S32Quatloos(42);
+ ensure("int assignment is preserved", int_quatloos == S32Quatloos(42));
+ float_quatloos = int_quatloos;
+ ensure("float assignment from int preserves value", float_quatloos == F32Quatloos(42.f));
+
+ int_quatloos = float_quatloos;
+ ensure("int assignment from float preserves value", int_quatloos == S32Quatloos(42));
+
+ float_quatloos = F32Quatloos(42.1f);
+ int_quatloos = float_quatloos;
+ ensure("int units truncate float units on assignment", int_quatloos == S32Quatloos(42));
+
+ LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
+ ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == S32Quatloos(42));
+
+ S32Solari int_solari(1);
+
+ float_quatloos = int_solari;
+ ensure("fractional units are preserved in conversion from integer to float type", float_quatloos == F32Quatloos(0.25f));
+
+ int_quatloos = S32Quatloos(1);
+ F32Solari float_solari = int_quatloos;
+ ensure("can convert with fractional intermediates from integer to float type", float_solari == F32Solari(4.f));
+ }
+
+ // conversions to/from base unit
+ template<> template<>
+ void units_object_t::test<2>()
+ {
+ LLUnit<F32, Quatloos> quatloos(1.f);
+ LLUnit<F32, Latinum> latinum_bars(quatloos);
+ ensure("conversion between units is automatic via initialization", latinum_bars == F32Latinum(1.f / 4.f));
+
+ latinum_bars = S32Latinum(256);
+ quatloos = latinum_bars;
+ ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == S32Quatloos(1024));
+
+ LLUnit<S32, Quatloos> single_quatloo(1);
+ LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
+ ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == F32Latinum(0.25f));
+ }
+
+ // conversions across non-base units
+ template<> template<>
+ void units_object_t::test<3>()
+ {
+ LLUnit<F32, Quatloos> quatloos(1024);
+ LLUnit<F32, Solari> solari(quatloos);
+ ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == S32Solari(4096));
+
+ LLUnit<F32, Latinum> latinum_bars = solari;
+ ensure("Non base units can be converted between each other", latinum_bars == S32Latinum(256));
+ }
+
+ // math operations
+ template<> template<>
+ void units_object_t::test<4>()
+ {
+ // exercise math operations
+ LLUnit<F32, Quatloos> quatloos(1.f);
+ quatloos *= 4.f;
+ ensure(quatloos == S32Quatloos(4));
+ quatloos = quatloos * 2;
+ ensure(quatloos == S32Quatloos(8));
+ quatloos = 2.f * quatloos;
+ ensure(quatloos == S32Quatloos(16));
+
+ quatloos += F32Quatloos(4.f);
+ ensure(quatloos == S32Quatloos(20));
+ quatloos += S32Quatloos(4);
+ ensure(quatloos == S32Quatloos(24));
+ quatloos = quatloos + S32Quatloos(4);
+ ensure(quatloos == S32Quatloos(28));
+ quatloos = S32Quatloos(4) + quatloos;
+ ensure(quatloos == S32Quatloos(32));
+ quatloos += quatloos * 3;
+ ensure(quatloos == S32Quatloos(128));
+
+ quatloos -= quatloos / 4 * 3;
+ ensure(quatloos == S32Quatloos(32));
+ quatloos = quatloos - S32Quatloos(8);
+ ensure(quatloos == S32Quatloos(24));
+ quatloos -= S32Quatloos(4);
+ ensure(quatloos == S32Quatloos(20));
+ quatloos -= F32Quatloos(4.f);
+ ensure(quatloos == S32Quatloos(16));
+
+ quatloos /= 2.f;
+ ensure(quatloos == S32Quatloos(8));
+ quatloos = quatloos / 4;
+ ensure(quatloos == S32Quatloos(2));
+
+ F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
+ ensure(ratio == 1);
+ ratio = quatloos / LLUnit<F32, Solari>(8.f);
+ ensure(ratio == 1);
+
+ quatloos += LLUnit<F32, Solari>(8.f);
+ ensure(quatloos == S32Quatloos(4));
+ quatloos -= LLUnit<F32, Latinum>(1.f);
+ ensure(quatloos == S32Quatloos(0));
+ }
+
+ // comparison operators
+ template<> template<>
+ void units_object_t::test<5>()
+ {
+ LLUnit<S32, Quatloos> quatloos(1);
+ ensure("can perform less than comparison against same type", quatloos < S32Quatloos(2));
+ ensure("can perform less than comparison against different storage type", quatloos < F32Quatloos(2.f));
+ ensure("can perform less than comparison against different units", quatloos < S32Latinum(5));
+ ensure("can perform less than comparison against different storage type and units", quatloos < F32Latinum(5.f));
+
+ ensure("can perform greater than comparison against same type", quatloos > S32Quatloos(0));
+ ensure("can perform greater than comparison against different storage type", quatloos > F32Quatloos(0.f));
+ ensure("can perform greater than comparison against different units", quatloos > S32Latinum(0));
+ ensure("can perform greater than comparison against different storage type and units", quatloos > F32Latinum(0.f));
+
+ }
+
+ bool accept_explicit_quatloos(S32Quatloos q)
+ {
+ return true;
+ }
+
+ bool accept_implicit_quatloos(S32Quatloos q)
+ {
+ return true;
+ }
+
+ // signature compatibility
+ template<> template<>
+ void units_object_t::test<6>()
+ {
+ S32Quatloos quatloos(1);
+ ensure("can pass unit values as argument", accept_explicit_quatloos(S32Quatloos(1)));
+ ensure("can pass unit values as argument", accept_explicit_quatloos(quatloos));
+ }
+
+ // implicit units
+ template<> template<>
+ void units_object_t::test<7>()
+ {
+ LLUnit<F32, Quatloos> quatloos;
+ LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + S32Quatloos(1);
+ ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
+
+ quatloos = quatloos_implicit;
+ ensure("can assign implicit unit to explicit unit", quatloos == S32Quatloos(1));
+ quatloos += quatloos_implicit;
+ ensure("can perform math operation using mixture of implicit and explicit units", quatloos == S32Quatloos(2));
+
+ // math operations on implicits
+ quatloos_implicit = 1;
+ ensure(quatloos_implicit == 1);
+
+ quatloos_implicit += 2;
+ ensure(quatloos_implicit == 3);
+
+ quatloos_implicit *= 2;
+ ensure(quatloos_implicit == 6);
+
+ quatloos_implicit -= 1;
+ ensure(quatloos_implicit == 5);
+
+ quatloos_implicit /= 5;
+ ensure(quatloos_implicit == 1);
+
+ quatloos_implicit = quatloos_implicit + 3 + quatloos_implicit;
+ ensure(quatloos_implicit == 5);
+
+ quatloos_implicit = 10 - quatloos_implicit - 1;
+ ensure(quatloos_implicit == 4);
+
+ quatloos_implicit = 2 * quatloos_implicit * 2;
+ ensure(quatloos_implicit == 16);
+
+ F32 one_half = quatloos_implicit / (quatloos_implicit * 2);
+ ensure(one_half == 0.5f);
+
+ // implicit conversion to POD
+ F32 float_val = quatloos_implicit;
+ ensure("implicit units convert implicitly to regular values", float_val == 16);
+
+ S32 int_val = quatloos_implicit;
+ ensure("implicit units convert implicitly to regular values", int_val == 16);
+
+ // conversion of implicits
+ LLUnitImplicit<F32, Latinum> latinum_implicit(2);
+ ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
+
+ quatloos_implicit += F32Quatloos(10);
+ ensure("can add-assign explicit units", quatloos_implicit == 26);
+
+ quatloos_implicit -= F32Quatloos(10);
+ ensure("can subtract-assign explicit units", quatloos_implicit == 16);
+
+ // comparisons
+ ensure("can compare greater than implicit unit", quatloos_implicit > F32QuatloosImplicit(0.f));
+ ensure("can compare greater than non-implicit unit", quatloos_implicit > F32Quatloos(0.f));
+ ensure("can compare greater than or equal to implicit unit", quatloos_implicit >= F32QuatloosImplicit(0.f));
+ ensure("can compare greater than or equal to non-implicit unit", quatloos_implicit >= F32Quatloos(0.f));
+ ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(20.f));
+ ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(20.f));
+ ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(20.f));
+ ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(20.f));
+ }
+
+ // precision tests
+ template<> template<>
+ void units_object_t::test<8>()
+ {
+ U32Bytes max_bytes(U32_MAX);
+ S32Megabytes mega_bytes = max_bytes;
+ ensure("max available precision is used when converting units", mega_bytes == (S32Megabytes)4095);
+
+ mega_bytes = (S32Megabytes)-5 + (U32Megabytes)1;
+ ensure("can mix signed and unsigned in units addition", mega_bytes == (S32Megabytes)-4);
+
+ mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;
+ ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4);
+ }
+
+ // default units
+ template<> template<>
+ void units_object_t::test<9>()
+ {
+ U32Gigabytes GB(1);
+ U32Megabytes MB(GB);
+ U32Kilobytes KB(GB);
+ U32Bytes B(GB);
+
+ ensure("GB -> MB conversion", MB.value() == 1024);
+ ensure("GB -> KB conversion", KB.value() == 1024 * 1024);
+ ensure("GB -> B conversion", B.value() == 1024 * 1024 * 1024);
+
+ KB = U32Kilobytes(1);
+ U32Kilobits Kb(KB);
+ U32Bits b(KB);
+ ensure("KB -> Kb conversion", Kb.value() == 8);
+ ensure("KB -> b conversion", b.value() == 8 * 1024);
+
+ U32Days days(1);
+ U32Hours hours(days);
+ U32Minutes minutes(days);
+ U32Seconds seconds(days);
+ U32Milliseconds ms(days);
+
+ ensure("days -> hours conversion", hours.value() == 24);
+ ensure("days -> minutes conversion", minutes.value() == 24 * 60);
+ ensure("days -> seconds conversion", seconds.value() == 24 * 60 * 60);
+ ensure("days -> ms conversion", ms.value() == 24 * 60 * 60 * 1000);
+
+ U32Kilometers km(1);
+ U32Meters m(km);
+ U32Centimeters cm(km);
+ U32Millimeters mm(km);
+
+ ensure("km -> m conversion", m.value() == 1000);
+ ensure("km -> cm conversion", cm.value() == 1000 * 100);
+ ensure("km -> mm conversion", mm.value() == 1000 * 1000);
+
+ U32Gigahertz GHz(1);
+ U32Megahertz MHz(GHz);
+ U32Kilohertz KHz(GHz);
+ U32Hertz Hz(GHz);
+
+ ensure("GHz -> MHz conversion", MHz.value() == 1000);
+ ensure("GHz -> KHz conversion", KHz.value() == 1000 * 1000);
+ ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000);
+
+ F32Radians rad(6.2831853071795f);
+ S32Degrees deg(rad);
+ ensure("radians -> degrees conversion", deg.value() == 360);
+
+ F32Percent percent(50);
+ F32Ratio ratio(percent);
+ ensure("percent -> ratio conversion", ratio.value() == 0.5f);
+
+ U32Kilotriangles ktris(1);
+ U32Triangles tris(ktris);
+ ensure("kilotriangles -> triangles conversion", tris.value() == 1000);
+ }
+
+ bool value_near(F32 value, F32 target, F32 threshold)
+ {
+ return fabsf(value - target) < threshold;
+ }
+
+ // linear transforms
+ template<> template<>
+ void units_object_t::test<10>()
+ {
+ F32Celcius float_celcius(100);
+ F32Fahrenheit float_fahrenheit(float_celcius);
+ ensure("floating point celcius -> fahrenheit conversion using linear transform", value_near(float_fahrenheit.value(), 212, 0.1f) );
+
+ float_celcius = float_fahrenheit;
+ ensure("floating point fahrenheit -> celcius conversion using linear transform (round trip)", value_near(float_celcius.value(), 100.f, 0.1f) );
+
+ S32Celcius int_celcius(100);
+ S32Fahrenheit int_fahrenheit(int_celcius);
+ ensure("integer celcius -> fahrenheit conversion using linear transform", int_fahrenheit.value() == 212);
+
+ int_celcius = int_fahrenheit;
+ ensure("integer fahrenheit -> celcius conversion using linear transform (round trip)", int_celcius.value() == 100);
+ }
}
diff --git a/indra/llcommon/tests/lluri_test.cpp b/indra/llcommon/tests/lluri_test.cpp
index 1a4c6641b9..b48dd3ef1b 100644
--- a/indra/llcommon/tests/lluri_test.cpp
+++ b/indra/llcommon/tests/lluri_test.cpp
@@ -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$
*/
@@ -34,359 +34,359 @@
namespace tut
{
- struct URITestData {
- void checkParts(const LLURI& u,
- const char* expectedScheme,
- const char* expectedOpaque,
- const char* expectedAuthority,
- const char* expectedPath,
- const char* expectedQuery = "")
- {
- ensure_equals("scheme", u.scheme(), expectedScheme);
- ensure_equals("opaque", u.opaque(), expectedOpaque);
- ensure_equals("authority", u.authority(), expectedAuthority);
- ensure_equals("path", u.path(), expectedPath);
- ensure_equals("query", u.query(), expectedQuery);
- }
-
- void escapeRoundTrip(const std::string& uri_raw_1)
- {
- std::string uri_esc_1(LLURI::escape(uri_raw_1));
- std::string uri_raw_2(LLURI::unescape(uri_esc_1));
- ensure_equals("escape/unescape raw", uri_raw_2, uri_raw_1);
- std::string uri_esc_2(LLURI::escape(uri_raw_2));
- ensure_equals("escape/unescape escaped", uri_esc_2, uri_esc_1);
- }
- };
-
- typedef test_group<URITestData> URITestGroup;
- typedef URITestGroup::object URITestObject;
-
- URITestGroup uriTestGroup("LLURI");
-
- template<> template<>
- void URITestObject::test<1>()
- {
- LLURI u("http://abc.com/def/ghi?x=37&y=hello");
-
- ensure_equals("scheme", u.scheme(), "http");
- ensure_equals("authority", u.authority(), "abc.com");
- ensure_equals("path", u.path(), "/def/ghi");
- ensure_equals("query", u.query(), "x=37&y=hello");
-
- ensure_equals("host name", u.hostName(), "abc.com");
- ensure_equals("host port", u.hostPort(), 80);
-
- LLSD query = u.queryMap();
- ensure_equals("query x", query["x"].asInteger(), 37);
- ensure_equals("query y", query["y"].asString(), "hello");
-
- query = LLURI::queryMap("x=22.23&y=https://lindenlab.com/");
- ensure_equals("query x", query["x"].asReal(), 22.23);
- ensure_equals("query y", query["y"].asURI().asString(), "https://lindenlab.com/");
- }
-
- template<> template<>
- void URITestObject::test<2>()
- {
- set_test_name("empty string");
- checkParts(LLURI(""), "", "", "", "");
- }
-
- template<> template<>
- void URITestObject::test<3>()
- {
- set_test_name("no scheme");
- checkParts(LLURI("foo"), "", "foo", "", "");
- checkParts(LLURI("foo%3A"), "", "foo:", "", "");
- }
-
- template<> template<>
- void URITestObject::test<4>()
- {
- set_test_name("scheme w/o paths");
- checkParts(LLURI("mailto:zero@ll.com"),
- "mailto", "zero@ll.com", "", "");
- checkParts(LLURI("silly://abc/def?foo"),
- "silly", "//abc/def?foo", "", "");
- }
-
- template<> template<>
- void URITestObject::test<5>()
- {
- set_test_name("authority section");
- checkParts(LLURI("http:///"),
- "http", "///", "", "/");
-
- checkParts(LLURI("http://abc"),
- "http", "//abc", "abc", "");
-
- checkParts(LLURI("http://a%2Fb/cd"),
- "http", "//a/b/cd", "a/b", "/cd");
-
- checkParts(LLURI("http://host?"),
- "http", "//host?", "host", "");
- }
-
- template<> template<>
- void URITestObject::test<6>()
- {
- set_test_name("path section");
- checkParts(LLURI("http://host/a/b/"),
- "http", "//host/a/b/", "host", "/a/b/");
-
- checkParts(LLURI("http://host/a%3Fb/"),
- "http", "//host/a?b/", "host", "/a?b/");
-
- checkParts(LLURI("http://host/a:b/"),
- "http", "//host/a:b/", "host", "/a:b/");
- }
-
- template<> template<>
- void URITestObject::test<7>()
- {
- set_test_name("query string");
- checkParts(LLURI("http://host/?"),
- "http", "//host/?", "host", "/", "");
-
- checkParts(LLURI("http://host/?x"),
- "http", "//host/?x", "host", "/", "x");
-
- checkParts(LLURI("http://host/??"),
- "http", "//host/??", "host", "/", "?");
-
- checkParts(LLURI("http://host/?%3F"),
- "http", "//host/??", "host", "/", "?");
- }
-
- template<> template<>
- void URITestObject::test<8>()
- {
- LLSD path;
- path.append("x");
- path.append("123");
- checkParts(LLURI::buildHTTP("host", path),
- "http", "//host/x/123", "host", "/x/123");
-
- LLSD query;
- query["123"] = "12";
- query["abcd"] = "abc";
- checkParts(LLURI::buildHTTP("host", path, query),
- "http", "//host/x/123?123=12&abcd=abc",
- "host", "/x/123", "123=12&abcd=abc");
-
- ensure_equals(LLURI::buildHTTP("host", "").asString(),
- "http://host");
- ensure_equals(LLURI::buildHTTP("host", "/").asString(),
- "http://host/");
- ensure_equals(LLURI::buildHTTP("host", "//").asString(),
- "http://host/");
- ensure_equals(LLURI::buildHTTP("host", "dir name").asString(),
- "http://host/dir%20name");
- ensure_equals(LLURI::buildHTTP("host", "dir name/").asString(),
- "http://host/dir%20name/");
- ensure_equals(LLURI::buildHTTP("host", "/dir name").asString(),
- "http://host/dir%20name");
- ensure_equals(LLURI::buildHTTP("host", "/dir name/").asString(),
- "http://host/dir%20name/");
- ensure_equals(LLURI::buildHTTP("host", "dir name/subdir name").asString(),
- "http://host/dir%20name/subdir%20name");
- ensure_equals(LLURI::buildHTTP("host", "dir name/subdir name/").asString(),
- "http://host/dir%20name/subdir%20name/");
- ensure_equals(LLURI::buildHTTP("host", "/dir name/subdir name").asString(),
- "http://host/dir%20name/subdir%20name");
- ensure_equals(LLURI::buildHTTP("host", "/dir name/subdir name/").asString(),
- "http://host/dir%20name/subdir%20name/");
- ensure_equals(LLURI::buildHTTP("host", "//dir name//subdir name//").asString(),
- "http://host/dir%20name/subdir%20name/");
- }
-
- template<> template<>
- void URITestObject::test<9>()
- {
- set_test_name("test unescaped path components");
- LLSD path;
- path.append("x@*//*$&^");
- path.append("123");
- checkParts(LLURI::buildHTTP("host", path),
- "http", "//host/x@*//*$&^/123", "host", "/x@*//*$&^/123");
- }
-
- template<> template<>
- void URITestObject::test<10>()
- {
- set_test_name("test unescaped query components");
- LLSD path;
- path.append("x");
- path.append("123");
- LLSD query;
- query["123"] = "?&*#//";
- query["**@&?//"] = "abc";
- checkParts(LLURI::buildHTTP("host", path, query),
- "http", "//host/x/123?**@&?//=abc&123=?&*#//",
- "host", "/x/123", "**@&?//=abc&123=?&*#//");
- }
-
- template<> template<>
- void URITestObject::test<11>()
- {
- set_test_name("test unescaped host components");
- LLSD path;
- path.append("x");
- path.append("123");
- LLSD query;
- query["123"] = "12";
- query["abcd"] = "abc";
- checkParts(LLURI::buildHTTP("hi123*33--}{:portstuffs", path, query),
- "http", "//hi123*33--}{:portstuffs/x/123?123=12&abcd=abc",
- "hi123*33--}{:portstuffs", "/x/123", "123=12&abcd=abc");
- }
-
- template<> template<>
- void URITestObject::test<12>()
- {
- set_test_name("test funky host_port values that are actually prefixes");
-
- checkParts(LLURI::buildHTTP("http://example.com:8080", LLSD()),
- "http", "//example.com:8080",
- "example.com:8080", "");
-
- checkParts(LLURI::buildHTTP("http://example.com:8080/", LLSD()),
- "http", "//example.com:8080/",
- "example.com:8080", "/");
-
- checkParts(LLURI::buildHTTP("http://example.com:8080/a/b", LLSD()),
- "http", "//example.com:8080/a/b",
- "example.com:8080", "/a/b");
- }
-
- template<> template<>
- void URITestObject::test<13>()
- {
- const std::string unreserved =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "-._~";
- set_test_name("test escape");
- ensure_equals("escaping", LLURI::escape("abcdefg", "abcdef"), "abcdef%67");
- ensure_equals("escaping", LLURI::escape("|/&\\+-_!@", ""), "%7C%2F%26%5C%2B%2D%5F%21%40");
- ensure_equals("escaping as query variable",
- LLURI::escape("http://10.0.1.4:12032/agent/god/agent-id/map/layer/?resume=http://station3.ll.com:12032/agent/203ad6df-b522-491d-ba48-4e24eb57aeff/send-postcard", unreserved + ":@!$'()*+,="),
- "http:%2F%2F10.0.1.4:12032%2Fagent%2Fgod%2Fagent-id%2Fmap%2Flayer%2F%3Fresume=http:%2F%2Fstation3.ll.com:12032%2Fagent%2F203ad6df-b522-491d-ba48-4e24eb57aeff%2Fsend-postcard");
- // French cedilla (C with squiggle, like in the word Francais) is UTF-8 C3 A7
+ struct URITestData {
+ void checkParts(const LLURI& u,
+ const char* expectedScheme,
+ const char* expectedOpaque,
+ const char* expectedAuthority,
+ const char* expectedPath,
+ const char* expectedQuery = "")
+ {
+ ensure_equals("scheme", u.scheme(), expectedScheme);
+ ensure_equals("opaque", u.opaque(), expectedOpaque);
+ ensure_equals("authority", u.authority(), expectedAuthority);
+ ensure_equals("path", u.path(), expectedPath);
+ ensure_equals("query", u.query(), expectedQuery);
+ }
+
+ void escapeRoundTrip(const std::string& uri_raw_1)
+ {
+ std::string uri_esc_1(LLURI::escape(uri_raw_1));
+ std::string uri_raw_2(LLURI::unescape(uri_esc_1));
+ ensure_equals("escape/unescape raw", uri_raw_2, uri_raw_1);
+ std::string uri_esc_2(LLURI::escape(uri_raw_2));
+ ensure_equals("escape/unescape escaped", uri_esc_2, uri_esc_1);
+ }
+ };
+
+ typedef test_group<URITestData> URITestGroup;
+ typedef URITestGroup::object URITestObject;
+
+ URITestGroup uriTestGroup("LLURI");
+
+ template<> template<>
+ void URITestObject::test<1>()
+ {
+ LLURI u("http://abc.com/def/ghi?x=37&y=hello");
+
+ ensure_equals("scheme", u.scheme(), "http");
+ ensure_equals("authority", u.authority(), "abc.com");
+ ensure_equals("path", u.path(), "/def/ghi");
+ ensure_equals("query", u.query(), "x=37&y=hello");
+
+ ensure_equals("host name", u.hostName(), "abc.com");
+ ensure_equals("host port", u.hostPort(), 80);
+
+ LLSD query = u.queryMap();
+ ensure_equals("query x", query["x"].asInteger(), 37);
+ ensure_equals("query y", query["y"].asString(), "hello");
+
+ query = LLURI::queryMap("x=22.23&y=https://lindenlab.com/");
+ ensure_equals("query x", query["x"].asReal(), 22.23);
+ ensure_equals("query y", query["y"].asURI().asString(), "https://lindenlab.com/");
+ }
+
+ template<> template<>
+ void URITestObject::test<2>()
+ {
+ set_test_name("empty string");
+ checkParts(LLURI(""), "", "", "", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<3>()
+ {
+ set_test_name("no scheme");
+ checkParts(LLURI("foo"), "", "foo", "", "");
+ checkParts(LLURI("foo%3A"), "", "foo:", "", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<4>()
+ {
+ set_test_name("scheme w/o paths");
+ checkParts(LLURI("mailto:zero@ll.com"),
+ "mailto", "zero@ll.com", "", "");
+ checkParts(LLURI("silly://abc/def?foo"),
+ "silly", "//abc/def?foo", "", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<5>()
+ {
+ set_test_name("authority section");
+ checkParts(LLURI("http:///"),
+ "http", "///", "", "/");
+
+ checkParts(LLURI("http://abc"),
+ "http", "//abc", "abc", "");
+
+ checkParts(LLURI("http://a%2Fb/cd"),
+ "http", "//a/b/cd", "a/b", "/cd");
+
+ checkParts(LLURI("http://host?"),
+ "http", "//host?", "host", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<6>()
+ {
+ set_test_name("path section");
+ checkParts(LLURI("http://host/a/b/"),
+ "http", "//host/a/b/", "host", "/a/b/");
+
+ checkParts(LLURI("http://host/a%3Fb/"),
+ "http", "//host/a?b/", "host", "/a?b/");
+
+ checkParts(LLURI("http://host/a:b/"),
+ "http", "//host/a:b/", "host", "/a:b/");
+ }
+
+ template<> template<>
+ void URITestObject::test<7>()
+ {
+ set_test_name("query string");
+ checkParts(LLURI("http://host/?"),
+ "http", "//host/?", "host", "/", "");
+
+ checkParts(LLURI("http://host/?x"),
+ "http", "//host/?x", "host", "/", "x");
+
+ checkParts(LLURI("http://host/??"),
+ "http", "//host/??", "host", "/", "?");
+
+ checkParts(LLURI("http://host/?%3F"),
+ "http", "//host/??", "host", "/", "?");
+ }
+
+ template<> template<>
+ void URITestObject::test<8>()
+ {
+ LLSD path;
+ path.append("x");
+ path.append("123");
+ checkParts(LLURI::buildHTTP("host", path),
+ "http", "//host/x/123", "host", "/x/123");
+
+ LLSD query;
+ query["123"] = "12";
+ query["abcd"] = "abc";
+ checkParts(LLURI::buildHTTP("host", path, query),
+ "http", "//host/x/123?123=12&abcd=abc",
+ "host", "/x/123", "123=12&abcd=abc");
+
+ ensure_equals(LLURI::buildHTTP("host", "").asString(),
+ "http://host");
+ ensure_equals(LLURI::buildHTTP("host", "/").asString(),
+ "http://host/");
+ ensure_equals(LLURI::buildHTTP("host", "//").asString(),
+ "http://host/");
+ ensure_equals(LLURI::buildHTTP("host", "dir name").asString(),
+ "http://host/dir%20name");
+ ensure_equals(LLURI::buildHTTP("host", "dir name/").asString(),
+ "http://host/dir%20name/");
+ ensure_equals(LLURI::buildHTTP("host", "/dir name").asString(),
+ "http://host/dir%20name");
+ ensure_equals(LLURI::buildHTTP("host", "/dir name/").asString(),
+ "http://host/dir%20name/");
+ ensure_equals(LLURI::buildHTTP("host", "dir name/subdir name").asString(),
+ "http://host/dir%20name/subdir%20name");
+ ensure_equals(LLURI::buildHTTP("host", "dir name/subdir name/").asString(),
+ "http://host/dir%20name/subdir%20name/");
+ ensure_equals(LLURI::buildHTTP("host", "/dir name/subdir name").asString(),
+ "http://host/dir%20name/subdir%20name");
+ ensure_equals(LLURI::buildHTTP("host", "/dir name/subdir name/").asString(),
+ "http://host/dir%20name/subdir%20name/");
+ ensure_equals(LLURI::buildHTTP("host", "//dir name//subdir name//").asString(),
+ "http://host/dir%20name/subdir%20name/");
+ }
+
+ template<> template<>
+ void URITestObject::test<9>()
+ {
+ set_test_name("test unescaped path components");
+ LLSD path;
+ path.append("x@*//*$&^");
+ path.append("123");
+ checkParts(LLURI::buildHTTP("host", path),
+ "http", "//host/x@*//*$&^/123", "host", "/x@*//*$&^/123");
+ }
+
+ template<> template<>
+ void URITestObject::test<10>()
+ {
+ set_test_name("test unescaped query components");
+ LLSD path;
+ path.append("x");
+ path.append("123");
+ LLSD query;
+ query["123"] = "?&*#//";
+ query["**@&?//"] = "abc";
+ checkParts(LLURI::buildHTTP("host", path, query),
+ "http", "//host/x/123?**@&?//=abc&123=?&*#//",
+ "host", "/x/123", "**@&?//=abc&123=?&*#//");
+ }
+
+ template<> template<>
+ void URITestObject::test<11>()
+ {
+ set_test_name("test unescaped host components");
+ LLSD path;
+ path.append("x");
+ path.append("123");
+ LLSD query;
+ query["123"] = "12";
+ query["abcd"] = "abc";
+ checkParts(LLURI::buildHTTP("hi123*33--}{:portstuffs", path, query),
+ "http", "//hi123*33--}{:portstuffs/x/123?123=12&abcd=abc",
+ "hi123*33--}{:portstuffs", "/x/123", "123=12&abcd=abc");
+ }
+
+ template<> template<>
+ void URITestObject::test<12>()
+ {
+ set_test_name("test funky host_port values that are actually prefixes");
+
+ checkParts(LLURI::buildHTTP("http://example.com:8080", LLSD()),
+ "http", "//example.com:8080",
+ "example.com:8080", "");
+
+ checkParts(LLURI::buildHTTP("http://example.com:8080/", LLSD()),
+ "http", "//example.com:8080/",
+ "example.com:8080", "/");
+
+ checkParts(LLURI::buildHTTP("http://example.com:8080/a/b", LLSD()),
+ "http", "//example.com:8080/a/b",
+ "example.com:8080", "/a/b");
+ }
+
+ template<> template<>
+ void URITestObject::test<13>()
+ {
+ const std::string unreserved =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._~";
+ set_test_name("test escape");
+ ensure_equals("escaping", LLURI::escape("abcdefg", "abcdef"), "abcdef%67");
+ ensure_equals("escaping", LLURI::escape("|/&\\+-_!@", ""), "%7C%2F%26%5C%2B%2D%5F%21%40");
+ ensure_equals("escaping as query variable",
+ LLURI::escape("http://10.0.1.4:12032/agent/god/agent-id/map/layer/?resume=http://station3.ll.com:12032/agent/203ad6df-b522-491d-ba48-4e24eb57aeff/send-postcard", unreserved + ":@!$'()*+,="),
+ "http:%2F%2F10.0.1.4:12032%2Fagent%2Fgod%2Fagent-id%2Fmap%2Flayer%2F%3Fresume=http:%2F%2Fstation3.ll.com:12032%2Fagent%2F203ad6df-b522-491d-ba48-4e24eb57aeff%2Fsend-postcard");
+ // French cedilla (C with squiggle, like in the word Francais) is UTF-8 C3 A7
#if LL_WINDOWS
#pragma warning(disable: 4309)
#endif
- std::string cedilla;
- cedilla.push_back( (char)0xC3 );
- cedilla.push_back( (char)0xA7 );
- ensure_equals("escape UTF8", LLURI::escape( cedilla, unreserved), "%C3%A7");
- }
-
-
- template<> template<>
- void URITestObject::test<14>()
- {
- set_test_name("make sure escape and unescape of empty strings return empty strings.");
- std::string uri_esc(LLURI::escape(""));
- ensure("escape string empty", uri_esc.empty());
- std::string uri_raw(LLURI::unescape(""));
- ensure("unescape string empty", uri_raw.empty());
- }
-
- template<> template<>
- void URITestObject::test<15>()
- {
- set_test_name("do some round-trip tests");
- escapeRoundTrip("http://secondlife.com");
- escapeRoundTrip("http://secondlife.com/url with spaces");
- escapeRoundTrip("http://bad[domain]name.com/");
- escapeRoundTrip("ftp://bill.gates@ms/micro$oft.com/c:\\autoexec.bat");
- escapeRoundTrip("");
- }
-
- template<> template<>
- void URITestObject::test<16>()
- {
- set_test_name("Test the default escaping");
- // yes -- this mangles the url. This is expected behavior
- std::string simple("http://secondlife.com");
- ensure_equals(
- "simple http",
- LLURI::escape(simple),
- "http%3A%2F%2Fsecondlife.com");
- ensure_equals(
- "needs escape",
- LLURI::escape("http://get.secondlife.com/windows viewer"),
- "http%3A%2F%2Fget.secondlife.com%2Fwindows%20viewer");
- }
-
- template<> template<>
- void URITestObject::test<17>()
- {
- set_test_name("do some round-trip tests with very long strings.");
- escapeRoundTrip("Welcome to Second Life.We hope you'll have a richly rewarding experience, filled with creativity, self expression and fun.The goals of the Community Standards are simple: treat each other with respect and without harassment, adhere to local standards as indicated by simulator ratings, and refrain from any hate activity which slurs a real-world individual or real-world community. Behavioral Guidelines - The Big Six");
- escapeRoundTrip(
- "'asset_data':b(12100){'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale"
- "\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tf"
- "aces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204"
- "\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffff"
- "ff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t"
- "0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t"
- "\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t"
- "\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreat"
- "or_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundra"
- "dius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0"
- "\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f"
- "25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000"
- "000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1"
- ".57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemI"
- "D STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n");
- }
-
-
- template<> template<>
- void URITestObject::test<18>()
- {
- LLURI u("secondlife:///app/login?first_name=Testert4&last_name=Tester&web_login_key=test");
- // if secondlife is the scheme, LLURI should parse /app/login as path, with no authority
- ensure_equals("scheme", u.scheme(), "secondlife");
- ensure_equals("authority", u.authority(), "");
- ensure_equals("path", u.path(), "/app/login");
- ensure_equals("pathmap", u.pathArray()[0].asString(), "app");
- ensure_equals("pathmap", u.pathArray()[1].asString(), "login");
- ensure_equals("query", u.query(), "first_name=Testert4&last_name=Tester&web_login_key=test");
- ensure_equals("query map element", u.queryMap()["last_name"].asString(), "Tester");
-
- u = LLURI("secondlife://Da Boom/128/128/128");
- // if secondlife is the scheme, LLURI should parse /128/128/128 as path, with Da Boom as authority
- ensure_equals("scheme", u.scheme(), "secondlife");
- ensure_equals("authority", u.authority(), "Da Boom");
- ensure_equals("path", u.path(), "/128/128/128");
- ensure_equals("pathmap", u.pathArray()[0].asString(), "128");
- ensure_equals("pathmap", u.pathArray()[1].asString(), "128");
- ensure_equals("pathmap", u.pathArray()[2].asString(), "128");
- ensure_equals("query", u.query(), "");
- }
-
- template<> template<>
- void URITestObject::test<19>()
- {
- set_test_name("Parse about: schemes");
- LLURI u("about:blank?redirect-http-hack=secondlife%3A%2F%2F%2Fapp%2Flogin%3Ffirst_name%3DCallum%26last_name%3DLinden%26location%3Dspecify%26grid%3Dvaak%26region%3D%2FMorris%2F128%2F128%26web_login_key%3Defaa4795-c2aa-4c58-8966-763c27931e78");
- ensure_equals("scheme", u.scheme(), "about");
- ensure_equals("authority", u.authority(), "");
- ensure_equals("path", u.path(), "blank");
- ensure_equals("pathmap", u.pathArray()[0].asString(), "blank");
- ensure_equals("query", u.query(), "redirect-http-hack=secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
- ensure_equals("query map element", u.queryMap()["redirect-http-hack"].asString(), "secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
- }
-
- template<> template<>
- void URITestObject::test<20>()
- {
+ std::string cedilla;
+ cedilla.push_back( (char)0xC3 );
+ cedilla.push_back( (char)0xA7 );
+ ensure_equals("escape UTF8", LLURI::escape( cedilla, unreserved), "%C3%A7");
+ }
+
+
+ template<> template<>
+ void URITestObject::test<14>()
+ {
+ set_test_name("make sure escape and unescape of empty strings return empty strings.");
+ std::string uri_esc(LLURI::escape(""));
+ ensure("escape string empty", uri_esc.empty());
+ std::string uri_raw(LLURI::unescape(""));
+ ensure("unescape string empty", uri_raw.empty());
+ }
+
+ template<> template<>
+ void URITestObject::test<15>()
+ {
+ set_test_name("do some round-trip tests");
+ escapeRoundTrip("http://secondlife.com");
+ escapeRoundTrip("http://secondlife.com/url with spaces");
+ escapeRoundTrip("http://bad[domain]name.com/");
+ escapeRoundTrip("ftp://bill.gates@ms/micro$oft.com/c:\\autoexec.bat");
+ escapeRoundTrip("");
+ }
+
+ template<> template<>
+ void URITestObject::test<16>()
+ {
+ set_test_name("Test the default escaping");
+ // yes -- this mangles the url. This is expected behavior
+ std::string simple("http://secondlife.com");
+ ensure_equals(
+ "simple http",
+ LLURI::escape(simple),
+ "http%3A%2F%2Fsecondlife.com");
+ ensure_equals(
+ "needs escape",
+ LLURI::escape("http://get.secondlife.com/windows viewer"),
+ "http%3A%2F%2Fget.secondlife.com%2Fwindows%20viewer");
+ }
+
+ template<> template<>
+ void URITestObject::test<17>()
+ {
+ set_test_name("do some round-trip tests with very long strings.");
+ escapeRoundTrip("Welcome to Second Life.We hope you'll have a richly rewarding experience, filled with creativity, self expression and fun.The goals of the Community Standards are simple: treat each other with respect and without harassment, adhere to local standards as indicated by simulator ratings, and refrain from any hate activity which slurs a real-world individual or real-world community. Behavioral Guidelines - The Big Six");
+ escapeRoundTrip(
+ "'asset_data':b(12100){'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale"
+ "\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tf"
+ "aces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204"
+ "\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffff"
+ "ff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t"
+ "0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t"
+ "\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t"
+ "\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreat"
+ "or_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundra"
+ "dius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0"
+ "\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f"
+ "25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000"
+ "000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1"
+ ".57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemI"
+ "D STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n");
+ }
+
+
+ template<> template<>
+ void URITestObject::test<18>()
+ {
+ LLURI u("secondlife:///app/login?first_name=Testert4&last_name=Tester&web_login_key=test");
+ // if secondlife is the scheme, LLURI should parse /app/login as path, with no authority
+ ensure_equals("scheme", u.scheme(), "secondlife");
+ ensure_equals("authority", u.authority(), "");
+ ensure_equals("path", u.path(), "/app/login");
+ ensure_equals("pathmap", u.pathArray()[0].asString(), "app");
+ ensure_equals("pathmap", u.pathArray()[1].asString(), "login");
+ ensure_equals("query", u.query(), "first_name=Testert4&last_name=Tester&web_login_key=test");
+ ensure_equals("query map element", u.queryMap()["last_name"].asString(), "Tester");
+
+ u = LLURI("secondlife://Da Boom/128/128/128");
+ // if secondlife is the scheme, LLURI should parse /128/128/128 as path, with Da Boom as authority
+ ensure_equals("scheme", u.scheme(), "secondlife");
+ ensure_equals("authority", u.authority(), "Da Boom");
+ ensure_equals("path", u.path(), "/128/128/128");
+ ensure_equals("pathmap", u.pathArray()[0].asString(), "128");
+ ensure_equals("pathmap", u.pathArray()[1].asString(), "128");
+ ensure_equals("pathmap", u.pathArray()[2].asString(), "128");
+ ensure_equals("query", u.query(), "");
+ }
+
+ template<> template<>
+ void URITestObject::test<19>()
+ {
+ set_test_name("Parse about: schemes");
+ LLURI u("about:blank?redirect-http-hack=secondlife%3A%2F%2F%2Fapp%2Flogin%3Ffirst_name%3DCallum%26last_name%3DLinden%26location%3Dspecify%26grid%3Dvaak%26region%3D%2FMorris%2F128%2F128%26web_login_key%3Defaa4795-c2aa-4c58-8966-763c27931e78");
+ ensure_equals("scheme", u.scheme(), "about");
+ ensure_equals("authority", u.authority(), "");
+ ensure_equals("path", u.path(), "blank");
+ ensure_equals("pathmap", u.pathArray()[0].asString(), "blank");
+ ensure_equals("query", u.query(), "redirect-http-hack=secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
+ ensure_equals("query map element", u.queryMap()["redirect-http-hack"].asString(), "secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
+ }
+
+ template<> template<>
+ void URITestObject::test<20>()
+ {
set_test_name("escapePathAndData uri test");
// Basics scheme:[//authority]path[?query][#fragment]
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index 2a4ed44a67..a3ce7f8e3d 100644
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2008-09-12
* @brief Test of stringize.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$
*/
@@ -78,7 +78,7 @@ namespace tut
float f;
double d;
std::string abc;
- std::wstring def;
+ std::wstring def;
LLSD llsd;
};
typedef test_group<stringize_data> stringize_group;
diff --git a/indra/llcommon/tests/threadsafeschedule_test.cpp b/indra/llcommon/tests/threadsafeschedule_test.cpp
index 8851590189..f2f17dd2e6 100644
--- a/indra/llcommon/tests/threadsafeschedule_test.cpp
+++ b/indra/llcommon/tests/threadsafeschedule_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-04
* @brief Test for threadsafeschedule.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/tuple_test.cpp b/indra/llcommon/tests/tuple_test.cpp
index af94e2086c..aff129753f 100644
--- a/indra/llcommon/tests/tuple_test.cpp
+++ b/indra/llcommon/tests/tuple_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-04
* @brief Test for tuple.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp
index df16f4a46e..209b6b868c 100644
--- a/indra/llcommon/tests/workqueue_test.cpp
+++ b/indra/llcommon/tests/workqueue_test.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-07
* @brief Test for workqueue.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 6978c296b3..9cd2c69b11 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -3,25 +3,25 @@
* @author Nat Goodspeed
* @date 2009-03-11
* @brief Define a class useful for unit tests that engage llerrs (LL_ERRS) functionality
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -117,9 +117,9 @@ class CaptureLogRecorder : public LLError::Recorder, public boost::noncopyable
{
public:
CaptureLogRecorder()
- : LLError::Recorder(),
- boost::noncopyable(),
- mMessages()
+ : LLError::Recorder(),
+ boost::noncopyable(),
+ mMessages()
{
}
diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp
index c48989358e..302bbe6f8d 100644
--- a/indra/llcommon/threadpool.cpp
+++ b/indra/llcommon/threadpool.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-21
* @brief Implementation for threadpool.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index 74056aea17..0eb1891754 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -4,7 +4,7 @@
* @date 2021-10-21
* @brief ThreadPool configures a WorkQueue along with a pool of threads to
* service it.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/threadpool_fwd.h b/indra/llcommon/threadpool_fwd.h
index 1aa3c4a0e2..50e212ef05 100644
--- a/indra/llcommon/threadpool_fwd.h
+++ b/indra/llcommon/threadpool_fwd.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2022-12-09
* @brief Forward declarations for ThreadPool et al.
- *
+ *
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Copyright (c) 2022, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h
index 92bc7da940..0c7f583819 100644
--- a/indra/llcommon/threadsafeschedule.h
+++ b/indra/llcommon/threadsafeschedule.h
@@ -4,7 +4,7 @@
* @date 2021-10-02
* @brief ThreadSafeSchedule is an ordered queue in which every item has an
* associated timestamp.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
@@ -18,7 +18,7 @@
#include "llthreadsafequeue.h"
#include "tuple.h"
#include <chrono>
-#include <tuple>
+#include <tuple>
namespace LL
{
diff --git a/indra/llcommon/timer.h b/indra/llcommon/timer.h
index 82d19c2d32..aaa0cf0775 100644
--- a/indra/llcommon/timer.h
+++ b/indra/llcommon/timer.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file timer.h
* @brief Legacy wrapper header.
*
* $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$
*/
diff --git a/indra/llcommon/tuple.h b/indra/llcommon/tuple.h
index bfe7e3c2ba..21337650ef 100644
--- a/indra/llcommon/tuple.h
+++ b/indra/llcommon/tuple.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-04
* @brief A couple tuple utilities
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/u64.cpp b/indra/llcommon/u64.cpp
index 02c2c15d26..1d39d3c3e5 100644
--- a/indra/llcommon/u64.cpp
+++ b/indra/llcommon/u64.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file u64.cpp
* @brief Utilities to deal with U64s.
*
* $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$
*/
@@ -31,75 +31,75 @@
U64 str_to_U64(const std::string& str)
{
- U64 result = 0;
- const char *aptr = strpbrk(str.c_str(),"0123456789");
+ U64 result = 0;
+ const char *aptr = strpbrk(str.c_str(),"0123456789");
- if (!aptr)
- {
- LL_WARNS() << "str_to_U64: Bad string to U64 conversion attempt: format\n" << LL_ENDL;
- }
- else
- {
- while ((*aptr >= '0') && (*aptr <= '9'))
- {
- result = result*10 + (*aptr++ - '0');
- }
- }
- return (result);
+ if (!aptr)
+ {
+ LL_WARNS() << "str_to_U64: Bad string to U64 conversion attempt: format\n" << LL_ENDL;
+ }
+ else
+ {
+ while ((*aptr >= '0') && (*aptr <= '9'))
+ {
+ result = result*10 + (*aptr++ - '0');
+ }
+ }
+ return (result);
}
-std::string U64_to_str(U64 value)
+std::string U64_to_str(U64 value)
{
- std::string res;
- U32 part1,part2,part3;
-
- part3 = (U32)(value % (U64)10000000);
-
- value /= 10000000;
- part2 = (U32)(value % (U64)10000000);
-
- value /= 10000000;
- part1 = (U32)(value % (U64)10000000);
-
- // three cases to avoid leading zeroes unless necessary
-
- if (part1)
- {
- res = llformat("%u%07u%07u",part1,part2,part3);
- }
- else if (part2)
- {
- res = llformat("%u%07u",part2,part3);
- }
- else
- {
- res = llformat("%u",part3);
- }
- return res;
-}
+ std::string res;
+ U32 part1,part2,part3;
+
+ part3 = (U32)(value % (U64)10000000);
+
+ value /= 10000000;
+ part2 = (U32)(value % (U64)10000000);
+
+ value /= 10000000;
+ part1 = (U32)(value % (U64)10000000);
+
+ // three cases to avoid leading zeroes unless necessary
+
+ if (part1)
+ {
+ res = llformat("%u%07u%07u",part1,part2,part3);
+ }
+ else if (part2)
+ {
+ res = llformat("%u%07u",part2,part3);
+ }
+ else
+ {
+ res = llformat("%u",part3);
+ }
+ return res;
+}
-char* U64_to_str(U64 value, char* result, S32 result_size)
+char* U64_to_str(U64 value, char* result, S32 result_size)
{
- std::string res = U64_to_str(value);
- LLStringUtil::copy(result, res.c_str(), result_size);
- return result;
+ std::string res = U64_to_str(value);
+ LLStringUtil::copy(result, res.c_str(), result_size);
+ return result;
}
F64 U64_to_F64(const U64 value)
{
- S64 top_bits = (S64)(value >> 1);
- F64 result = (F64)top_bits;
- result *= 2.f;
- result += (U32)(value & 0x01);
- return result;
+ S64 top_bits = (S64)(value >> 1);
+ F64 result = (F64)top_bits;
+ result *= 2.f;
+ result += (U32)(value & 0x01);
+ return result;
}
-U64 llstrtou64(const char* str, char** end, S32 base)
+U64 llstrtou64(const char* str, char** end, S32 base)
{
#ifdef LL_WINDOWS
- return _strtoui64(str,end,base);
+ return _strtoui64(str,end,base);
#else
- return strtoull(str,end,base);
+ return strtoull(str,end,base);
#endif
}
diff --git a/indra/llcommon/u64.h b/indra/llcommon/u64.h
index 75c8a59136..d70477feb0 100644
--- a/indra/llcommon/u64.h
+++ b/indra/llcommon/u64.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file u64.h
* @brief Utilities to deal with U64s.
*
* $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$
*/
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index cf80ce0656..6066e74fb5 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-10-06
* @brief Implementation for WorkQueue.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index ec0700a718..9d7bbfbf7a 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -3,7 +3,7 @@
* @author Nat Goodspeed
* @date 2021-09-30
* @brief Queue used for inter-thread work passing.
- *
+ *
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$