Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef vm_MatchPairs_h
8 : #define vm_MatchPairs_h
9 :
10 : #include "jsalloc.h"
11 :
12 : #include "ds/LifoAlloc.h"
13 : #include "js/Vector.h"
14 :
15 : /*
16 : * RegExp match results are succinctly represented by pairs of integer
17 : * indices delimiting (start, limit] segments of the input string.
18 : *
19 : * The pair count for a given RegExp match is the capturing parentheses
20 : * count plus one for the "0 capturing paren" whole text match.
21 : */
22 :
23 : namespace js {
24 :
25 : struct MatchPair
26 : {
27 : int32_t start;
28 : int32_t limit;
29 :
30 : MatchPair()
31 : : start(-1), limit(-1)
32 : { }
33 :
34 : MatchPair(int32_t start, int32_t limit)
35 : : start(start), limit(limit)
36 : { }
37 :
38 118 : size_t length() const { MOZ_ASSERT(!isUndefined()); return limit - start; }
39 : bool isEmpty() const { return length() == 0; }
40 391 : bool isUndefined() const { return start < 0; }
41 :
42 : void displace(size_t amount) {
43 : start += (start < 0) ? 0 : amount;
44 : limit += (limit < 0) ? 0 : amount;
45 : }
46 :
47 141 : inline bool check() const {
48 141 : MOZ_ASSERT(limit >= start);
49 141 : MOZ_ASSERT_IF(start < 0, start == -1);
50 141 : MOZ_ASSERT_IF(limit < 0, limit == -1);
51 141 : return true;
52 : }
53 : };
54 :
55 : /* Base class for RegExp execution output. */
56 : class MatchPairs
57 : {
58 : protected:
59 : /* Length of pairs_. */
60 : uint32_t pairCount_;
61 :
62 : /* Raw pointer into an allocated MatchPair buffer. */
63 : MatchPair* pairs_;
64 :
65 : protected:
66 : /* Not used directly: use ScopedMatchPairs or VectorMatchPairs. */
67 137 : MatchPairs()
68 137 : : pairCount_(0), pairs_(nullptr)
69 137 : { }
70 :
71 : protected:
72 : /* Functions used by friend classes. */
73 : friend class RegExpShared;
74 : friend class RegExpStatics;
75 :
76 : /* MatchPair buffer allocator: set pairs_ and pairCount_. */
77 : virtual bool allocOrExpandArray(size_t pairCount) = 0;
78 :
79 : bool initArrayFrom(MatchPairs& copyFrom);
80 13 : void forgetArray() { pairs_ = nullptr; }
81 :
82 66 : void checkAgainst(size_t inputLength) {
83 : #ifdef DEBUG
84 207 : for (size_t i = 0; i < pairCount_; i++) {
85 141 : const MatchPair& p = (*this)[i];
86 141 : MOZ_ASSERT(p.check());
87 141 : if (p.isUndefined())
88 14 : continue;
89 127 : MOZ_ASSERT(size_t(p.limit) <= inputLength);
90 : }
91 : #endif
92 66 : }
93 :
94 : public:
95 : /* Querying functions in the style of RegExpStatics. */
96 6 : bool empty() const { return pairCount_ == 0; }
97 120 : size_t pairCount() const { MOZ_ASSERT(pairCount_ > 0); return pairCount_; }
98 : size_t parenCount() const { return pairCount_ - 1; }
99 :
100 22 : static size_t offsetOfPairs() { return offsetof(MatchPairs, pairs_); }
101 22 : static size_t offsetOfPairCount() { return offsetof(MatchPairs, pairCount_); }
102 :
103 0 : int32_t* pairsRaw() { return reinterpret_cast<int32_t*>(pairs_); }
104 :
105 : public:
106 57 : size_t length() const { return pairCount_; }
107 :
108 195 : const MatchPair& operator[](size_t i) const {
109 195 : MOZ_ASSERT(i < pairCount_);
110 195 : return pairs_[i];
111 : }
112 159 : MatchPair& operator[](size_t i) {
113 159 : MOZ_ASSERT(i < pairCount_);
114 159 : return pairs_[i];
115 : }
116 : };
117 :
118 : /* MatchPairs allocated into temporary storage, removed when out of scope. */
119 124 : class ScopedMatchPairs : public MatchPairs
120 : {
121 : LifoAllocScope lifoScope_;
122 :
123 : public:
124 : /* Constructs an implicit LifoAllocScope. */
125 124 : explicit ScopedMatchPairs(LifoAlloc* lifoAlloc)
126 124 : : lifoScope_(lifoAlloc)
127 124 : { }
128 :
129 : protected:
130 : bool allocOrExpandArray(size_t pairCount);
131 : };
132 :
133 : /*
134 : * MatchPairs allocated into permanent storage, for RegExpStatics.
135 : * The Vector of MatchPairs is reusable by Vector expansion.
136 : */
137 0 : class VectorMatchPairs : public MatchPairs
138 : {
139 : Vector<MatchPair, 10, SystemAllocPolicy> vec_;
140 :
141 : public:
142 13 : VectorMatchPairs() {
143 13 : vec_.clear();
144 13 : }
145 :
146 : protected:
147 : friend class RegExpStatics;
148 : bool allocOrExpandArray(size_t pairCount);
149 : };
150 :
151 : } /* namespace js */
152 :
153 : #endif /* vm_MatchPairs_h */
|