summaryrefslogtreecommitdiffstats
path: root/dom/xslt/xslt/txKey.h
blob: e3bf56ebaa11fa3b5f51419b8b7e72e3fc1a71ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef txKey_h__
#define txKey_h__

#include "nsTHashtable.h"
#include "txExpandedNameMap.h"
#include "txList.h"
#include "txNodeSet.h"
#include "txXSLTPatterns.h"
#include "txXMLUtils.h"

class txPattern;
class Expr;
class txExecutionState;

class txKeyValueHashKey {
 public:
  txKeyValueHashKey(const txExpandedName& aKeyName, int32_t aRootIdentifier,
                    const nsAString& aKeyValue)
      : mKeyName(aKeyName),
        mKeyValue(aKeyValue),
        mRootIdentifier(aRootIdentifier) {}

  txExpandedName mKeyName;
  nsString mKeyValue;
  int32_t mRootIdentifier;
};

struct txKeyValueHashEntry : public PLDHashEntryHdr {
 public:
  using KeyType = const txKeyValueHashKey&;
  using KeyTypePointer = const txKeyValueHashKey*;

  explicit txKeyValueHashEntry(KeyTypePointer aKey)
      : mKey(*aKey), mNodeSet(new txNodeSet(nullptr)) {}

  txKeyValueHashEntry(const txKeyValueHashEntry& entry)
      : mKey(entry.mKey), mNodeSet(entry.mNodeSet) {}

  bool KeyEquals(KeyTypePointer aKey) const;

  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }

  static PLDHashNumber HashKey(KeyTypePointer aKey);

  enum { ALLOW_MEMMOVE = true };

  txKeyValueHashKey mKey;
  RefPtr<txNodeSet> mNodeSet;
};

using txKeyValueHash = nsTHashtable<txKeyValueHashEntry>;

class txIndexedKeyHashKey {
 public:
  txIndexedKeyHashKey(txExpandedName aKeyName, int32_t aRootIdentifier)
      : mKeyName(aKeyName), mRootIdentifier(aRootIdentifier) {}

  txExpandedName mKeyName;
  int32_t mRootIdentifier;
};

struct txIndexedKeyHashEntry : public PLDHashEntryHdr {
 public:
  using KeyType = const txIndexedKeyHashKey&;
  using KeyTypePointer = const txIndexedKeyHashKey*;

  explicit txIndexedKeyHashEntry(KeyTypePointer aKey)
      : mKey(*aKey), mIndexed(false) {}

  txIndexedKeyHashEntry(const txIndexedKeyHashEntry& entry)
      : mKey(entry.mKey), mIndexed(entry.mIndexed) {}

  bool KeyEquals(KeyTypePointer aKey) const;

  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }

  static PLDHashNumber HashKey(KeyTypePointer aKey);

  enum { ALLOW_MEMMOVE = true };

  txIndexedKeyHashKey mKey;
  bool mIndexed;
};

using txIndexedKeyHash = nsTHashtable<txIndexedKeyHashEntry>;

/**
 * Class holding all <xsl:key>s of a particular expanded name in the
 * stylesheet.
 */
class txXSLKey {
 public:
  explicit txXSLKey(const txExpandedName& aName) : mName(aName) {}

  /**
   * Adds a match/use pair.
   * @param aMatch  match-pattern
   * @param aUse    use-expression
   * @return false if an error occurred, true otherwise
   */
  bool addKey(mozilla::UniquePtr<txPattern>&& aMatch,
              mozilla::UniquePtr<Expr>&& aUse);

  /**
   * Indexes a subtree and adds it to the hash of key values
   * @param aRoot         Subtree root to index and add
   * @param aKeyValueHash Hash to add values to
   * @param aEs           txExecutionState to use for XPath evaluation
   */
  nsresult indexSubtreeRoot(const txXPathNode& aRoot,
                            txKeyValueHash& aKeyValueHash,
                            txExecutionState& aEs);

 private:
  /**
   * Recursively searches a node, its attributes and its subtree for
   * nodes matching any of the keys match-patterns.
   * @param aNode         Node to search
   * @param aKey          Key to use when adding into the hash
   * @param aKeyValueHash Hash to add values to
   * @param aEs           txExecutionState to use for XPath evaluation
   */
  nsresult indexTree(const txXPathNode& aNode, txKeyValueHashKey& aKey,
                     txKeyValueHash& aKeyValueHash, txExecutionState& aEs);

  /**
   * Tests one node if it matches any of the keys match-patterns. If
   * the node matches its values are added to the index.
   * @param aNode         Node to test
   * @param aKey          Key to use when adding into the hash
   * @param aKeyValueHash Hash to add values to
   * @param aEs           txExecutionState to use for XPath evaluation
   */
  nsresult testNode(const txXPathNode& aNode, txKeyValueHashKey& aKey,
                    txKeyValueHash& aKeyValueHash, txExecutionState& aEs);

  /**
   * represents one match/use pair
   */
  struct Key {
    mozilla::UniquePtr<txPattern> matchPattern;
    mozilla::UniquePtr<Expr> useExpr;
  };

  /**
   * List of all match/use pairs. The items as |Key|s
   */
  nsTArray<Key> mKeys;

  /**
   * Name of this key
   */
  txExpandedName mName;
};

class txKeyHash {
 public:
  explicit txKeyHash(const txOwningExpandedNameMap<txXSLKey>& aKeys)
      : mKeyValues(4), mIndexedKeys(1), mKeys(aKeys) {}

  nsresult init();

  nsresult getKeyNodes(const txExpandedName& aKeyName, const txXPathNode& aRoot,
                       const nsAString& aKeyValue, bool aIndexIfNotFound,
                       txExecutionState& aEs, txNodeSet** aResult);

 private:
  // Hash of all indexed key-values
  txKeyValueHash mKeyValues;

  // Hash showing which keys+roots has been indexed
  txIndexedKeyHash mIndexedKeys;

  // Map of txXSLKeys
  const txOwningExpandedNameMap<txXSLKey>& mKeys;

  // Empty nodeset returned if no key is found
  RefPtr<txNodeSet> mEmptyNodeSet;
};

#endif  // txKey_h__