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