LCOV - code coverage report
Current view: top level - dom/xul/templates - nsRuleNetwork.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 190 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 93 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 rule discrimination network implementation based on ideas from
       9             :   RETE and TREAT.
      10             : 
      11             :   RETE is described in Charles Forgy, "Rete: A Fast Algorithm for the
      12             :   Many Patterns/Many Objects Match Problem", Artificial Intelligence
      13             :   19(1): pp. 17-37, 1982.
      14             : 
      15             :   TREAT is described in Daniel P. Miranker, "TREAT: A Better Match
      16             :   Algorithm for AI Production System Matching", AAAI 1987: pp. 42-47.
      17             : 
      18             :   --
      19             : 
      20             :   TO DO:
      21             : 
      22             :   . nsAssignmentSet::List objects are allocated by the gallon. We
      23             :     should make it so that these are always allocated from a pool,
      24             :     maybe owned by the nsRuleNetwork?
      25             : 
      26             :  */
      27             : 
      28             : #ifndef nsRuleNetwork_h__
      29             : #define nsRuleNetwork_h__
      30             : 
      31             : #include "mozilla/Attributes.h"
      32             : #include "nsCOMPtr.h"
      33             : #include "nsCOMArray.h"
      34             : #include "nsIAtom.h"
      35             : #include "nsIDOMNode.h"
      36             : #include "plhash.h"
      37             : #include "PLDHashTable.h"
      38             : #include "nsIRDFNode.h"
      39             : 
      40             : class nsXULTemplateResultSetRDF;
      41             : 
      42             : //----------------------------------------------------------------------
      43             : 
      44             : /**
      45             :  * A memory element that supports an instantiation. A memory element holds a
      46             :  * set of nodes involved in an RDF test such as <member> or <triple> test. A
      47             :  * memory element is created when a specific test matches. The query processor
      48             :  * maintains a map between the memory elements and the results they eventually
      49             :  * matched. When an assertion is removed from the graph, this map is consulted
      50             :  * to determine which results will no longer match.
      51             :  */
      52             : class MemoryElement {
      53             : protected:
      54           0 :     MemoryElement() { MOZ_COUNT_CTOR(MemoryElement); }
      55             : 
      56             : public:
      57           0 :     virtual ~MemoryElement() { MOZ_COUNT_DTOR(MemoryElement); }
      58             : 
      59             :     virtual const char* Type() const = 0;
      60             :     virtual PLHashNumber Hash() const = 0;
      61             :     virtual bool Equals(const MemoryElement& aElement) const = 0;
      62             : 
      63           0 :     bool operator==(const MemoryElement& aMemoryElement) const {
      64           0 :         return Equals(aMemoryElement);
      65             :     }
      66             : 
      67             :     bool operator!=(const MemoryElement& aMemoryElement) const {
      68             :         return !Equals(aMemoryElement);
      69             :     }
      70             : };
      71             : 
      72             : //----------------------------------------------------------------------
      73             : 
      74             : /**
      75             :  * A collection of memory elements
      76             :  */
      77             : class MemoryElementSet {
      78             : public:
      79             :     class ConstIterator;
      80             :     friend class ConstIterator;
      81             : 
      82             : protected:
      83             :     class List {
      84             :     public:
      85           0 :         List() { MOZ_COUNT_CTOR(MemoryElementSet::List); }
      86             : 
      87             :     protected:
      88           0 :         ~List() {
      89           0 :             MOZ_COUNT_DTOR(MemoryElementSet::List);
      90           0 :             delete mElement;
      91           0 :             NS_IF_RELEASE(mNext); }
      92             : 
      93             :     public:
      94           0 :         int32_t AddRef() { return ++mRefCnt; }
      95             : 
      96           0 :         int32_t Release() {
      97           0 :             int32_t refcnt = --mRefCnt;
      98           0 :             if (refcnt == 0) delete this;
      99           0 :             return refcnt; }
     100             : 
     101             :         MemoryElement* mElement;
     102             :         int32_t        mRefCnt;
     103             :         List*          mNext;
     104             :     };
     105             : 
     106             :     List* mElements;
     107             : 
     108             : public:
     109           0 :     MemoryElementSet() : mElements(nullptr) {
     110           0 :         MOZ_COUNT_CTOR(MemoryElementSet); }
     111             : 
     112           0 :     MemoryElementSet(const MemoryElementSet& aSet) : mElements(aSet.mElements) {
     113           0 :         MOZ_COUNT_CTOR(MemoryElementSet);
     114           0 :         NS_IF_ADDREF(mElements); }
     115             : 
     116           0 :     MemoryElementSet& operator=(const MemoryElementSet& aSet) {
     117           0 :         NS_IF_RELEASE(mElements);
     118           0 :         mElements = aSet.mElements;
     119           0 :         NS_IF_ADDREF(mElements);
     120           0 :         return *this; }
     121             : 
     122           0 :     ~MemoryElementSet() {
     123           0 :         MOZ_COUNT_DTOR(MemoryElementSet);
     124           0 :         NS_IF_RELEASE(mElements); }
     125             : 
     126             : public:
     127             :     class ConstIterator {
     128             :     public:
     129           0 :         explicit ConstIterator(List* aElementList) : mCurrent(aElementList) {
     130           0 :             NS_IF_ADDREF(mCurrent); }
     131             : 
     132             :         ConstIterator(const ConstIterator& aConstIterator)
     133             :             : mCurrent(aConstIterator.mCurrent) {
     134             :             NS_IF_ADDREF(mCurrent); }
     135             : 
     136             :         ConstIterator& operator=(const ConstIterator& aConstIterator) {
     137             :             NS_IF_RELEASE(mCurrent);
     138             :             mCurrent = aConstIterator.mCurrent;
     139             :             NS_IF_ADDREF(mCurrent);
     140             :             return *this; }
     141             : 
     142           0 :         ~ConstIterator() { NS_IF_RELEASE(mCurrent); }
     143             : 
     144           0 :         ConstIterator& operator++() {
     145           0 :             List* next = mCurrent->mNext;
     146           0 :             NS_RELEASE(mCurrent);
     147           0 :             mCurrent = next;
     148           0 :             NS_IF_ADDREF(mCurrent);
     149           0 :             return *this; }
     150             : 
     151             :         ConstIterator operator++(int) {
     152             :             ConstIterator result(*this);
     153             :             List* next = mCurrent->mNext;
     154             :             NS_RELEASE(mCurrent);
     155             :             mCurrent = next;
     156             :             NS_IF_ADDREF(mCurrent);
     157             :             return result; }
     158             : 
     159           0 :         const MemoryElement& operator*() const {
     160           0 :             return *mCurrent->mElement; }
     161             : 
     162           0 :         const MemoryElement* operator->() const {
     163           0 :             return mCurrent->mElement; }
     164             : 
     165             :         bool operator==(const ConstIterator& aConstIterator) const {
     166             :             return mCurrent == aConstIterator.mCurrent; }
     167             : 
     168           0 :         bool operator!=(const ConstIterator& aConstIterator) const {
     169           0 :             return mCurrent != aConstIterator.mCurrent; }
     170             : 
     171             :     protected:
     172             :         List* mCurrent;
     173             :     };
     174             : 
     175           0 :     ConstIterator First() const { return ConstIterator(mElements); }
     176           0 :     ConstIterator Last() const { return ConstIterator(nullptr); }
     177             : 
     178             :     // N.B. that the set assumes ownership of the element
     179             :     nsresult Add(MemoryElement* aElement);
     180             : };
     181             : 
     182             : //----------------------------------------------------------------------
     183             : 
     184             : /**
     185             :  * An assignment of a value to a variable
     186             :  */
     187             : class nsAssignment {
     188             : public:
     189             :     const nsCOMPtr<nsIAtom> mVariable;
     190             :     nsCOMPtr<nsIRDFNode> mValue;
     191             : 
     192           0 :     nsAssignment(nsIAtom* aVariable, nsIRDFNode* aValue)
     193           0 :         : mVariable(aVariable),
     194           0 :           mValue(aValue)
     195           0 :         { MOZ_COUNT_CTOR(nsAssignment); }
     196             : 
     197           0 :     nsAssignment(const nsAssignment& aAssignment)
     198           0 :         : mVariable(aAssignment.mVariable),
     199           0 :           mValue(aAssignment.mValue)
     200           0 :         { MOZ_COUNT_CTOR(nsAssignment); }
     201             : 
     202           0 :     ~nsAssignment() { MOZ_COUNT_DTOR(nsAssignment); }
     203             : 
     204             :     bool operator==(const nsAssignment& aAssignment) const {
     205             :         return mVariable == aAssignment.mVariable && mValue == aAssignment.mValue; }
     206             : 
     207             :     bool operator!=(const nsAssignment& aAssignment) const {
     208             :         return mVariable != aAssignment.mVariable || mValue != aAssignment.mValue; }
     209             : 
     210           0 :     PLHashNumber Hash() const {
     211             :         // XXX I have no idea if this hashing function is good or not // XXX change this
     212           0 :         PLHashNumber temp = PLHashNumber(NS_PTR_TO_INT32(mValue.get())) >> 2; // strip alignment bits
     213           0 :         return (temp & 0xffff) | NS_PTR_TO_INT32(mVariable.get()); }
     214             : };
     215             : 
     216             : 
     217             : //----------------------------------------------------------------------
     218             : 
     219             : /**
     220             :  * A collection of value-to-variable assignments that minimizes
     221             :  * copying by sharing subsets when possible.
     222             :  */
     223             : class nsAssignmentSet {
     224             : public:
     225             :     class ConstIterator;
     226             :     friend class ConstIterator;
     227             : 
     228             : protected:
     229             :     class List {
     230             :     public:
     231           0 :         explicit List(const nsAssignment& aAssignment) : mAssignment(aAssignment) {
     232           0 :             MOZ_COUNT_CTOR(nsAssignmentSet::List); }
     233             : 
     234             :     protected:
     235           0 :         ~List() {
     236           0 :             MOZ_COUNT_DTOR(nsAssignmentSet::List);
     237           0 :             NS_IF_RELEASE(mNext); }
     238             : 
     239             :     public:
     240             : 
     241           0 :         int32_t AddRef() { return ++mRefCnt; }
     242             : 
     243           0 :         int32_t Release() {
     244           0 :             int32_t refcnt = --mRefCnt;
     245           0 :             if (refcnt == 0) delete this;
     246           0 :             return refcnt; }
     247             : 
     248             :         nsAssignment mAssignment;
     249             :         int32_t mRefCnt;
     250             :         List*   mNext;
     251             :     };
     252             : 
     253             :     List* mAssignments;
     254             : 
     255             : public:
     256           0 :     nsAssignmentSet()
     257           0 :         : mAssignments(nullptr)
     258           0 :         { MOZ_COUNT_CTOR(nsAssignmentSet); }
     259             : 
     260           0 :     nsAssignmentSet(const nsAssignmentSet& aSet)
     261           0 :         : mAssignments(aSet.mAssignments) {
     262           0 :         MOZ_COUNT_CTOR(nsAssignmentSet);
     263           0 :         NS_IF_ADDREF(mAssignments); }
     264             : 
     265           0 :     nsAssignmentSet& operator=(const nsAssignmentSet& aSet) {
     266           0 :         NS_IF_RELEASE(mAssignments);
     267           0 :         mAssignments = aSet.mAssignments;
     268           0 :         NS_IF_ADDREF(mAssignments);
     269           0 :         return *this; }
     270             : 
     271           0 :     ~nsAssignmentSet() {
     272           0 :         MOZ_COUNT_DTOR(nsAssignmentSet);
     273           0 :         NS_IF_RELEASE(mAssignments); }
     274             : 
     275             : public:
     276             :     class ConstIterator {
     277             :     public:
     278           0 :         explicit ConstIterator(List* aAssignmentList) : mCurrent(aAssignmentList) {
     279           0 :             NS_IF_ADDREF(mCurrent); }
     280             : 
     281             :         ConstIterator(const ConstIterator& aConstIterator)
     282             :             : mCurrent(aConstIterator.mCurrent) {
     283             :             NS_IF_ADDREF(mCurrent); }
     284             : 
     285             :         ConstIterator& operator=(const ConstIterator& aConstIterator) {
     286             :             NS_IF_RELEASE(mCurrent);
     287             :             mCurrent = aConstIterator.mCurrent;
     288             :             NS_IF_ADDREF(mCurrent);
     289             :             return *this; }
     290             : 
     291           0 :         ~ConstIterator() { NS_IF_RELEASE(mCurrent); }
     292             : 
     293           0 :         ConstIterator& operator++() {
     294           0 :             List* next = mCurrent->mNext;
     295           0 :             NS_RELEASE(mCurrent);
     296           0 :             mCurrent = next;
     297           0 :             NS_IF_ADDREF(mCurrent);
     298           0 :             return *this; }
     299             : 
     300             :         ConstIterator operator++(int) {
     301             :             ConstIterator result(*this);
     302             :             List* next = mCurrent->mNext;
     303             :             NS_RELEASE(mCurrent);
     304             :             mCurrent = next;
     305             :             NS_IF_ADDREF(mCurrent);
     306             :             return result; }
     307             : 
     308             :         const nsAssignment& operator*() const {
     309             :             return mCurrent->mAssignment; }
     310             : 
     311           0 :         const nsAssignment* operator->() const {
     312           0 :             return &mCurrent->mAssignment; }
     313             : 
     314             :         bool operator==(const ConstIterator& aConstIterator) const {
     315             :             return mCurrent == aConstIterator.mCurrent; }
     316             : 
     317           0 :         bool operator!=(const ConstIterator& aConstIterator) const {
     318           0 :             return mCurrent != aConstIterator.mCurrent; }
     319             : 
     320             :     protected:
     321             :         List* mCurrent;
     322             :     };
     323             : 
     324           0 :     ConstIterator First() const { return ConstIterator(mAssignments); }
     325           0 :     ConstIterator Last() const { return ConstIterator(nullptr); }
     326             : 
     327             : public:
     328             :     /**
     329             :      * Add an assignment to the set
     330             :      * @param aElement the assigment to add
     331             :      * @return NS_OK if all is well, NS_ERROR_OUT_OF_MEMORY if memory
     332             :      *   could not be allocated for the addition.
     333             :      */
     334             :     nsresult Add(const nsAssignment& aElement);
     335             : 
     336             :     /**
     337             :      * Determine if the assignment set contains the specified variable
     338             :      * to value assignment.
     339             :      * @param aVariable the variable for which to lookup the binding
     340             :      * @param aValue the value to query
     341             :      * @return true if aVariable is bound to aValue; false otherwise.
     342             :      */
     343             :     bool HasAssignment(nsIAtom* aVariable, nsIRDFNode* aValue) const;
     344             : 
     345             :     /**
     346             :      * Determine if the assignment set contains the specified assignment
     347             :      * @param aAssignment the assignment to search for
     348             :      * @return true if the set contains the assignment, false otherwise.
     349             :      */
     350             :     bool HasAssignment(const nsAssignment& aAssignment) const {
     351             :         return HasAssignment(aAssignment.mVariable, aAssignment.mValue); }
     352             : 
     353             :     /**
     354             :      * Determine whether the assignment set has an assignment for the
     355             :      * specified variable.
     356             :      * @param aVariable the variable to query
     357             :      * @return true if the assignment set has an assignment for the variable,
     358             :      *   false otherwise.
     359             :      */
     360             :     bool HasAssignmentFor(nsIAtom* aVariable) const;
     361             : 
     362             :     /**
     363             :      * Retrieve the assignment for the specified variable
     364             :      * @param aVariable the variable to query
     365             :      * @param aValue an out parameter that will receive the value assigned
     366             :      *   to the variable, if any.
     367             :      * @return true if the variable has an assignment, false
     368             :      *   if there was no assignment for the variable.
     369             :      */
     370             :     bool GetAssignmentFor(nsIAtom* aVariable, nsIRDFNode** aValue) const;
     371             : 
     372             :     /**
     373             :      * Count the number of assignments in the set
     374             :      * @return the number of assignments in the set
     375             :      */
     376             :     int32_t Count() const;
     377             : 
     378             :     /**
     379             :      * Determine if the set is empty
     380             :      * @return true if the assignment set is empty, false otherwise.
     381             :      */
     382             :     bool IsEmpty() const { return mAssignments == nullptr; }
     383             : 
     384             :     bool Equals(const nsAssignmentSet& aSet) const;
     385           0 :     bool operator==(const nsAssignmentSet& aSet) const { return Equals(aSet); }
     386             :     bool operator!=(const nsAssignmentSet& aSet) const { return !Equals(aSet); }
     387             : };
     388             : 
     389             : 
     390             : //----------------------------------------------------------------------
     391             : 
     392             : /**
     393             :  * A collection of variable-to-value bindings, with the memory elements
     394             :  * that support those bindings. Essentially, an instantiation is the
     395             :  * collection of variables and values assigned to those variables for a single
     396             :  * result. For each RDF rule in the rule network, each instantiation is
     397             :  * examined and either extended with additional bindings specified by the RDF
     398             :  * rule, or removed if the rule doesn't apply (for instance if a node has no
     399             :  * children). When an instantiation gets to the last node of the rule network,
     400             :  * which is always an nsInstantiationNode, a result is created for it.
     401             :  *
     402             :  * An instantiation object is typically created by "extending" another
     403             :  * instantiation object. That is, using the copy constructor, and
     404             :  * adding bindings and support to the instantiation.
     405             :  */
     406             : class Instantiation
     407             : {
     408             : public:
     409             :     /**
     410             :      * The variable-to-value bindings
     411             :      */
     412             :     nsAssignmentSet  mAssignments;
     413             : 
     414             :     /**
     415             :      * The memory elements that support the bindings.
     416             :      */
     417             :     MemoryElementSet mSupport;
     418             : 
     419           0 :     Instantiation() { MOZ_COUNT_CTOR(Instantiation); }
     420             : 
     421           0 :     Instantiation(const Instantiation& aInstantiation)
     422           0 :         : mAssignments(aInstantiation.mAssignments),
     423           0 :           mSupport(aInstantiation.mSupport) {
     424           0 :         MOZ_COUNT_CTOR(Instantiation); }
     425             : 
     426           0 :     Instantiation& operator=(const Instantiation& aInstantiation) {
     427           0 :         mAssignments = aInstantiation.mAssignments;
     428           0 :         mSupport  = aInstantiation.mSupport;
     429           0 :         return *this; }
     430             : 
     431           0 :     ~Instantiation() { MOZ_COUNT_DTOR(Instantiation); }
     432             : 
     433             :     /**
     434             :      * Add the specified variable-to-value assignment to the instantiation's
     435             :      * set of assignments.
     436             :      * @param aVariable the variable to which is being assigned
     437             :      * @param aValue the value that is being assigned
     438             :      * @return NS_OK if no errors, NS_ERROR_OUT_OF_MEMORY if there
     439             :      *   is not enough memory to perform the operation
     440             :      */
     441           0 :     nsresult AddAssignment(nsIAtom* aVariable, nsIRDFNode* aValue) {
     442           0 :         mAssignments.Add(nsAssignment(aVariable, aValue));
     443           0 :         return NS_OK; }
     444             : 
     445             :     /**
     446             :      * Add a memory element to the set of memory elements that are
     447             :      * supporting the instantiation
     448             :      * @param aMemoryElement the memory element to add to the
     449             :      *   instantiation's set of support
     450             :      * @return NS_OK if no errors occurred, NS_ERROR_OUT_OF_MEMORY
     451             :      *   if there is not enough memory to perform the operation.
     452             :      */
     453           0 :     nsresult AddSupportingElement(MemoryElement* aMemoryElement) {
     454           0 :         mSupport.Add(aMemoryElement);
     455           0 :         return NS_OK; }
     456             : 
     457           0 :     bool Equals(const Instantiation& aInstantiation) const {
     458           0 :         return mAssignments == aInstantiation.mAssignments; }
     459             : 
     460           0 :     bool operator==(const Instantiation& aInstantiation) const {
     461           0 :         return Equals(aInstantiation); }
     462             : 
     463             :     bool operator!=(const Instantiation& aInstantiation) const {
     464             :         return !Equals(aInstantiation); }
     465             : 
     466             :     static PLHashNumber Hash(const void* aKey);
     467             :     static int Compare(const void* aLeft, const void* aRight);
     468             : };
     469             : 
     470             : 
     471             : //----------------------------------------------------------------------
     472             : 
     473             : /**
     474             :  * A collection of intantiations
     475             :  */
     476             : class InstantiationSet
     477             : {
     478             : public:
     479             :     InstantiationSet();
     480             :     InstantiationSet(const InstantiationSet& aInstantiationSet);
     481             :     InstantiationSet& operator=(const InstantiationSet& aInstantiationSet);
     482             : 
     483           0 :     ~InstantiationSet() {
     484           0 :         MOZ_COUNT_DTOR(InstantiationSet);
     485           0 :         Clear(); }
     486             : 
     487             :     class ConstIterator;
     488             :     friend class ConstIterator;
     489             : 
     490             :     class Iterator;
     491             :     friend class Iterator;
     492             : 
     493             :     friend class nsXULTemplateResultSetRDF; // so it can get to the List
     494             : 
     495             : protected:
     496             :     class List {
     497             :     public:
     498             :         Instantiation mInstantiation;
     499             :         List*         mNext;
     500             :         List*         mPrev;
     501             : 
     502           0 :         List() { MOZ_COUNT_CTOR(InstantiationSet::List); }
     503           0 :         ~List() { MOZ_COUNT_DTOR(InstantiationSet::List); }
     504             :     };
     505             : 
     506             :     List mHead;
     507             : 
     508             : public:
     509             :     class ConstIterator {
     510             :     protected:
     511             :         friend class Iterator; // XXXwaterson so broken.
     512             :         List* mCurrent;
     513             : 
     514             :     public:
     515           0 :         explicit ConstIterator(List* aList) : mCurrent(aList) {}
     516             : 
     517           0 :         ConstIterator(const ConstIterator& aConstIterator)
     518           0 :             : mCurrent(aConstIterator.mCurrent) {}
     519             : 
     520             :         ConstIterator& operator=(const ConstIterator& aConstIterator) {
     521             :             mCurrent = aConstIterator.mCurrent;
     522             :             return *this; }
     523             : 
     524           0 :         ConstIterator& operator++() {
     525           0 :             mCurrent = mCurrent->mNext;
     526           0 :             return *this; }
     527             : 
     528             :         ConstIterator operator++(int) {
     529             :             ConstIterator result(*this);
     530             :             mCurrent = mCurrent->mNext;
     531             :             return result; }
     532             : 
     533             :         ConstIterator& operator--() {
     534             :             mCurrent = mCurrent->mPrev;
     535             :             return *this; }
     536             : 
     537             :         ConstIterator operator--(int) {
     538             :             ConstIterator result(*this);
     539             :             mCurrent = mCurrent->mPrev;
     540             :             return result; }
     541             : 
     542           0 :         const Instantiation& operator*() const {
     543           0 :             return mCurrent->mInstantiation; }
     544             : 
     545           0 :         const Instantiation* operator->() const {
     546           0 :             return &mCurrent->mInstantiation; }
     547             : 
     548           0 :         bool operator==(const ConstIterator& aConstIterator) const {
     549           0 :             return mCurrent == aConstIterator.mCurrent; }
     550             : 
     551           0 :         bool operator!=(const ConstIterator& aConstIterator) const {
     552           0 :             return mCurrent != aConstIterator.mCurrent; }
     553             :     };
     554             : 
     555           0 :     ConstIterator First() const { return ConstIterator(mHead.mNext); }
     556           0 :     ConstIterator Last() const { return ConstIterator(const_cast<List*>(&mHead)); }
     557             : 
     558           0 :     class Iterator : public ConstIterator {
     559             :     public:
     560           0 :         explicit Iterator(List* aList) : ConstIterator(aList) {}
     561             : 
     562           0 :         Iterator& operator++() {
     563           0 :             mCurrent = mCurrent->mNext;
     564           0 :             return *this; }
     565             : 
     566           0 :         Iterator operator++(int) {
     567           0 :             Iterator result(*this);
     568           0 :             mCurrent = mCurrent->mNext;
     569           0 :             return result; }
     570             : 
     571             :         Iterator& operator--() {
     572             :             mCurrent = mCurrent->mPrev;
     573             :             return *this; }
     574             : 
     575           0 :         Iterator operator--(int) {
     576           0 :             Iterator result(*this);
     577           0 :             mCurrent = mCurrent->mPrev;
     578           0 :             return result; }
     579             : 
     580           0 :         Instantiation& operator*() const {
     581           0 :             return mCurrent->mInstantiation; }
     582             : 
     583           0 :         Instantiation* operator->() const {
     584           0 :             return &mCurrent->mInstantiation; }
     585             : 
     586             :         bool operator==(const ConstIterator& aConstIterator) const {
     587             :             return mCurrent == aConstIterator.mCurrent; }
     588             : 
     589           0 :         bool operator!=(const ConstIterator& aConstIterator) const {
     590           0 :             return mCurrent != aConstIterator.mCurrent; }
     591             : 
     592             :         friend class InstantiationSet;
     593             :     };
     594             : 
     595           0 :     Iterator First() { return Iterator(mHead.mNext); }
     596           0 :     Iterator Last() { return Iterator(&mHead); }
     597             : 
     598           0 :     bool Empty() const { return First() == Last(); }
     599             : 
     600           0 :     Iterator Append(const Instantiation& aInstantiation) {
     601           0 :         return Insert(Last(), aInstantiation); }
     602             : 
     603             :     Iterator Insert(Iterator aBefore, const Instantiation& aInstantiation);
     604             : 
     605             :     Iterator Erase(Iterator aElement);
     606             : 
     607             :     void Clear();
     608             : 
     609             :     bool HasAssignmentFor(nsIAtom* aVariable) const;
     610             : };
     611             : 
     612             : //----------------------------------------------------------------------
     613             : 
     614             : /**
     615             :  * A abstract base class for all nodes in the rule network
     616             :  */
     617             : class ReteNode
     618             : {
     619             : public:
     620           0 :     ReteNode() {}
     621           0 :     virtual ~ReteNode() {}
     622             : 
     623             :     /**
     624             :      * Propagate a set of instantiations "down" through the
     625             :      * network. Each instantiation is a partial set of
     626             :      * variable-to-value assignments, along with the memory elements
     627             :      * that support it.
     628             :      *
     629             :      * The node must evaluate each instantiation, and either 1)
     630             :      * extend it with additional assignments and memory-element
     631             :      * support, or 2) remove it from the set because it is
     632             :      * inconsistent with the constraints that this node applies.
     633             :      *
     634             :      * The node must then pass the resulting instantiation set along
     635             :      * to any of its children in the network. (In other words, the
     636             :      * node must recursively call Propagate() on its children. We
     637             :      * should fix this to make the algorithm interruptable.)
     638             :      *
     639             :      * See TestNode::Propagate for details about instantiation set ownership
     640             :      *
     641             :      * @param aInstantiations the set of instantiations to propagate
     642             :      *   down through the network.
     643             :      * @param aIsUpdate true if updating, false for first generation
     644             :      * @param aTakenInstantiations true if the ownership over aInstantiations
     645             :      *                             has been taken from the caller. If false,
     646             :      *                             the caller owns it.
     647             :      * @return NS_OK if no errors occurred.
     648             :      */
     649             :     virtual nsresult Propagate(InstantiationSet& aInstantiations,
     650             :                                bool aIsUpdate, bool& aTakenInstantiations) = 0;
     651             : };
     652             : 
     653             : //----------------------------------------------------------------------
     654             : 
     655             : /**
     656             :  * A collection of nodes in the rule network
     657             :  */
     658             : class ReteNodeSet
     659             : {
     660             : public:
     661             :     ReteNodeSet();
     662             :     ~ReteNodeSet();
     663             : 
     664             :     nsresult Add(ReteNode* aNode);
     665             :     nsresult Clear();
     666             : 
     667             :     class Iterator;
     668             : 
     669             :     class ConstIterator {
     670             :     public:
     671           0 :         explicit ConstIterator(ReteNode** aNode) : mCurrent(aNode) {}
     672             : 
     673           0 :         ConstIterator(const ConstIterator& aConstIterator)
     674           0 :             : mCurrent(aConstIterator.mCurrent) {}
     675             : 
     676             :         ConstIterator& operator=(const ConstIterator& aConstIterator) {
     677             :             mCurrent = aConstIterator.mCurrent;
     678             :             return *this; }
     679             : 
     680           0 :         ConstIterator& operator++() {
     681           0 :             ++mCurrent;
     682           0 :             return *this; }
     683             : 
     684             :         ConstIterator operator++(int) {
     685             :             ConstIterator result(*this);
     686             :             ++mCurrent;
     687             :             return result; }
     688             : 
     689           0 :         const ReteNode* operator*() const {
     690           0 :             return *mCurrent; }
     691             : 
     692             :         const ReteNode* operator->() const {
     693             :             return *mCurrent; }
     694             : 
     695             :         bool operator==(const ConstIterator& aConstIterator) const {
     696             :             return mCurrent == aConstIterator.mCurrent; }
     697             : 
     698           0 :         bool operator!=(const ConstIterator& aConstIterator) const {
     699           0 :             return mCurrent != aConstIterator.mCurrent; }
     700             : 
     701             :     protected:
     702             :         friend class Iterator; // XXXwaterson this is so wrong!
     703             :         ReteNode** mCurrent;
     704             :     };
     705             : 
     706             :     ConstIterator First() const { return ConstIterator(mNodes); }
     707             :     ConstIterator Last() const { return ConstIterator(mNodes + mCount); }
     708             : 
     709             :     class Iterator : public ConstIterator {
     710             :     public:
     711           0 :         explicit Iterator(ReteNode** aNode) : ConstIterator(aNode) {}
     712             : 
     713           0 :         Iterator& operator++() {
     714           0 :             ++mCurrent;
     715           0 :             return *this; }
     716             : 
     717             :         Iterator operator++(int) {
     718             :             Iterator result(*this);
     719             :             ++mCurrent;
     720             :             return result; }
     721             : 
     722           0 :         ReteNode* operator*() const {
     723           0 :             return *mCurrent; }
     724             : 
     725           0 :         ReteNode* operator->() const {
     726           0 :             return *mCurrent; }
     727             : 
     728             :         bool operator==(const ConstIterator& aConstIterator) const {
     729             :             return mCurrent == aConstIterator.mCurrent; }
     730             : 
     731           0 :         bool operator!=(const ConstIterator& aConstIterator) const {
     732           0 :             return mCurrent != aConstIterator.mCurrent; }
     733             :     };
     734             : 
     735           0 :     Iterator First() { return Iterator(mNodes); }
     736           0 :     Iterator Last() { return Iterator(mNodes + mCount); }
     737             : 
     738           0 :     int32_t Count() const { return mCount; }
     739             : 
     740             : protected:
     741             :     ReteNode** mNodes;
     742             :     int32_t mCount;
     743             :     int32_t mCapacity;
     744             : };
     745             : 
     746             : //----------------------------------------------------------------------
     747             : 
     748             : /**
     749             :  * A node that applies a test condition to a set of instantiations.
     750             :  *
     751             :  * This class provides implementations of Propagate() and Constrain()
     752             :  * in terms of one simple operation, FilterInstantiations(). A node
     753             :  * that is a "simple test node" in a rule network should derive from
     754             :  * this class, and need only implement FilterInstantiations().
     755             :  */
     756           0 : class TestNode : public ReteNode
     757             : {
     758             : public:
     759             :     explicit TestNode(TestNode* aParent);
     760             : 
     761             :     /**
     762             :      * Retrieve the test node's parent
     763             :      * @return the test node's parent
     764             :      */
     765           0 :     TestNode* GetParent() const { return mParent; }
     766             : 
     767             :     /**
     768             :      * Calls FilterInstantiations() on the instantiation set, and if
     769             :      * the resulting set isn't empty, propagates the new set down to
     770             :      * each of the test node's children.
     771             :      *
     772             :      * Note that the caller of Propagate is responsible for deleting
     773             :      * aInstantiations if necessary as described below.
     774             :      *
     775             :      * Propagate may be called in update or non-update mode as indicated
     776             :      * by the aIsUpdate argument. Non-update mode is used when initially
     777             :      * generating results, whereas update mode is used when the datasource
     778             :      * changes and new results might be available.
     779             :      *
     780             :      * The last node in a chain of TestNodes is always an nsInstantiationNode.
     781             :      * In non-update mode, this nsInstantiationNode will cache the results
     782             :      * in the query using the SetCachedResults method. The query processor
     783             :      * takes these cached results and creates a nsXULTemplateResultSetRDF
     784             :      * which is the enumeration returned to the template builder. This
     785             :      * nsXULTemplateResultSetRDF owns the instantiations and they will be
     786             :      * deleted when the nsXULTemplateResultSetRDF goes away.
     787             :      *
     788             :      * In update mode, the nsInstantiationNode node will iterate over the
     789             :      * instantiations itself and callback to the builder to update any matches
     790             :      * and generated content. If no instantiations match, then the builder
     791             :      * will never be called.
     792             :      *
     793             :      * Thus, the difference between update and non-update modes is that in
     794             :      * update mode, the results and instantiations have been already handled
     795             :      * whereas in non-update mode they are expected to be returned in an
     796             :      * nsXULTemplateResultSetRDF for further processing by the builder.
     797             :      *
     798             :      * Regardless, aTakenInstantiations will be set to true if the
     799             :      * ownership over aInstantiations has been transferred to a result set.
     800             :      * If set to false, the caller is still responsible for aInstantiations.
     801             :      * aTakenInstantiations will be set properly even if an error occurs.
     802             :      */
     803             :     virtual nsresult Propagate(InstantiationSet& aInstantiations,
     804             :                                bool aIsUpdate, bool& aTakenInstantiations) override;
     805             : 
     806             :     /**
     807             :      * This is called by a child node on its parent to allow the
     808             :      * parent's constraints to apply to the set of instantiations.
     809             :      *
     810             :      * A node must iterate through the set of instantiations, and for
     811             :      * each instantiation, either 1) extend the instantiation by
     812             :      * adding variable-to-value assignments and memory element support
     813             :      * for those assignments, or 2) remove the instantiation because
     814             :      * it is inconsistent.
     815             :      *
     816             :      * The node must then pass the resulting set of instantiations up
     817             :      * to its parent (by recursive call; we should make this iterative
     818             :      * & interruptable at some point.)
     819             :      *
     820             :      * @param aInstantiations the set of instantiations that must
     821             :      *   be constrained
     822             :      * @return NS_OK if no errors occurred
     823             :      */
     824             :     virtual nsresult Constrain(InstantiationSet& aInstantiations);
     825             : 
     826             :     /**
     827             :      * Given a set of instantiations, filter out any that are
     828             :      * inconsistent with the test node's test, and append
     829             :      * variable-to-value assignments and memory element support for
     830             :      * those which do pass the test node's test.
     831             :      *
     832             :      * @param aInstantiations the set of instantiations to be
     833             :      *        filtered
     834             :      * @param aCantHandleYet [out] true if the instantiations do not contain
     835             :      *        enough information to constrain the data. May be null if this
     836             :      *        isn't important to the caller.
     837             :      * @return NS_OK if no errors occurred.
     838             :      */
     839             :     virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
     840             :                                           bool* aCantHandleYet) const = 0;
     841             :     //XXX probably better named "ApplyConstraints" or "Discrminiate" or something
     842             : 
     843             :     /**
     844             :      * Add another node as a child of this node.
     845             :      * @param aNode the node to add.
     846             :      * @return NS_OK if no errors occur.
     847             :      */
     848           0 :     nsresult AddChild(ReteNode* aNode) { return mKids.Add(aNode); }
     849             : 
     850             :     /**
     851             :      * Remove all the children of this node
     852             :      * @return NS_OK if no errors occur.
     853             :      */
     854             :     nsresult RemoveAllChildren() { return mKids.Clear(); }
     855             : 
     856             : protected:
     857             :     TestNode* mParent;
     858             :     ReteNodeSet mKids;
     859             : };
     860             : 
     861             : #endif // nsRuleNetwork_h__

Generated by: LCOV version 1.13