MatchPairs.h (3789B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 "js/AllocPolicy.h" 11 #include "js/Vector.h" 12 13 /* 14 * RegExp match results are succinctly represented by pairs of integer 15 * indices delimiting (start, limit] segments of the input string. 16 * 17 * The pair count for a given RegExp match is the capturing parentheses 18 * count plus one for the "0 capturing paren" whole text match. 19 */ 20 21 namespace js { 22 23 struct MatchPair final { 24 int32_t start; 25 int32_t limit; 26 27 static constexpr int32_t NoMatch = -1; 28 29 MatchPair() : start(NoMatch), limit(NoMatch) {} 30 31 MatchPair(int32_t start, int32_t limit) : start(start), limit(limit) {} 32 33 size_t length() const { 34 MOZ_ASSERT(!isUndefined()); 35 return limit - start; 36 } 37 bool isUndefined() const { return start < 0; } 38 39 inline bool check() const { 40 MOZ_ASSERT(limit >= start); 41 MOZ_ASSERT_IF(start < 0, start == NoMatch); 42 MOZ_ASSERT_IF(limit < 0, limit == NoMatch); 43 return true; 44 } 45 46 // Note: return int32_t instead of size_t to prevent signed => unsigned 47 // conversions in caller functions. 48 static constexpr int32_t offsetOfStart() { 49 return int32_t(offsetof(MatchPair, start)); 50 } 51 static constexpr int32_t offsetOfLimit() { 52 return int32_t(offsetof(MatchPair, limit)); 53 } 54 }; 55 56 // MachPairs is used as base class for VectorMatchPairs but can also be 57 // stack-allocated (without a Vector) in JIT code. 58 class MatchPairs { 59 protected: 60 /* Length of pairs_. */ 61 uint32_t pairCount_; 62 63 /* Raw pointer into an allocated MatchPair buffer. */ 64 MatchPair* pairs_; 65 66 protected: 67 /* Not used directly: use VectorMatchPairs. */ 68 MatchPairs() : pairCount_(0), pairs_(nullptr) {} 69 70 protected: 71 /* Functions used by friend classes. */ 72 friend class RegExpShared; 73 friend class RegExpStatics; 74 75 void forgetArray() { pairs_ = nullptr; } 76 77 public: 78 void checkAgainst(size_t inputLength) { 79 #ifdef DEBUG 80 for (size_t i = 0; i < pairCount_; i++) { 81 const MatchPair& p = (*this)[i]; 82 MOZ_ASSERT(p.check()); 83 if (p.isUndefined()) { 84 continue; 85 } 86 MOZ_ASSERT(size_t(p.limit) <= inputLength); 87 } 88 #endif 89 } 90 91 /* Querying functions in the style of RegExpStatics. */ 92 bool empty() const { return pairCount_ == 0; } 93 size_t pairCount() const { 94 MOZ_ASSERT(pairCount_ > 0); 95 return pairCount_; 96 } 97 98 // Note: return int32_t instead of size_t to prevent signed => unsigned 99 // conversions in caller functions. 100 static constexpr int32_t offsetOfPairs() { 101 return int32_t(offsetof(MatchPairs, pairs_)); 102 } 103 static constexpr int32_t offsetOfPairCount() { 104 return int32_t(offsetof(MatchPairs, pairCount_)); 105 } 106 107 int32_t* pairsRaw() { return reinterpret_cast<int32_t*>(pairs_); } 108 109 public: 110 size_t length() const { return pairCount_; } 111 112 const MatchPair& operator[](size_t i) const { 113 MOZ_ASSERT(i < pairCount_); 114 return pairs_[i]; 115 } 116 MatchPair& operator[](size_t i) { 117 MOZ_ASSERT(i < pairCount_); 118 return pairs_[i]; 119 } 120 }; 121 122 class VectorMatchPairs : public MatchPairs { 123 Vector<MatchPair, 10, SystemAllocPolicy> vec_; 124 125 protected: 126 friend class RegExpShared; 127 friend class RegExpStatics; 128 129 /* MatchPair buffer allocator: set pairs_ and pairCount_. */ 130 bool allocOrExpandArray(size_t pairCount); 131 132 bool initArrayFrom(VectorMatchPairs& copyFrom); 133 134 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { 135 return vec_.sizeOfExcludingThis(mallocSizeOf); 136 } 137 }; 138 139 } /* namespace js */ 140 141 #endif /* vm_MatchPairs_h */