Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
8 Implementation for the RDF container utils.
10 */
13 #include "nsCOMPtr.h"
14 #include "nsIServiceManager.h"
15 #include "nsIRDFContainer.h"
16 #include "nsIRDFContainerUtils.h"
17 #include "nsIRDFService.h"
18 #include "nsRDFCID.h"
19 #include "nsString.h"
20 #include "nsXPIDLString.h"
21 #include "plstr.h"
22 #include "prprf.h"
23 #include "rdf.h"
24 #include "rdfutil.h"
26 class RDFContainerUtilsImpl : public nsIRDFContainerUtils
27 {
28 public:
29 // nsISupports interface
30 NS_DECL_ISUPPORTS
32 // nsIRDFContainerUtils interface
33 NS_DECL_NSIRDFCONTAINERUTILS
35 private:
36 friend nsresult NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult);
38 RDFContainerUtilsImpl();
39 virtual ~RDFContainerUtilsImpl();
41 nsresult MakeContainer(nsIRDFDataSource* aDataSource,
42 nsIRDFResource* aResource,
43 nsIRDFResource* aType,
44 nsIRDFContainer** aResult);
46 bool IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType);
48 // pseudo constants
49 static int32_t gRefCnt;
50 static nsIRDFService* gRDFService;
51 static nsIRDFResource* kRDF_instanceOf;
52 static nsIRDFResource* kRDF_nextVal;
53 static nsIRDFResource* kRDF_Bag;
54 static nsIRDFResource* kRDF_Seq;
55 static nsIRDFResource* kRDF_Alt;
56 static nsIRDFLiteral* kOne;
57 static const char kRDFNameSpaceURI[];
58 };
60 int32_t RDFContainerUtilsImpl::gRefCnt = 0;
61 nsIRDFService* RDFContainerUtilsImpl::gRDFService;
62 nsIRDFResource* RDFContainerUtilsImpl::kRDF_instanceOf;
63 nsIRDFResource* RDFContainerUtilsImpl::kRDF_nextVal;
64 nsIRDFResource* RDFContainerUtilsImpl::kRDF_Bag;
65 nsIRDFResource* RDFContainerUtilsImpl::kRDF_Seq;
66 nsIRDFResource* RDFContainerUtilsImpl::kRDF_Alt;
67 nsIRDFLiteral* RDFContainerUtilsImpl::kOne;
68 const char RDFContainerUtilsImpl::kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
70 ////////////////////////////////////////////////////////////////////////
71 // nsISupports interface
73 NS_IMPL_ISUPPORTS(RDFContainerUtilsImpl, nsIRDFContainerUtils)
75 ////////////////////////////////////////////////////////////////////////
76 // nsIRDFContainerUtils interface
78 NS_IMETHODIMP
79 RDFContainerUtilsImpl::IsOrdinalProperty(nsIRDFResource *aProperty, bool *_retval)
80 {
81 NS_PRECONDITION(aProperty != nullptr, "null ptr");
82 if (! aProperty)
83 return NS_ERROR_NULL_POINTER;
85 nsresult rv;
87 const char *propertyStr;
88 rv = aProperty->GetValueConst( &propertyStr );
89 if (NS_FAILED(rv)) return rv;
91 if (PL_strncmp(propertyStr, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
92 *_retval = false;
93 return NS_OK;
94 }
96 const char* s = propertyStr;
97 s += sizeof(kRDFNameSpaceURI) - 1;
98 if (*s != '_') {
99 *_retval = false;
100 return NS_OK;
101 }
103 ++s;
104 while (*s) {
105 if (*s < '0' || *s > '9') {
106 *_retval = false;
107 return NS_OK;
108 }
110 ++s;
111 }
113 *_retval = true;
114 return NS_OK;
115 }
118 NS_IMETHODIMP
119 RDFContainerUtilsImpl::IndexToOrdinalResource(int32_t aIndex, nsIRDFResource **aOrdinal)
120 {
121 NS_PRECONDITION(aIndex > 0, "illegal value");
122 if (aIndex <= 0)
123 return NS_ERROR_ILLEGAL_VALUE;
125 nsAutoCString uri(kRDFNameSpaceURI);
126 uri.Append('_');
127 uri.AppendInt(aIndex);
129 nsresult rv = gRDFService->GetResource(uri, aOrdinal);
130 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get ordinal resource");
131 if (NS_FAILED(rv)) return rv;
133 return NS_OK;
134 }
137 NS_IMETHODIMP
138 RDFContainerUtilsImpl::OrdinalResourceToIndex(nsIRDFResource *aOrdinal, int32_t *aIndex)
139 {
140 NS_PRECONDITION(aOrdinal != nullptr, "null ptr");
141 if (! aOrdinal)
142 return NS_ERROR_NULL_POINTER;
144 const char *ordinalStr;
145 if (NS_FAILED(aOrdinal->GetValueConst( &ordinalStr )))
146 return NS_ERROR_FAILURE;
148 const char* s = ordinalStr;
149 if (PL_strncmp(s, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
150 NS_ERROR("not an ordinal");
151 return NS_ERROR_UNEXPECTED;
152 }
154 s += sizeof(kRDFNameSpaceURI) - 1;
155 if (*s != '_') {
156 NS_ERROR("not an ordinal");
157 return NS_ERROR_UNEXPECTED;
158 }
160 int32_t idx = 0;
162 ++s;
163 while (*s) {
164 if (*s < '0' || *s > '9') {
165 NS_ERROR("not an ordinal");
166 return NS_ERROR_UNEXPECTED;
167 }
169 idx *= 10;
170 idx += (*s - '0');
172 ++s;
173 }
175 *aIndex = idx;
176 return NS_OK;
177 }
179 NS_IMETHODIMP
180 RDFContainerUtilsImpl::IsContainer(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
181 {
182 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
183 if (! aDataSource)
184 return NS_ERROR_NULL_POINTER;
186 NS_PRECONDITION(aResource != nullptr, "null ptr");
187 if (! aResource)
188 return NS_ERROR_NULL_POINTER;
190 NS_PRECONDITION(_retval != nullptr, "null ptr");
191 if (! _retval)
192 return NS_ERROR_NULL_POINTER;
194 if (IsA(aDataSource, aResource, kRDF_Seq) ||
195 IsA(aDataSource, aResource, kRDF_Bag) ||
196 IsA(aDataSource, aResource, kRDF_Alt)) {
197 *_retval = true;
198 }
199 else {
200 *_retval = false;
201 }
202 return NS_OK;
203 }
206 NS_IMETHODIMP
207 RDFContainerUtilsImpl::IsEmpty(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, bool* _retval)
208 {
209 if (! aDataSource)
210 return NS_ERROR_NULL_POINTER;
212 nsresult rv;
214 // By default, say that we're an empty container. Even if we're not
215 // really even a container.
216 *_retval = true;
218 nsCOMPtr<nsIRDFNode> nextValNode;
219 rv = aDataSource->GetTarget(aResource, kRDF_nextVal, true, getter_AddRefs(nextValNode));
220 if (NS_FAILED(rv)) return rv;
222 if (rv == NS_RDF_NO_VALUE)
223 return NS_OK;
225 nsCOMPtr<nsIRDFLiteral> nextValLiteral;
226 rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
227 if (NS_FAILED(rv)) return rv;
229 if (nextValLiteral.get() != kOne)
230 *_retval = false;
232 return NS_OK;
233 }
236 NS_IMETHODIMP
237 RDFContainerUtilsImpl::IsBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
238 {
239 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
240 if (! aDataSource)
241 return NS_ERROR_NULL_POINTER;
243 NS_PRECONDITION(aResource != nullptr, "null ptr");
244 if (! aResource)
245 return NS_ERROR_NULL_POINTER;
247 NS_PRECONDITION(_retval != nullptr, "null ptr");
248 if (! _retval)
249 return NS_ERROR_NULL_POINTER;
251 *_retval = IsA(aDataSource, aResource, kRDF_Bag);
252 return NS_OK;
253 }
256 NS_IMETHODIMP
257 RDFContainerUtilsImpl::IsSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
258 {
259 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
260 if (! aDataSource)
261 return NS_ERROR_NULL_POINTER;
263 NS_PRECONDITION(aResource != nullptr, "null ptr");
264 if (! aResource)
265 return NS_ERROR_NULL_POINTER;
267 NS_PRECONDITION(_retval != nullptr, "null ptr");
268 if (! _retval)
269 return NS_ERROR_NULL_POINTER;
271 *_retval = IsA(aDataSource, aResource, kRDF_Seq);
272 return NS_OK;
273 }
276 NS_IMETHODIMP
277 RDFContainerUtilsImpl::IsAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
278 {
279 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
280 if (! aDataSource)
281 return NS_ERROR_NULL_POINTER;
283 NS_PRECONDITION(aResource != nullptr, "null ptr");
284 if (! aResource)
285 return NS_ERROR_NULL_POINTER;
287 NS_PRECONDITION(_retval != nullptr, "null ptr");
288 if (! _retval)
289 return NS_ERROR_NULL_POINTER;
291 *_retval = IsA(aDataSource, aResource, kRDF_Alt);
292 return NS_OK;
293 }
296 NS_IMETHODIMP
297 RDFContainerUtilsImpl::MakeBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
298 {
299 return MakeContainer(aDataSource, aResource, kRDF_Bag, _retval);
300 }
303 NS_IMETHODIMP
304 RDFContainerUtilsImpl::MakeSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
305 {
306 return MakeContainer(aDataSource, aResource, kRDF_Seq, _retval);
307 }
310 NS_IMETHODIMP
311 RDFContainerUtilsImpl::MakeAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
312 {
313 return MakeContainer(aDataSource, aResource, kRDF_Alt, _retval);
314 }
318 ////////////////////////////////////////////////////////////////////////
321 RDFContainerUtilsImpl::RDFContainerUtilsImpl()
322 {
323 if (gRefCnt++ == 0) {
324 nsresult rv;
326 NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
327 rv = CallGetService(kRDFServiceCID, &gRDFService);
329 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
330 if (NS_SUCCEEDED(rv)) {
331 gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
332 &kRDF_instanceOf);
333 gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
334 &kRDF_nextVal);
335 gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Bag"),
336 &kRDF_Bag);
337 gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Seq"),
338 &kRDF_Seq);
339 gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Alt"),
340 &kRDF_Alt);
341 gRDFService->GetLiteral(MOZ_UTF16("1"), &kOne);
342 }
343 }
344 }
347 RDFContainerUtilsImpl::~RDFContainerUtilsImpl()
348 {
349 #ifdef DEBUG_REFS
350 --gInstanceCount;
351 fprintf(stdout, "%d - RDF: RDFContainerUtilsImpl\n", gInstanceCount);
352 #endif
354 if (--gRefCnt == 0) {
355 NS_IF_RELEASE(gRDFService);
356 NS_IF_RELEASE(kRDF_instanceOf);
357 NS_IF_RELEASE(kRDF_nextVal);
358 NS_IF_RELEASE(kRDF_Bag);
359 NS_IF_RELEASE(kRDF_Seq);
360 NS_IF_RELEASE(kRDF_Alt);
361 NS_IF_RELEASE(kOne);
362 }
363 }
367 nsresult
368 NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult)
369 {
370 NS_PRECONDITION(aResult != nullptr, "null ptr");
371 if (! aResult)
372 return NS_ERROR_NULL_POINTER;
374 RDFContainerUtilsImpl* result =
375 new RDFContainerUtilsImpl();
377 if (! result)
378 return NS_ERROR_OUT_OF_MEMORY;
380 NS_ADDREF(result);
381 *aResult = result;
382 return NS_OK;
383 }
386 nsresult
387 RDFContainerUtilsImpl::MakeContainer(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType, nsIRDFContainer** aResult)
388 {
389 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
390 if (! aDataSource) return NS_ERROR_NULL_POINTER;
392 NS_PRECONDITION(aResource != nullptr, "null ptr");
393 if (! aResource) return NS_ERROR_NULL_POINTER;
395 NS_PRECONDITION(aType != nullptr, "null ptr");
396 if (! aType) return NS_ERROR_NULL_POINTER;
398 if (aResult) *aResult = nullptr;
400 nsresult rv;
402 // Check to see if somebody has already turned it into a container; if so
403 // don't try to do it again.
404 bool isContainer;
405 rv = IsContainer(aDataSource, aResource, &isContainer);
406 if (NS_FAILED(rv)) return rv;
408 if (!isContainer)
409 {
410 rv = aDataSource->Assert(aResource, kRDF_instanceOf, aType, true);
411 if (NS_FAILED(rv)) return rv;
413 rv = aDataSource->Assert(aResource, kRDF_nextVal, kOne, true);
414 if (NS_FAILED(rv)) return rv;
415 }
417 if (aResult) {
418 rv = NS_NewRDFContainer(aResult);
419 if (NS_FAILED(rv)) return rv;
421 rv = (*aResult)->Init(aDataSource, aResource);
422 if (NS_FAILED(rv)) return rv;
423 }
425 return NS_OK;
426 }
428 bool
429 RDFContainerUtilsImpl::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType)
430 {
431 if (!aDataSource || !aResource || !aType) {
432 NS_WARNING("Unexpected null argument");
433 return false;
434 }
436 nsresult rv;
438 bool result;
439 rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, true, &result);
440 if (NS_FAILED(rv))
441 return false;
443 return result;
444 }
446 NS_IMETHODIMP
447 RDFContainerUtilsImpl::IndexOf(nsIRDFDataSource* aDataSource, nsIRDFResource* aContainer, nsIRDFNode* aElement, int32_t* aIndex)
448 {
449 if (!aDataSource || !aContainer)
450 return NS_ERROR_NULL_POINTER;
452 // Assume we can't find it.
453 *aIndex = -1;
455 // If the resource is null, bail quietly
456 if (! aElement)
457 return NS_OK;
459 // We'll assume that fan-out is much higher than fan-in, so grovel
460 // through the inbound arcs, look for an ordinal resource, and
461 // decode it.
462 nsCOMPtr<nsISimpleEnumerator> arcsIn;
463 aDataSource->ArcLabelsIn(aElement, getter_AddRefs(arcsIn));
464 if (! arcsIn)
465 return NS_OK;
467 while (1) {
468 bool hasMoreArcs = false;
469 arcsIn->HasMoreElements(&hasMoreArcs);
470 if (! hasMoreArcs)
471 break;
473 nsCOMPtr<nsISupports> isupports;
474 arcsIn->GetNext(getter_AddRefs(isupports));
475 if (! isupports)
476 break;
478 nsCOMPtr<nsIRDFResource> property =
479 do_QueryInterface(isupports);
481 if (! property)
482 continue;
484 bool isOrdinal;
485 IsOrdinalProperty(property, &isOrdinal);
486 if (! isOrdinal)
487 continue;
489 nsCOMPtr<nsISimpleEnumerator> sources;
490 aDataSource->GetSources(property, aElement, true, getter_AddRefs(sources));
491 if (! sources)
492 continue;
494 while (1) {
495 bool hasMoreSources = false;
496 sources->HasMoreElements(&hasMoreSources);
497 if (! hasMoreSources)
498 break;
500 nsCOMPtr<nsISupports> isupports2;
501 sources->GetNext(getter_AddRefs(isupports2));
502 if (! isupports2)
503 break;
505 nsCOMPtr<nsIRDFResource> source =
506 do_QueryInterface(isupports2);
508 if (source == aContainer)
509 // Found it.
510 return OrdinalResourceToIndex(property, aIndex);
511 }
512 }
514 return NS_OK;
515 }