rdf/base/src/nsContainerEnumerator.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 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7
michael@0 8 A simple cursor that enumerates the elements of an RDF container
michael@0 9 (RDF:Bag, RDF:Seq, or RDF:Alt).
michael@0 10
michael@0 11 Caveats
michael@0 12 -------
michael@0 13
michael@0 14 1. This uses an implementation-specific detail to determine the
michael@0 15 index of the last element in the container; specifically, the RDF
michael@0 16 utilities maintain a counter attribute on the container that
michael@0 17 holds the numeric value of the next value that is to be
michael@0 18 assigned. So, this cursor will bust if you use it with a bag that
michael@0 19 hasn't been created using the RDF utility routines.
michael@0 20
michael@0 21 */
michael@0 22
michael@0 23 #include "nscore.h"
michael@0 24 #include "nsCOMPtr.h"
michael@0 25 #include "nsIRDFContainerUtils.h"
michael@0 26 #include "nsIRDFDataSource.h"
michael@0 27 #include "nsIRDFNode.h"
michael@0 28 #include "nsIRDFService.h"
michael@0 29 #include "nsIServiceManager.h"
michael@0 30 #include "nsRDFCID.h"
michael@0 31 #include "nsString.h"
michael@0 32 #include "nsXPIDLString.h"
michael@0 33 #include "prlog.h"
michael@0 34 #include "rdf.h"
michael@0 35 #include "rdfutil.h"
michael@0 36
michael@0 37 ////////////////////////////////////////////////////////////////////////
michael@0 38
michael@0 39 class ContainerEnumeratorImpl : public nsISimpleEnumerator {
michael@0 40 private:
michael@0 41 // pseudo-constants
michael@0 42 static nsrefcnt gRefCnt;
michael@0 43 static nsIRDFResource* kRDF_nextVal;
michael@0 44 static nsIRDFContainerUtils* gRDFC;
michael@0 45
michael@0 46 nsCOMPtr<nsIRDFDataSource> mDataSource;
michael@0 47 nsCOMPtr<nsIRDFResource> mContainer;
michael@0 48 nsCOMPtr<nsIRDFResource> mOrdinalProperty;
michael@0 49
michael@0 50 nsCOMPtr<nsISimpleEnumerator> mCurrent;
michael@0 51 nsCOMPtr<nsIRDFNode> mResult;
michael@0 52 int32_t mNextIndex;
michael@0 53
michael@0 54 public:
michael@0 55 ContainerEnumeratorImpl(nsIRDFDataSource* ds, nsIRDFResource* container);
michael@0 56 virtual ~ContainerEnumeratorImpl();
michael@0 57
michael@0 58 nsresult Init();
michael@0 59
michael@0 60 NS_DECL_ISUPPORTS
michael@0 61 NS_DECL_NSISIMPLEENUMERATOR
michael@0 62 };
michael@0 63
michael@0 64 nsrefcnt ContainerEnumeratorImpl::gRefCnt;
michael@0 65 nsIRDFResource* ContainerEnumeratorImpl::kRDF_nextVal;
michael@0 66 nsIRDFContainerUtils* ContainerEnumeratorImpl::gRDFC;
michael@0 67
michael@0 68
michael@0 69 ContainerEnumeratorImpl::ContainerEnumeratorImpl(nsIRDFDataSource* aDataSource,
michael@0 70 nsIRDFResource* aContainer)
michael@0 71 : mDataSource(aDataSource),
michael@0 72 mContainer(aContainer),
michael@0 73 mNextIndex(1)
michael@0 74 {
michael@0 75 }
michael@0 76
michael@0 77 nsresult
michael@0 78 ContainerEnumeratorImpl::Init()
michael@0 79 {
michael@0 80 if (gRefCnt++ == 0) {
michael@0 81 nsresult rv;
michael@0 82
michael@0 83 NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
michael@0 84 nsCOMPtr<nsIRDFService> rdf = do_GetService(kRDFServiceCID);
michael@0 85 NS_ASSERTION(rdf != nullptr, "unable to acquire resource manager");
michael@0 86 if (! rdf)
michael@0 87 return NS_ERROR_FAILURE;
michael@0 88
michael@0 89 rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"), &kRDF_nextVal);
michael@0 90 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource");
michael@0 91 if (NS_FAILED(rv)) return rv;
michael@0 92
michael@0 93 NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
michael@0 94 rv = CallGetService(kRDFContainerUtilsCID, &gRDFC);
michael@0 95 if (NS_FAILED(rv)) return rv;
michael@0 96 }
michael@0 97
michael@0 98 return NS_OK;
michael@0 99 }
michael@0 100
michael@0 101
michael@0 102 ContainerEnumeratorImpl::~ContainerEnumeratorImpl()
michael@0 103 {
michael@0 104 if (--gRefCnt == 0) {
michael@0 105 NS_IF_RELEASE(kRDF_nextVal);
michael@0 106 NS_IF_RELEASE(gRDFC);
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110 NS_IMPL_ISUPPORTS(ContainerEnumeratorImpl, nsISimpleEnumerator)
michael@0 111
michael@0 112
michael@0 113 NS_IMETHODIMP
michael@0 114 ContainerEnumeratorImpl::HasMoreElements(bool* aResult)
michael@0 115 {
michael@0 116 NS_PRECONDITION(aResult != nullptr, "null ptr");
michael@0 117 if (! aResult)
michael@0 118 return NS_ERROR_NULL_POINTER;
michael@0 119
michael@0 120 nsresult rv;
michael@0 121
michael@0 122 // If we've already queued up a next value, then we know there are more elements.
michael@0 123 if (mResult) {
michael@0 124 *aResult = true;
michael@0 125 return NS_OK;
michael@0 126 }
michael@0 127
michael@0 128 // Otherwise, we need to grovel
michael@0 129
michael@0 130 // Figure out the upper bound so we'll know when we're done. Since it's
michael@0 131 // possible that we're targeting a composite datasource, we'll need to
michael@0 132 // "GetTargets()" and take the maximum value of "nextVal" to know the
michael@0 133 // upper bound.
michael@0 134 //
michael@0 135 // Remember that since nextVal is the next index that we'd assign
michael@0 136 // to an element in a container, it's *one more* than count of
michael@0 137 // elements in the container.
michael@0 138 int32_t max = 0;
michael@0 139
michael@0 140 nsCOMPtr<nsISimpleEnumerator> targets;
michael@0 141 rv = mDataSource->GetTargets(mContainer, kRDF_nextVal, true, getter_AddRefs(targets));
michael@0 142 if (NS_FAILED(rv)) return rv;
michael@0 143
michael@0 144 while (1) {
michael@0 145 bool hasmore;
michael@0 146 targets->HasMoreElements(&hasmore);
michael@0 147 if (! hasmore)
michael@0 148 break;
michael@0 149
michael@0 150 nsCOMPtr<nsISupports> isupports;
michael@0 151 targets->GetNext(getter_AddRefs(isupports));
michael@0 152
michael@0 153 nsCOMPtr<nsIRDFLiteral> nextValLiteral = do_QueryInterface(isupports);
michael@0 154 if (! nextValLiteral)
michael@0 155 continue;
michael@0 156
michael@0 157 const char16_t *nextValStr;
michael@0 158 nextValLiteral->GetValueConst(&nextValStr);
michael@0 159
michael@0 160 nsresult err;
michael@0 161 int32_t nextVal = nsAutoString(nextValStr).ToInteger(&err);
michael@0 162
michael@0 163 if (nextVal > max)
michael@0 164 max = nextVal;
michael@0 165 }
michael@0 166
michael@0 167 // Now pre-fetch our next value into mResult.
michael@0 168 while (mCurrent || mNextIndex < max) {
michael@0 169
michael@0 170 // If mCurrent has been depleted, then conjure up a new one
michael@0 171 if (! mCurrent) {
michael@0 172 rv = gRDFC->IndexToOrdinalResource(mNextIndex, getter_AddRefs(mOrdinalProperty));
michael@0 173 if (NS_FAILED(rv)) return rv;
michael@0 174
michael@0 175 rv = mDataSource->GetTargets(mContainer, mOrdinalProperty, true, getter_AddRefs(mCurrent));
michael@0 176 if (NS_FAILED(rv)) return rv;
michael@0 177
michael@0 178 ++mNextIndex;
michael@0 179 }
michael@0 180
michael@0 181 if (mCurrent) {
michael@0 182 bool hasMore;
michael@0 183 rv = mCurrent->HasMoreElements(&hasMore);
michael@0 184 if (NS_FAILED(rv)) return rv;
michael@0 185
michael@0 186 // Is the current enumerator depleted? If so, iterate to
michael@0 187 // the next index.
michael@0 188 if (! hasMore) {
michael@0 189 mCurrent = nullptr;
michael@0 190 continue;
michael@0 191 }
michael@0 192
michael@0 193 // "Peek" ahead and pull out the next target.
michael@0 194 nsCOMPtr<nsISupports> result;
michael@0 195 rv = mCurrent->GetNext(getter_AddRefs(result));
michael@0 196 if (NS_FAILED(rv)) return rv;
michael@0 197
michael@0 198 mResult = do_QueryInterface(result, &rv);
michael@0 199 if (NS_FAILED(rv)) return rv;
michael@0 200
michael@0 201 *aResult = true;
michael@0 202 return NS_OK;
michael@0 203 }
michael@0 204 }
michael@0 205
michael@0 206 // If we get here, we ran out of elements. The cursor is empty.
michael@0 207 *aResult = false;
michael@0 208 return NS_OK;
michael@0 209 }
michael@0 210
michael@0 211
michael@0 212 NS_IMETHODIMP
michael@0 213 ContainerEnumeratorImpl::GetNext(nsISupports** aResult)
michael@0 214 {
michael@0 215 nsresult rv;
michael@0 216
michael@0 217 bool hasMore;
michael@0 218 rv = HasMoreElements(&hasMore);
michael@0 219 if (NS_FAILED(rv)) return rv;
michael@0 220
michael@0 221 if (! hasMore)
michael@0 222 return NS_ERROR_UNEXPECTED;
michael@0 223
michael@0 224 NS_ADDREF(*aResult = mResult);
michael@0 225 mResult = nullptr;
michael@0 226
michael@0 227 return NS_OK;
michael@0 228 }
michael@0 229
michael@0 230
michael@0 231 ////////////////////////////////////////////////////////////////////////
michael@0 232
michael@0 233 nsresult
michael@0 234 NS_NewContainerEnumerator(nsIRDFDataSource* aDataSource,
michael@0 235 nsIRDFResource* aContainer,
michael@0 236 nsISimpleEnumerator** aResult)
michael@0 237 {
michael@0 238 NS_PRECONDITION(aDataSource != nullptr, "null ptr");
michael@0 239 if (! aDataSource)
michael@0 240 return NS_ERROR_NULL_POINTER;
michael@0 241
michael@0 242 NS_PRECONDITION(aContainer != nullptr, "null ptr");
michael@0 243 if (! aContainer)
michael@0 244 return NS_ERROR_NULL_POINTER;
michael@0 245
michael@0 246 NS_PRECONDITION(aResult != nullptr, "null ptr");
michael@0 247 if (! aResult)
michael@0 248 return NS_ERROR_NULL_POINTER;
michael@0 249
michael@0 250 ContainerEnumeratorImpl* result = new ContainerEnumeratorImpl(aDataSource, aContainer);
michael@0 251 if (! result)
michael@0 252 return NS_ERROR_OUT_OF_MEMORY;
michael@0 253
michael@0 254 NS_ADDREF(result);
michael@0 255
michael@0 256 nsresult rv = result->Init();
michael@0 257 if (NS_FAILED(rv))
michael@0 258 NS_RELEASE(result);
michael@0 259
michael@0 260 *aResult = result;
michael@0 261 return rv;
michael@0 262 }

mercurial