LCOV - code coverage report
Current view: top level - rdf/base - nsRDFContainer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 83 305 27.2 %
Date: 2017-07-14 16:53:18 Functions: 9 22 40.9 %
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             :   Implementation for the RDF container.
       9             : 
      10             :   Notes
      11             :   -----
      12             : 
      13             :   1. RDF containers are one-indexed. This means that a lot of the loops
      14             :      that you'd normally think you'd write like this:
      15             : 
      16             :        for (i = 0; i < count; ++i) {}
      17             : 
      18             :      You've gotta write like this:
      19             : 
      20             :        for (i = 1; i <= count; ++i) {}
      21             : 
      22             :      "Sure, right, yeah, of course.", you say. Well maybe I'm just
      23             :      thick, but it's easy to slip up.
      24             : 
      25             :   2. The RDF:nextVal property on the container is an
      26             :      implementation-level hack that is used to quickly compute the
      27             :      next value for appending to the container. It will no doubt
      28             :      become royally screwed up in the case of aggregation.
      29             : 
      30             :   3. The RDF:nextVal property is also used to retrieve the count of
      31             :      elements in the container.
      32             : 
      33             :  */
      34             : 
      35             : 
      36             : #include "nsCOMPtr.h"
      37             : #include "nsIRDFContainer.h"
      38             : #include "nsIRDFContainerUtils.h"
      39             : #include "nsIRDFInMemoryDataSource.h"
      40             : #include "nsIRDFPropagatableDataSource.h"
      41             : #include "nsIRDFService.h"
      42             : #include "nsIServiceManager.h"
      43             : #include "nsRDFCID.h"
      44             : #include "nsString.h"
      45             : #include "nsXPIDLString.h"
      46             : #include "rdf.h"
      47             : 
      48             : #define RDF_SEQ_LIST_LIMIT   8
      49             : 
      50             : class RDFContainerImpl : public nsIRDFContainer
      51             : {
      52             : public:
      53             : 
      54             :     // nsISupports interface
      55             :     NS_DECL_ISUPPORTS
      56             : 
      57             :     // nsIRDFContainer interface
      58             :     NS_DECL_NSIRDFCONTAINER
      59             : 
      60             : private:
      61             :     friend nsresult NS_NewRDFContainer(nsIRDFContainer** aResult);
      62             : 
      63             :     RDFContainerImpl();
      64             :     virtual ~RDFContainerImpl();
      65             : 
      66             :     nsresult Init();
      67             : 
      68             :     nsresult Renumber(int32_t aStartIndex, int32_t aIncrement);
      69             :     nsresult SetNextValue(int32_t aIndex);
      70             :     nsresult GetNextValue(nsIRDFResource** aResult);
      71             : 
      72             :     nsIRDFDataSource* mDataSource;
      73             :     nsIRDFResource*   mContainer;
      74             : 
      75             :     // pseudo constants
      76             :     static int32_t gRefCnt;
      77             :     static nsIRDFService*        gRDFService;
      78             :     static nsIRDFContainerUtils* gRDFContainerUtils;
      79             :     static nsIRDFResource*       kRDF_nextVal;
      80             : };
      81             : 
      82             : 
      83             : int32_t               RDFContainerImpl::gRefCnt = 0;
      84             : nsIRDFService*        RDFContainerImpl::gRDFService;
      85             : nsIRDFContainerUtils* RDFContainerImpl::gRDFContainerUtils;
      86             : nsIRDFResource*       RDFContainerImpl::kRDF_nextVal;
      87             : 
      88             : ////////////////////////////////////////////////////////////////////////
      89             : // nsISupports interface
      90             : 
      91          12 : NS_IMPL_ISUPPORTS(RDFContainerImpl, nsIRDFContainer)
      92             : 
      93             : 
      94             : 
      95             : ////////////////////////////////////////////////////////////////////////
      96             : // nsIRDFContainer interface
      97             : 
      98             : NS_IMETHODIMP
      99           0 : RDFContainerImpl::GetDataSource(nsIRDFDataSource** _retval)
     100             : {
     101           0 :     *_retval = mDataSource;
     102           0 :     NS_IF_ADDREF(*_retval);
     103           0 :     return NS_OK;
     104             : }
     105             : 
     106             : 
     107             : NS_IMETHODIMP
     108           0 : RDFContainerImpl::GetResource(nsIRDFResource** _retval)
     109             : {
     110           0 :     *_retval = mContainer;
     111           0 :     NS_IF_ADDREF(*_retval);
     112           0 :     return NS_OK;
     113             : }
     114             : 
     115             : 
     116             : NS_IMETHODIMP
     117           3 : RDFContainerImpl::Init(nsIRDFDataSource *aDataSource, nsIRDFResource *aContainer)
     118             : {
     119           3 :     NS_PRECONDITION(aDataSource != nullptr, "null ptr");
     120           3 :     if (! aDataSource)
     121           0 :         return NS_ERROR_NULL_POINTER;
     122             : 
     123           3 :     NS_PRECONDITION(aContainer != nullptr, "null ptr");
     124           3 :     if (! aContainer)
     125           0 :         return NS_ERROR_NULL_POINTER;
     126             : 
     127             :     nsresult rv;
     128             :     bool isContainer;
     129           3 :     rv = gRDFContainerUtils->IsContainer(aDataSource, aContainer, &isContainer);
     130           3 :     if (NS_FAILED(rv)) return rv;
     131             : 
     132             :     // ``throw'' if we can't create a container on the specified
     133             :     // datasource/resource combination.
     134           3 :     if (! isContainer)
     135           0 :         return NS_ERROR_FAILURE;
     136             : 
     137           3 :     NS_IF_RELEASE(mDataSource);
     138           3 :     mDataSource = aDataSource;
     139           3 :     NS_ADDREF(mDataSource);
     140             : 
     141           3 :     NS_IF_RELEASE(mContainer);
     142           3 :     mContainer = aContainer;
     143           3 :     NS_ADDREF(mContainer);
     144             : 
     145           3 :     return NS_OK;
     146             : }
     147             : 
     148             : 
     149             : NS_IMETHODIMP
     150           0 : RDFContainerImpl::GetCount(int32_t *aCount)
     151             : {
     152           0 :     if (!mDataSource || !mContainer)
     153           0 :         return NS_ERROR_NOT_INITIALIZED;
     154             : 
     155             :     nsresult rv;
     156             : 
     157             :     // Get the next value, which hangs off of the bag via the
     158             :     // RDF:nextVal property. This is the _next value_ that will get
     159             :     // assigned in a one-indexed array. So, it's actually _one more_
     160             :     // than the actual count of elements in the container.
     161             :     //
     162             :     // XXX To handle aggregation, this should probably be a
     163             :     // GetTargets() that enumerates all of the values and picks the
     164             :     // largest one.
     165           0 :     nsCOMPtr<nsIRDFNode> nextValNode;
     166           0 :     rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, true, getter_AddRefs(nextValNode));
     167           0 :     if (NS_FAILED(rv)) return rv;
     168             : 
     169           0 :     if (rv == NS_RDF_NO_VALUE)
     170           0 :         return NS_ERROR_UNEXPECTED;
     171             : 
     172           0 :     nsCOMPtr<nsIRDFLiteral> nextValLiteral;
     173           0 :     rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
     174           0 :     if (NS_FAILED(rv)) return rv;
     175             : 
     176             :     const char16_t *s;
     177           0 :     rv = nextValLiteral->GetValueConst( &s );
     178           0 :     if (NS_FAILED(rv)) return rv;
     179             : 
     180           0 :     nsAutoString nextValStr(s);
     181             : 
     182             :     int32_t nextVal;
     183             :     nsresult err;
     184           0 :     nextVal = nextValStr.ToInteger(&err);
     185           0 :     if (NS_FAILED(err))
     186           0 :         return NS_ERROR_UNEXPECTED;
     187             : 
     188           0 :     *aCount = nextVal - 1;
     189           0 :     return NS_OK;
     190             : }
     191             : 
     192             : 
     193             : NS_IMETHODIMP
     194           0 : RDFContainerImpl::GetElements(nsISimpleEnumerator **_retval)
     195             : {
     196           0 :     if (!mDataSource || !mContainer)
     197           0 :         return NS_ERROR_NOT_INITIALIZED;
     198             : 
     199           0 :     return NS_NewContainerEnumerator(mDataSource, mContainer, _retval);
     200             : }
     201             : 
     202             : 
     203             : NS_IMETHODIMP
     204           1 : RDFContainerImpl::AppendElement(nsIRDFNode *aElement)
     205             : {
     206           1 :     if (!mDataSource || !mContainer)
     207           0 :         return NS_ERROR_NOT_INITIALIZED;
     208             : 
     209           1 :     NS_PRECONDITION(aElement != nullptr, "null ptr");
     210           1 :     if (! aElement)
     211           0 :         return NS_ERROR_NULL_POINTER;
     212             : 
     213             :     nsresult rv;
     214             : 
     215           2 :     nsCOMPtr<nsIRDFResource> nextVal;
     216           1 :     rv = GetNextValue(getter_AddRefs(nextVal));
     217           1 :     if (NS_FAILED(rv)) return rv;
     218             : 
     219           1 :     rv = mDataSource->Assert(mContainer, nextVal, aElement, true);
     220           1 :     if (NS_FAILED(rv)) return rv;
     221             : 
     222           1 :     return NS_OK;
     223             : }
     224             : 
     225             : 
     226             : NS_IMETHODIMP
     227           0 : RDFContainerImpl::RemoveElement(nsIRDFNode *aElement, bool aRenumber)
     228             : {
     229           0 :     if (!mDataSource || !mContainer)
     230           0 :         return NS_ERROR_NOT_INITIALIZED;
     231             : 
     232           0 :     NS_PRECONDITION(aElement != nullptr, "null ptr");
     233           0 :     if (! aElement)
     234           0 :         return NS_ERROR_NULL_POINTER;
     235             : 
     236             :     nsresult rv;
     237             : 
     238             :     int32_t idx;
     239           0 :     rv = IndexOf(aElement, &idx);
     240           0 :     if (NS_FAILED(rv)) return rv;
     241             : 
     242           0 :     if (idx < 0)
     243           0 :         return NS_OK;
     244             : 
     245             :     // Remove the element.
     246           0 :     nsCOMPtr<nsIRDFResource> ordinal;
     247           0 :     rv = gRDFContainerUtils->IndexToOrdinalResource(idx,
     248           0 :                                                     getter_AddRefs(ordinal));
     249           0 :     if (NS_FAILED(rv)) return rv;
     250             : 
     251           0 :     rv = mDataSource->Unassert(mContainer, ordinal, aElement);
     252           0 :     if (NS_FAILED(rv)) return rv;
     253             : 
     254           0 :     if (aRenumber) {
     255             :         // Now slide the rest of the collection backwards to fill in
     256             :         // the gap. This will have the side effect of completely
     257             :         // renumber the container from index to the end.
     258           0 :         rv = Renumber(idx + 1, -1);
     259           0 :         if (NS_FAILED(rv)) return rv;
     260             :     }
     261             : 
     262           0 :     return NS_OK;
     263             : }
     264             : 
     265             : 
     266             : NS_IMETHODIMP
     267           0 : RDFContainerImpl::InsertElementAt(nsIRDFNode *aElement, int32_t aIndex, bool aRenumber)
     268             : {
     269           0 :     if (!mDataSource || !mContainer)
     270           0 :         return NS_ERROR_NOT_INITIALIZED;
     271             : 
     272           0 :     NS_PRECONDITION(aElement != nullptr, "null ptr");
     273           0 :     if (! aElement)
     274           0 :         return NS_ERROR_NULL_POINTER;
     275             : 
     276           0 :     NS_PRECONDITION(aIndex >= 1, "illegal value");
     277           0 :     if (aIndex < 1)
     278           0 :         return NS_ERROR_ILLEGAL_VALUE;
     279             : 
     280             :     nsresult rv;
     281             : 
     282             :     int32_t count;
     283           0 :     rv = GetCount(&count);
     284           0 :     if (NS_FAILED(rv)) return rv;
     285             : 
     286           0 :     NS_ASSERTION(aIndex <= count + 1, "illegal value");
     287           0 :     if (aIndex > count + 1)
     288           0 :         return NS_ERROR_ILLEGAL_VALUE;
     289             : 
     290           0 :     if (aRenumber) {
     291             :         // Make a hole for the element. This will have the side effect of
     292             :         // completely renumbering the container from 'aIndex' to 'count',
     293             :         // and will spew assertions.
     294           0 :         rv = Renumber(aIndex, +1);
     295           0 :         if (NS_FAILED(rv)) return rv;
     296             :     }
     297             : 
     298           0 :     nsCOMPtr<nsIRDFResource> ordinal;
     299           0 :     rv = gRDFContainerUtils->IndexToOrdinalResource(aIndex, getter_AddRefs(ordinal));
     300           0 :     if (NS_FAILED(rv)) return rv;
     301             : 
     302           0 :     rv = mDataSource->Assert(mContainer, ordinal, aElement, true);
     303           0 :     if (NS_FAILED(rv)) return rv;
     304             : 
     305           0 :     return NS_OK;
     306             : }
     307             : 
     308             : NS_IMETHODIMP
     309           0 : RDFContainerImpl::RemoveElementAt(int32_t aIndex, bool aRenumber, nsIRDFNode** _retval)
     310             : {
     311           0 :     if (!mDataSource || !mContainer)
     312           0 :         return NS_ERROR_NOT_INITIALIZED;
     313             : 
     314           0 :     *_retval = nullptr;
     315             : 
     316           0 :     if (aIndex< 1)
     317           0 :         return NS_ERROR_ILLEGAL_VALUE;
     318             : 
     319             :     nsresult rv;
     320             : 
     321             :     int32_t count;
     322           0 :     rv = GetCount(&count);
     323           0 :     if (NS_FAILED(rv)) return rv;
     324             : 
     325           0 :     if (aIndex > count)
     326           0 :         return NS_ERROR_ILLEGAL_VALUE;
     327             : 
     328           0 :     nsCOMPtr<nsIRDFResource> ordinal;
     329           0 :     rv = gRDFContainerUtils->IndexToOrdinalResource(aIndex, getter_AddRefs(ordinal));
     330           0 :     if (NS_FAILED(rv)) return rv;
     331             : 
     332           0 :     nsCOMPtr<nsIRDFNode> old;
     333           0 :     rv = mDataSource->GetTarget(mContainer, ordinal, true, getter_AddRefs(old));
     334           0 :     if (NS_FAILED(rv)) return rv;
     335             : 
     336           0 :     if (rv == NS_OK) {
     337           0 :         rv = mDataSource->Unassert(mContainer, ordinal, old);
     338           0 :         if (NS_FAILED(rv)) return rv;
     339             : 
     340           0 :         if (aRenumber) {
     341             :             // Now slide the rest of the collection backwards to fill in
     342             :             // the gap. This will have the side effect of completely
     343             :             // renumber the container from index to the end.
     344           0 :             rv = Renumber(aIndex + 1, -1);
     345           0 :             if (NS_FAILED(rv)) return rv;
     346             :         }
     347             :     }
     348             : 
     349           0 :     old.swap(*_retval);
     350             : 
     351           0 :     return NS_OK;
     352             : }
     353             : 
     354             : NS_IMETHODIMP
     355           0 : RDFContainerImpl::IndexOf(nsIRDFNode *aElement, int32_t *aIndex)
     356             : {
     357           0 :     if (!mDataSource || !mContainer)
     358           0 :         return NS_ERROR_NOT_INITIALIZED;
     359             : 
     360           0 :     return gRDFContainerUtils->IndexOf(mDataSource, mContainer,
     361           0 :                                        aElement, aIndex);
     362             : }
     363             : 
     364             : 
     365             : ////////////////////////////////////////////////////////////////////////
     366             : 
     367             : 
     368           3 : RDFContainerImpl::RDFContainerImpl()
     369           3 :     : mDataSource(nullptr), mContainer(nullptr)
     370             : {
     371           3 : }
     372             : 
     373             : 
     374             : nsresult
     375           3 : RDFContainerImpl::Init()
     376             : {
     377           3 :     if (gRefCnt++ == 0) {
     378             :         nsresult rv;
     379             : 
     380           3 :         NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
     381           3 :         rv = CallGetService(kRDFServiceCID, &gRDFService);
     382           3 :         if (NS_FAILED(rv)) {
     383           0 :             NS_ERROR("unable to get RDF service");
     384           0 :             return rv;
     385             :         }
     386             : 
     387          12 :         rv = gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
     388           9 :                                       &kRDF_nextVal);
     389           3 :         if (NS_FAILED(rv)) return rv;
     390             : 
     391           3 :         NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
     392           3 :         rv = CallGetService(kRDFContainerUtilsCID, &gRDFContainerUtils);
     393           3 :         if (NS_FAILED(rv)) {
     394           0 :             NS_ERROR("unable to get RDF container utils service");
     395           0 :             return rv;
     396             :         }
     397             :     }
     398             : 
     399           3 :     return NS_OK;
     400             : }
     401             : 
     402             : 
     403           0 : RDFContainerImpl::~RDFContainerImpl()
     404             : {
     405             : #ifdef DEBUG_REFS
     406             :     --gInstanceCount;
     407             :     fprintf(stdout, "%d - RDF: RDFContainerImpl\n", gInstanceCount);
     408             : #endif
     409             : 
     410           0 :     NS_IF_RELEASE(mContainer);
     411           0 :     NS_IF_RELEASE(mDataSource);
     412             : 
     413           0 :     if (--gRefCnt == 0) {
     414           0 :         NS_IF_RELEASE(gRDFContainerUtils);
     415           0 :         NS_IF_RELEASE(gRDFService);
     416           0 :         NS_IF_RELEASE(kRDF_nextVal);
     417             :     }
     418           0 : }
     419             : 
     420             : 
     421             : nsresult
     422           3 : NS_NewRDFContainer(nsIRDFContainer** aResult)
     423             : {
     424           3 :     RDFContainerImpl* result = new RDFContainerImpl();
     425           3 :     if (! result)
     426           0 :         return NS_ERROR_OUT_OF_MEMORY;
     427             : 
     428             :     nsresult rv;
     429           3 :     rv = result->Init();
     430           3 :     if (NS_FAILED(rv)) {
     431           0 :         delete result;
     432           0 :         return rv;
     433             :     }
     434             : 
     435           3 :     NS_ADDREF(result);
     436           3 :     *aResult = result;
     437           3 :     return NS_OK;
     438             : }
     439             : 
     440             : 
     441             : nsresult
     442           0 : NS_NewRDFContainer(nsIRDFDataSource* aDataSource,
     443             :                    nsIRDFResource* aResource,
     444             :                    nsIRDFContainer** aResult)
     445             : {
     446             :     nsresult rv;
     447           0 :     rv = NS_NewRDFContainer(aResult);
     448           0 :     if (NS_FAILED(rv)) return rv;
     449             : 
     450           0 :     rv = (*aResult)->Init(aDataSource, aResource);
     451           0 :     if (NS_FAILED(rv)) {
     452           0 :         NS_RELEASE(*aResult);
     453             :     }
     454           0 :     return rv;
     455             : }
     456             : 
     457             : 
     458             : nsresult
     459           0 : RDFContainerImpl::Renumber(int32_t aStartIndex, int32_t aIncrement)
     460             : {
     461           0 :     if (!mDataSource || !mContainer)
     462           0 :         return NS_ERROR_NOT_INITIALIZED;
     463             : 
     464             :     // Renumber the elements in the container starting with
     465             :     // aStartIndex, updating each element's index by aIncrement. For
     466             :     // example,
     467             :     //
     468             :     //   (1:a 2:b 3:c)
     469             :     //   Renumber(2, +1);
     470             :     //   (1:a 3:b 4:c)
     471             :     //   Renumber(3, -1);
     472             :     //   (1:a 2:b 3:c)
     473             :     //
     474             :     nsresult rv;
     475             : 
     476           0 :     if (! aIncrement)
     477           0 :         return NS_OK;
     478             : 
     479             :     int32_t count;
     480           0 :     rv = GetCount(&count);
     481           0 :     if (NS_FAILED(rv)) return rv;
     482             : 
     483           0 :     if (aIncrement > 0) {
     484             :         // Update the container's nextVal to reflect the
     485             :         // renumbering. We do this now if aIncrement > 0 because we'll
     486             :         // want to be able to acknowledge that new elements are in the
     487             :         // container.
     488           0 :         rv = SetNextValue(count + aIncrement + 1);
     489           0 :         if (NS_FAILED(rv)) return rv;
     490             :     }
     491             : 
     492             :     int32_t i;
     493           0 :     if (aIncrement < 0) {
     494           0 :         i = aStartIndex;
     495             :     }
     496             :     else {
     497           0 :         i = count; // we're one-indexed.
     498             :     }
     499             : 
     500             :     // Note: once we disable notifications, don't exit this method until
     501             :     // enabling notifications
     502             :     nsCOMPtr<nsIRDFPropagatableDataSource> propagatable =
     503           0 :         do_QueryInterface(mDataSource);
     504           0 :     if (propagatable) {
     505           0 :         propagatable->SetPropagateChanges(false);
     506             :     }
     507             : 
     508           0 :     bool    err = false;
     509           0 :     while (!err && ((aIncrement < 0) ? (i <= count) : (i >= aStartIndex)))
     510             :     {
     511           0 :         nsCOMPtr<nsIRDFResource> oldOrdinal;
     512           0 :         rv = gRDFContainerUtils->IndexToOrdinalResource(i, getter_AddRefs(oldOrdinal));
     513           0 :         if (NS_FAILED(rv))
     514             :         {
     515           0 :             err = true;
     516           0 :             continue;
     517             :         }
     518             : 
     519           0 :         nsCOMPtr<nsIRDFResource> newOrdinal;
     520           0 :         rv = gRDFContainerUtils->IndexToOrdinalResource(i + aIncrement, getter_AddRefs(newOrdinal));
     521           0 :         if (NS_FAILED(rv))
     522             :         {
     523           0 :             err = true;
     524           0 :             continue;
     525             :         }
     526             : 
     527             :         // Because of aggregation, we need to be paranoid about the
     528             :         // possibility that >1 element may be present per ordinal. If
     529             :         // there _is_ in fact more than one element, they'll all get
     530             :         // assigned to the same new ordinal; i.e., we don't make any
     531             :         // attempt to "clean up" the duplicate numbering. (Doing so
     532             :         // would require two passes.)
     533           0 :         nsCOMPtr<nsISimpleEnumerator> targets;
     534           0 :         rv = mDataSource->GetTargets(mContainer, oldOrdinal, true, getter_AddRefs(targets));
     535           0 :         if (NS_FAILED(rv))
     536             :         {
     537           0 :             err = true;
     538           0 :             continue;
     539             :         }
     540             : 
     541             :         while (1) {
     542             :             bool hasMore;
     543           0 :             rv = targets->HasMoreElements(&hasMore);
     544           0 :             if (NS_FAILED(rv))
     545             :             {
     546           0 :                 err = true;
     547           0 :                 break;
     548             :             }
     549             : 
     550           0 :             if (! hasMore)
     551           0 :                 break;
     552             : 
     553           0 :             nsCOMPtr<nsISupports> isupports;
     554           0 :             rv = targets->GetNext(getter_AddRefs(isupports));
     555           0 :             if (NS_FAILED(rv))
     556             :             {
     557           0 :                 err = true;
     558           0 :                 break;
     559             :             }
     560             : 
     561           0 :             nsCOMPtr<nsIRDFNode> element( do_QueryInterface(isupports) );
     562           0 :             NS_ASSERTION(element != nullptr, "something funky in the enumerator");
     563           0 :             if (! element)
     564             :             {
     565           0 :                 err = true;
     566           0 :                 rv = NS_ERROR_UNEXPECTED;
     567           0 :                 break;
     568             :             }
     569             : 
     570           0 :             rv = mDataSource->Unassert(mContainer, oldOrdinal, element);
     571           0 :             if (NS_FAILED(rv))
     572             :             {
     573           0 :                 err = true;
     574           0 :                 break;
     575             :             }
     576             : 
     577           0 :             rv = mDataSource->Assert(mContainer, newOrdinal, element, true);
     578           0 :             if (NS_FAILED(rv))
     579             :             {
     580           0 :                 err = true;
     581           0 :                 break;
     582             :             }
     583           0 :         }
     584             : 
     585           0 :         i -= aIncrement;
     586             :     }
     587             : 
     588           0 :     if (!err && (aIncrement < 0))
     589             :     {
     590             :         // Update the container's nextVal to reflect the
     591             :         // renumbering. We do this now if aIncrement < 0 because, up
     592             :         // until this point, we'll want people to be able to find
     593             :         // things that are still "at the end".
     594           0 :         rv = SetNextValue(count + aIncrement + 1);
     595           0 :         if (NS_FAILED(rv))
     596             :         {
     597           0 :             err = true;
     598             :         }
     599             :     }
     600             : 
     601             :     // Note: MUST enable notifications before exiting this method
     602           0 :     if (propagatable) {
     603           0 :         propagatable->SetPropagateChanges(true);
     604             :     }
     605             : 
     606           0 :     if (err) return(rv);
     607             : 
     608           0 :     return NS_OK;
     609             : }
     610             : 
     611             : 
     612             : 
     613             : nsresult
     614           0 : RDFContainerImpl::SetNextValue(int32_t aIndex)
     615             : {
     616           0 :     if (!mDataSource || !mContainer)
     617           0 :         return NS_ERROR_NOT_INITIALIZED;
     618             : 
     619             :     nsresult rv;
     620             : 
     621             :     // Remove the current value of nextVal, if there is one.
     622           0 :     nsCOMPtr<nsIRDFNode> nextValNode;
     623           0 :     if (NS_SUCCEEDED(rv = mDataSource->GetTarget(mContainer,
     624             :                                                  kRDF_nextVal,
     625             :                                                  true,
     626             :                                                  getter_AddRefs(nextValNode)))) {
     627           0 :         if (NS_FAILED(rv = mDataSource->Unassert(mContainer, kRDF_nextVal, nextValNode))) {
     628           0 :             NS_ERROR("unable to update nextVal");
     629           0 :             return rv;
     630             :         }
     631             :     }
     632             : 
     633           0 :     nsAutoString s;
     634           0 :     s.AppendInt(aIndex, 10);
     635             : 
     636           0 :     nsCOMPtr<nsIRDFLiteral> nextVal;
     637           0 :     if (NS_FAILED(rv = gRDFService->GetLiteral(s.get(), getter_AddRefs(nextVal)))) {
     638           0 :         NS_ERROR("unable to get nextVal literal");
     639           0 :         return rv;
     640             :     }
     641             : 
     642           0 :     rv = mDataSource->Assert(mContainer, kRDF_nextVal, nextVal, true);
     643           0 :     if (rv != NS_RDF_ASSERTION_ACCEPTED) {
     644           0 :         NS_ERROR("unable to update nextVal");
     645           0 :         return NS_ERROR_FAILURE;
     646             :     }
     647             : 
     648           0 :     return NS_OK;
     649             : }
     650             : 
     651             : 
     652             : nsresult
     653           1 : RDFContainerImpl::GetNextValue(nsIRDFResource** aResult)
     654             : {
     655           1 :     if (!mDataSource || !mContainer)
     656           0 :         return NS_ERROR_NOT_INITIALIZED;
     657             : 
     658             :     nsresult rv;
     659             : 
     660             :     // Get the next value, which hangs off of the bag via the
     661             :     // RDF:nextVal property.
     662           2 :     nsCOMPtr<nsIRDFNode> nextValNode;
     663           1 :     rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, true, getter_AddRefs(nextValNode));
     664           1 :     if (NS_FAILED(rv)) return rv;
     665             : 
     666           1 :     if (rv == NS_RDF_NO_VALUE)
     667           0 :         return NS_ERROR_UNEXPECTED;
     668             : 
     669           2 :     nsCOMPtr<nsIRDFLiteral> nextValLiteral;
     670           1 :     rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
     671           1 :     if (NS_FAILED(rv)) return rv;
     672             : 
     673             :     const char16_t* s;
     674           1 :     rv = nextValLiteral->GetValueConst(&s);
     675           1 :     if (NS_FAILED(rv)) return rv;
     676             : 
     677           1 :     int32_t nextVal = 0;
     678             :     {
     679           2 :         for (const char16_t* p = s; *p != 0; ++p) {
     680           1 :             NS_ASSERTION(*p >= '0' && *p <= '9', "not a digit");
     681           1 :             if (*p < '0' || *p > '9')
     682             :                 break;
     683             : 
     684           1 :             nextVal *= 10;
     685           1 :             nextVal += *p - '0';
     686             :         }
     687             :     }
     688             : 
     689             :     static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
     690             :     char buf[sizeof(kRDFNameSpaceURI) + 16];
     691           2 :     nsFixedCString nextValStr(buf, sizeof(buf), 0);
     692           1 :     nextValStr = kRDFNameSpaceURI;
     693           1 :     nextValStr.Append('_');
     694           1 :     nextValStr.AppendInt(nextVal, 10);
     695             : 
     696           1 :     rv = gRDFService->GetResource(nextValStr, aResult);
     697           1 :     if (NS_FAILED(rv)) return rv;
     698             : 
     699             :     // Now increment the RDF:nextVal property.
     700           1 :     rv = mDataSource->Unassert(mContainer, kRDF_nextVal, nextValLiteral);
     701           1 :     if (NS_FAILED(rv)) return rv;
     702             : 
     703           1 :     ++nextVal;
     704           1 :     nextValStr.Truncate();
     705           1 :     nextValStr.AppendInt(nextVal, 10);
     706             : 
     707           1 :     rv = gRDFService->GetLiteral(NS_ConvertASCIItoUTF16(nextValStr).get(), getter_AddRefs(nextValLiteral));
     708           1 :     if (NS_FAILED(rv)) return rv;
     709             : 
     710           1 :     rv = mDataSource->Assert(mContainer, kRDF_nextVal, nextValLiteral, true);
     711           1 :     if (NS_FAILED(rv)) return rv;
     712             : 
     713           1 :     if (RDF_SEQ_LIST_LIMIT == nextVal)
     714             :     {
     715             :         // focal point for RDF container mutation;
     716             :         // basically, provide a hint to allow for fast access
     717           0 :         nsCOMPtr<nsIRDFInMemoryDataSource> inMem = do_QueryInterface(mDataSource);
     718           0 :         if (inMem)
     719             :         {
     720             :             // ignore error; failure just means slower access
     721           0 :             (void)inMem->EnsureFastContainment(mContainer);
     722             :         }
     723             :     }
     724             : 
     725           1 :     return NS_OK;
     726             : }

Generated by: LCOV version 1.13