rdf/base/src/nsRDFService.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6 *
michael@0 7 *
michael@0 8 * This Original Code has been modified by IBM Corporation.
michael@0 9 * Modifications made by IBM described herein are
michael@0 10 * Copyright (c) International Business Machines
michael@0 11 * Corporation, 2000
michael@0 12 *
michael@0 13 * Modifications to Mozilla code or documentation
michael@0 14 * identified per MPL Section 3.3
michael@0 15 *
michael@0 16 * Date Modified by Description of modification
michael@0 17 * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
michael@0 18 * use in OS2
michael@0 19 */
michael@0 20
michael@0 21 /*
michael@0 22
michael@0 23 This file provides the implementation for the RDF service manager.
michael@0 24
michael@0 25 TO DO
michael@0 26 -----
michael@0 27
michael@0 28 1) Implement the CreateDataBase() methods.
michael@0 29
michael@0 30 2) Cache date and int literals.
michael@0 31
michael@0 32 */
michael@0 33
michael@0 34 #include "nsRDFService.h"
michael@0 35 #include "nsCOMPtr.h"
michael@0 36 #include "nsAutoPtr.h"
michael@0 37 #include "nsMemory.h"
michael@0 38 #include "nsIAtom.h"
michael@0 39 #include "nsIComponentManager.h"
michael@0 40 #include "nsIRDFDataSource.h"
michael@0 41 #include "nsIRDFNode.h"
michael@0 42 #include "nsIRDFRemoteDataSource.h"
michael@0 43 #include "nsIServiceManager.h"
michael@0 44 #include "nsIFactory.h"
michael@0 45 #include "nsRDFCID.h"
michael@0 46 #include "nsString.h"
michael@0 47 #include "nsXPIDLString.h"
michael@0 48 #include "nsNetUtil.h"
michael@0 49 #include "pldhash.h"
michael@0 50 #include "plhash.h"
michael@0 51 #include "plstr.h"
michael@0 52 #include "prlog.h"
michael@0 53 #include "prprf.h"
michael@0 54 #include "prmem.h"
michael@0 55 #include "rdf.h"
michael@0 56 #include "nsCRT.h"
michael@0 57 #include "nsCRTGlue.h"
michael@0 58 #include "mozilla/HashFunctions.h"
michael@0 59
michael@0 60 using namespace mozilla;
michael@0 61
michael@0 62 ////////////////////////////////////////////////////////////////////////
michael@0 63
michael@0 64 static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
michael@0 65 static NS_DEFINE_CID(kRDFDefaultResourceCID, NS_RDFDEFAULTRESOURCE_CID);
michael@0 66
michael@0 67 static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
michael@0 68 static NS_DEFINE_IID(kIRDFDateIID, NS_IRDFDATE_IID);
michael@0 69 static NS_DEFINE_IID(kIRDFIntIID, NS_IRDFINT_IID);
michael@0 70 static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
michael@0 71 static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
michael@0 72
michael@0 73 #ifdef PR_LOGGING
michael@0 74 static PRLogModuleInfo* gLog = nullptr;
michael@0 75 #endif
michael@0 76
michael@0 77 class BlobImpl;
michael@0 78
michael@0 79 // These functions are copied from nsprpub/lib/ds/plhash.c, with one
michael@0 80 // change to free the key in DataSourceFreeEntry.
michael@0 81 // XXX sigh, why were DefaultAllocTable et. al. declared static, anyway?
michael@0 82
michael@0 83 static void *
michael@0 84 DataSourceAllocTable(void *pool, size_t size)
michael@0 85 {
michael@0 86 return PR_MALLOC(size);
michael@0 87 }
michael@0 88
michael@0 89 static void
michael@0 90 DataSourceFreeTable(void *pool, void *item)
michael@0 91 {
michael@0 92 PR_Free(item);
michael@0 93 }
michael@0 94
michael@0 95 static PLHashEntry *
michael@0 96 DataSourceAllocEntry(void *pool, const void *key)
michael@0 97 {
michael@0 98 return PR_NEW(PLHashEntry);
michael@0 99 }
michael@0 100
michael@0 101 static void
michael@0 102 DataSourceFreeEntry(void *pool, PLHashEntry *he, unsigned flag)
michael@0 103 {
michael@0 104 if (flag == HT_FREE_ENTRY) {
michael@0 105 PL_strfree((char*) he->key);
michael@0 106 PR_Free(he);
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110 static PLHashAllocOps dataSourceHashAllocOps = {
michael@0 111 DataSourceAllocTable, DataSourceFreeTable,
michael@0 112 DataSourceAllocEntry, DataSourceFreeEntry
michael@0 113 };
michael@0 114
michael@0 115 //----------------------------------------------------------------------
michael@0 116 //
michael@0 117 // For the mResources hashtable.
michael@0 118 //
michael@0 119
michael@0 120 struct ResourceHashEntry : public PLDHashEntryHdr {
michael@0 121 const char *mKey;
michael@0 122 nsIRDFResource *mResource;
michael@0 123
michael@0 124 static PLDHashNumber
michael@0 125 HashKey(PLDHashTable *table, const void *key)
michael@0 126 {
michael@0 127 return HashString(static_cast<const char *>(key));
michael@0 128 }
michael@0 129
michael@0 130 static bool
michael@0 131 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
michael@0 132 const void *key)
michael@0 133 {
michael@0 134 const ResourceHashEntry *entry =
michael@0 135 static_cast<const ResourceHashEntry *>(hdr);
michael@0 136
michael@0 137 return 0 == nsCRT::strcmp(static_cast<const char *>(key),
michael@0 138 entry->mKey);
michael@0 139 }
michael@0 140 };
michael@0 141
michael@0 142 static const PLDHashTableOps gResourceTableOps = {
michael@0 143 PL_DHashAllocTable,
michael@0 144 PL_DHashFreeTable,
michael@0 145 ResourceHashEntry::HashKey,
michael@0 146 ResourceHashEntry::MatchEntry,
michael@0 147 PL_DHashMoveEntryStub,
michael@0 148 PL_DHashClearEntryStub,
michael@0 149 PL_DHashFinalizeStub,
michael@0 150 nullptr
michael@0 151 };
michael@0 152
michael@0 153 // ----------------------------------------------------------------------
michael@0 154 //
michael@0 155 // For the mLiterals hashtable.
michael@0 156 //
michael@0 157
michael@0 158 struct LiteralHashEntry : public PLDHashEntryHdr {
michael@0 159 nsIRDFLiteral *mLiteral;
michael@0 160 const char16_t *mKey;
michael@0 161
michael@0 162 static PLDHashNumber
michael@0 163 HashKey(PLDHashTable *table, const void *key)
michael@0 164 {
michael@0 165 return HashString(static_cast<const char16_t *>(key));
michael@0 166 }
michael@0 167
michael@0 168 static bool
michael@0 169 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
michael@0 170 const void *key)
michael@0 171 {
michael@0 172 const LiteralHashEntry *entry =
michael@0 173 static_cast<const LiteralHashEntry *>(hdr);
michael@0 174
michael@0 175 return 0 == nsCRT::strcmp(static_cast<const char16_t *>(key),
michael@0 176 entry->mKey);
michael@0 177 }
michael@0 178 };
michael@0 179
michael@0 180 static const PLDHashTableOps gLiteralTableOps = {
michael@0 181 PL_DHashAllocTable,
michael@0 182 PL_DHashFreeTable,
michael@0 183 LiteralHashEntry::HashKey,
michael@0 184 LiteralHashEntry::MatchEntry,
michael@0 185 PL_DHashMoveEntryStub,
michael@0 186 PL_DHashClearEntryStub,
michael@0 187 PL_DHashFinalizeStub,
michael@0 188 nullptr
michael@0 189 };
michael@0 190
michael@0 191 // ----------------------------------------------------------------------
michael@0 192 //
michael@0 193 // For the mInts hashtable.
michael@0 194 //
michael@0 195
michael@0 196 struct IntHashEntry : public PLDHashEntryHdr {
michael@0 197 nsIRDFInt *mInt;
michael@0 198 int32_t mKey;
michael@0 199
michael@0 200 static PLDHashNumber
michael@0 201 HashKey(PLDHashTable *table, const void *key)
michael@0 202 {
michael@0 203 return PLDHashNumber(*static_cast<const int32_t *>(key));
michael@0 204 }
michael@0 205
michael@0 206 static bool
michael@0 207 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
michael@0 208 const void *key)
michael@0 209 {
michael@0 210 const IntHashEntry *entry =
michael@0 211 static_cast<const IntHashEntry *>(hdr);
michael@0 212
michael@0 213 return *static_cast<const int32_t *>(key) == entry->mKey;
michael@0 214 }
michael@0 215 };
michael@0 216
michael@0 217 static const PLDHashTableOps gIntTableOps = {
michael@0 218 PL_DHashAllocTable,
michael@0 219 PL_DHashFreeTable,
michael@0 220 IntHashEntry::HashKey,
michael@0 221 IntHashEntry::MatchEntry,
michael@0 222 PL_DHashMoveEntryStub,
michael@0 223 PL_DHashClearEntryStub,
michael@0 224 PL_DHashFinalizeStub,
michael@0 225 nullptr
michael@0 226 };
michael@0 227
michael@0 228 // ----------------------------------------------------------------------
michael@0 229 //
michael@0 230 // For the mDates hashtable.
michael@0 231 //
michael@0 232
michael@0 233 struct DateHashEntry : public PLDHashEntryHdr {
michael@0 234 nsIRDFDate *mDate;
michael@0 235 PRTime mKey;
michael@0 236
michael@0 237 static PLDHashNumber
michael@0 238 HashKey(PLDHashTable *table, const void *key)
michael@0 239 {
michael@0 240 // xor the low 32 bits with the high 32 bits.
michael@0 241 PRTime t = *static_cast<const PRTime *>(key);
michael@0 242 int32_t h32 = int32_t(t >> 32);
michael@0 243 int32_t l32 = int32_t(0xffffffff & t);
michael@0 244 return PLDHashNumber(l32 ^ h32);
michael@0 245 }
michael@0 246
michael@0 247 static bool
michael@0 248 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
michael@0 249 const void *key)
michael@0 250 {
michael@0 251 const DateHashEntry *entry =
michael@0 252 static_cast<const DateHashEntry *>(hdr);
michael@0 253
michael@0 254 return *static_cast<const PRTime *>(key) == entry->mKey;
michael@0 255 }
michael@0 256 };
michael@0 257
michael@0 258 static const PLDHashTableOps gDateTableOps = {
michael@0 259 PL_DHashAllocTable,
michael@0 260 PL_DHashFreeTable,
michael@0 261 DateHashEntry::HashKey,
michael@0 262 DateHashEntry::MatchEntry,
michael@0 263 PL_DHashMoveEntryStub,
michael@0 264 PL_DHashClearEntryStub,
michael@0 265 PL_DHashFinalizeStub,
michael@0 266 nullptr
michael@0 267 };
michael@0 268
michael@0 269 class BlobImpl : public nsIRDFBlob
michael@0 270 {
michael@0 271 public:
michael@0 272 struct Data {
michael@0 273 int32_t mLength;
michael@0 274 uint8_t *mBytes;
michael@0 275 };
michael@0 276
michael@0 277 BlobImpl(const uint8_t *aBytes, int32_t aLength)
michael@0 278 {
michael@0 279 mData.mLength = aLength;
michael@0 280 mData.mBytes = new uint8_t[aLength];
michael@0 281 memcpy(mData.mBytes, aBytes, aLength);
michael@0 282 NS_ADDREF(RDFServiceImpl::gRDFService);
michael@0 283 RDFServiceImpl::gRDFService->RegisterBlob(this);
michael@0 284 }
michael@0 285
michael@0 286 virtual ~BlobImpl()
michael@0 287 {
michael@0 288 RDFServiceImpl::gRDFService->UnregisterBlob(this);
michael@0 289 // Use NS_RELEASE2() here, because we want to decrease the
michael@0 290 // refcount, but not null out the gRDFService pointer (which is
michael@0 291 // what a vanilla NS_RELEASE() would do).
michael@0 292 nsrefcnt refcnt;
michael@0 293 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
michael@0 294 delete[] mData.mBytes;
michael@0 295 }
michael@0 296
michael@0 297 NS_DECL_ISUPPORTS
michael@0 298 NS_DECL_NSIRDFNODE
michael@0 299 NS_DECL_NSIRDFBLOB
michael@0 300
michael@0 301 Data mData;
michael@0 302 };
michael@0 303
michael@0 304 NS_IMPL_ISUPPORTS(BlobImpl, nsIRDFNode, nsIRDFBlob)
michael@0 305
michael@0 306 NS_IMETHODIMP
michael@0 307 BlobImpl::EqualsNode(nsIRDFNode *aNode, bool *aEquals)
michael@0 308 {
michael@0 309 nsCOMPtr<nsIRDFBlob> blob = do_QueryInterface(aNode);
michael@0 310 if (blob) {
michael@0 311 int32_t length;
michael@0 312 blob->GetLength(&length);
michael@0 313
michael@0 314 if (length == mData.mLength) {
michael@0 315 const uint8_t *bytes;
michael@0 316 blob->GetValue(&bytes);
michael@0 317
michael@0 318 if (0 == memcmp(bytes, mData.mBytes, length)) {
michael@0 319 *aEquals = true;
michael@0 320 return NS_OK;
michael@0 321 }
michael@0 322 }
michael@0 323 }
michael@0 324
michael@0 325 *aEquals = false;
michael@0 326 return NS_OK;
michael@0 327 }
michael@0 328
michael@0 329 NS_IMETHODIMP
michael@0 330 BlobImpl::GetValue(const uint8_t **aResult)
michael@0 331 {
michael@0 332 *aResult = mData.mBytes;
michael@0 333 return NS_OK;
michael@0 334 }
michael@0 335
michael@0 336 NS_IMETHODIMP
michael@0 337 BlobImpl::GetLength(int32_t *aResult)
michael@0 338 {
michael@0 339 *aResult = mData.mLength;
michael@0 340 return NS_OK;
michael@0 341 }
michael@0 342
michael@0 343 // ----------------------------------------------------------------------
michael@0 344 //
michael@0 345 // For the mBlobs hashtable.
michael@0 346 //
michael@0 347
michael@0 348 struct BlobHashEntry : public PLDHashEntryHdr {
michael@0 349 BlobImpl *mBlob;
michael@0 350
michael@0 351 static PLDHashNumber
michael@0 352 HashKey(PLDHashTable *table, const void *key)
michael@0 353 {
michael@0 354 const BlobImpl::Data *data =
michael@0 355 static_cast<const BlobImpl::Data *>(key);
michael@0 356 return HashBytes(data->mBytes, data->mLength);
michael@0 357 }
michael@0 358
michael@0 359 static bool
michael@0 360 MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
michael@0 361 const void *key)
michael@0 362 {
michael@0 363 const BlobHashEntry *entry =
michael@0 364 static_cast<const BlobHashEntry *>(hdr);
michael@0 365
michael@0 366 const BlobImpl::Data *left = &entry->mBlob->mData;
michael@0 367
michael@0 368 const BlobImpl::Data *right =
michael@0 369 static_cast<const BlobImpl::Data *>(key);
michael@0 370
michael@0 371 return (left->mLength == right->mLength)
michael@0 372 && 0 == memcmp(left->mBytes, right->mBytes, right->mLength);
michael@0 373 }
michael@0 374 };
michael@0 375
michael@0 376 static const PLDHashTableOps gBlobTableOps = {
michael@0 377 PL_DHashAllocTable,
michael@0 378 PL_DHashFreeTable,
michael@0 379 BlobHashEntry::HashKey,
michael@0 380 BlobHashEntry::MatchEntry,
michael@0 381 PL_DHashMoveEntryStub,
michael@0 382 PL_DHashClearEntryStub,
michael@0 383 PL_DHashFinalizeStub,
michael@0 384 nullptr
michael@0 385 };
michael@0 386
michael@0 387 ////////////////////////////////////////////////////////////////////////
michael@0 388 // LiteralImpl
michael@0 389 //
michael@0 390 // Currently, all literals are implemented exactly the same way;
michael@0 391 // i.e., there is are no resource factories to allow you to generate
michael@0 392 // customer resources. I doubt that makes sense, anyway.
michael@0 393 //
michael@0 394 class LiteralImpl : public nsIRDFLiteral {
michael@0 395 public:
michael@0 396 static nsresult
michael@0 397 Create(const char16_t* aValue, nsIRDFLiteral** aResult);
michael@0 398
michael@0 399 // nsISupports
michael@0 400 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 401
michael@0 402 // nsIRDFNode
michael@0 403 NS_DECL_NSIRDFNODE
michael@0 404
michael@0 405 // nsIRDFLiteral
michael@0 406 NS_DECL_NSIRDFLITERAL
michael@0 407
michael@0 408 protected:
michael@0 409 LiteralImpl(const char16_t* s);
michael@0 410 virtual ~LiteralImpl();
michael@0 411
michael@0 412 const char16_t* GetValue() const {
michael@0 413 size_t objectSize = ((sizeof(LiteralImpl) + sizeof(char16_t) - 1) / sizeof(char16_t)) * sizeof(char16_t);
michael@0 414 return reinterpret_cast<const char16_t*>(reinterpret_cast<const unsigned char*>(this) + objectSize);
michael@0 415 }
michael@0 416 };
michael@0 417
michael@0 418
michael@0 419 nsresult
michael@0 420 LiteralImpl::Create(const char16_t* aValue, nsIRDFLiteral** aResult)
michael@0 421 {
michael@0 422 // Goofy math to get alignment right. Copied from nsSharedString.h.
michael@0 423 size_t objectSize = ((sizeof(LiteralImpl) + sizeof(char16_t) - 1) / sizeof(char16_t)) * sizeof(char16_t);
michael@0 424 size_t stringLen = nsCharTraits<char16_t>::length(aValue);
michael@0 425 size_t stringSize = (stringLen + 1) * sizeof(char16_t);
michael@0 426
michael@0 427 void* objectPtr = operator new(objectSize + stringSize);
michael@0 428 if (! objectPtr)
michael@0 429 return NS_ERROR_NULL_POINTER;
michael@0 430
michael@0 431 char16_t* buf = reinterpret_cast<char16_t*>(static_cast<unsigned char*>(objectPtr) + objectSize);
michael@0 432 nsCharTraits<char16_t>::copy(buf, aValue, stringLen + 1);
michael@0 433
michael@0 434 NS_ADDREF(*aResult = new (objectPtr) LiteralImpl(buf));
michael@0 435 return NS_OK;
michael@0 436 }
michael@0 437
michael@0 438
michael@0 439 LiteralImpl::LiteralImpl(const char16_t* s)
michael@0 440 {
michael@0 441 RDFServiceImpl::gRDFService->RegisterLiteral(this);
michael@0 442 NS_ADDREF(RDFServiceImpl::gRDFService);
michael@0 443 }
michael@0 444
michael@0 445 LiteralImpl::~LiteralImpl()
michael@0 446 {
michael@0 447 RDFServiceImpl::gRDFService->UnregisterLiteral(this);
michael@0 448
michael@0 449 // Use NS_RELEASE2() here, because we want to decrease the
michael@0 450 // refcount, but not null out the gRDFService pointer (which is
michael@0 451 // what a vanilla NS_RELEASE() would do).
michael@0 452 nsrefcnt refcnt;
michael@0 453 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
michael@0 454 }
michael@0 455
michael@0 456 NS_IMPL_ADDREF(LiteralImpl)
michael@0 457 NS_IMPL_RELEASE(LiteralImpl)
michael@0 458
michael@0 459 nsresult
michael@0 460 LiteralImpl::QueryInterface(REFNSIID iid, void** result)
michael@0 461 {
michael@0 462 if (! result)
michael@0 463 return NS_ERROR_NULL_POINTER;
michael@0 464
michael@0 465 *result = nullptr;
michael@0 466 if (iid.Equals(kIRDFLiteralIID) ||
michael@0 467 iid.Equals(kIRDFNodeIID) ||
michael@0 468 iid.Equals(kISupportsIID)) {
michael@0 469 *result = static_cast<nsIRDFLiteral*>(this);
michael@0 470 AddRef();
michael@0 471 return NS_OK;
michael@0 472 }
michael@0 473 return NS_NOINTERFACE;
michael@0 474 }
michael@0 475
michael@0 476 NS_IMETHODIMP
michael@0 477 LiteralImpl::EqualsNode(nsIRDFNode* aNode, bool* aResult)
michael@0 478 {
michael@0 479 nsresult rv;
michael@0 480 nsIRDFLiteral* literal;
michael@0 481 rv = aNode->QueryInterface(kIRDFLiteralIID, (void**) &literal);
michael@0 482 if (NS_SUCCEEDED(rv)) {
michael@0 483 *aResult = (static_cast<nsIRDFLiteral*>(this) == literal);
michael@0 484 NS_RELEASE(literal);
michael@0 485 return NS_OK;
michael@0 486 }
michael@0 487 else if (rv == NS_NOINTERFACE) {
michael@0 488 *aResult = false;
michael@0 489 return NS_OK;
michael@0 490 }
michael@0 491 else {
michael@0 492 return rv;
michael@0 493 }
michael@0 494 }
michael@0 495
michael@0 496 NS_IMETHODIMP
michael@0 497 LiteralImpl::GetValue(char16_t* *value)
michael@0 498 {
michael@0 499 NS_ASSERTION(value, "null ptr");
michael@0 500 if (! value)
michael@0 501 return NS_ERROR_NULL_POINTER;
michael@0 502
michael@0 503 const char16_t *temp = GetValue();
michael@0 504 *value = temp? NS_strdup(temp) : 0;
michael@0 505 return NS_OK;
michael@0 506 }
michael@0 507
michael@0 508
michael@0 509 NS_IMETHODIMP
michael@0 510 LiteralImpl::GetValueConst(const char16_t** aValue)
michael@0 511 {
michael@0 512 *aValue = GetValue();
michael@0 513 return NS_OK;
michael@0 514 }
michael@0 515
michael@0 516 ////////////////////////////////////////////////////////////////////////
michael@0 517 // DateImpl
michael@0 518 //
michael@0 519
michael@0 520 class DateImpl : public nsIRDFDate {
michael@0 521 public:
michael@0 522 DateImpl(const PRTime s);
michael@0 523 virtual ~DateImpl();
michael@0 524
michael@0 525 // nsISupports
michael@0 526 NS_DECL_ISUPPORTS
michael@0 527
michael@0 528 // nsIRDFNode
michael@0 529 NS_DECL_NSIRDFNODE
michael@0 530
michael@0 531 // nsIRDFDate
michael@0 532 NS_IMETHOD GetValue(PRTime *value);
michael@0 533
michael@0 534 private:
michael@0 535 nsresult EqualsDate(nsIRDFDate* date, bool* result);
michael@0 536 PRTime mValue;
michael@0 537 };
michael@0 538
michael@0 539
michael@0 540 DateImpl::DateImpl(const PRTime s)
michael@0 541 : mValue(s)
michael@0 542 {
michael@0 543 RDFServiceImpl::gRDFService->RegisterDate(this);
michael@0 544 NS_ADDREF(RDFServiceImpl::gRDFService);
michael@0 545 }
michael@0 546
michael@0 547 DateImpl::~DateImpl()
michael@0 548 {
michael@0 549 RDFServiceImpl::gRDFService->UnregisterDate(this);
michael@0 550
michael@0 551 // Use NS_RELEASE2() here, because we want to decrease the
michael@0 552 // refcount, but not null out the gRDFService pointer (which is
michael@0 553 // what a vanilla NS_RELEASE() would do).
michael@0 554 nsrefcnt refcnt;
michael@0 555 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
michael@0 556 }
michael@0 557
michael@0 558 NS_IMPL_ADDREF(DateImpl)
michael@0 559 NS_IMPL_RELEASE(DateImpl)
michael@0 560
michael@0 561 nsresult
michael@0 562 DateImpl::QueryInterface(REFNSIID iid, void** result)
michael@0 563 {
michael@0 564 if (! result)
michael@0 565 return NS_ERROR_NULL_POINTER;
michael@0 566
michael@0 567 *result = nullptr;
michael@0 568 if (iid.Equals(kIRDFDateIID) ||
michael@0 569 iid.Equals(kIRDFNodeIID) ||
michael@0 570 iid.Equals(kISupportsIID)) {
michael@0 571 *result = static_cast<nsIRDFDate*>(this);
michael@0 572 AddRef();
michael@0 573 return NS_OK;
michael@0 574 }
michael@0 575 return NS_NOINTERFACE;
michael@0 576 }
michael@0 577
michael@0 578 NS_IMETHODIMP
michael@0 579 DateImpl::EqualsNode(nsIRDFNode* node, bool* result)
michael@0 580 {
michael@0 581 nsresult rv;
michael@0 582 nsIRDFDate* date;
michael@0 583 if (NS_SUCCEEDED(node->QueryInterface(kIRDFDateIID, (void**) &date))) {
michael@0 584 rv = EqualsDate(date, result);
michael@0 585 NS_RELEASE(date);
michael@0 586 }
michael@0 587 else {
michael@0 588 *result = false;
michael@0 589 rv = NS_OK;
michael@0 590 }
michael@0 591 return rv;
michael@0 592 }
michael@0 593
michael@0 594 NS_IMETHODIMP
michael@0 595 DateImpl::GetValue(PRTime *value)
michael@0 596 {
michael@0 597 NS_ASSERTION(value, "null ptr");
michael@0 598 if (! value)
michael@0 599 return NS_ERROR_NULL_POINTER;
michael@0 600
michael@0 601 *value = mValue;
michael@0 602 return NS_OK;
michael@0 603 }
michael@0 604
michael@0 605
michael@0 606 nsresult
michael@0 607 DateImpl::EqualsDate(nsIRDFDate* date, bool* result)
michael@0 608 {
michael@0 609 NS_ASSERTION(date && result, "null ptr");
michael@0 610 if (!date || !result)
michael@0 611 return NS_ERROR_NULL_POINTER;
michael@0 612
michael@0 613 nsresult rv;
michael@0 614 PRTime p;
michael@0 615 if (NS_FAILED(rv = date->GetValue(&p)))
michael@0 616 return rv;
michael@0 617
michael@0 618 *result = p == mValue;
michael@0 619 return NS_OK;
michael@0 620 }
michael@0 621
michael@0 622 ////////////////////////////////////////////////////////////////////////
michael@0 623 // IntImpl
michael@0 624 //
michael@0 625
michael@0 626 class IntImpl : public nsIRDFInt {
michael@0 627 public:
michael@0 628 IntImpl(int32_t s);
michael@0 629 virtual ~IntImpl();
michael@0 630
michael@0 631 // nsISupports
michael@0 632 NS_DECL_ISUPPORTS
michael@0 633
michael@0 634 // nsIRDFNode
michael@0 635 NS_DECL_NSIRDFNODE
michael@0 636
michael@0 637 // nsIRDFInt
michael@0 638 NS_IMETHOD GetValue(int32_t *value);
michael@0 639
michael@0 640 private:
michael@0 641 nsresult EqualsInt(nsIRDFInt* value, bool* result);
michael@0 642 int32_t mValue;
michael@0 643 };
michael@0 644
michael@0 645
michael@0 646 IntImpl::IntImpl(int32_t s)
michael@0 647 : mValue(s)
michael@0 648 {
michael@0 649 RDFServiceImpl::gRDFService->RegisterInt(this);
michael@0 650 NS_ADDREF(RDFServiceImpl::gRDFService);
michael@0 651 }
michael@0 652
michael@0 653 IntImpl::~IntImpl()
michael@0 654 {
michael@0 655 RDFServiceImpl::gRDFService->UnregisterInt(this);
michael@0 656
michael@0 657 // Use NS_RELEASE2() here, because we want to decrease the
michael@0 658 // refcount, but not null out the gRDFService pointer (which is
michael@0 659 // what a vanilla NS_RELEASE() would do).
michael@0 660 nsrefcnt refcnt;
michael@0 661 NS_RELEASE2(RDFServiceImpl::gRDFService, refcnt);
michael@0 662 }
michael@0 663
michael@0 664 NS_IMPL_ADDREF(IntImpl)
michael@0 665 NS_IMPL_RELEASE(IntImpl)
michael@0 666
michael@0 667 nsresult
michael@0 668 IntImpl::QueryInterface(REFNSIID iid, void** result)
michael@0 669 {
michael@0 670 if (! result)
michael@0 671 return NS_ERROR_NULL_POINTER;
michael@0 672
michael@0 673 *result = nullptr;
michael@0 674 if (iid.Equals(kIRDFIntIID) ||
michael@0 675 iid.Equals(kIRDFNodeIID) ||
michael@0 676 iid.Equals(kISupportsIID)) {
michael@0 677 *result = static_cast<nsIRDFInt*>(this);
michael@0 678 AddRef();
michael@0 679 return NS_OK;
michael@0 680 }
michael@0 681 return NS_NOINTERFACE;
michael@0 682 }
michael@0 683
michael@0 684 NS_IMETHODIMP
michael@0 685 IntImpl::EqualsNode(nsIRDFNode* node, bool* result)
michael@0 686 {
michael@0 687 nsresult rv;
michael@0 688 nsIRDFInt* intValue;
michael@0 689 if (NS_SUCCEEDED(node->QueryInterface(kIRDFIntIID, (void**) &intValue))) {
michael@0 690 rv = EqualsInt(intValue, result);
michael@0 691 NS_RELEASE(intValue);
michael@0 692 }
michael@0 693 else {
michael@0 694 *result = false;
michael@0 695 rv = NS_OK;
michael@0 696 }
michael@0 697 return rv;
michael@0 698 }
michael@0 699
michael@0 700 NS_IMETHODIMP
michael@0 701 IntImpl::GetValue(int32_t *value)
michael@0 702 {
michael@0 703 NS_ASSERTION(value, "null ptr");
michael@0 704 if (! value)
michael@0 705 return NS_ERROR_NULL_POINTER;
michael@0 706
michael@0 707 *value = mValue;
michael@0 708 return NS_OK;
michael@0 709 }
michael@0 710
michael@0 711
michael@0 712 nsresult
michael@0 713 IntImpl::EqualsInt(nsIRDFInt* intValue, bool* result)
michael@0 714 {
michael@0 715 NS_ASSERTION(intValue && result, "null ptr");
michael@0 716 if (!intValue || !result)
michael@0 717 return NS_ERROR_NULL_POINTER;
michael@0 718
michael@0 719 nsresult rv;
michael@0 720 int32_t p;
michael@0 721 if (NS_FAILED(rv = intValue->GetValue(&p)))
michael@0 722 return rv;
michael@0 723
michael@0 724 *result = (p == mValue);
michael@0 725 return NS_OK;
michael@0 726 }
michael@0 727
michael@0 728 ////////////////////////////////////////////////////////////////////////
michael@0 729 // RDFServiceImpl
michael@0 730
michael@0 731 RDFServiceImpl*
michael@0 732 RDFServiceImpl::gRDFService;
michael@0 733
michael@0 734 RDFServiceImpl::RDFServiceImpl()
michael@0 735 : mNamedDataSources(nullptr)
michael@0 736 {
michael@0 737 mResources.ops = nullptr;
michael@0 738 mLiterals.ops = nullptr;
michael@0 739 mInts.ops = nullptr;
michael@0 740 mDates.ops = nullptr;
michael@0 741 mBlobs.ops = nullptr;
michael@0 742 gRDFService = this;
michael@0 743 }
michael@0 744
michael@0 745 nsresult
michael@0 746 RDFServiceImpl::Init()
michael@0 747 {
michael@0 748 nsresult rv;
michael@0 749
michael@0 750 mNamedDataSources = PL_NewHashTable(23,
michael@0 751 PL_HashString,
michael@0 752 PL_CompareStrings,
michael@0 753 PL_CompareValues,
michael@0 754 &dataSourceHashAllocOps, nullptr);
michael@0 755
michael@0 756 if (! mNamedDataSources)
michael@0 757 return NS_ERROR_OUT_OF_MEMORY;
michael@0 758
michael@0 759 PL_DHashTableInit(&mResources, &gResourceTableOps, nullptr,
michael@0 760 sizeof(ResourceHashEntry), PL_DHASH_MIN_SIZE);
michael@0 761
michael@0 762 PL_DHashTableInit(&mLiterals, &gLiteralTableOps, nullptr,
michael@0 763 sizeof(LiteralHashEntry), PL_DHASH_MIN_SIZE);
michael@0 764
michael@0 765 PL_DHashTableInit(&mInts, &gIntTableOps, nullptr,
michael@0 766 sizeof(IntHashEntry), PL_DHASH_MIN_SIZE);
michael@0 767
michael@0 768 PL_DHashTableInit(&mDates, &gDateTableOps, nullptr,
michael@0 769 sizeof(DateHashEntry), PL_DHASH_MIN_SIZE);
michael@0 770
michael@0 771 PL_DHashTableInit(&mBlobs, &gBlobTableOps, nullptr,
michael@0 772 sizeof(BlobHashEntry), PL_DHASH_MIN_SIZE);
michael@0 773
michael@0 774 mDefaultResourceFactory = do_GetClassObject(kRDFDefaultResourceCID, &rv);
michael@0 775 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get default resource factory");
michael@0 776 if (NS_FAILED(rv)) return rv;
michael@0 777
michael@0 778 #ifdef PR_LOGGING
michael@0 779 if (! gLog)
michael@0 780 gLog = PR_NewLogModule("nsRDFService");
michael@0 781 #endif
michael@0 782
michael@0 783 return NS_OK;
michael@0 784 }
michael@0 785
michael@0 786
michael@0 787 RDFServiceImpl::~RDFServiceImpl()
michael@0 788 {
michael@0 789 if (mNamedDataSources) {
michael@0 790 PL_HashTableDestroy(mNamedDataSources);
michael@0 791 mNamedDataSources = nullptr;
michael@0 792 }
michael@0 793 if (mResources.ops)
michael@0 794 PL_DHashTableFinish(&mResources);
michael@0 795 if (mLiterals.ops)
michael@0 796 PL_DHashTableFinish(&mLiterals);
michael@0 797 if (mInts.ops)
michael@0 798 PL_DHashTableFinish(&mInts);
michael@0 799 if (mDates.ops)
michael@0 800 PL_DHashTableFinish(&mDates);
michael@0 801 if (mBlobs.ops)
michael@0 802 PL_DHashTableFinish(&mBlobs);
michael@0 803 gRDFService = nullptr;
michael@0 804 }
michael@0 805
michael@0 806
michael@0 807 // static
michael@0 808 nsresult
michael@0 809 RDFServiceImpl::CreateSingleton(nsISupports* aOuter,
michael@0 810 const nsIID& aIID, void **aResult)
michael@0 811 {
michael@0 812 NS_ENSURE_NO_AGGREGATION(aOuter);
michael@0 813
michael@0 814 if (gRDFService) {
michael@0 815 NS_ERROR("Trying to create RDF serviec twice.");
michael@0 816 return gRDFService->QueryInterface(aIID, aResult);
michael@0 817 }
michael@0 818
michael@0 819 nsRefPtr<RDFServiceImpl> serv = new RDFServiceImpl();
michael@0 820 if (!serv)
michael@0 821 return NS_ERROR_OUT_OF_MEMORY;
michael@0 822
michael@0 823 nsresult rv = serv->Init();
michael@0 824 if (NS_FAILED(rv))
michael@0 825 return rv;
michael@0 826
michael@0 827 return serv->QueryInterface(aIID, aResult);
michael@0 828 }
michael@0 829
michael@0 830 NS_IMPL_ISUPPORTS(RDFServiceImpl, nsIRDFService, nsISupportsWeakReference)
michael@0 831
michael@0 832 // Per RFC2396.
michael@0 833 static const uint8_t
michael@0 834 kLegalSchemeChars[] = {
michael@0 835 // ASCII Bits Ordered Hex
michael@0 836 // 01234567 76543210
michael@0 837 0x00, // 00-07
michael@0 838 0x00, // 08-0F
michael@0 839 0x00, // 10-17
michael@0 840 0x00, // 18-1F
michael@0 841 0x00, // 20-27 !"#$%&' 00000000 00000000
michael@0 842 0x28, // 28-2F ()*+,-./ 00010100 00101000 0x28
michael@0 843 0xff, // 30-37 01234567 11111111 11111111 0xFF
michael@0 844 0x03, // 38-3F 89:;<=>? 11000000 00000011 0x03
michael@0 845 0xfe, // 40-47 @ABCDEFG 01111111 11111110 0xFE
michael@0 846 0xff, // 48-4F HIJKLMNO 11111111 11111111 0xFF
michael@0 847 0xff, // 50-57 PQRSTUVW 11111111 11111111 0xFF
michael@0 848 0x87, // 58-5F XYZ[\]^_ 11100001 10000111 0x87
michael@0 849 0xfe, // 60-67 `abcdefg 01111111 11111110 0xFE
michael@0 850 0xff, // 68-6F hijklmno 11111111 11111111 0xFF
michael@0 851 0xff, // 70-77 pqrstuvw 11111111 11111111 0xFF
michael@0 852 0x07, // 78-7F xyz{|}~ 11100000 00000111 0x07
michael@0 853 0x00, 0x00, 0x00, 0x00, // >= 80
michael@0 854 0x00, 0x00, 0x00, 0x00,
michael@0 855 0x00, 0x00, 0x00, 0x00,
michael@0 856 0x00, 0x00, 0x00, 0x00
michael@0 857 };
michael@0 858
michael@0 859 static inline bool
michael@0 860 IsLegalSchemeCharacter(const char aChar)
michael@0 861 {
michael@0 862 uint8_t mask = kLegalSchemeChars[aChar >> 3];
michael@0 863 uint8_t bit = 1u << (aChar & 0x7);
michael@0 864 return bool((mask & bit) != 0);
michael@0 865 }
michael@0 866
michael@0 867
michael@0 868 NS_IMETHODIMP
michael@0 869 RDFServiceImpl::GetResource(const nsACString& aURI, nsIRDFResource** aResource)
michael@0 870 {
michael@0 871 // Sanity checks
michael@0 872 NS_PRECONDITION(aResource != nullptr, "null ptr");
michael@0 873 NS_PRECONDITION(!aURI.IsEmpty(), "URI is empty");
michael@0 874 if (! aResource)
michael@0 875 return NS_ERROR_NULL_POINTER;
michael@0 876 if (aURI.IsEmpty())
michael@0 877 return NS_ERROR_INVALID_ARG;
michael@0 878
michael@0 879 const nsAFlatCString& flatURI = PromiseFlatCString(aURI);
michael@0 880 PR_LOG(gLog, PR_LOG_DEBUG, ("rdfserv get-resource %s", flatURI.get()));
michael@0 881
michael@0 882 // First, check the cache to see if we've already created and
michael@0 883 // registered this thing.
michael@0 884 PLDHashEntryHdr *hdr =
michael@0 885 PL_DHashTableOperate(&mResources, flatURI.get(), PL_DHASH_LOOKUP);
michael@0 886
michael@0 887 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
michael@0 888 ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
michael@0 889 NS_ADDREF(*aResource = entry->mResource);
michael@0 890 return NS_OK;
michael@0 891 }
michael@0 892
michael@0 893 // Nope. So go to the repository to create it.
michael@0 894
michael@0 895 // Compute the scheme of the URI. Scan forward until we either:
michael@0 896 //
michael@0 897 // 1. Reach the end of the string
michael@0 898 // 2. Encounter a non-alpha character
michael@0 899 // 3. Encouter a colon.
michael@0 900 //
michael@0 901 // If we encounter a colon _before_ encountering a non-alpha
michael@0 902 // character, then assume it's the scheme.
michael@0 903 //
michael@0 904 // XXX Although it's really not correct, we'll allow underscore
michael@0 905 // characters ('_'), too.
michael@0 906 nsACString::const_iterator p, end;
michael@0 907 aURI.BeginReading(p);
michael@0 908 aURI.EndReading(end);
michael@0 909 while (p != end && IsLegalSchemeCharacter(*p))
michael@0 910 ++p;
michael@0 911
michael@0 912 nsresult rv;
michael@0 913 nsCOMPtr<nsIFactory> factory;
michael@0 914
michael@0 915 nsACString::const_iterator begin;
michael@0 916 aURI.BeginReading(begin);
michael@0 917 if (*p == ':') {
michael@0 918 // There _was_ a scheme. First see if it's the same scheme
michael@0 919 // that we just tried to use...
michael@0 920 if (mLastFactory && mLastURIPrefix.Equals(Substring(begin, p)))
michael@0 921 factory = mLastFactory;
michael@0 922 else {
michael@0 923 // Try to find a factory using the component manager.
michael@0 924 nsACString::const_iterator begin;
michael@0 925 aURI.BeginReading(begin);
michael@0 926 nsAutoCString contractID;
michael@0 927 contractID = NS_LITERAL_CSTRING(NS_RDF_RESOURCE_FACTORY_CONTRACTID_PREFIX) +
michael@0 928 Substring(begin, p);
michael@0 929
michael@0 930 factory = do_GetClassObject(contractID.get());
michael@0 931 if (factory) {
michael@0 932 // Store the factory in our one-element cache.
michael@0 933 if (p != begin) {
michael@0 934 mLastFactory = factory;
michael@0 935 mLastURIPrefix = Substring(begin, p);
michael@0 936 }
michael@0 937 }
michael@0 938 }
michael@0 939 }
michael@0 940
michael@0 941 if (! factory) {
michael@0 942 // fall through to using the "default" resource factory if either:
michael@0 943 //
michael@0 944 // 1. The URI didn't have a scheme, or
michael@0 945 // 2. There was no resource factory registered for the scheme.
michael@0 946 factory = mDefaultResourceFactory;
michael@0 947
michael@0 948 // Store the factory in our one-element cache.
michael@0 949 if (p != begin) {
michael@0 950 mLastFactory = factory;
michael@0 951 mLastURIPrefix = Substring(begin, p);
michael@0 952 }
michael@0 953 }
michael@0 954
michael@0 955 nsIRDFResource *result;
michael@0 956 rv = factory->CreateInstance(nullptr, NS_GET_IID(nsIRDFResource), (void**) &result);
michael@0 957 if (NS_FAILED(rv)) return rv;
michael@0 958
michael@0 959 // Now initialize it with its URI. At this point, the resource
michael@0 960 // implementation should register itself with the RDF service.
michael@0 961 rv = result->Init(flatURI.get());
michael@0 962 if (NS_FAILED(rv)) {
michael@0 963 NS_ERROR("unable to initialize resource");
michael@0 964 NS_RELEASE(result);
michael@0 965 return rv;
michael@0 966 }
michael@0 967
michael@0 968 *aResource = result; // already refcounted from repository
michael@0 969 return rv;
michael@0 970 }
michael@0 971
michael@0 972 NS_IMETHODIMP
michael@0 973 RDFServiceImpl::GetUnicodeResource(const nsAString& aURI, nsIRDFResource** aResource)
michael@0 974 {
michael@0 975 return GetResource(NS_ConvertUTF16toUTF8(aURI), aResource);
michael@0 976 }
michael@0 977
michael@0 978
michael@0 979 NS_IMETHODIMP
michael@0 980 RDFServiceImpl::GetAnonymousResource(nsIRDFResource** aResult)
michael@0 981 {
michael@0 982 static uint32_t gCounter = 0;
michael@0 983 static char gChars[] = "0123456789abcdef"
michael@0 984 "ghijklmnopqrstuv"
michael@0 985 "wxyzABCDEFGHIJKL"
michael@0 986 "MNOPQRSTUVWXYZ.+";
michael@0 987
michael@0 988 static int32_t kMask = 0x003f;
michael@0 989 static int32_t kShift = 6;
michael@0 990
michael@0 991 if (! gCounter) {
michael@0 992 // Start it at a semi-unique value, just to minimize the
michael@0 993 // chance that we get into a situation where
michael@0 994 //
michael@0 995 // 1. An anonymous resource gets serialized out in a graph
michael@0 996 // 2. Reboot
michael@0 997 // 3. The same anonymous resource gets requested, and refers
michael@0 998 // to something completely different.
michael@0 999 // 4. The serialization is read back in.
michael@0 1000 gCounter = uint32_t(PR_Now());
michael@0 1001 }
michael@0 1002
michael@0 1003 nsresult rv;
michael@0 1004 nsAutoCString s;
michael@0 1005
michael@0 1006 do {
michael@0 1007 // Ugh, this is a really sloppy way to do this; I copied the
michael@0 1008 // implementation from the days when it lived outside the RDF
michael@0 1009 // service. Now that it's a member we can be more cleverer.
michael@0 1010
michael@0 1011 s.Truncate();
michael@0 1012 s.Append("rdf:#$");
michael@0 1013
michael@0 1014 uint32_t id = ++gCounter;
michael@0 1015 while (id) {
michael@0 1016 char ch = gChars[(id & kMask)];
michael@0 1017 s.Append(ch);
michael@0 1018 id >>= kShift;
michael@0 1019 }
michael@0 1020
michael@0 1021 nsIRDFResource* resource;
michael@0 1022 rv = GetResource(s, &resource);
michael@0 1023 if (NS_FAILED(rv)) return rv;
michael@0 1024
michael@0 1025 // XXX an ugly but effective way to make sure that this
michael@0 1026 // resource is really unique in the world.
michael@0 1027 resource->AddRef();
michael@0 1028 nsrefcnt refcnt = resource->Release();
michael@0 1029
michael@0 1030 if (refcnt == 1) {
michael@0 1031 *aResult = resource;
michael@0 1032 break;
michael@0 1033 }
michael@0 1034
michael@0 1035 NS_RELEASE(resource);
michael@0 1036 } while (1);
michael@0 1037
michael@0 1038 return NS_OK;
michael@0 1039 }
michael@0 1040
michael@0 1041
michael@0 1042 NS_IMETHODIMP
michael@0 1043 RDFServiceImpl::GetLiteral(const char16_t* aValue, nsIRDFLiteral** aLiteral)
michael@0 1044 {
michael@0 1045 NS_PRECONDITION(aValue != nullptr, "null ptr");
michael@0 1046 if (! aValue)
michael@0 1047 return NS_ERROR_NULL_POINTER;
michael@0 1048
michael@0 1049 NS_PRECONDITION(aLiteral != nullptr, "null ptr");
michael@0 1050 if (! aLiteral)
michael@0 1051 return NS_ERROR_NULL_POINTER;
michael@0 1052
michael@0 1053 // See if we have one already cached
michael@0 1054 PLDHashEntryHdr *hdr =
michael@0 1055 PL_DHashTableOperate(&mLiterals, aValue, PL_DHASH_LOOKUP);
michael@0 1056
michael@0 1057 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
michael@0 1058 LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
michael@0 1059 NS_ADDREF(*aLiteral = entry->mLiteral);
michael@0 1060 return NS_OK;
michael@0 1061 }
michael@0 1062
michael@0 1063 // Nope. Create a new one
michael@0 1064 return LiteralImpl::Create(aValue, aLiteral);
michael@0 1065 }
michael@0 1066
michael@0 1067 NS_IMETHODIMP
michael@0 1068 RDFServiceImpl::GetDateLiteral(PRTime aTime, nsIRDFDate** aResult)
michael@0 1069 {
michael@0 1070 // See if we have one already cached
michael@0 1071 PLDHashEntryHdr *hdr =
michael@0 1072 PL_DHashTableOperate(&mDates, &aTime, PL_DHASH_LOOKUP);
michael@0 1073
michael@0 1074 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
michael@0 1075 DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
michael@0 1076 NS_ADDREF(*aResult = entry->mDate);
michael@0 1077 return NS_OK;
michael@0 1078 }
michael@0 1079
michael@0 1080 DateImpl* result = new DateImpl(aTime);
michael@0 1081 if (! result)
michael@0 1082 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1083
michael@0 1084 NS_ADDREF(*aResult = result);
michael@0 1085 return NS_OK;
michael@0 1086 }
michael@0 1087
michael@0 1088 NS_IMETHODIMP
michael@0 1089 RDFServiceImpl::GetIntLiteral(int32_t aInt, nsIRDFInt** aResult)
michael@0 1090 {
michael@0 1091 // See if we have one already cached
michael@0 1092 PLDHashEntryHdr *hdr =
michael@0 1093 PL_DHashTableOperate(&mInts, &aInt, PL_DHASH_LOOKUP);
michael@0 1094
michael@0 1095 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
michael@0 1096 IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
michael@0 1097 NS_ADDREF(*aResult = entry->mInt);
michael@0 1098 return NS_OK;
michael@0 1099 }
michael@0 1100
michael@0 1101 IntImpl* result = new IntImpl(aInt);
michael@0 1102 if (! result)
michael@0 1103 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1104
michael@0 1105 NS_ADDREF(*aResult = result);
michael@0 1106 return NS_OK;
michael@0 1107 }
michael@0 1108
michael@0 1109 NS_IMETHODIMP
michael@0 1110 RDFServiceImpl::GetBlobLiteral(const uint8_t *aBytes, int32_t aLength,
michael@0 1111 nsIRDFBlob **aResult)
michael@0 1112 {
michael@0 1113 BlobImpl::Data key = { aLength, const_cast<uint8_t *>(aBytes) };
michael@0 1114
michael@0 1115 PLDHashEntryHdr *hdr =
michael@0 1116 PL_DHashTableOperate(&mBlobs, &key, PL_DHASH_LOOKUP);
michael@0 1117
michael@0 1118 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
michael@0 1119 BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
michael@0 1120 NS_ADDREF(*aResult = entry->mBlob);
michael@0 1121 return NS_OK;
michael@0 1122 }
michael@0 1123
michael@0 1124 BlobImpl *result = new BlobImpl(aBytes, aLength);
michael@0 1125 if (! result)
michael@0 1126 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1127
michael@0 1128 NS_ADDREF(*aResult = result);
michael@0 1129 return NS_OK;
michael@0 1130 }
michael@0 1131
michael@0 1132 NS_IMETHODIMP
michael@0 1133 RDFServiceImpl::IsAnonymousResource(nsIRDFResource* aResource, bool* _result)
michael@0 1134 {
michael@0 1135 NS_PRECONDITION(aResource != nullptr, "null ptr");
michael@0 1136 if (! aResource)
michael@0 1137 return NS_ERROR_NULL_POINTER;
michael@0 1138
michael@0 1139 nsresult rv;
michael@0 1140
michael@0 1141 const char* uri;
michael@0 1142 rv = aResource->GetValueConst(&uri);
michael@0 1143 if (NS_FAILED(rv)) return rv;
michael@0 1144
michael@0 1145 if ((uri[0] == 'r') &&
michael@0 1146 (uri[1] == 'd') &&
michael@0 1147 (uri[2] == 'f') &&
michael@0 1148 (uri[3] == ':') &&
michael@0 1149 (uri[4] == '#') &&
michael@0 1150 (uri[5] == '$')) {
michael@0 1151 *_result = true;
michael@0 1152 }
michael@0 1153 else {
michael@0 1154 *_result = false;
michael@0 1155 }
michael@0 1156
michael@0 1157 return NS_OK;
michael@0 1158 }
michael@0 1159
michael@0 1160 NS_IMETHODIMP
michael@0 1161 RDFServiceImpl::RegisterResource(nsIRDFResource* aResource, bool aReplace)
michael@0 1162 {
michael@0 1163 NS_PRECONDITION(aResource != nullptr, "null ptr");
michael@0 1164 if (! aResource)
michael@0 1165 return NS_ERROR_NULL_POINTER;
michael@0 1166
michael@0 1167 nsresult rv;
michael@0 1168
michael@0 1169 const char* uri;
michael@0 1170 rv = aResource->GetValueConst(&uri);
michael@0 1171 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get URI from resource");
michael@0 1172 if (NS_FAILED(rv)) return rv;
michael@0 1173
michael@0 1174 NS_ASSERTION(uri != nullptr, "resource has no URI");
michael@0 1175 if (! uri)
michael@0 1176 return NS_ERROR_NULL_POINTER;
michael@0 1177
michael@0 1178 PLDHashEntryHdr *hdr =
michael@0 1179 PL_DHashTableOperate(&mResources, uri, PL_DHASH_LOOKUP);
michael@0 1180
michael@0 1181 if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
michael@0 1182 if (!aReplace) {
michael@0 1183 NS_WARNING("resource already registered, and replace not specified");
michael@0 1184 return NS_ERROR_FAILURE; // already registered
michael@0 1185 }
michael@0 1186
michael@0 1187 // N.B., we do _not_ release the original resource because we
michael@0 1188 // only ever held a weak reference to it. We simply replace
michael@0 1189 // it.
michael@0 1190
michael@0 1191 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1192 ("rdfserv replace-resource [%p] <-- [%p] %s",
michael@0 1193 static_cast<ResourceHashEntry *>(hdr)->mResource,
michael@0 1194 aResource, (const char*) uri));
michael@0 1195 }
michael@0 1196 else {
michael@0 1197 hdr = PL_DHashTableOperate(&mResources, uri, PL_DHASH_ADD);
michael@0 1198 if (! hdr)
michael@0 1199 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1200
michael@0 1201 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1202 ("rdfserv register-resource [%p] %s",
michael@0 1203 aResource, (const char*) uri));
michael@0 1204 }
michael@0 1205
michael@0 1206 // N.B., we only hold a weak reference to the resource: that way,
michael@0 1207 // the resource can be destroyed when the last refcount goes
michael@0 1208 // away. The single addref that the CreateResource() call made
michael@0 1209 // will be owned by the callee.
michael@0 1210 ResourceHashEntry *entry = static_cast<ResourceHashEntry *>(hdr);
michael@0 1211 entry->mResource = aResource;
michael@0 1212 entry->mKey = uri;
michael@0 1213
michael@0 1214 return NS_OK;
michael@0 1215 }
michael@0 1216
michael@0 1217 NS_IMETHODIMP
michael@0 1218 RDFServiceImpl::UnregisterResource(nsIRDFResource* aResource)
michael@0 1219 {
michael@0 1220 NS_PRECONDITION(aResource != nullptr, "null ptr");
michael@0 1221 if (! aResource)
michael@0 1222 return NS_ERROR_NULL_POINTER;
michael@0 1223
michael@0 1224 nsresult rv;
michael@0 1225
michael@0 1226 const char* uri;
michael@0 1227 rv = aResource->GetValueConst(&uri);
michael@0 1228 if (NS_FAILED(rv)) return rv;
michael@0 1229
michael@0 1230 NS_ASSERTION(uri != nullptr, "resource has no URI");
michael@0 1231 if (! uri)
michael@0 1232 return NS_ERROR_UNEXPECTED;
michael@0 1233
michael@0 1234 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1235 ("rdfserv unregister-resource [%p] %s",
michael@0 1236 aResource, (const char*) uri));
michael@0 1237
michael@0 1238 #ifdef DEBUG
michael@0 1239 if (PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mResources, uri, PL_DHASH_LOOKUP)))
michael@0 1240 NS_WARNING("resource was never registered");
michael@0 1241 #endif
michael@0 1242
michael@0 1243 PL_DHashTableOperate(&mResources, uri, PL_DHASH_REMOVE);
michael@0 1244 return NS_OK;
michael@0 1245 }
michael@0 1246
michael@0 1247 NS_IMETHODIMP
michael@0 1248 RDFServiceImpl::RegisterDataSource(nsIRDFDataSource* aDataSource, bool aReplace)
michael@0 1249 {
michael@0 1250 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
michael@0 1251 if (! aDataSource)
michael@0 1252 return NS_ERROR_NULL_POINTER;
michael@0 1253
michael@0 1254 nsresult rv;
michael@0 1255
michael@0 1256 nsXPIDLCString uri;
michael@0 1257 rv = aDataSource->GetURI(getter_Copies(uri));
michael@0 1258 if (NS_FAILED(rv)) return rv;
michael@0 1259
michael@0 1260 PLHashEntry** hep =
michael@0 1261 PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
michael@0 1262
michael@0 1263 if (*hep) {
michael@0 1264 if (! aReplace)
michael@0 1265 return NS_ERROR_FAILURE; // already registered
michael@0 1266
michael@0 1267 // N.B., we only hold a weak reference to the datasource, so
michael@0 1268 // just replace the old with the new and don't touch any
michael@0 1269 // refcounts.
michael@0 1270 PR_LOG(gLog, PR_LOG_NOTICE,
michael@0 1271 ("rdfserv replace-datasource [%p] <-- [%p] %s",
michael@0 1272 (*hep)->value, aDataSource, (const char*) uri));
michael@0 1273
michael@0 1274 (*hep)->value = aDataSource;
michael@0 1275 }
michael@0 1276 else {
michael@0 1277 const char* key = PL_strdup(uri);
michael@0 1278 if (! key)
michael@0 1279 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1280
michael@0 1281 PL_HashTableAdd(mNamedDataSources, key, aDataSource);
michael@0 1282
michael@0 1283 PR_LOG(gLog, PR_LOG_NOTICE,
michael@0 1284 ("rdfserv register-datasource [%p] %s",
michael@0 1285 aDataSource, (const char*) uri));
michael@0 1286
michael@0 1287 // N.B., we only hold a weak reference to the datasource, so don't
michael@0 1288 // addref.
michael@0 1289 }
michael@0 1290
michael@0 1291 return NS_OK;
michael@0 1292 }
michael@0 1293
michael@0 1294 NS_IMETHODIMP
michael@0 1295 RDFServiceImpl::UnregisterDataSource(nsIRDFDataSource* aDataSource)
michael@0 1296 {
michael@0 1297 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
michael@0 1298 if (! aDataSource)
michael@0 1299 return NS_ERROR_NULL_POINTER;
michael@0 1300
michael@0 1301 nsresult rv;
michael@0 1302
michael@0 1303 nsXPIDLCString uri;
michael@0 1304 rv = aDataSource->GetURI(getter_Copies(uri));
michael@0 1305 if (NS_FAILED(rv)) return rv;
michael@0 1306
michael@0 1307 //NS_ASSERTION(uri != nullptr, "datasource has no URI");
michael@0 1308 if (! uri)
michael@0 1309 return NS_ERROR_UNEXPECTED;
michael@0 1310
michael@0 1311 PLHashEntry** hep =
michael@0 1312 PL_HashTableRawLookup(mNamedDataSources, (*mNamedDataSources->keyHash)(uri), uri);
michael@0 1313
michael@0 1314 // It may well be that this datasource was never registered. If
michael@0 1315 // so, don't unregister it.
michael@0 1316 if (! *hep || ((*hep)->value != aDataSource))
michael@0 1317 return NS_OK;
michael@0 1318
michael@0 1319 // N.B., we only held a weak reference to the datasource, so we
michael@0 1320 // don't release here.
michael@0 1321 PL_HashTableRawRemove(mNamedDataSources, hep, *hep);
michael@0 1322
michael@0 1323 PR_LOG(gLog, PR_LOG_NOTICE,
michael@0 1324 ("rdfserv unregister-datasource [%p] %s",
michael@0 1325 aDataSource, (const char*) uri));
michael@0 1326
michael@0 1327 return NS_OK;
michael@0 1328 }
michael@0 1329
michael@0 1330 NS_IMETHODIMP
michael@0 1331 RDFServiceImpl::GetDataSource(const char* aURI, nsIRDFDataSource** aDataSource)
michael@0 1332 {
michael@0 1333 // Use the other GetDataSource and ask for a non-blocking Refresh.
michael@0 1334 // If you wanted it loaded synchronously, then you should've tried to do it
michael@0 1335 // yourself, or used GetDataSourceBlocking.
michael@0 1336 return GetDataSource( aURI, false, aDataSource );
michael@0 1337 }
michael@0 1338
michael@0 1339 NS_IMETHODIMP
michael@0 1340 RDFServiceImpl::GetDataSourceBlocking(const char* aURI, nsIRDFDataSource** aDataSource)
michael@0 1341 {
michael@0 1342 // Use GetDataSource and ask for a blocking Refresh.
michael@0 1343 return GetDataSource( aURI, true, aDataSource );
michael@0 1344 }
michael@0 1345
michael@0 1346 nsresult
michael@0 1347 RDFServiceImpl::GetDataSource(const char* aURI, bool aBlock, nsIRDFDataSource** aDataSource)
michael@0 1348 {
michael@0 1349 NS_PRECONDITION(aURI != nullptr, "null ptr");
michael@0 1350 if (! aURI)
michael@0 1351 return NS_ERROR_NULL_POINTER;
michael@0 1352
michael@0 1353 nsresult rv;
michael@0 1354
michael@0 1355 // Attempt to canonify the URI before we look for it in the
michael@0 1356 // cache. We won't bother doing this on `rdf:' URIs to avoid
michael@0 1357 // useless (and expensive) protocol handler lookups.
michael@0 1358 nsAutoCString spec(aURI);
michael@0 1359
michael@0 1360 if (!StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
michael@0 1361 nsCOMPtr<nsIURI> uri;
michael@0 1362 NS_NewURI(getter_AddRefs(uri), spec);
michael@0 1363 if (uri)
michael@0 1364 uri->GetSpec(spec);
michael@0 1365 }
michael@0 1366
michael@0 1367 // First, check the cache to see if we already have this
michael@0 1368 // datasource loaded and initialized.
michael@0 1369 {
michael@0 1370 nsIRDFDataSource* cached =
michael@0 1371 static_cast<nsIRDFDataSource*>(PL_HashTableLookup(mNamedDataSources, spec.get()));
michael@0 1372
michael@0 1373 if (cached) {
michael@0 1374 NS_ADDREF(cached);
michael@0 1375 *aDataSource = cached;
michael@0 1376 return NS_OK;
michael@0 1377 }
michael@0 1378 }
michael@0 1379
michael@0 1380 // Nope. So go to the repository to try to create it.
michael@0 1381 nsCOMPtr<nsIRDFDataSource> ds;
michael@0 1382 if (StringBeginsWith(spec, NS_LITERAL_CSTRING("rdf:"))) {
michael@0 1383 // It's a built-in data source. Convert it to a contract ID.
michael@0 1384 nsAutoCString contractID(
michael@0 1385 NS_LITERAL_CSTRING(NS_RDF_DATASOURCE_CONTRACTID_PREFIX) +
michael@0 1386 Substring(spec, 4, spec.Length() - 4));
michael@0 1387
michael@0 1388 // Strip params to get ``base'' contractID for data source.
michael@0 1389 int32_t p = contractID.FindChar(char16_t('&'));
michael@0 1390 if (p >= 0)
michael@0 1391 contractID.Truncate(p);
michael@0 1392
michael@0 1393 ds = do_GetService(contractID.get(), &rv);
michael@0 1394 if (NS_FAILED(rv)) return rv;
michael@0 1395
michael@0 1396 nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(ds);
michael@0 1397 if (remote) {
michael@0 1398 rv = remote->Init(spec.get());
michael@0 1399 if (NS_FAILED(rv)) return rv;
michael@0 1400 }
michael@0 1401 }
michael@0 1402 else {
michael@0 1403 // Try to load this as an RDF/XML data source
michael@0 1404 ds = do_CreateInstance(kRDFXMLDataSourceCID, &rv);
michael@0 1405 if (NS_FAILED(rv)) return rv;
michael@0 1406
michael@0 1407 nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(ds));
michael@0 1408 NS_ASSERTION(remote, "not a remote RDF/XML data source!");
michael@0 1409 if (! remote) return NS_ERROR_UNEXPECTED;
michael@0 1410
michael@0 1411 rv = remote->Init(spec.get());
michael@0 1412 if (NS_FAILED(rv)) return rv;
michael@0 1413
michael@0 1414 rv = remote->Refresh(aBlock);
michael@0 1415 if (NS_FAILED(rv)) return rv;
michael@0 1416 }
michael@0 1417
michael@0 1418 *aDataSource = ds;
michael@0 1419 NS_ADDREF(*aDataSource);
michael@0 1420 return NS_OK;
michael@0 1421 }
michael@0 1422
michael@0 1423 ////////////////////////////////////////////////////////////////////////
michael@0 1424
michael@0 1425 nsresult
michael@0 1426 RDFServiceImpl::RegisterLiteral(nsIRDFLiteral* aLiteral)
michael@0 1427 {
michael@0 1428 const char16_t* value;
michael@0 1429 aLiteral->GetValueConst(&value);
michael@0 1430
michael@0 1431 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mLiterals,
michael@0 1432 value,
michael@0 1433 PL_DHASH_LOOKUP)),
michael@0 1434 "literal already registered");
michael@0 1435
michael@0 1436 PLDHashEntryHdr *hdr =
michael@0 1437 PL_DHashTableOperate(&mLiterals, value, PL_DHASH_ADD);
michael@0 1438
michael@0 1439 if (! hdr)
michael@0 1440 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1441
michael@0 1442 LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
michael@0 1443
michael@0 1444 // N.B., we only hold a weak reference to the literal: that
michael@0 1445 // way, the literal can be destroyed when the last refcount
michael@0 1446 // goes away. The single addref that the CreateLiteral() call
michael@0 1447 // made will be owned by the callee.
michael@0 1448 entry->mLiteral = aLiteral;
michael@0 1449 entry->mKey = value;
michael@0 1450
michael@0 1451 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1452 ("rdfserv register-literal [%p] %s",
michael@0 1453 aLiteral, (const char16_t*) value));
michael@0 1454
michael@0 1455 return NS_OK;
michael@0 1456 }
michael@0 1457
michael@0 1458
michael@0 1459 nsresult
michael@0 1460 RDFServiceImpl::UnregisterLiteral(nsIRDFLiteral* aLiteral)
michael@0 1461 {
michael@0 1462 const char16_t* value;
michael@0 1463 aLiteral->GetValueConst(&value);
michael@0 1464
michael@0 1465 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mLiterals,
michael@0 1466 value,
michael@0 1467 PL_DHASH_LOOKUP)),
michael@0 1468 "literal was never registered");
michael@0 1469
michael@0 1470 PL_DHashTableOperate(&mLiterals, value, PL_DHASH_REMOVE);
michael@0 1471
michael@0 1472 // N.B. that we _don't_ release the literal: we only held a weak
michael@0 1473 // reference to it in the hashtable.
michael@0 1474 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1475 ("rdfserv unregister-literal [%p] %s",
michael@0 1476 aLiteral, (const char16_t*) value));
michael@0 1477
michael@0 1478 return NS_OK;
michael@0 1479 }
michael@0 1480
michael@0 1481 //----------------------------------------------------------------------
michael@0 1482
michael@0 1483 nsresult
michael@0 1484 RDFServiceImpl::RegisterInt(nsIRDFInt* aInt)
michael@0 1485 {
michael@0 1486 int32_t value;
michael@0 1487 aInt->GetValue(&value);
michael@0 1488
michael@0 1489 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mInts,
michael@0 1490 &value,
michael@0 1491 PL_DHASH_LOOKUP)),
michael@0 1492 "int already registered");
michael@0 1493
michael@0 1494 PLDHashEntryHdr *hdr =
michael@0 1495 PL_DHashTableOperate(&mInts, &value, PL_DHASH_ADD);
michael@0 1496
michael@0 1497 if (! hdr)
michael@0 1498 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1499
michael@0 1500 IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
michael@0 1501
michael@0 1502 // N.B., we only hold a weak reference to the literal: that
michael@0 1503 // way, the literal can be destroyed when the last refcount
michael@0 1504 // goes away. The single addref that the CreateInt() call
michael@0 1505 // made will be owned by the callee.
michael@0 1506 entry->mInt = aInt;
michael@0 1507 entry->mKey = value;
michael@0 1508
michael@0 1509 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1510 ("rdfserv register-int [%p] %d",
michael@0 1511 aInt, value));
michael@0 1512
michael@0 1513 return NS_OK;
michael@0 1514 }
michael@0 1515
michael@0 1516
michael@0 1517 nsresult
michael@0 1518 RDFServiceImpl::UnregisterInt(nsIRDFInt* aInt)
michael@0 1519 {
michael@0 1520 int32_t value;
michael@0 1521 aInt->GetValue(&value);
michael@0 1522
michael@0 1523 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mInts,
michael@0 1524 &value,
michael@0 1525 PL_DHASH_LOOKUP)),
michael@0 1526 "int was never registered");
michael@0 1527
michael@0 1528 PL_DHashTableOperate(&mInts, &value, PL_DHASH_REMOVE);
michael@0 1529
michael@0 1530 // N.B. that we _don't_ release the literal: we only held a weak
michael@0 1531 // reference to it in the hashtable.
michael@0 1532 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1533 ("rdfserv unregister-int [%p] %d",
michael@0 1534 aInt, value));
michael@0 1535
michael@0 1536 return NS_OK;
michael@0 1537 }
michael@0 1538
michael@0 1539 //----------------------------------------------------------------------
michael@0 1540
michael@0 1541 nsresult
michael@0 1542 RDFServiceImpl::RegisterDate(nsIRDFDate* aDate)
michael@0 1543 {
michael@0 1544 PRTime value;
michael@0 1545 aDate->GetValue(&value);
michael@0 1546
michael@0 1547 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mDates,
michael@0 1548 &value,
michael@0 1549 PL_DHASH_LOOKUP)),
michael@0 1550 "date already registered");
michael@0 1551
michael@0 1552 PLDHashEntryHdr *hdr =
michael@0 1553 PL_DHashTableOperate(&mDates, &value, PL_DHASH_ADD);
michael@0 1554
michael@0 1555 if (! hdr)
michael@0 1556 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1557
michael@0 1558 DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
michael@0 1559
michael@0 1560 // N.B., we only hold a weak reference to the literal: that
michael@0 1561 // way, the literal can be destroyed when the last refcount
michael@0 1562 // goes away. The single addref that the CreateDate() call
michael@0 1563 // made will be owned by the callee.
michael@0 1564 entry->mDate = aDate;
michael@0 1565 entry->mKey = value;
michael@0 1566
michael@0 1567 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1568 ("rdfserv register-date [%p] %ld",
michael@0 1569 aDate, value));
michael@0 1570
michael@0 1571 return NS_OK;
michael@0 1572 }
michael@0 1573
michael@0 1574
michael@0 1575 nsresult
michael@0 1576 RDFServiceImpl::UnregisterDate(nsIRDFDate* aDate)
michael@0 1577 {
michael@0 1578 PRTime value;
michael@0 1579 aDate->GetValue(&value);
michael@0 1580
michael@0 1581 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mDates,
michael@0 1582 &value,
michael@0 1583 PL_DHASH_LOOKUP)),
michael@0 1584 "date was never registered");
michael@0 1585
michael@0 1586 PL_DHashTableOperate(&mDates, &value, PL_DHASH_REMOVE);
michael@0 1587
michael@0 1588 // N.B. that we _don't_ release the literal: we only held a weak
michael@0 1589 // reference to it in the hashtable.
michael@0 1590 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1591 ("rdfserv unregister-date [%p] %ld",
michael@0 1592 aDate, value));
michael@0 1593
michael@0 1594 return NS_OK;
michael@0 1595 }
michael@0 1596
michael@0 1597 nsresult
michael@0 1598 RDFServiceImpl::RegisterBlob(BlobImpl *aBlob)
michael@0 1599 {
michael@0 1600 NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mBlobs,
michael@0 1601 &aBlob->mData,
michael@0 1602 PL_DHASH_LOOKUP)),
michael@0 1603 "blob already registered");
michael@0 1604
michael@0 1605 PLDHashEntryHdr *hdr =
michael@0 1606 PL_DHashTableOperate(&mBlobs, &aBlob->mData, PL_DHASH_ADD);
michael@0 1607
michael@0 1608 if (! hdr)
michael@0 1609 return NS_ERROR_OUT_OF_MEMORY;
michael@0 1610
michael@0 1611 BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
michael@0 1612
michael@0 1613 // N.B., we only hold a weak reference to the literal: that
michael@0 1614 // way, the literal can be destroyed when the last refcount
michael@0 1615 // goes away. The single addref that the CreateInt() call
michael@0 1616 // made will be owned by the callee.
michael@0 1617 entry->mBlob = aBlob;
michael@0 1618
michael@0 1619 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1620 ("rdfserv register-blob [%p] %s",
michael@0 1621 aBlob, aBlob->mData.mBytes));
michael@0 1622
michael@0 1623 return NS_OK;
michael@0 1624 }
michael@0 1625
michael@0 1626 nsresult
michael@0 1627 RDFServiceImpl::UnregisterBlob(BlobImpl *aBlob)
michael@0 1628 {
michael@0 1629 NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(PL_DHashTableOperate(&mBlobs,
michael@0 1630 &aBlob->mData,
michael@0 1631 PL_DHASH_LOOKUP)),
michael@0 1632 "blob was never registered");
michael@0 1633
michael@0 1634 PL_DHashTableOperate(&mBlobs, &aBlob->mData, PL_DHASH_REMOVE);
michael@0 1635
michael@0 1636 // N.B. that we _don't_ release the literal: we only held a weak
michael@0 1637 // reference to it in the hashtable.
michael@0 1638 PR_LOG(gLog, PR_LOG_DEBUG,
michael@0 1639 ("rdfserv unregister-blob [%p] %s",
michael@0 1640 aBlob, aBlob->mData.mBytes));
michael@0 1641
michael@0 1642 return NS_OK;
michael@0 1643 }

mercurial