00001
00032 #include "linden_common.h"
00033 #include "llsd.h"
00034
00035 #include "llerror.h"
00036 #include "../llmath/llmath.h"
00037 #include "llformat.h"
00038
00039 namespace {
00040 class ImplMap;
00041 class ImplArray;
00042 }
00043
00044 class LLSD::Impl
00051 {
00052 private:
00053 U32 mUseCount;
00054
00055 protected:
00056 Impl();
00057
00058 enum StaticAllocationMarker { STATIC };
00059 Impl(StaticAllocationMarker);
00061
00062
00063
00064 virtual ~Impl();
00065
00066 bool shared() const { return mUseCount > 1; }
00067
00068 public:
00069 static void reset(Impl*& var, Impl* impl);
00071
00072 static Impl& safe( Impl*);
00073 static const Impl& safe(const Impl*);
00075
00076
00077 virtual ImplMap& makeMap(Impl*& var);
00078 virtual ImplArray& makeArray(Impl*& var);
00080
00081 virtual LLSD::Type type() const { return LLSD::TypeUndefined; }
00082
00083 static void assignUndefined(LLSD::Impl*& var);
00084 static void assign(LLSD::Impl*& var, const LLSD::Impl* other);
00085
00086 virtual void assign(Impl*& var, LLSD::Boolean);
00087 virtual void assign(Impl*& var, LLSD::Integer);
00088 virtual void assign(Impl*& var, LLSD::Real);
00089 virtual void assign(Impl*& var, const LLSD::String&);
00090 virtual void assign(Impl*& var, const LLSD::UUID&);
00091 virtual void assign(Impl*& var, const LLSD::Date&);
00092 virtual void assign(Impl*& var, const LLSD::URI&);
00093 virtual void assign(Impl*& var, const LLSD::Binary&);
00095
00096
00097
00098 virtual Boolean asBoolean() const { return false; }
00099 virtual Integer asInteger() const { return 0; }
00100 virtual Real asReal() const { return 0.0; }
00101 virtual String asString() const { return std::string(); }
00102 virtual UUID asUUID() const { return LLUUID(); }
00103 virtual Date asDate() const { return LLDate(); }
00104 virtual URI asURI() const { return LLURI(); }
00105 virtual Binary asBinary() const { return std::vector<U8>(); }
00106
00107 virtual bool has(const String&) const { return false; }
00108 virtual LLSD get(const String&) const { return LLSD(); }
00109 virtual void erase(const String&) { }
00110 virtual const LLSD& ref(const String&) const{ return undef(); }
00111
00112 virtual int size() const { return 0; }
00113 virtual LLSD get(Integer) const { return LLSD(); }
00114 virtual void erase(Integer) { }
00115 virtual const LLSD& ref(Integer) const { return undef(); }
00116
00117 virtual LLSD::map_const_iterator beginMap() const { return LLSD::map_const_iterator(); }
00118 virtual LLSD::map_const_iterator endMap() const { return LLSD::map_const_iterator(); }
00119 virtual LLSD::array_const_iterator beginArray() const { return LLSD::array_const_iterator(); }
00120 virtual LLSD::array_const_iterator endArray() const { return LLSD::array_const_iterator(); }
00121
00122 static const LLSD& undef();
00123
00124 static U32 sAllocationCount;
00125 static U32 sOutstandingCount;
00126 };
00127
00128 namespace {
00129 template<LLSD::Type T, class Data, class DataRef = Data>
00130 class ImplBase : public LLSD::Impl
00132
00133
00134 {
00135 protected:
00136 Data mValue;
00137
00138 typedef ImplBase Base;
00139
00140 public:
00141 ImplBase(DataRef value) : mValue(value) { }
00142
00143 virtual LLSD::Type type() const { return T; }
00144
00145 virtual void assign(LLSD::Impl*& var, DataRef value) {
00146 if (shared())
00147 {
00148 Impl::assign(var, value);
00149 }
00150 else
00151 {
00152 mValue = value;
00153 }
00154 }
00155 };
00156
00157
00158 class ImplBoolean
00159 : public ImplBase<LLSD::TypeBoolean, LLSD::Boolean>
00160 {
00161 public:
00162 ImplBoolean(LLSD::Boolean v) : Base(v) { }
00163
00164 virtual LLSD::Boolean asBoolean() const { return mValue; }
00165 virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; }
00166 virtual LLSD::Real asReal() const { return mValue ? 1 : 0; }
00167 virtual LLSD::String asString() const;
00168 };
00169
00170 LLSD::String ImplBoolean::asString() const
00171 { return mValue ? "true" : ""; }
00172
00173
00174 class ImplInteger
00175 : public ImplBase<LLSD::TypeInteger, LLSD::Integer>
00176 {
00177 public:
00178 ImplInteger(LLSD::Integer v) : Base(v) { }
00179
00180 virtual LLSD::Boolean asBoolean() const { return mValue != 0; }
00181 virtual LLSD::Integer asInteger() const { return mValue; }
00182 virtual LLSD::Real asReal() const { return mValue; }
00183 virtual LLSD::String asString() const;
00184 };
00185
00186 LLSD::String ImplInteger::asString() const
00187 { return llformat("%d", mValue); }
00188
00189
00190 class ImplReal
00191 : public ImplBase<LLSD::TypeReal, LLSD::Real>
00192 {
00193 public:
00194 ImplReal(LLSD::Real v) : Base(v) { }
00195
00196 virtual LLSD::Boolean asBoolean() const;
00197 virtual LLSD::Integer asInteger() const;
00198 virtual LLSD::Real asReal() const { return mValue; }
00199 virtual LLSD::String asString() const;
00200 };
00201
00202 LLSD::Boolean ImplReal::asBoolean() const
00203 { return !llisnan(mValue) && mValue != 0.0; }
00204
00205 LLSD::Integer ImplReal::asInteger() const
00206 { return !llisnan(mValue) ? (LLSD::Integer)mValue : 0; }
00207
00208 LLSD::String ImplReal::asString() const
00209 { return llformat("%lg", mValue); }
00210
00211
00212 class ImplString
00213 : public ImplBase<LLSD::TypeString, LLSD::String, const LLSD::String&>
00214 {
00215 public:
00216 ImplString(const LLSD::String& v) : Base(v) { }
00217
00218 virtual LLSD::Boolean asBoolean() const { return !mValue.empty(); }
00219 virtual LLSD::Integer asInteger() const;
00220 virtual LLSD::Real asReal() const;
00221 virtual LLSD::String asString() const { return mValue; }
00222 virtual LLSD::UUID asUUID() const { return LLUUID(mValue); }
00223 virtual LLSD::Date asDate() const { return LLDate(mValue); }
00224 virtual LLSD::URI asURI() const { return LLURI(mValue); }
00225 };
00226
00227 LLSD::Integer ImplString::asInteger() const
00228 {
00229
00230
00231
00232
00233
00234 return (int)asReal();
00235 }
00236
00237 LLSD::Real ImplString::asReal() const
00238 {
00239 F64 v = 0.0;
00240 std::istringstream i_stream(mValue);
00241 i_stream >> v;
00242
00243
00244
00245
00246
00247
00248
00249 int c = i_stream.get();
00250 return ((EOF ==c) ? v : 0.0);
00251 }
00252
00253
00254 class ImplUUID
00255 : public ImplBase<LLSD::TypeUUID, LLSD::UUID, const LLSD::UUID&>
00256 {
00257 public:
00258 ImplUUID(const LLSD::UUID& v) : Base(v) { }
00259
00260 virtual LLSD::String asString() const{ return mValue.asString(); }
00261 virtual LLSD::UUID asUUID() const { return mValue; }
00262 };
00263
00264
00265 class ImplDate
00266 : public ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>
00267 {
00268 public:
00269 ImplDate(const LLSD::Date& v)
00270 : ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>(v)
00271 { }
00272
00273 virtual LLSD::Integer asInteger() const
00274 {
00275 return (LLSD::Integer)(mValue.secondsSinceEpoch());
00276 }
00277 virtual LLSD::Real asReal() const
00278 {
00279 return mValue.secondsSinceEpoch();
00280 }
00281 virtual LLSD::String asString() const{ return mValue.asString(); }
00282 virtual LLSD::Date asDate() const { return mValue; }
00283 };
00284
00285
00286 class ImplURI
00287 : public ImplBase<LLSD::TypeURI, LLSD::URI, const LLSD::URI&>
00288 {
00289 public:
00290 ImplURI(const LLSD::URI& v) : Base(v) { }
00291
00292 virtual LLSD::String asString() const{ return mValue.asString(); }
00293 virtual LLSD::URI asURI() const { return mValue; }
00294 };
00295
00296
00297 class ImplBinary
00298 : public ImplBase<LLSD::TypeBinary, LLSD::Binary, const LLSD::Binary&>
00299 {
00300 public:
00301 ImplBinary(const LLSD::Binary& v) : Base(v) { }
00302
00303 virtual LLSD::Binary asBinary() const{ return mValue; }
00304 };
00305
00306
00307 class ImplMap : public LLSD::Impl
00308 {
00309 private:
00310 typedef std::map<LLSD::String, LLSD> DataMap;
00311
00312 DataMap mData;
00313
00314 protected:
00315 ImplMap(const DataMap& data) : mData(data) { }
00316
00317 public:
00318 ImplMap() { }
00319
00320 virtual ImplMap& makeMap(LLSD::Impl*&);
00321
00322 virtual LLSD::Type type() const { return LLSD::TypeMap; }
00323
00324 virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
00325
00326 virtual bool has(const LLSD::String&) const;
00327 virtual LLSD get(const LLSD::String&) const;
00328 void insert(const LLSD::String& k, const LLSD& v);
00329 virtual void erase(const LLSD::String&);
00330 LLSD& ref(const LLSD::String&);
00331 virtual const LLSD& ref(const LLSD::String&) const;
00332
00333 virtual int size() const { return mData.size(); }
00334
00335 LLSD::map_iterator beginMap() { return mData.begin(); }
00336 LLSD::map_iterator endMap() { return mData.end(); }
00337 virtual LLSD::map_const_iterator beginMap() const { return mData.begin(); }
00338 virtual LLSD::map_const_iterator endMap() const { return mData.end(); }
00339 };
00340
00341 ImplMap& ImplMap::makeMap(LLSD::Impl*& var)
00342 {
00343 if (shared())
00344 {
00345 ImplMap* i = new ImplMap(mData);
00346 Impl::assign(var, i);
00347 return *i;
00348 }
00349 else
00350 {
00351 return *this;
00352 }
00353 }
00354
00355 bool ImplMap::has(const LLSD::String& k) const
00356 {
00357 DataMap::const_iterator i = mData.find(k);
00358 return i != mData.end();
00359 }
00360
00361 LLSD ImplMap::get(const LLSD::String& k) const
00362 {
00363 DataMap::const_iterator i = mData.find(k);
00364 return (i != mData.end()) ? i->second : LLSD();
00365 }
00366
00367 void ImplMap::insert(const LLSD::String& k, const LLSD& v)
00368 {
00369 mData.insert(DataMap::value_type(k, v));
00370 }
00371
00372 void ImplMap::erase(const LLSD::String& k)
00373 {
00374 mData.erase(k);
00375 }
00376
00377 LLSD& ImplMap::ref(const LLSD::String& k)
00378 {
00379 return mData[k];
00380 }
00381
00382 const LLSD& ImplMap::ref(const LLSD::String& k) const
00383 {
00384 DataMap::const_iterator i = mData.lower_bound(k);
00385 if (i == mData.end() || mData.key_comp()(k, i->first))
00386 {
00387 return undef();
00388 }
00389
00390 return i->second;
00391 }
00392
00393 class ImplArray : public LLSD::Impl
00394 {
00395 private:
00396 typedef std::vector<LLSD> DataVector;
00397
00398 DataVector mData;
00399
00400 protected:
00401 ImplArray(const DataVector& data) : mData(data) { }
00402
00403 public:
00404 ImplArray() { }
00405
00406 virtual ImplArray& makeArray(Impl*&);
00407
00408 virtual LLSD::Type type() const { return LLSD::TypeArray; }
00409
00410 virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
00411
00412 virtual int size() const;
00413 virtual LLSD get(LLSD::Integer) const;
00414 void set(LLSD::Integer, const LLSD&);
00415 void insert(LLSD::Integer, const LLSD&);
00416 void append(const LLSD&);
00417 virtual void erase(LLSD::Integer);
00418 LLSD& ref(LLSD::Integer);
00419 virtual const LLSD& ref(LLSD::Integer) const;
00420
00421 LLSD::array_iterator beginArray() { return mData.begin(); }
00422 LLSD::array_iterator endArray() { return mData.end(); }
00423 virtual LLSD::array_const_iterator beginArray() const { return mData.begin(); }
00424 virtual LLSD::array_const_iterator endArray() const { return mData.end(); }
00425 };
00426
00427 ImplArray& ImplArray::makeArray(Impl*& var)
00428 {
00429 if (shared())
00430 {
00431 ImplArray* i = new ImplArray(mData);
00432 Impl::assign(var, i);
00433 return *i;
00434 }
00435 else
00436 {
00437 return *this;
00438 }
00439 }
00440
00441 int ImplArray::size() const { return mData.size(); }
00442
00443 LLSD ImplArray::get(LLSD::Integer i) const
00444 {
00445 if (i < 0) { return LLSD(); }
00446 DataVector::size_type index = i;
00447
00448 return (index < mData.size()) ? mData[index] : LLSD();
00449 }
00450
00451 void ImplArray::set(LLSD::Integer i, const LLSD& v)
00452 {
00453 if (i < 0) { return; }
00454 DataVector::size_type index = i;
00455
00456 if (index >= mData.size())
00457 {
00458 mData.resize(index + 1);
00459 }
00460
00461 mData[index] = v;
00462 }
00463
00464 void ImplArray::insert(LLSD::Integer i, const LLSD& v)
00465 {
00466 if (i < 0) { return; }
00467 DataVector::size_type index = i;
00468
00469 if (index >= mData.size())
00470 {
00471 mData.resize(index + 1);
00472 }
00473
00474 mData.insert(mData.begin() + index, v);
00475 }
00476
00477 void ImplArray::append(const LLSD& v)
00478 {
00479 mData.push_back(v);
00480 }
00481
00482 void ImplArray::erase(LLSD::Integer i)
00483 {
00484 if (i < 0) { return; }
00485 DataVector::size_type index = i;
00486
00487 if (index < mData.size())
00488 {
00489 mData.erase(mData.begin() + index);
00490 }
00491 }
00492
00493 LLSD& ImplArray::ref(LLSD::Integer i)
00494 {
00495 DataVector::size_type index = i >= 0 ? i : 0;
00496
00497 if (index >= mData.size())
00498 {
00499 mData.resize(i + 1);
00500 }
00501
00502 return mData[index];
00503 }
00504
00505 const LLSD& ImplArray::ref(LLSD::Integer i) const
00506 {
00507 if (i < 0) { return undef(); }
00508 DataVector::size_type index = i;
00509
00510 if (index >= mData.size())
00511 {
00512 return undef();
00513 }
00514
00515 return mData[index];
00516 }
00517 }
00518
00519 LLSD::Impl::Impl()
00520 : mUseCount(0)
00521 {
00522 ++sAllocationCount;
00523 ++sOutstandingCount;
00524 }
00525
00526 LLSD::Impl::Impl(StaticAllocationMarker)
00527 : mUseCount(0)
00528 {
00529 }
00530
00531 LLSD::Impl::~Impl()
00532 {
00533 --sOutstandingCount;
00534 }
00535
00536 void LLSD::Impl::reset(Impl*& var, Impl* impl)
00537 {
00538 if (impl) ++impl->mUseCount;
00539 if (var && --var->mUseCount == 0)
00540 {
00541 delete var;
00542 }
00543 var = impl;
00544 }
00545
00546 LLSD::Impl& LLSD::Impl::safe(Impl* impl)
00547 {
00548 static Impl theUndefined(STATIC);
00549 return impl ? *impl : theUndefined;
00550 }
00551
00552 const LLSD::Impl& LLSD::Impl::safe(const Impl* impl)
00553 {
00554 static Impl theUndefined(STATIC);
00555 return impl ? *impl : theUndefined;
00556 }
00557
00558 ImplMap& LLSD::Impl::makeMap(Impl*& var)
00559 {
00560 ImplMap* im = new ImplMap;
00561 reset(var, im);
00562 return *im;
00563 }
00564
00565 ImplArray& LLSD::Impl::makeArray(Impl*& var)
00566 {
00567 ImplArray* ia = new ImplArray;
00568 reset(var, ia);
00569 return *ia;
00570 }
00571
00572
00573 void LLSD::Impl::assign(Impl*& var, const Impl* other)
00574 {
00575 reset(var, const_cast<Impl*>(other));
00576 }
00577
00578 void LLSD::Impl::assignUndefined(Impl*& var)
00579 {
00580 reset(var, 0);
00581 }
00582
00583 void LLSD::Impl::assign(Impl*& var, LLSD::Boolean v)
00584 {
00585 reset(var, new ImplBoolean(v));
00586 }
00587
00588 void LLSD::Impl::assign(Impl*& var, LLSD::Integer v)
00589 {
00590 reset(var, new ImplInteger(v));
00591 }
00592
00593 void LLSD::Impl::assign(Impl*& var, LLSD::Real v)
00594 {
00595 reset(var, new ImplReal(v));
00596 }
00597
00598 void LLSD::Impl::assign(Impl*& var, const LLSD::String& v)
00599 {
00600 reset(var, new ImplString(v));
00601 }
00602
00603 void LLSD::Impl::assign(Impl*& var, const LLSD::UUID& v)
00604 {
00605 reset(var, new ImplUUID(v));
00606 }
00607
00608 void LLSD::Impl::assign(Impl*& var, const LLSD::Date& v)
00609 {
00610 reset(var, new ImplDate(v));
00611 }
00612
00613 void LLSD::Impl::assign(Impl*& var, const LLSD::URI& v)
00614 {
00615 reset(var, new ImplURI(v));
00616 }
00617
00618 void LLSD::Impl::assign(Impl*& var, const LLSD::Binary& v)
00619 {
00620 reset(var, new ImplBinary(v));
00621 }
00622
00623
00624 const LLSD& LLSD::Impl::undef()
00625 {
00626 static const LLSD immutableUndefined;
00627 return immutableUndefined;
00628 }
00629
00630 U32 LLSD::Impl::sAllocationCount = 0;
00631 U32 LLSD::Impl::sOutstandingCount = 0;
00632
00633
00634
00635 namespace {
00636 inline LLSD::Impl& safe(LLSD::Impl* impl)
00637 { return LLSD::Impl::safe(impl); }
00638
00639 inline const LLSD::Impl& safe(const LLSD::Impl* impl)
00640 { return LLSD::Impl::safe(impl); }
00641
00642 inline ImplMap& makeMap(LLSD::Impl*& var)
00643 { return safe(var).makeMap(var); }
00644
00645 inline ImplArray& makeArray(LLSD::Impl*& var)
00646 { return safe(var).makeArray(var); }
00647 }
00648
00649
00650 LLSD::LLSD() : impl(0) { }
00651 LLSD::~LLSD() { Impl::reset(impl, 0); }
00652
00653 LLSD::LLSD(const LLSD& other) : impl(0) { assign(other); }
00654 void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); }
00655
00656
00657 void LLSD::clear() { Impl::assignUndefined(impl); }
00658
00659 LLSD::Type LLSD::type() const { return safe(impl).type(); }
00660
00661
00662 LLSD::LLSD(Boolean v) : impl(0) { assign(v); }
00663 LLSD::LLSD(Integer v) : impl(0) { assign(v); }
00664 LLSD::LLSD(Real v) : impl(0) { assign(v); }
00665 LLSD::LLSD(const UUID& v) : impl(0) { assign(v); }
00666 LLSD::LLSD(const String& v) : impl(0) { assign(v); }
00667 LLSD::LLSD(const Date& v) : impl(0) { assign(v); }
00668 LLSD::LLSD(const URI& v) : impl(0) { assign(v); }
00669 LLSD::LLSD(const Binary& v) : impl(0) { assign(v); }
00670
00671
00672 LLSD::LLSD(F32 v) : impl(0) { assign((Real)v); }
00673
00674
00675 void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); }
00676 void LLSD::assign(Integer v) { safe(impl).assign(impl, v); }
00677 void LLSD::assign(Real v) { safe(impl).assign(impl, v); }
00678 void LLSD::assign(const String& v) { safe(impl).assign(impl, v); }
00679 void LLSD::assign(const UUID& v) { safe(impl).assign(impl, v); }
00680 void LLSD::assign(const Date& v) { safe(impl).assign(impl, v); }
00681 void LLSD::assign(const URI& v) { safe(impl).assign(impl, v); }
00682 void LLSD::assign(const Binary& v) { safe(impl).assign(impl, v); }
00683
00684
00685 LLSD::Boolean LLSD::asBoolean() const { return safe(impl).asBoolean(); }
00686 LLSD::Integer LLSD::asInteger() const { return safe(impl).asInteger(); }
00687 LLSD::Real LLSD::asReal() const { return safe(impl).asReal(); }
00688 LLSD::String LLSD::asString() const { return safe(impl).asString(); }
00689 LLSD::UUID LLSD::asUUID() const { return safe(impl).asUUID(); }
00690 LLSD::Date LLSD::asDate() const { return safe(impl).asDate(); }
00691 LLSD::URI LLSD::asURI() const { return safe(impl).asURI(); }
00692 LLSD::Binary LLSD::asBinary() const { return safe(impl).asBinary(); }
00693
00694
00695 LLSD::LLSD(const char* v) : impl(0) { assign(v); }
00696 void LLSD::assign(const char* v)
00697 {
00698 if(v) assign(std::string(v));
00699 else assign(std::string());
00700 }
00701
00702
00703 LLSD LLSD::emptyMap()
00704 {
00705 LLSD v;
00706 makeMap(v.impl);
00707 return v;
00708 }
00709
00710 bool LLSD::has(const String& k) const { return safe(impl).has(k); }
00711 LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
00712
00713 void LLSD::insert(const String& k, const LLSD& v)
00714 { makeMap(impl).insert(k, v); }
00715 void LLSD::erase(const String& k) { makeMap(impl).erase(k); }
00716
00717 LLSD& LLSD::operator[](const String& k)
00718 { return makeMap(impl).ref(k); }
00719 const LLSD& LLSD::operator[](const String& k) const
00720 { return safe(impl).ref(k); }
00721
00722
00723 LLSD LLSD::emptyArray()
00724 {
00725 LLSD v;
00726 makeArray(v.impl);
00727 return v;
00728 }
00729
00730 int LLSD::size() const { return safe(impl).size(); }
00731
00732 LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
00733 void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); }
00734
00735 void LLSD::insert(Integer i, const LLSD& v)
00736 { makeArray(impl).insert(i, v); }
00737 void LLSD::append(const LLSD& v) { makeArray(impl).append(v); }
00738 void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
00739
00740 LLSD& LLSD::operator[](Integer i)
00741 { return makeArray(impl).ref(i); }
00742 const LLSD& LLSD::operator[](Integer i) const
00743 { return safe(impl).ref(i); }
00744
00745 U32 LLSD::allocationCount() { return Impl::sAllocationCount; }
00746 U32 LLSD::outstandingCount() { return Impl::sOutstandingCount; }
00747
00748 LLSD::map_iterator LLSD::beginMap() { return makeMap(impl).beginMap(); }
00749 LLSD::map_iterator LLSD::endMap() { return makeMap(impl).endMap(); }
00750 LLSD::map_const_iterator LLSD::beginMap() const { return safe(impl).beginMap(); }
00751 LLSD::map_const_iterator LLSD::endMap() const { return safe(impl).endMap(); }
00752
00753 LLSD::array_iterator LLSD::beginArray() { return makeArray(impl).beginArray(); }
00754 LLSD::array_iterator LLSD::endArray() { return makeArray(impl).endArray(); }
00755 LLSD::array_const_iterator LLSD::beginArray() const{ return safe(impl).beginArray(); }
00756 LLSD::array_const_iterator LLSD::endArray() const { return safe(impl).endArray(); }