LCOV - code coverage report
Current view: top level - rdf/base - nsContainerEnumerator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 97 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13