diff -r 000000000000 -r 6474c204b198 js/src/vm/MatchPairs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/vm/MatchPairs.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 vm_MatchPairs_h +#define vm_MatchPairs_h + +#include "jsalloc.h" + +#include "ds/LifoAlloc.h" +#include "js/Vector.h" + +/* + * RegExp match results are succinctly represented by pairs of integer + * indices delimiting (start, limit] segments of the input string. + * + * The pair count for a given RegExp match is the capturing parentheses + * count plus one for the "0 capturing paren" whole text match. + */ + +namespace js { + +struct MatchPair +{ + int start; + int limit; + + MatchPair() + : start(-1), limit(-1) + { } + + MatchPair(int start, int limit) + : start(start), limit(limit) + { } + + size_t length() const { JS_ASSERT(!isUndefined()); return limit - start; } + bool isEmpty() const { return length() == 0; } + bool isUndefined() const { return start < 0; } + + void displace(size_t amount) { + start += (start < 0) ? 0 : amount; + limit += (limit < 0) ? 0 : amount; + } + + inline bool check() const { + JS_ASSERT(limit >= start); + JS_ASSERT_IF(start < 0, start == -1); + JS_ASSERT_IF(limit < 0, limit == -1); + return true; + } +}; + +/* Base class for RegExp execution output. */ +class MatchPairs +{ + protected: + size_t pairCount_; /* Length of pairs_. */ + MatchPair *pairs_; /* Raw pointer into an allocated MatchPair buffer. */ + + protected: + /* Not used directly: use ScopedMatchPairs or VectorMatchPairs. */ + MatchPairs() + : pairCount_(0), pairs_(nullptr) + { } + + protected: + /* Functions used by friend classes. */ + friend class RegExpShared; + friend class RegExpStatics; + + /* MatchPair buffer allocator: set pairs_ and pairCount_. */ + virtual bool allocOrExpandArray(size_t pairCount) = 0; + + bool initArray(size_t pairCount); + bool initArrayFrom(MatchPairs ©From); + void forgetArray() { pairs_ = nullptr; } + + void displace(size_t disp); + void checkAgainst(size_t inputLength) { +#ifdef DEBUG + for (size_t i = 0; i < pairCount_; i++) { + const MatchPair &p = pair(i); + JS_ASSERT(p.check()); + if (p.isUndefined()) + continue; + JS_ASSERT(size_t(p.limit) <= inputLength); + } +#endif + } + + public: + /* Querying functions in the style of RegExpStatics. */ + bool empty() const { return pairCount_ == 0; } + size_t pairCount() const { JS_ASSERT(pairCount_ > 0); return pairCount_; } + size_t parenCount() const { return pairCount_ - 1; } + + public: + unsigned *rawBuf() const { return reinterpret_cast(pairs_); } + size_t length() const { return pairCount_; } + + /* Pair accessors. */ + const MatchPair &pair(size_t i) const { + JS_ASSERT(pairCount_ && i < pairCount_); + JS_ASSERT(pairs_); + return pairs_[i]; + } + + const MatchPair &operator[](size_t i) const { return pair(i); } +}; + +/* MatchPairs allocated into temporary storage, removed when out of scope. */ +class ScopedMatchPairs : public MatchPairs +{ + LifoAllocScope lifoScope_; + + public: + /* Constructs an implicit LifoAllocScope. */ + ScopedMatchPairs(LifoAlloc *lifoAlloc) + : lifoScope_(lifoAlloc) + { } + + const MatchPair &operator[](size_t i) const { return pair(i); } + + protected: + bool allocOrExpandArray(size_t pairCount); +}; + +/* + * MatchPairs allocated into permanent storage, for RegExpStatics. + * The Vector of MatchPairs is reusable by Vector expansion. + */ +class VectorMatchPairs : public MatchPairs +{ + Vector vec_; + + public: + VectorMatchPairs() { + vec_.clear(); + } + + const MatchPair &operator[](size_t i) const { return pair(i); } + + protected: + friend class RegExpStatics; + bool allocOrExpandArray(size_t pairCount); +}; + +/* + * Passes either MatchPair or MatchPairs through ExecuteRegExp() + * to avoid duplication of generic code. + */ +struct MatchConduit +{ + union { + MatchPair *pair; + MatchPairs *pairs; + } u; + bool isPair; + + explicit MatchConduit(MatchPair *pair) { + isPair = true; + u.pair = pair; + } + explicit MatchConduit(MatchPairs *pairs) { + isPair = false; + u.pairs = pairs; + } +}; + +} /* namespace js */ + +#endif /* vm_MatchPairs_h */