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.

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

mercurial