LCOV - code coverage report
Current view: directory - content/xul/templates/src - nsRuleNetwork.h (source / functions) Found Hit Coverage
Test: app.info Lines: 185 0 0.0 %
Date: 2012-06-02 Functions: 92 0 0.0 %

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

Generated by: LCOV version 1.7