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