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 #ifndef txKey_h__ 7 #define txKey_h__ 8 9 #include "nsTHashtable.h" 10 #include "txNodeSet.h" 11 #include "txList.h" 12 #include "txXSLTPatterns.h" 13 #include "txXMLUtils.h" 14 15 class txPattern; 16 class Expr; 17 class txExecutionState; 18 19 class txKeyValueHashKey 20 { 21 public: txKeyValueHashKey(const txExpandedName & aKeyName,int32_t aRootIdentifier,const nsAString & aKeyValue)22 txKeyValueHashKey(const txExpandedName& aKeyName, 23 int32_t aRootIdentifier, 24 const nsAString& aKeyValue) 25 : mKeyName(aKeyName), 26 mKeyValue(aKeyValue), 27 mRootIdentifier(aRootIdentifier) 28 { 29 } 30 31 txExpandedName mKeyName; 32 nsString mKeyValue; 33 int32_t mRootIdentifier; 34 }; 35 36 struct txKeyValueHashEntry : public PLDHashEntryHdr 37 { 38 public: 39 typedef const txKeyValueHashKey& KeyType; 40 typedef const txKeyValueHashKey* KeyTypePointer; 41 txKeyValueHashEntrytxKeyValueHashEntry42 explicit txKeyValueHashEntry(KeyTypePointer aKey) 43 : mKey(*aKey), 44 mNodeSet(new txNodeSet(nullptr)) { } 45 txKeyValueHashEntrytxKeyValueHashEntry46 txKeyValueHashEntry(const txKeyValueHashEntry& entry) 47 : mKey(entry.mKey), 48 mNodeSet(entry.mNodeSet) { } 49 50 bool KeyEquals(KeyTypePointer aKey) const; 51 KeyToPointertxKeyValueHashEntry52 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } 53 54 static PLDHashNumber HashKey(KeyTypePointer aKey); 55 56 enum { ALLOW_MEMMOVE = true }; 57 58 txKeyValueHashKey mKey; 59 RefPtr<txNodeSet> mNodeSet; 60 }; 61 62 typedef nsTHashtable<txKeyValueHashEntry> txKeyValueHash; 63 64 class txIndexedKeyHashKey 65 { 66 public: txIndexedKeyHashKey(txExpandedName aKeyName,int32_t aRootIdentifier)67 txIndexedKeyHashKey(txExpandedName aKeyName, 68 int32_t aRootIdentifier) 69 : mKeyName(aKeyName), 70 mRootIdentifier(aRootIdentifier) 71 { 72 } 73 74 txExpandedName mKeyName; 75 int32_t mRootIdentifier; 76 }; 77 78 struct txIndexedKeyHashEntry : public PLDHashEntryHdr 79 { 80 public: 81 typedef const txIndexedKeyHashKey& KeyType; 82 typedef const txIndexedKeyHashKey* KeyTypePointer; 83 txIndexedKeyHashEntrytxIndexedKeyHashEntry84 explicit txIndexedKeyHashEntry(KeyTypePointer aKey) 85 : mKey(*aKey), 86 mIndexed(false) { } 87 txIndexedKeyHashEntrytxIndexedKeyHashEntry88 txIndexedKeyHashEntry(const txIndexedKeyHashEntry& entry) 89 : mKey(entry.mKey), 90 mIndexed(entry.mIndexed) { } 91 92 bool KeyEquals(KeyTypePointer aKey) const; 93 KeyToPointertxIndexedKeyHashEntry94 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } 95 96 static PLDHashNumber HashKey(KeyTypePointer aKey); 97 98 enum { ALLOW_MEMMOVE = true }; 99 100 txIndexedKeyHashKey mKey; 101 bool mIndexed; 102 }; 103 104 typedef nsTHashtable<txIndexedKeyHashEntry> txIndexedKeyHash; 105 106 /** 107 * Class holding all <xsl:key>s of a particular expanded name in the 108 * stylesheet. 109 */ 110 class txXSLKey { 111 112 public: txXSLKey(const txExpandedName & aName)113 explicit txXSLKey(const txExpandedName& aName) : mName(aName) 114 { 115 } 116 117 /** 118 * Adds a match/use pair. 119 * @param aMatch match-pattern 120 * @param aUse use-expression 121 * @return false if an error occurred, true otherwise 122 */ 123 bool addKey(nsAutoPtr<txPattern>&& aMatch, nsAutoPtr<Expr>&& aUse); 124 125 /** 126 * Indexes a subtree and adds it to the hash of key values 127 * @param aRoot Subtree root to index and add 128 * @param aKeyValueHash Hash to add values to 129 * @param aEs txExecutionState to use for XPath evaluation 130 */ 131 nsresult indexSubtreeRoot(const txXPathNode& aRoot, 132 txKeyValueHash& aKeyValueHash, 133 txExecutionState& aEs); 134 135 private: 136 /** 137 * Recursively searches a node, its attributes and its subtree for 138 * nodes matching any of the keys match-patterns. 139 * @param aNode Node to search 140 * @param aKey Key to use when adding into the hash 141 * @param aKeyValueHash Hash to add values to 142 * @param aEs txExecutionState to use for XPath evaluation 143 */ 144 nsresult indexTree(const txXPathNode& aNode, txKeyValueHashKey& aKey, 145 txKeyValueHash& aKeyValueHash, txExecutionState& aEs); 146 147 /** 148 * Tests one node if it matches any of the keys match-patterns. If 149 * the node matches its values are added to the index. 150 * @param aNode Node to test 151 * @param aKey Key to use when adding into the hash 152 * @param aKeyValueHash Hash to add values to 153 * @param aEs txExecutionState to use for XPath evaluation 154 */ 155 nsresult testNode(const txXPathNode& aNode, txKeyValueHashKey& aKey, 156 txKeyValueHash& aKeyValueHash, txExecutionState& aEs); 157 158 /** 159 * represents one match/use pair 160 */ 161 struct Key { 162 nsAutoPtr<txPattern> matchPattern; 163 nsAutoPtr<Expr> useExpr; 164 }; 165 166 /** 167 * List of all match/use pairs. The items as |Key|s 168 */ 169 nsTArray<Key> mKeys; 170 171 /** 172 * Name of this key 173 */ 174 txExpandedName mName; 175 }; 176 177 178 class txKeyHash 179 { 180 public: txKeyHash(const txOwningExpandedNameMap<txXSLKey> & aKeys)181 explicit txKeyHash(const txOwningExpandedNameMap<txXSLKey>& aKeys) 182 : mKeyValues(4) 183 , mIndexedKeys(1) 184 , mKeys(aKeys) 185 { 186 } 187 188 nsresult init(); 189 190 nsresult getKeyNodes(const txExpandedName& aKeyName, 191 const txXPathNode& aRoot, 192 const nsAString& aKeyValue, 193 bool aIndexIfNotFound, 194 txExecutionState& aEs, 195 txNodeSet** aResult); 196 197 private: 198 // Hash of all indexed key-values 199 txKeyValueHash mKeyValues; 200 201 // Hash showing which keys+roots has been indexed 202 txIndexedKeyHash mIndexedKeys; 203 204 // Map of txXSLKeys 205 const txOwningExpandedNameMap<txXSLKey>& mKeys; 206 207 // Empty nodeset returned if no key is found 208 RefPtr<txNodeSet> mEmptyNodeSet; 209 }; 210 211 212 #endif //txKey_h__ 213