summaryrefslogtreecommitdiff
path: root/indra/llcommon/llsd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llsd.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llcommon/llsd.cpp270
1 files changed, 206 insertions, 64 deletions
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index c863d4e266..57aa7d9c07 100644..100755
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -2,34 +2,31 @@
* @file llsd.cpp
* @brief LLSD flexible data system
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
+// Must turn on conditional declarations in header file so definitions end up
+// with proper linkage.
+#define LLSD_DEBUG_INFO
#include "linden_common.h"
#include "llsd.h"
@@ -37,6 +34,7 @@
#include "../llmath/llmath.h"
#include "llformat.h"
#include "llsdserialize.h"
+#include "stringize.h"
#ifndef LL_RELEASE_FOR_DOWNLOAD
#define NAME_UNNAMED_NAMESPACE
@@ -56,6 +54,18 @@ namespace
using namespace LLSDUnnamedNamespace;
#endif
+namespace llsd
+{
+
+// statics
+S32 sLLSDAllocationCount = 0;
+S32 sLLSDNetObjects = 0;
+
+} // namespace llsd
+
+#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
@@ -64,13 +74,10 @@ class LLSD::Impl
*/
{
-private:
- U32 mUseCount;
-
protected:
Impl();
- enum StaticAllocationMarker { STATIC };
+ 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
@@ -78,8 +85,10 @@ protected:
virtual ~Impl();
- bool shared() const { return mUseCount > 1; }
+ 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)
@@ -117,7 +126,9 @@ public:
virtual UUID asUUID() const { return LLUUID(); }
virtual Date asDate() const { return LLDate(); }
virtual URI asURI() const { return LLURI(); }
- virtual Binary asBinary() const { return std::vector<U8>(); }
+ 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(); }
@@ -134,6 +145,18 @@ public:
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;
@@ -248,6 +271,8 @@ namespace
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 int size() const { return mValue.size(); }
+ virtual const LLSD::String& asStringRef() const { return mValue; }
};
LLSD::Integer ImplString::asInteger() const
@@ -326,7 +351,7 @@ namespace
public:
ImplBinary(const LLSD::Binary& v) : Base(v) { }
- virtual LLSD::Binary asBinary() const{ return mValue; }
+ virtual const LLSD::Binary& asBinary() const{ return mValue; }
};
@@ -366,6 +391,9 @@ namespace
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)
@@ -420,6 +448,34 @@ namespace
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:
@@ -453,8 +509,12 @@ namespace
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)
@@ -496,12 +556,13 @@ namespace
void ImplArray::insert(LLSD::Integer i, const LLSD& v)
{
- if (i < 0) {
+ if (i < 0)
+ {
return;
}
DataVector::size_type index = i;
- if (index >= mData.size())
+ if (index >= mData.size()) // tbd - sanity check limit for index ?
{
mData.resize(index + 1);
}
@@ -549,6 +610,19 @@ namespace
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()
@@ -570,8 +644,11 @@ LLSD::Impl::~Impl()
void LLSD::Impl::reset(Impl*& var, Impl* impl)
{
- if (impl) ++impl->mUseCount;
- if (var && --var->mUseCount == 0)
+ if (impl && impl->mUseCount != STATIC_USAGE_COUNT)
+ {
+ ++impl->mUseCount;
+ }
+ if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0)
{
delete var;
}
@@ -580,13 +657,13 @@ void LLSD::Impl::reset(Impl*& var, Impl* impl)
LLSD::Impl& LLSD::Impl::safe(Impl* impl)
{
- static Impl theUndefined(STATIC);
+ static Impl theUndefined(STATIC_USAGE_COUNT);
return impl ? *impl : theUndefined;
}
const LLSD::Impl& LLSD::Impl::safe(const Impl* impl)
{
- static Impl theUndefined(STATIC);
+ static Impl theUndefined(STATIC_USAGE_COUNT);
return impl ? *impl : theUndefined;
}
@@ -662,6 +739,43 @@ const LLSD& LLSD::Impl::undef()
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++;
+ }
+}
+
+
+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]++;
+ }
+ }
+}
+
+
U32 LLSD::Impl::sAllocationCount = 0;
U32 LLSD::Impl::sOutstandingCount = 0;
@@ -675,10 +789,7 @@ namespace
{
inline LLSD::Impl& safe(LLSD::Impl* impl)
{ return LLSD::Impl::safe(impl); }
-
- inline const LLSD::Impl& safe(const LLSD::Impl* impl)
- { return LLSD::Impl::safe(impl); }
-
+
inline ImplMap& makeMap(LLSD::Impl*& var)
{ return safe(var).makeMap(var); }
@@ -687,10 +798,10 @@ namespace
}
-LLSD::LLSD() : impl(0) { }
-LLSD::~LLSD() { 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) { assign(other); }
+LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); }
void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); }
@@ -698,18 +809,18 @@ void LLSD::clear() { Impl::assignUndefined(impl); }
LLSD::Type LLSD::type() const { return safe(impl).type(); }
-// Scaler Constructors
-LLSD::LLSD(Boolean v) : impl(0) { assign(v); }
-LLSD::LLSD(Integer v) : impl(0) { assign(v); }
-LLSD::LLSD(Real v) : impl(0) { assign(v); }
-LLSD::LLSD(const UUID& v) : impl(0) { assign(v); }
-LLSD::LLSD(const String& v) : impl(0) { assign(v); }
-LLSD::LLSD(const Date& v) : impl(0) { assign(v); }
-LLSD::LLSD(const URI& v) : impl(0) { assign(v); }
-LLSD::LLSD(const Binary& v) : impl(0) { assign(v); }
+// 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); }
// Convenience Constructors
-LLSD::LLSD(F32 v) : impl(0) { assign((Real)v); }
+LLSD::LLSD(F32 v) : impl(0) { ALLOC_LLSD_OBJECT; assign((Real)v); }
// Scalar Assignment
void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); }
@@ -729,10 +840,12 @@ 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(); }
-LLSD::Binary LLSD::asBinary() const { return safe(impl).asBinary(); }
+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) { 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));
@@ -790,9 +903,6 @@ LLSD& LLSD::operator[](Integer i)
const LLSD& LLSD::operator[](Integer i) const
{ return safe(impl).ref(i); }
-U32 LLSD::allocationCount() { return Impl::sAllocationCount; }
-U32 LLSD::outstandingCount() { return Impl::sOutstandingCount; }
-
static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat)
{
// sStorage is used to hold the string representation of the llsd last
@@ -807,15 +917,9 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat)
{
std::ostringstream out;
if (useXMLFormat)
- {
- LLSDXMLStreamer xml_streamer(llsd);
- out << xml_streamer;
- }
+ out << LLSDXMLStreamer(llsd);
else
- {
- LLSDNotationStreamer notation_streamer(llsd);
- out << notation_streamer;
- }
+ out << LLSDNotationStreamer(llsd);
out_string = out.str();
}
int len = out_string.length();
@@ -846,3 +950,41 @@ 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(); }
+
+namespace llsd
+{
+
+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(); }
+
+} // namespace llsd
+
+// static
+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);
+}